OSDN Git Service

40106f3eba483d2364acde7bc8db968a09eec270
[charactermanaj/CharacterManaJ.git] / src / main / java / charactermanaj / model / io / CharacterDataXMLReader.java
1 package charactermanaj.model.io;\r
2 \r
3 import static charactermanaj.util.XMLUtilities.*;\r
4 \r
5 import java.awt.Color;\r
6 import java.awt.Dimension;\r
7 import java.io.IOException;\r
8 import java.io.InputStream;\r
9 import java.net.URI;\r
10 import java.net.URL;\r
11 import java.util.ArrayList;\r
12 import java.util.LinkedHashMap;\r
13 import java.util.List;\r
14 import java.util.Locale;\r
15 import java.util.Map;\r
16 import java.util.logging.Level;\r
17 import java.util.logging.Logger;\r
18 \r
19 import org.w3c.dom.Document;\r
20 import org.w3c.dom.Element;\r
21 \r
22 import charactermanaj.graphics.colormodel.ColorModels;\r
23 import charactermanaj.graphics.filters.ColorConv;\r
24 import charactermanaj.graphics.filters.ColorConvertParameter;\r
25 import charactermanaj.model.CharacterData;\r
26 import charactermanaj.model.ColorGroup;\r
27 import charactermanaj.model.IndependentPartsColorInfo;\r
28 import charactermanaj.model.IndependentPartsSetInfo;\r
29 import charactermanaj.model.IndependentPartsSetInfoList;\r
30 import charactermanaj.model.Layer;\r
31 import charactermanaj.model.PartsCategory;\r
32 import charactermanaj.model.PartsSet;\r
33 import charactermanaj.model.RecommendationURL;\r
34 import charactermanaj.util.XMLUtilities;\r
35 \r
36 /**\r
37  * キャラクターデータを格納したXMLを読み込むためのクラス.\r
38  *\r
39  * @author seraphy\r
40  */\r
41 public class CharacterDataXMLReader {\r
42 \r
43         /**\r
44          * character.xmlのデフォルトの名前空間\r
45          */\r
46         private static final String NS_PREFIX = "http://charactermanaj.sourceforge.jp/schema/charactermanaj";\r
47 \r
48         /**\r
49          * favorites.xmlのデフォルトの名前空間.\r
50          * (character.xmlの名前空間と別にすべきだったかもしれないが、v0.991まで、これでやってきたので、とりあえず、このままとする。)\r
51          */\r
52         private static final String NS_PREFIX_FAVORITES = "http://charactermanaj.sourceforge.jp/schema/charactermanaj";\r
53 \r
54         /**\r
55          * ロガー\r
56          */\r
57         private static final Logger logger = Logger\r
58                         .getLogger(CharacterDataXMLReader.class.getName());\r
59 \r
60         /**\r
61          * キャラクター定義(プロファイル)をロードする.\r
62          *\r
63          * @param docBase\r
64          *            対象xml\r
65          * @return キャラクターデータ\r
66          * @throws IOException\r
67          */\r
68         public CharacterData loadCharacterDataFromXML(URI docBase)\r
69                         throws IOException {\r
70                 if (docBase == null) {\r
71                         throw new IllegalArgumentException();\r
72                 }\r
73 \r
74                 URL docBaseURL = docBase.toURL();\r
75                 CharacterData cd;\r
76                 InputStream is = docBaseURL.openStream();\r
77                 try {\r
78                         cd = loadCharacterDataFromXML(is, docBase);\r
79 \r
80                 } finally {\r
81                         is.close();\r
82                 }\r
83                 return cd;\r
84         }\r
85 \r
86         /**\r
87          * XMLコンテンツに対する入力ストリームからキャラクターデータを取り出す.<br>\r
88          * docbaseはXMLファイルの位置を示すものであり、XMLデータ中には含まれず、キャラクターデータのロード時にセットされる.<br>\r
89          * そのため引数としてdocbaseを引き渡す.<br>\r
90          * 読み取りは現在のデフォルトロケールで行われる.<br>\r
91          *\r
92          * @param is\r
93          *            入力ストリーム\r
94          * @param docBase\r
95          *            XMLファイルの位置を示すURI、nullの場合はnullが設定される。\r
96          * @param docInfo\r
97          *            ドキュメントのタイプ\r
98          * @return 読み取られたプロファイル\r
99          * @throws IOException\r
100          *             読み取りに失敗\r
101          */\r
102         public CharacterData loadCharacterDataFromXML(InputStream is, URI docBase)\r
103                         throws IOException {\r
104                 return loadCharacterDataFromXML(is, docBase, Locale.getDefault());\r
105         }\r
106 \r
107         /**\r
108          * XMLコンテンツに対する入力ストリームからキャラクターデータを取り出す.<br>\r
109          * docbaseはXMLファイルの位置を示すものであり、XMLデータ中には含まれず、キャラクターデータのロード時にセットされる.<br>\r
110          * そのため引数としてdocbaseを引き渡す.<br>\r
111          * 設定ファイル中の表示文字列にロケール指定がある場合、引数に指定したロケールに合致する言語の情報を取得する.<br>\r
112          * 合致するものがなければ最初のものを使用する.<br>\r
113          *\r
114          * @param is\r
115          *            入力ストリーム\r
116          * @param docBase\r
117          *            XMLファイルの位置を示すURI、nullの場合はnullが設定される。\r
118          * @param docInfo\r
119          *            ドキュメントのタイプ\r
120          * @param locale\r
121          *            読み取るロケール\r
122          * @return 読み取られたプロファイル\r
123          * @throws IOException\r
124          *             読み取りに失敗\r
125          */\r
126         public CharacterData loadCharacterDataFromXML(InputStream is, URI docBase,\r
127                         Locale locale) throws IOException {\r
128                 if (is == null || locale == null) {\r
129                         throw new IllegalArgumentException();\r
130                 }\r
131 \r
132                 Document doc = XMLUtilities.loadDocument(is);\r
133 \r
134                 CharacterData characterData = new CharacterData();\r
135                 characterData.setDocBase(docBase);\r
136 \r
137                 try {\r
138                         Element docElm = doc.getDocumentElement();\r
139                         if (!"character".equals(docElm.getNodeName())) {\r
140                                 throw new IOException("Invalid Format.");\r
141                         }\r
142                         String ns = docElm.getNamespaceURI();\r
143                         if (ns == null || !ns.startsWith(NS_PREFIX)) {\r
144                                 throw new IOException("unsupported xml format");\r
145                         }\r
146 \r
147                         String docVersion = docElm.getAttribute("version").trim();\r
148                         if (!"1.0".equals(docVersion)) {\r
149                                 throw new IOException("unsupported version: " + docVersion);\r
150                         }\r
151                         String characterId = docElm.getAttribute("id").trim();\r
152                         String characterRev = docElm.getAttribute("rev").trim();\r
153 \r
154                         characterData.setId(characterId);\r
155                         characterData.setRev(characterRev);\r
156 \r
157                         // language\r
158                         String lang = locale.getLanguage();\r
159 \r
160                         // name\r
161                         String characterName = getLocalizedElementText(docElm, "name", lang);\r
162                         if (characterName == null) {\r
163                                 characterName = "default";\r
164                         }\r
165                         characterData.setName(characterName.trim());\r
166 \r
167                         // information/author, information/description\r
168                         String author = null;\r
169                         String description = null;\r
170                         for (Element infoElm : getChildElements(docElm, "information")) {\r
171                                 if (author == null) {\r
172                                         author = getLocalizedElementText(infoElm, "author", lang);\r
173                                 }\r
174                                 if (description == null) {\r
175                                         description = getLocalizedElementText(infoElm,\r
176                                                         "description", lang);\r
177                                 }\r
178                         }\r
179                         if (author == null) {\r
180                                 author = "";\r
181                         }\r
182                         characterData.setAuthor(author.trim());\r
183 \r
184                         if (description == null) {\r
185                                 description = null;\r
186                         }\r
187                         characterData.setDescription(description);\r
188 \r
189                         // image-size/width, image-size/height\r
190                         int width = 0;\r
191                         int height = 0;\r
192 \r
193                         for (Element sizeElm : getChildElements(docElm, "image-size")) {\r
194                                 String tmpWidth = getLocalizedElementText(sizeElm, "width",\r
195                                                 lang);\r
196                                 if (tmpWidth != null && tmpWidth.trim().length() > 0) {\r
197                                         width = Integer.parseInt(tmpWidth.trim());\r
198                                 }\r
199                                 String tmpHeight = getLocalizedElementText(sizeElm, "height",\r
200                                                 lang);\r
201                                 if (tmpHeight != null && tmpHeight.trim().length() > 0) {\r
202                                         height = Integer.parseInt(tmpHeight.trim());\r
203                                 }\r
204                                 break;\r
205                         }\r
206                         if (width <= 0) {\r
207                                 width = 300;\r
208                         }\r
209                         if (height <= 0) {\r
210                                 height = 400;\r
211                         }\r
212                         characterData.setImageSize(new Dimension(width, height));\r
213 \r
214                         // settings\r
215                         for (Element settingElm : getChildElements(docElm, "settings")) {\r
216                                 for (Element entElm : getChildElements(settingElm, "entry")) {\r
217                                         String key = entElm.getAttribute("key").trim();\r
218                                         String val = entElm.getTextContent();\r
219                                         characterData.setProperty(key, val);\r
220                                 }\r
221                         }\r
222 \r
223                         // colorGroups/colorGroup\r
224                         ArrayList<ColorGroup> colorGroups = new ArrayList<ColorGroup>();\r
225                         for (Element colorGroupsElm : getChildElements(docElm,\r
226                                         "colorGroups")) {\r
227                                 for (Element colorGroupElm : getChildElements(colorGroupsElm,\r
228                                                 "colorGroup")) {\r
229                                         String colorGroupId = colorGroupElm.getAttribute("id")\r
230                                                         .trim();\r
231                                         String colorGroupDisplayName = getLocalizedElementText(\r
232                                                         colorGroupElm, "display-name", lang);\r
233 \r
234                                         ColorGroup colorGroup = new ColorGroup(colorGroupId,\r
235                                                         colorGroupDisplayName);\r
236                                         colorGroups.add(colorGroup);\r
237                                 }\r
238                         }\r
239                         characterData.setColorGroups(colorGroups);\r
240 \r
241                         // categories/category\r
242                         ArrayList<PartsCategory> categories = new ArrayList<PartsCategory>();\r
243                         for (Element catsElm : getChildElements(docElm, "categories")) {\r
244                                 for (Element catElm : getChildElements(catsElm, "category")) {\r
245                                         String categoryId = catElm.getAttribute("id").trim();\r
246                                         boolean multipleSelectable = Boolean.parseBoolean(catElm\r
247                                                         .getAttribute("multipleSelectable"));\r
248 \r
249                                         String categoryDisplayName = getLocalizedElementText(\r
250                                                         catElm, "display-name", lang);\r
251 \r
252                                         int visibleRows = 0;\r
253                                         String tmpVisibleRows = getLocalizedElementText(catElm,\r
254                                                         "visible-rows", lang);\r
255                                         if (tmpVisibleRows != null\r
256                                                         && tmpVisibleRows.trim().length() > 0) {\r
257                                                 visibleRows = Integer.parseInt(tmpVisibleRows.trim());\r
258                                         }\r
259                                         if (visibleRows <= 0) {\r
260                                                 visibleRows = 0;\r
261                                         }\r
262 \r
263                                         // layers/layer\r
264                                         ArrayList<Layer> layers = new ArrayList<Layer>();\r
265                                         for (Element layersElm : getChildElements(catElm, "layers")) {\r
266                                                 for (Element layerElm : getChildElements(layersElm,\r
267                                                                 "layer")) {\r
268                                                         String layerId = layerElm.getAttribute("id");\r
269                                                         String layerDisplayName = getLocalizedElementText(\r
270                                                                         layerElm, "display-name", lang);\r
271 \r
272                                                         // レイヤーの重ね順\r
273                                                         String strOrder = getElementText(layerElm, "order");\r
274                                                         int order = layers.size();\r
275                                                         if (strOrder != null\r
276                                                                         && strOrder.trim().length() > 0) {\r
277                                                                 order = Integer.parseInt(strOrder.trim());\r
278                                                         }\r
279 \r
280                                                         // レイヤーの画像ディレクトリ名\r
281                                                         String layerDir = getElementText(layerElm, "dir");\r
282                                                         if (layerDir == null\r
283                                                                         || layerDir.trim().length() == 0) {\r
284                                                                 throw new IOException("layer's dir is null");\r
285                                                         }\r
286 \r
287                                                         // カラーモデル(省略可)\r
288                                                         String colorModelName = getElementText(layerElm,\r
289                                                                         "colorModel");\r
290                                                         if (colorModelName == null\r
291                                                                         || colorModelName.length() == 0) {\r
292                                                                 // 省略時はデフォルトのカラーモデル名を使用する.\r
293                                                                 colorModelName = ColorModels.DEFAULT.name();\r
294                                                         }\r
295 \r
296                                                         // layer/colorGroup カラーグループ\r
297                                                         boolean initSync = false;\r
298                                                         ColorGroup colorGroup = null;\r
299                                                         Element lcgElm = getFirstChildElement(layerElm,\r
300                                                                         "colorGroup");\r
301                                                         if (lcgElm != null) {\r
302                                                                 String tmpInitSync = lcgElm\r
303                                                                                 .getAttribute("init-sync");\r
304                                                                 if (tmpInitSync.trim().length() > 0) {\r
305                                                                         initSync = Boolean.parseBoolean(tmpInitSync\r
306                                                                                         .trim());\r
307                                                                 }\r
308                                                                 if (colorGroup == null) {\r
309                                                                         String colorGroupRefId = lcgElm\r
310                                                                                         .getAttribute("refid").trim();\r
311                                                                         colorGroup = characterData\r
312                                                                                         .getColorGroup(colorGroupRefId);\r
313                                                                 }\r
314                                                         }\r
315 \r
316                                                         Layer layer = new Layer(layerId, layerDisplayName,\r
317                                                                         order, colorGroup, initSync, layerDir,\r
318                                                                         colorModelName);\r
319                                                         layers.add(layer);\r
320                                                 }\r
321                                         }\r
322 \r
323                                         PartsCategory category = new PartsCategory(\r
324                                                         categories.size(), categoryId, categoryDisplayName,\r
325                                                         multipleSelectable, visibleRows,\r
326                                                         layers.toArray(new Layer[layers.size()]));\r
327                                         categories.add(category);\r
328                                 }\r
329                         }\r
330                         characterData.setPartsCategories(categories\r
331                                         .toArray(new PartsCategory[categories.size()]));\r
332 \r
333                         // presets\r
334                         for (Element presetssElm : getChildElements(docElm, "presets")) {\r
335                                 loadPartsSet(characterData, presetssElm, true, lang);\r
336                         }\r
337 \r
338                         // recommendations\r
339                         List<RecommendationURL> recommendationURLList = null; // お勧めノードがない場合はnull\r
340                         for (Element recmsElm : getChildElements(docElm, "recommendations")) {\r
341                                 for (Element recmElm : getChildElements(recmsElm,\r
342                                                 "recommendation")) {\r
343                                         String recommentDescription = getLocalizedElementText(\r
344                                                         recmElm, "description", lang);\r
345                                         String url = getLocalizedElementText(recmElm, "URL", lang);\r
346 \r
347                                         if (recommentDescription != null) {\r
348                                                 recommentDescription = recommentDescription.trim();\r
349                                         }\r
350                                         if (url != null) {\r
351                                                 url = url.trim();\r
352                                         }\r
353 \r
354                                         RecommendationURL recommendationURL = new RecommendationURL();\r
355                                         recommendationURL.setDisplayName(recommentDescription);\r
356                                         recommendationURL.setUrl(url);\r
357 \r
358                                         if (recommendationURLList == null) {\r
359                                                 recommendationURLList = new ArrayList<RecommendationURL>();\r
360                                         }\r
361                                         recommendationURLList.add(recommendationURL);\r
362                                 }\r
363                         }\r
364                         characterData.setRecommendationURLList(recommendationURLList);\r
365 \r
366                 } catch (RuntimeException ex) {\r
367                         IOException ex2 = new IOException("CharacterData invalid format.");\r
368                         ex2.initCause(ex);\r
369                         throw ex2;\r
370                 }\r
371 \r
372                 return characterData;\r
373         }\r
374 \r
375         /**\r
376          * 入力ストリームからパーツセット定義(Favorites.xml)を読み込んで、 characterDataに追加登録する.<br>\r
377          *\r
378          * @param characterData\r
379          *            お気に入りを登録されるキャラクターデータ\r
380          * @param inpstm\r
381          *            お気に入りのxmlへの入力ストリーム\r
382          * @param docInfo\r
383          *            ドキュメントタイプ\r
384          * @throws IOException\r
385          *             読み込みに失敗した場合\r
386          */\r
387         public void loadPartsSet(CharacterData characterData, InputStream inpstm)\r
388                         throws IOException {\r
389                 if (characterData == null || inpstm == null) {\r
390                         throw new IllegalArgumentException();\r
391                 }\r
392 \r
393                 Document doc = XMLUtilities.loadDocument(inpstm);\r
394                 Element docElm = doc.getDocumentElement();\r
395                 if (!"partssets".equals(docElm.getNodeName())) {\r
396                         logger.log(Level.WARNING, "invalid partsets format.");\r
397                         return;\r
398                 }\r
399 \r
400                 String ns = docElm.getNamespaceURI();\r
401                 if (ns == null || !ns.startsWith(NS_PREFIX_FAVORITES)) {\r
402                         logger.log(Level.WARNING, "invalid partsets format.");\r
403                         return;\r
404                 }\r
405 \r
406                 String lang = Locale.getDefault().getLanguage();\r
407                 loadPartsSet(characterData, docElm, false, lang);\r
408         }\r
409 \r
410         /**\r
411          * CharacterDataのプリセットまたはFavoritesのパーツセットのXMLからパーツセットを読み取って登録する.<br>\r
412          *\r
413          * @param characterData\r
414          *            キャラクターデータ\r
415          * @param nodePartssets\r
416          *            パーツセットのノード、プリセットまたはパーツセットノード\r
417          * @param presetParts\r
418          *            ロードしたパーツセットにプリセットフラグをたてる場合はtrue\r
419          * @param lang\r
420          *            言語\r
421          */\r
422         protected void loadPartsSet(CharacterData characterData,\r
423                         Element nodePartssets, boolean presetParts, String lang) {\r
424                 IndependentPartsSetInfoList partsSetLst = loadPartsSetList(\r
425                                 nodePartssets, lang);\r
426                 logger.info("partsSetList: size=" + partsSetLst.size());\r
427 \r
428                 if (presetParts) {\r
429                         characterData\r
430                                         .setDefaultPartsSetId(partsSetLst.getDefaultPresetId());\r
431                 }\r
432 \r
433                 for (IndependentPartsSetInfo partsSetInfo : partsSetLst) {\r
434                         PartsSet partsSet = IndependentPartsSetInfo.convertPartsSet(\r
435                                         partsSetInfo, characterData, presetParts);\r
436                         characterData.addPartsSet(partsSet);\r
437                 }\r
438         }\r
439 \r
440         /**\r
441          * CharacterDataのプリセットまたはFavoritesのパーツセットのXMLからパーツセットを読み取って登録する.<br>\r
442          *\r
443          * @param nodePartssets\r
444          *            パーツセットのノード、プリセットまたはパーツセットノード\r
445          * @param lang\r
446          *            言語\r
447          */\r
448         public IndependentPartsSetInfoList loadPartsSetList(Element nodePartssets,\r
449                         String lang) {\r
450                 if (nodePartssets == null || lang == null || lang.length() == 0) {\r
451                         throw new IllegalArgumentException();\r
452                 }\r
453 \r
454                 IndependentPartsSetInfoList partsSetLst = new IndependentPartsSetInfoList();\r
455 \r
456                 // デフォルトのパーツセットID\r
457                 String defaultPresetId = nodePartssets.getAttribute("default-preset");\r
458                 if (defaultPresetId != null) {\r
459                         defaultPresetId = defaultPresetId.trim();\r
460                 }\r
461 \r
462                 // パーツセットリストの読み込み\r
463                 for (Element presetElm : getChildElements(nodePartssets, "preset")) {\r
464                         IndependentPartsSetInfo partsSetInfo = loadPartsSet(presetElm, lang);\r
465                         if (partsSetInfo != null) {\r
466                                 String partsSetId = partsSetInfo.getId();\r
467 \r
468                                 // デフォルトのパーツセットIDがない場合は先頭をデフォルトとみなす.\r
469                                 if (defaultPresetId == null || defaultPresetId.length() == 0) {\r
470                                         defaultPresetId = partsSetId;\r
471                                 }\r
472 \r
473                                 partsSetLst.add(partsSetInfo);\r
474                         }\r
475                 }\r
476 \r
477                 if (defaultPresetId.length() == 0) {\r
478                         // デフォルトパーツセットがないことを示すためのnull\r
479                         defaultPresetId = null;\r
480                 }\r
481                 partsSetLst.setDefaultPresetId(defaultPresetId);\r
482 \r
483                 return partsSetLst;\r
484         }\r
485 \r
486         /**\r
487          * CharacterDataのプリセットまたはFavoritesのパーツセットのXMLからパーツセットを読み取る.<br>\r
488          *\r
489          * @param nodePartssets\r
490          *            パーツセットのノード、プリセットまたはパーツセットノード\r
491          * @param lang\r
492          *            言語\r
493          * @return 素のパーツセット情報、無ければnull\r
494          */\r
495         public IndependentPartsSetInfo loadPartsSet(Element presetElm, String lang) {\r
496                 if (presetElm == null || lang == null) {\r
497                         return null;\r
498                 }\r
499 \r
500                 IndependentPartsSetInfo partsSetInfo = new IndependentPartsSetInfo();\r
501 \r
502                 // id\r
503                 String partsSetId = presetElm.getAttribute("id");\r
504                 if (partsSetId != null) {\r
505                         partsSetId = partsSetId.trim();\r
506                 }\r
507                 if (partsSetId != null && partsSetId.length() == 0) {\r
508                         partsSetId = null;\r
509                 }\r
510                 partsSetInfo.setId(partsSetId);\r
511 \r
512                 // display-name\r
513                 String displayName = getLocalizedElementText(presetElm, "display-name",\r
514                                 lang);\r
515                 partsSetInfo.setDisplayName(displayName);\r
516 \r
517                 // bgColor\r
518                 Element bgColorElm = getFirstChildElement(presetElm, "background-color");\r
519                 if (bgColorElm != null) {\r
520                         String tmpBgColor = bgColorElm.getAttribute("color");\r
521                         try {\r
522                                 Color bgColor = Color.decode(tmpBgColor);\r
523                                 partsSetInfo.setBackgroundColor(bgColor);\r
524 \r
525                         } catch (Exception ex) {\r
526                                 logger.log(Level.WARNING, "bgColor parameter is invalid. :"\r
527                                                 + tmpBgColor, ex);\r
528                                 // 無視する\r
529                         }\r
530                 }\r
531 \r
532                 // affine-transform-parameter\r
533                 String tmpAffienTrans = getElementText(presetElm,\r
534                                 "affine-transform-parameter");\r
535                 if (tmpAffienTrans != null && tmpAffienTrans.trim().length() > 0) {\r
536                         try {\r
537                                 ArrayList<Double> affineTransformParameterArr = new ArrayList<Double>();\r
538                                 for (String strParam : tmpAffienTrans.split("\\s+")) {\r
539                                         affineTransformParameterArr.add(Double.valueOf(strParam));\r
540                                 }\r
541                                 double[] affineTransformParameter = new double[affineTransformParameterArr\r
542                                                 .size()];\r
543                                 int idx = 0;\r
544                                 for (double aaffineItem : affineTransformParameterArr) {\r
545                                         affineTransformParameter[idx++] = aaffineItem;\r
546                                 }\r
547                                 partsSetInfo\r
548                                                 .setAffineTransformParameter(affineTransformParameter);\r
549 \r
550                         } catch (Exception ex) {\r
551                                 logger.log(Level.WARNING,\r
552                                                 "affine transform parameter is invalid. :"\r
553                                                                 + tmpAffienTrans, ex);\r
554                                 // 無視する.\r
555                         }\r
556                 }\r
557 \r
558                 // カテゴリIDをキーとし、パーツ名をキーとしカラー情報のリストを値とするマップを値とする.\r
559                 Map<String, Map<String, List<IndependentPartsColorInfo>>> partsMap = partsSetInfo\r
560                                 .getPartsMap();\r
561 \r
562                 // Category\r
563                 for (Element catElm : getChildElements(presetElm, "category")) {\r
564                         String categoryId = catElm.getAttribute("refid");\r
565                         if (categoryId != null) {\r
566                                 categoryId = categoryId.trim();\r
567                         }\r
568                         if (categoryId == null || categoryId.length() == 0) {\r
569                                 logger.log(Level.WARNING, "missing category refid: " + catElm);\r
570                                 continue;\r
571                         }\r
572 \r
573                         // パーツ名をキーとしカラー情報のリストを値とするマップ.\r
574                         Map<String, List<IndependentPartsColorInfo>> categoryPartsMap = partsMap\r
575                                         .get(categoryId);\r
576                         if (categoryPartsMap == null) {\r
577                                 // ※ パーツの出現順を維持する必要があるためLinkedHashMapを用いる\r
578                                 categoryPartsMap = new LinkedHashMap<String, List<IndependentPartsColorInfo>>();\r
579                                 partsMap.put(categoryId, categoryPartsMap);\r
580                         }\r
581 \r
582                         // Parts\r
583                         for (Element partsElm : getChildElements(catElm, "parts")) {\r
584                                 String partsName = partsElm.getAttribute("name");\r
585                                 if (partsName != null) {\r
586                                         partsName = partsName.trim();\r
587                                 }\r
588                                 if (partsName == null || partsName.length() == 0) {\r
589                                         logger.log(Level.WARNING, "missing parts name. " + partsElm);\r
590                                         continue;\r
591                                 }\r
592 \r
593                                 // Color/Layer\r
594                                 List<IndependentPartsColorInfo> infoList = null;\r
595                                 for (Element colorElm : getChildElements(partsElm, "color")) {\r
596                                         infoList = readPartsColor(colorElm);\r
597                                         break;\r
598                                 }\r
599                                 categoryPartsMap.put(partsName, infoList);\r
600                         }\r
601                 }\r
602                 return partsSetInfo;\r
603         }\r
604 \r
605         /**\r
606          * パーツごとのカラー情報のXMLを読み込んで返す.<br>\r
607          * パーツは複数のレイヤーから構成されるので、複数レイヤーのカラー情報のリストとして返される.<br>\r
608          * (パーツは複数レイヤーをまとめる1つのカテゴリになるので、カテゴリ単位の情報となる.)<br>\r
609          *\r
610          * @param colorElm\r
611          *            カラーのXML要素\r
612          * @return 素のカラー情報\r
613          */\r
614         public List<IndependentPartsColorInfo> readPartsColor(Element colorElm) {\r
615                 if (colorElm == null) {\r
616                         throw new IllegalArgumentException();\r
617                 }\r
618 \r
619                 ArrayList<IndependentPartsColorInfo> infoList = new ArrayList<IndependentPartsColorInfo>();\r
620                 for (Element layerElm : getChildElements(colorElm, "layer")) {\r
621                         IndependentPartsColorInfo info = new IndependentPartsColorInfo();\r
622 \r
623                         String layerId = layerElm.getAttribute("refid");\r
624                         if (layerId != null) {\r
625                                 layerId = layerId.trim();\r
626                         }\r
627                         if (layerId == null || layerId.length() == 0) {\r
628                                 logger.log(Level.WARNING, "missing layer-id: " + layerElm);\r
629                                 continue;\r
630                         }\r
631                         info.setLayerId(layerId);\r
632 \r
633                         // color-group\r
634                         Element colorGroupElm = getFirstChildElement(layerElm,\r
635                                         "color-group");\r
636                         if (colorGroupElm != null) {\r
637                                 String colorGroupId = colorGroupElm.getAttribute("group")\r
638                                                 .trim();\r
639                                 info.setColorGroupId(colorGroupId);\r
640                                 boolean syncColorGroup = Boolean.parseBoolean(colorGroupElm\r
641                                                 .getAttribute("synchronized").trim());\r
642                                 info.setSyncColorGroup(syncColorGroup);\r
643                         }\r
644 \r
645                         // rgb\r
646                         ColorConvertParameter param = info.getColorConvertParameter();\r
647                         Element nodeRgb = getFirstChildElement(layerElm, "rgb");\r
648                         if (nodeRgb != null) {\r
649                                 for (Element elmRgb : getChildElements(nodeRgb, null)) {\r
650                                         String rgbName = elmRgb.getNodeName();\r
651                                         int offset = Integer\r
652                                                         .parseInt(elmRgb.getAttribute("offset"));\r
653                                         float factor = Float.parseFloat(elmRgb\r
654                                                         .getAttribute("factor"));\r
655                                         float gamma = Float\r
656                                                         .parseFloat(elmRgb.getAttribute("gamma"));\r
657                                         if ("red".equals(rgbName)) {\r
658                                                 param.setOffsetR(offset);\r
659                                                 param.setFactorR(factor);\r
660                                                 param.setGammaR(gamma);\r
661                                         } else if ("green".equals(rgbName)) {\r
662                                                 param.setOffsetG(offset);\r
663                                                 param.setFactorG(factor);\r
664                                                 param.setGammaG(gamma);\r
665                                         } else if ("blue".equals(rgbName)) {\r
666                                                 param.setOffsetB(offset);\r
667                                                 param.setFactorB(factor);\r
668                                                 param.setGammaB(gamma);\r
669                                         } else if ("alpha".equals(rgbName)) {\r
670                                                 param.setOffsetA(offset);\r
671                                                 param.setFactorA(factor);\r
672                                                 param.setGammaA(gamma);\r
673                                         }\r
674                                 }\r
675                         }\r
676 \r
677                         // hsb\r
678                         Element elmHsb = getFirstChildElement(layerElm, "hsb");\r
679                         if (elmHsb != null) {\r
680                                 float hue = Float.parseFloat(elmHsb.getAttribute("hue"));\r
681                                 float saturation = Float.parseFloat(elmHsb\r
682                                                 .getAttribute("saturation"));\r
683                                 float brightness = Float.parseFloat(elmHsb\r
684                                                 .getAttribute("brightness"));\r
685                                 String strContrast = elmHsb.getAttribute("contrast").trim();\r
686                                 param.setHue(hue);\r
687                                 param.setSaturation(saturation);\r
688                                 param.setBrightness(brightness);\r
689                                 if (strContrast != null && strContrast.length() > 0) {\r
690                                         // ver0.96追加 optional\r
691                                         float contrast = Float.parseFloat(strContrast);\r
692                                         param.setContrast(contrast);\r
693                                 }\r
694                         }\r
695 \r
696                         // rgb-replace\r
697                         Element elmRgbReplace = getFirstChildElement(layerElm,\r
698                                         "rgb-replace");\r
699                         if (elmRgbReplace != null) {\r
700                                 Float grayLevel = Float.parseFloat(elmRgbReplace\r
701                                                 .getAttribute("gray"));\r
702                                 ColorConv colorType = ColorConv.valueOf(elmRgbReplace\r
703                                                 .getAttribute("replace-type"));\r
704                                 param.setGrayLevel(grayLevel);\r
705                                 param.setColorReplace(colorType);\r
706                         }\r
707 \r
708                         infoList.add(info);\r
709                 }\r
710                 return infoList;\r
711         }\r
712 }\r