OSDN Git Service

mavenによるビルドに変更
[charactermanaj/CharacterManaJ.git] / src / main / java / charactermanaj / model / io / PartsInfoXMLWriter.java
1 package charactermanaj.model.io;\r
2 \r
3 import java.io.ByteArrayOutputStream;\r
4 import java.io.File;\r
5 import java.io.FileOutputStream;\r
6 import java.io.IOException;\r
7 import java.io.OutputStream;\r
8 import java.io.OutputStreamWriter;\r
9 import java.net.URI;\r
10 import java.nio.charset.Charset;\r
11 import java.text.SimpleDateFormat;\r
12 import java.util.ArrayList;\r
13 import java.util.Collection;\r
14 import java.util.Collections;\r
15 import java.util.HashMap;\r
16 import java.util.List;\r
17 import java.util.Locale;\r
18 \r
19 import javax.xml.XMLConstants;\r
20 import javax.xml.parsers.DocumentBuilder;\r
21 import javax.xml.parsers.DocumentBuilderFactory;\r
22 import javax.xml.parsers.ParserConfigurationException;\r
23 import javax.xml.transform.OutputKeys;\r
24 import javax.xml.transform.Transformer;\r
25 import javax.xml.transform.TransformerConfigurationException;\r
26 import javax.xml.transform.TransformerException;\r
27 import javax.xml.transform.TransformerFactory;\r
28 import javax.xml.transform.dom.DOMSource;\r
29 import javax.xml.transform.stream.StreamResult;\r
30 \r
31 import org.w3c.dom.Attr;\r
32 import org.w3c.dom.Document;\r
33 import org.w3c.dom.Element;\r
34 \r
35 import charactermanaj.model.PartsAuthorInfo;\r
36 import charactermanaj.model.PartsManageData;\r
37 import charactermanaj.model.PartsManageData.PartsKey;\r
38 \r
39 public class PartsInfoXMLWriter {\r
40 \r
41         /**\r
42          * パーツ定義XMLファイルの名前空間\r
43          */\r
44         public static final String NS_PARTSDEF = "http://charactermanaj.sourceforge.jp/schema/charactermanaj-partsdef";\r
45 \r
46         /**\r
47          * パーツ管理情報をDocBaseと同じフォルダ上のparts-info.xmlに書き出す.<br>\r
48          * XML生成中に失敗した場合は既存の管理情報は残される.<br>\r
49          * (管理情報の書き込み中にI/O例外が発生した場合は管理情報は破壊される.)<br>\r
50          * \r
51          * @param docBase\r
52          *            character.xmlの位置\r
53          * @param partsManageData\r
54          *            パーツ管理情報\r
55          * @throws IOException\r
56          *             出力に失敗した場合\r
57          */\r
58         public void savePartsManageData(URI docBase, PartsManageData partsManageData)\r
59                         throws IOException {\r
60                 if (docBase == null || partsManageData == null) {\r
61                         throw new IllegalArgumentException();\r
62                 }\r
63 \r
64                 if (!"file".equals(docBase.getScheme())) {\r
65                         throw new IOException("ファイル以外はサポートしていません: " + docBase);\r
66                 }\r
67                 File docBaseFile = new File(docBase);\r
68                 File baseDir = docBaseFile.getParentFile();\r
69 \r
70                 // データからXMLを構築してストリームに出力する.\r
71                 // 完全に成功したXMLのみ書き込むようにするため、一旦バッファする。\r
72                 ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
73                 try {\r
74                         savePartsManageData(partsManageData, bos);\r
75                 } finally {\r
76                         bos.close();\r
77                 }\r
78 \r
79                 // バッファされたXMLデータを実際のファイルに書き込む\r
80                 File partsInfoXML = new File(baseDir, "parts-info.xml");\r
81                 FileOutputStream os = new FileOutputStream(partsInfoXML);\r
82                 try {\r
83                         os.write(bos.toByteArray());\r
84                 } finally {\r
85                         os.close();\r
86                 }\r
87         }\r
88 \r
89         /**\r
90          * パーツ管理情報をXMLとしてストリームに書き出す.<br>\r
91          * \r
92          * @param partsManageData\r
93          *            パーツ管理データ\r
94          * @param outstm\r
95          *            出力先ストリーム\r
96          * @throws IOException\r
97          *             出力に失敗した場合\r
98          */\r
99         public void savePartsManageData(PartsManageData partsManageData,\r
100                         OutputStream outstm) throws IOException {\r
101                 if (partsManageData == null || outstm == null) {\r
102                         throw new IllegalArgumentException();\r
103                 }\r
104 \r
105                 Document doc;\r
106                 try {\r
107                         DocumentBuilderFactory factory = DocumentBuilderFactory\r
108                                         .newInstance();\r
109                         factory.setNamespaceAware(true);\r
110                         DocumentBuilder builder = factory.newDocumentBuilder();\r
111                         doc = builder.newDocument();\r
112 \r
113                 } catch (ParserConfigurationException ex) {\r
114                         throw new RuntimeException("JAXP Configuration Exception.", ex);\r
115                 }\r
116 \r
117                 Locale locale = Locale.getDefault();\r
118                 String lang = locale.getLanguage();\r
119 \r
120                 Element root = doc.createElementNS(NS_PARTSDEF, "parts-definition");\r
121 \r
122                 root.setAttribute("xmlns:xml", XMLConstants.XML_NS_URI);\r
123                 root.setAttribute("xmlns:xsi",\r
124                                 "http://www.w3.org/2001/XMLSchema-instance");\r
125                 root.setAttribute("xsi:schemaLocation", NS_PARTSDEF\r
126                                 + " parts-definition.xsd");\r
127                 doc.appendChild(root);\r
128 \r
129                 // 作者情報を取得する\r
130                 Collection<PartsAuthorInfo> partsAuthors = partsManageData\r
131                                 .getAuthorInfos();\r
132                 for (PartsAuthorInfo partsAuthorInfo : partsAuthors) {\r
133                         String author = partsAuthorInfo.getAuthor();\r
134                         if (author == null || author.length() == 0) {\r
135                                 continue;\r
136                         }\r
137 \r
138                         // 作者情報の登録\r
139                         Element nodeAuthor = doc.createElementNS(NS_PARTSDEF, "author");\r
140                         Element nodeAuthorName = doc.createElementNS(NS_PARTSDEF, "name");\r
141                         Attr attrLang = doc.createAttributeNS(XMLConstants.XML_NS_URI,\r
142                                         "lang");\r
143                         attrLang.setValue(lang);\r
144                         nodeAuthorName.setAttributeNodeNS(attrLang);\r
145                         nodeAuthorName.setTextContent(author);\r
146                         nodeAuthor.appendChild(nodeAuthorName);\r
147 \r
148                         String homepageURL = partsAuthorInfo.getHomePage();\r
149                         if (homepageURL != null && homepageURL.length() > 0) {\r
150                                 Element nodeHomepage = doc.createElementNS(NS_PARTSDEF,\r
151                                                 "home-page");\r
152                                 Attr attrHomepageLang = doc.createAttributeNS(\r
153                                                 XMLConstants.XML_NS_URI, "lang");\r
154                                 attrHomepageLang.setValue(lang);\r
155                                 nodeHomepage.setAttributeNodeNS(attrHomepageLang);\r
156                                 nodeHomepage.setTextContent(homepageURL);\r
157                                 nodeAuthor.appendChild(nodeHomepage);\r
158                         }\r
159 \r
160                         root.appendChild(nodeAuthor);\r
161 \r
162                         Collection<PartsKey> partsKeys = partsManageData\r
163                                         .getPartsKeysByAuthor(author);\r
164 \r
165                         // ダウンロード別にパーツキーの集約\r
166                         HashMap<String, List<PartsKey>> downloadMap = new HashMap<String, List<PartsKey>>();\r
167                         for (PartsKey partsKey : partsKeys) {\r
168                                 PartsManageData.PartsVersionInfo versionInfo = partsManageData\r
169                                                 .getVersionStrict(partsKey);\r
170                                 String downloadURL = versionInfo.getDownloadURL();\r
171                                 if (downloadURL == null) {\r
172                                         downloadURL = "";\r
173                                 }\r
174                                 List<PartsKey> partsKeyGrp = downloadMap.get(downloadURL);\r
175                                 if (partsKeyGrp == null) {\r
176                                         partsKeyGrp = new ArrayList<PartsKey>();\r
177                                         downloadMap.put(downloadURL, partsKeyGrp);\r
178                                 }\r
179                                 partsKeyGrp.add(partsKey);\r
180                         }\r
181 \r
182                         // ダウンロード別にパーツ情報の登録\r
183                         ArrayList<String> downloadURLs = new ArrayList<String>(\r
184                                         downloadMap.keySet());\r
185                         Collections.sort(downloadURLs);\r
186 \r
187                         // 日時コンバータ\r
188                         final SimpleDateFormat dateTimeFmt = new SimpleDateFormat(\r
189                                         "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");\r
190 \r
191                         for (String downloadURL : downloadURLs) {\r
192                                 List<PartsKey> partsKeyGrp = downloadMap.get(downloadURL);\r
193                                 Collections.sort(partsKeyGrp);\r
194 \r
195                                 Element nodeDownload = doc.createElementNS(NS_PARTSDEF,\r
196                                                 "download-url");\r
197                                 nodeDownload.setTextContent(downloadURL);\r
198                                 root.appendChild(nodeDownload);\r
199 \r
200                                 for (PartsKey partsKey : partsKeyGrp) {\r
201                                         PartsManageData.PartsVersionInfo versionInfo = partsManageData\r
202                                                         .getVersionStrict(partsKey);\r
203 \r
204                                         Element nodeParts = doc.createElementNS(NS_PARTSDEF,\r
205                                                         "parts");\r
206 \r
207                                         nodeParts.setAttribute("name", partsKey.getPartsName());\r
208                                         if (partsKey.getCategoryId() != null) {\r
209                                                 nodeParts.setAttribute("category",\r
210                                                                 partsKey.getCategoryId());\r
211                                         }\r
212                                         if (versionInfo.getVersion() > 0) {\r
213                                                 nodeParts.setAttribute("version",\r
214                                                                 Double.toString(versionInfo.getVersion()));\r
215                                         }\r
216 \r
217                                         if (versionInfo.getLastModified() != null) {\r
218                                                 nodeParts.setAttribute("lastModified", dateTimeFmt\r
219                                                                 .format(versionInfo.getLastModified()));\r
220                                         }\r
221 \r
222                                         String localizedName = partsManageData\r
223                                                         .getLocalizedName(partsKey);\r
224                                         if (localizedName != null\r
225                                                         && localizedName.trim().length() > 0) {\r
226                                                 Element nodeLocalizedName = doc.createElementNS(\r
227                                                                 NS_PARTSDEF, "local-name");\r
228                                                 Attr attrLocalizedNameLang = doc.createAttributeNS(\r
229                                                                 XMLConstants.XML_NS_URI, "lang");\r
230                                                 attrLocalizedNameLang.setValue(lang);\r
231                                                 nodeLocalizedName\r
232                                                                 .setAttributeNodeNS(attrLocalizedNameLang);\r
233                                                 nodeLocalizedName.setTextContent(localizedName);\r
234                                                 nodeParts.appendChild(nodeLocalizedName);\r
235                                         }\r
236 \r
237                                         root.appendChild(nodeParts);\r
238                                 }\r
239                         }\r
240                 }\r
241 \r
242                 // output xml\r
243                 TransformerFactory txFactory = TransformerFactory.newInstance();\r
244                 txFactory.setAttribute("indent-number", Integer.valueOf(4));\r
245                 Transformer tfmr;\r
246                 try {\r
247                         tfmr = txFactory.newTransformer();\r
248                 } catch (TransformerConfigurationException ex) {\r
249                         throw new RuntimeException("JAXP Configuration Failed.", ex);\r
250                 }\r
251                 tfmr.setOutputProperty(OutputKeys.INDENT, "yes");\r
252 \r
253                 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4504745\r
254                 final String encoding = "UTF-8";\r
255                 tfmr.setOutputProperty("encoding", encoding);\r
256                 try {\r
257                         tfmr.transform(new DOMSource(doc), new StreamResult(\r
258                                         new OutputStreamWriter(outstm, Charset.forName(encoding))));\r
259 \r
260                 } catch (TransformerException ex) {\r
261                         IOException ex2 = new IOException("XML Convert failed.");\r
262                         ex2.initCause(ex);\r
263                         throw ex2;\r
264                 }\r
265         }\r
266 }\r