1 package charactermanaj.model.io;
\r
3 import static charactermanaj.model.io.CharacterDataPersistent.VERSION_SIG_1_0;
\r
5 import java.awt.Color;
\r
6 import java.io.IOException;
\r
7 import java.io.OutputStream;
\r
8 import java.io.OutputStreamWriter;
\r
9 import java.nio.charset.Charset;
\r
10 import java.util.Collection;
\r
11 import java.util.HashMap;
\r
12 import java.util.List;
\r
13 import java.util.Locale;
\r
14 import java.util.Map;
\r
16 import javax.xml.XMLConstants;
\r
17 import javax.xml.parsers.DocumentBuilder;
\r
18 import javax.xml.parsers.DocumentBuilderFactory;
\r
19 import javax.xml.parsers.ParserConfigurationException;
\r
20 import javax.xml.transform.OutputKeys;
\r
21 import javax.xml.transform.Transformer;
\r
22 import javax.xml.transform.TransformerConfigurationException;
\r
23 import javax.xml.transform.TransformerException;
\r
24 import javax.xml.transform.TransformerFactory;
\r
25 import javax.xml.transform.dom.DOMSource;
\r
26 import javax.xml.transform.stream.StreamResult;
\r
28 import org.w3c.dom.Attr;
\r
29 import org.w3c.dom.Document;
\r
30 import org.w3c.dom.Element;
\r
32 import charactermanaj.graphics.filters.ColorConv;
\r
33 import charactermanaj.graphics.filters.ColorConvertParameter;
\r
34 import charactermanaj.model.CharacterData;
\r
35 import charactermanaj.model.ColorGroup;
\r
36 import charactermanaj.model.ColorInfo;
\r
37 import charactermanaj.model.Layer;
\r
38 import charactermanaj.model.PartsCategory;
\r
39 import charactermanaj.model.PartsColorInfo;
\r
40 import charactermanaj.model.PartsIdentifier;
\r
41 import charactermanaj.model.PartsSet;
\r
42 import charactermanaj.model.RecommendationURL;
\r
45 * パーツ管理情報のXMLへの書き込み用クラス.
\r
49 public class CharacterDataXMLWriter {
\r
52 * キャラクター定義XMLファイルの名前空間
\r
54 private static final String NS = "http://charactermanaj.sourceforge.jp/schema/charactermanaj";
\r
56 public void writeXMLCharacterData(CharacterData characterData,
\r
57 OutputStream outstm) throws IOException {
\r
58 if (outstm == null || characterData == null) {
\r
59 throw new IllegalArgumentException();
\r
62 Locale locale = Locale.getDefault();
\r
63 String lang = locale.getLanguage();
\r
67 DocumentBuilderFactory factory = DocumentBuilderFactory
\r
69 factory.setNamespaceAware(true);
\r
70 DocumentBuilder builder = factory.newDocumentBuilder();
\r
71 doc = builder.newDocument();
\r
72 } catch (ParserConfigurationException ex) {
\r
73 throw new RuntimeException("JAXP Configuration failed.", ex);
\r
76 Element root = doc.createElementNS(NS, "character");
\r
77 root.setAttribute("version", VERSION_SIG_1_0);
\r
79 root.setAttribute("xmlns:xml", XMLConstants.XML_NS_URI);
\r
80 root.setAttribute("xmlns:xsi",
\r
81 "http://www.w3.org/2001/XMLSchema-instance");
\r
82 root.setAttribute("xsi:schemaLocation", NS + " character.xsd");
\r
83 root.setAttribute("id", characterData.getId());
\r
84 root.setAttribute("rev", characterData.getRev());
\r
85 doc.appendChild(root);
\r
88 Element nodeName = doc.createElementNS(NS, "name");
\r
89 Attr attrLang = doc.createAttributeNS(XMLConstants.XML_NS_URI, "lang");
\r
90 attrLang.setValue(lang);
\r
91 nodeName.setAttributeNodeNS(attrLang);
\r
92 nodeName.setTextContent(characterData.getName());
\r
93 root.appendChild(nodeName);
\r
96 String author = characterData.getAuthor();
\r
97 String description = characterData.getDescription();
\r
98 if ((author != null && author.length() > 0)
\r
99 || (description != null && description.length() > 0)) {
\r
100 Element nodeInfomation = doc.createElementNS(NS, "information");
\r
101 if (author != null && author.length() > 0) {
\r
102 Element nodeAuthor = doc.createElementNS(NS, "author");
\r
103 Attr attrNodeAuthorLang = doc.createAttributeNS(
\r
104 XMLConstants.XML_NS_URI, "lang");
\r
105 attrNodeAuthorLang.setValue(lang);
\r
106 nodeAuthor.setAttributeNodeNS(attrNodeAuthorLang);
\r
107 nodeAuthor.setTextContent(author);
\r
108 nodeInfomation.appendChild(nodeAuthor);
\r
110 if (description != null && description.length() > 0) {
\r
112 // 説明の改行コードはXML上ではLFとする.
\r
113 description = description.replace("\r\n", "\n");
\r
114 description = description.replace("\r", "\n");
\r
116 Element nodeDescription = doc
\r
117 .createElementNS(NS, "description");
\r
118 Attr attrNodeDescriptionLang = doc.createAttributeNS(
\r
119 XMLConstants.XML_NS_URI, "lang");
\r
120 attrNodeDescriptionLang.setValue(lang);
\r
121 nodeDescription.setAttributeNodeNS(attrNodeDescriptionLang);
\r
122 nodeDescription.setTextContent(description);
\r
123 nodeInfomation.appendChild(nodeDescription);
\r
125 root.appendChild(nodeInfomation);
\r
129 Element nodeSize = doc.createElementNS(NS, "image-size");
\r
130 Element nodeWidth = doc.createElementNS(NS, "width");
\r
131 nodeWidth.setTextContent(Integer.toString((int) characterData
\r
132 .getImageSize().getWidth()));
\r
133 Element nodeHeight = doc.createElementNS(NS, "height");
\r
134 nodeHeight.setTextContent(Integer.toString((int) characterData
\r
135 .getImageSize().getHeight()));
\r
136 nodeSize.appendChild(nodeWidth);
\r
137 nodeSize.appendChild(nodeHeight);
\r
138 root.appendChild(nodeSize);
\r
141 Element nodeSettings = doc.createElementNS(NS, "settings");
\r
142 root.appendChild(nodeSettings);
\r
143 for (String settingsEntryName : characterData.getPropertyNames()) {
\r
144 String value = characterData.getProperty(settingsEntryName);
\r
145 if (value != null) {
\r
146 Element nodeEntry = doc.createElementNS(NS, "entry");
\r
147 nodeEntry.setAttribute("key", settingsEntryName);
\r
148 nodeEntry.setTextContent(value);
\r
149 nodeSettings.appendChild(nodeEntry);
\r
154 Element nodeCategories = doc.createElementNS(NS, "categories");
\r
155 for (PartsCategory category : characterData.getPartsCategories()) {
\r
157 Element nodeCategory = doc.createElementNS(NS, "category");
\r
158 nodeCategory.setAttribute("id", category.getCategoryId());
\r
159 nodeCategory.setAttribute("multipleSelectable",
\r
160 category.isMultipleSelectable() ? "true" : "false");
\r
163 Element nodeVisibleRows = doc.createElementNS(NS, "visible-rows");
\r
164 nodeVisibleRows.setTextContent(Integer.toString(category
\r
165 .getVisibleRows()));
\r
166 nodeCategory.appendChild(nodeVisibleRows);
\r
169 Element nodeCategoryName = doc.createElementNS(NS, "display-name");
\r
170 Attr attrCategoryNameLang = doc.createAttributeNS(
\r
171 XMLConstants.XML_NS_URI, "lang");
\r
172 attrCategoryNameLang.setValue(lang);
\r
173 nodeCategoryName.setAttributeNodeNS(attrCategoryNameLang);
\r
175 .setTextContent(category.getLocalizedCategoryName());
\r
176 nodeCategory.appendChild(nodeCategoryName);
\r
179 Element nodeLayers = doc.createElementNS(NS, "layers");
\r
180 for (Layer layer : category.getLayers()) {
\r
182 Element nodeLayer = doc.createElementNS(NS, "layer");
\r
183 nodeLayer.setAttribute("id", layer.getId());
\r
185 Element nodeLayerName = doc.createElementNS(NS, "display-name");
\r
186 Attr attrLayerNameLang = doc.createAttributeNS(
\r
187 XMLConstants.XML_NS_URI, "lang");
\r
188 attrLayerNameLang.setValue(lang);
\r
189 nodeLayerName.setAttributeNodeNS(attrLayerNameLang);
\r
190 nodeLayerName.setTextContent(layer.getLocalizedName());
\r
191 nodeLayer.appendChild(nodeLayerName);
\r
193 Element nodeOrder = doc.createElementNS(NS, "order");
\r
194 nodeOrder.setTextContent(Integer.toString(layer.getOrder()));
\r
195 nodeLayer.appendChild(nodeOrder);
\r
197 ColorGroup colorGroup = layer.getColorGroup();
\r
198 if (colorGroup != null && colorGroup.isEnabled()) {
\r
199 Element nodeColorGroup = doc.createElementNS(NS,
\r
201 nodeColorGroup.setAttribute("refid", colorGroup.getId());
\r
202 nodeColorGroup.setAttribute("init-sync", layer.isInitSync()
\r
205 nodeLayer.appendChild(nodeColorGroup);
\r
208 Element nodeDir = doc.createElementNS(NS, "dir");
\r
209 nodeDir.setTextContent(layer.getDir());
\r
210 nodeLayer.appendChild(nodeDir);
\r
212 String colorModelName = layer.getColorModelName();
\r
213 if (colorModelName != null && colorModelName.length() > 0) {
\r
214 Element nodeColorModel = doc.createElementNS(NS,
\r
216 nodeColorModel.setTextContent(layer.getColorModelName());
\r
217 nodeLayer.appendChild(nodeColorModel);
\r
220 nodeLayers.appendChild(nodeLayer);
\r
222 nodeCategory.appendChild(nodeLayers);
\r
224 nodeCategories.appendChild(nodeCategory);
\r
226 root.appendChild(nodeCategories);
\r
229 Collection<ColorGroup> colorGroups = characterData.getColorGroups();
\r
230 if (colorGroups.size() > 0) {
\r
231 Element nodeColorGroups = doc.createElementNS(NS, "colorGroups");
\r
232 int colorGroupCount = 0;
\r
233 for (ColorGroup colorGroup : colorGroups) {
\r
234 if (!colorGroup.isEnabled()) {
\r
237 Element nodeColorGroup = doc.createElementNS(NS, "colorGroup");
\r
238 nodeColorGroup.setAttribute("id", colorGroup.getId());
\r
239 Element nodeColorGroupName = doc.createElementNS(NS,
\r
241 Attr attrColorGroupNameLang = doc.createAttributeNS(
\r
242 XMLConstants.XML_NS_URI, "lang");
\r
243 attrColorGroupNameLang.setValue(lang);
\r
244 nodeColorGroupName.setAttributeNodeNS(attrColorGroupNameLang);
\r
246 .setTextContent(colorGroup.getLocalizedName());
\r
247 nodeColorGroup.appendChild(nodeColorGroupName);
\r
248 nodeColorGroups.appendChild(nodeColorGroup);
\r
251 if (colorGroupCount > 0) {
\r
252 root.appendChild(nodeColorGroups);
\r
257 List<RecommendationURL> recommendations = characterData
\r
258 .getRecommendationURLList();
\r
259 if (recommendations != null) {
\r
260 Element nodeRecommendations = doc.createElementNS(NS,
\r
261 "recommendations");
\r
262 for (RecommendationURL recommendation : recommendations) {
\r
263 Element nodeRecommendation = doc.createElementNS(NS,
\r
265 String displayName = recommendation.getDisplayName();
\r
266 String url = recommendation.getUrl();
\r
268 Element nodeDescription = doc
\r
269 .createElementNS(NS, "description");
\r
270 Attr attrRecommendationDescriptionLang = doc.createAttributeNS(
\r
271 XMLConstants.XML_NS_URI, "lang");
\r
272 attrRecommendationDescriptionLang.setValue(lang);
\r
274 .setAttributeNodeNS(attrRecommendationDescriptionLang);
\r
275 nodeDescription.setTextContent(displayName);
\r
277 Element nodeURL = doc.createElementNS(NS, "URL");
\r
278 Attr attrRecommendationURLLang = doc.createAttributeNS(
\r
279 XMLConstants.XML_NS_URI, "lang");
\r
280 attrRecommendationURLLang.setValue(lang);
\r
281 nodeURL.setAttributeNodeNS(attrRecommendationURLLang);
\r
282 nodeURL.setTextContent(url);
\r
284 nodeRecommendation.appendChild(nodeDescription);
\r
285 nodeRecommendation.appendChild(nodeURL);
\r
287 nodeRecommendations.appendChild(nodeRecommendation);
\r
289 root.appendChild(nodeRecommendations);
\r
292 // presetsのelementを構築する.
\r
293 Element nodePresets = doc.createElementNS(NS, "presets");
\r
294 if (writePartsSetElements(doc, nodePresets, characterData, true, false) > 0) {
\r
295 root.appendChild(nodePresets);
\r
299 TransformerFactory txFactory = TransformerFactory.newInstance();
\r
300 txFactory.setAttribute("indent-number", Integer.valueOf(4));
\r
303 tfmr = txFactory.newTransformer();
\r
304 } catch (TransformerConfigurationException ex) {
\r
305 throw new RuntimeException("JAXP Configuration Failed.", ex);
\r
307 tfmr.setOutputProperty(OutputKeys.INDENT, "yes");
\r
309 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4504745
\r
310 final String encoding = "UTF-8";
\r
311 tfmr.setOutputProperty("encoding", encoding);
\r
313 tfmr.transform(new DOMSource(doc), new StreamResult(
\r
314 new OutputStreamWriter(outstm, Charset.forName(encoding))));
\r
316 } catch (TransformerException ex) {
\r
317 IOException ex2 = new IOException("XML Convert failed.");
\r
324 * キャラクターデータ内のPresetおよびFavotiesのPartssetの双方共通のパーツセット要素のリストを構築する.
\r
327 * ドキュメントオブジェクト(createElementNS用)
\r
328 * @param baseElement
\r
329 * 親要素、キャラクターデータの場合はPreset、Favoritesの場合はPartssetを示す要素
\r
330 * @param characterData
\r
332 * @param writePresets
\r
333 * Preset属性のパーツセットを登録する場合はtrue、Preset属性時はデフォルトプリセット属性も(あれば)登録される
\r
334 * @param writeFavorites
\r
335 * Preset属性のないパーツセットを登録する場合はtrue
\r
336 * @return 登録したパーツセットの個数
\r
338 protected int writePartsSetElements(Document doc, Element baseElement,
\r
339 CharacterData characterData, boolean writePresets,
\r
340 boolean writeFavorites) {
\r
341 Map<String, PartsSet> partsSetMap = characterData.getPartsSets();
\r
343 Locale locale = Locale.getDefault();
\r
344 String lang = locale.getLanguage();
\r
346 HashMap<String, PartsSet> registeredPartsSetMap = new HashMap<String, PartsSet>();
\r
348 for (Map.Entry<String, PartsSet> partsSetsEntry : partsSetMap
\r
350 PartsSet partsSet = partsSetsEntry.getValue();
\r
351 if (partsSet.isPresetParts() && !writePresets) {
\r
354 if (!partsSet.isPresetParts() && !writeFavorites) {
\r
358 if (partsSet.isEmpty()) {
\r
363 String partsSetId = partsSet.getPartsSetId();
\r
364 String localizedName = partsSet.getLocalizedName();
\r
366 Element nodePreset = doc.createElementNS(NS, "preset");
\r
367 nodePreset.setAttribute("id", partsSetId);
\r
368 baseElement.appendChild(nodePreset);
\r
369 registeredPartsSetMap.put(partsSet.getPartsSetId(), partsSet);
\r
372 Element nodeName = doc.createElementNS(NS, "display-name");
\r
373 Attr attrLang = doc.createAttributeNS(XMLConstants.XML_NS_URI,
\r
375 attrLang.setValue(lang);
\r
376 nodeName.setAttributeNode(attrLang);
\r
377 nodeName.setTextContent(localizedName);
\r
378 nodePreset.appendChild(nodeName);
\r
381 Color bgColor = partsSet.getBgColor();
\r
382 if (bgColor != null) {
\r
383 Element nodeBgColor = doc.createElementNS(NS,
\r
384 "background-color");
\r
385 nodeBgColor.setAttribute("color",
\r
386 "#" + Integer.toHexString(bgColor.getRGB() & 0xffffff));
\r
387 nodePreset.appendChild(nodeBgColor);
\r
390 // affine transform parameter
\r
391 double[] affineTransformParameter = partsSet
\r
392 .getAffineTransformParameter();
\r
393 if (affineTransformParameter != null) {
\r
394 Element nodeAffineTransform = doc.createElementNS(NS,
\r
395 "affine-transform-parameter");
\r
396 StringBuilder tmp = new StringBuilder();
\r
397 for (double affineItem : affineTransformParameter) {
\r
398 if (tmp.length() > 0) {
\r
401 tmp.append(Double.toString(affineItem));
\r
403 nodeAffineTransform.setTextContent(tmp.toString());
\r
404 nodePreset.appendChild(nodeAffineTransform);
\r
408 for (Map.Entry<PartsCategory, List<PartsIdentifier>> entry : partsSet
\r
410 PartsCategory partsCategory = entry.getKey();
\r
413 Element nodeCategory = doc.createElementNS(NS, "category");
\r
414 nodeCategory.setAttribute("refid",
\r
415 partsCategory.getCategoryId());
\r
416 nodePreset.appendChild(nodeCategory);
\r
418 List<PartsIdentifier> partsIdentifiers = entry.getValue();
\r
419 for (PartsIdentifier partsIdentifier : partsIdentifiers) {
\r
420 String partsName = partsIdentifier.getPartsName();
\r
421 Element nodeParts = doc.createElementNS(NS, "parts");
\r
422 nodeParts.setAttribute("name", partsName);
\r
423 nodeCategory.appendChild(nodeParts);
\r
425 PartsColorInfo partsColorInfo = partsSet
\r
426 .getColorInfo(partsIdentifier);
\r
427 if (partsColorInfo != null) {
\r
428 Element nodeColor = doc.createElementNS(NS, "color");
\r
429 nodeParts.appendChild(nodeColor);
\r
431 for (Map.Entry<Layer, ColorInfo> colorInfoEntry : partsColorInfo
\r
433 Layer layer = colorInfoEntry.getKey();
\r
434 ColorInfo colorInfo = colorInfoEntry.getValue();
\r
436 Element nodeLayer = doc
\r
437 .createElementNS(NS, "layer");
\r
438 nodeLayer.setAttribute("refid", layer.getId());
\r
439 nodeColor.appendChild(nodeLayer);
\r
442 ColorGroup colorGroup = colorInfo.getColorGroup();
\r
443 boolean colorSync = colorInfo.isSyncColorGroup();
\r
445 if (colorGroup.isEnabled()) {
\r
446 Element nodeColorGroup = doc.createElementNS(
\r
447 NS, "color-group");
\r
448 nodeColorGroup.setAttribute("group",
\r
449 colorGroup.getId());
\r
450 nodeColorGroup.setAttribute("synchronized",
\r
451 colorSync ? "true" : "false");
\r
452 nodeLayer.appendChild(nodeColorGroup);
\r
456 ColorConvertParameter param = colorInfo
\r
457 .getColorParameter();
\r
459 Element nodeRGB = doc.createElementNS(NS, "rgb");
\r
460 Object[][] rgbArgss = {
\r
461 {"red", param.getOffsetR(),
\r
462 param.getFactorR(),
\r
463 param.getGammaR()},
\r
464 {"green", param.getOffsetG(),
\r
465 param.getFactorG(),
\r
466 param.getGammaG()},
\r
467 {"blue", param.getOffsetB(),
\r
468 param.getFactorB(),
\r
469 param.getGammaB()},
\r
470 {"alpha", param.getOffsetA(),
\r
471 param.getFactorA(),
\r
472 param.getGammaA()},};
\r
473 for (Object[] rgbArgs : rgbArgss) {
\r
474 Element nodeRGBItem = doc.createElementNS(NS,
\r
475 rgbArgs[0].toString());
\r
476 nodeRGBItem.setAttribute("offset",
\r
477 rgbArgs[1].toString());
\r
478 nodeRGBItem.setAttribute("factor",
\r
479 rgbArgs[2].toString());
\r
480 nodeRGBItem.setAttribute("gamma",
\r
481 rgbArgs[3].toString());
\r
482 nodeRGB.appendChild(nodeRGBItem);
\r
484 nodeLayer.appendChild(nodeRGB);
\r
487 Element nodeHSB = doc.createElementNS(NS, "hsb");
\r
488 nodeHSB.setAttribute("hue",
\r
489 Float.toString(param.getHue()));
\r
490 nodeHSB.setAttribute("saturation",
\r
491 Float.toString(param.getSaturation()));
\r
492 nodeHSB.setAttribute("brightness",
\r
493 Float.toString(param.getBrightness()));
\r
494 if (param.getContrast() != 0.f) {
\r
495 // ver0.96追加、optional
\r
496 // ぴったり0.0fだったら省略する.
\r
497 nodeHSB.setAttribute("contrast",
\r
498 Float.toString(param.getContrast()));
\r
500 nodeLayer.appendChild(nodeHSB);
\r
503 Element nodeRGBReplace = doc.createElementNS(NS,
\r
505 ColorConv colorConv = param.getColorReplace();
\r
506 if (colorConv == null) {
\r
507 colorConv = ColorConv.NONE;
\r
509 nodeRGBReplace.setAttribute("replace-type",
\r
511 nodeRGBReplace.setAttribute("gray",
\r
512 Float.toString(param.getGrayLevel()));
\r
513 nodeLayer.appendChild(nodeRGBReplace);
\r
520 // プリセット登録時はデフォルトのプリセットIDがあれば、それも登録する.
\r
521 // (ただし、該当パーツセットが書き込み済みである場合のみ)
\r
522 if (writePresets) {
\r
523 String defaultPresetId = characterData.getDefaultPartsSetId();
\r
524 if (defaultPresetId != null && defaultPresetId.length() > 0) {
\r
525 PartsSet defaultPartsSet = registeredPartsSetMap
\r
526 .get(defaultPresetId);
\r
527 if (defaultPartsSet != null && defaultPartsSet.isPresetParts()) {
\r
528 baseElement.setAttribute("default-preset", defaultPresetId);
\r
533 return registeredPartsSetMap.size();
\r
536 public void saveFavorites(CharacterData characterData,
\r
537 OutputStream outstm) throws IOException {
\r
538 if (characterData == null || outstm == null) {
\r
539 throw new IllegalArgumentException();
\r
544 DocumentBuilderFactory factory = DocumentBuilderFactory
\r
546 factory.setNamespaceAware(true);
\r
547 DocumentBuilder builder = factory.newDocumentBuilder();
\r
548 doc = builder.newDocument();
\r
550 } catch (ParserConfigurationException ex) {
\r
551 throw new RuntimeException("JAXP Configuration Exception.", ex);
\r
554 Element root = doc.createElementNS(NS, "partssets");
\r
556 root.setAttribute("xmlns:xml", XMLConstants.XML_NS_URI);
\r
557 root.setAttribute("xmlns:xsi",
\r
558 "http://www.w3.org/2001/XMLSchema-instance");
\r
559 root.setAttribute("xsi:schemaLocation", NS + " partsset.xsd");
\r
560 doc.appendChild(root);
\r
562 // presetsのelementを構築する.(Presetは除く)
\r
563 writePartsSetElements(doc, root, characterData, false, true);
\r
566 TransformerFactory txFactory = TransformerFactory.newInstance();
\r
567 txFactory.setAttribute("indent-number", Integer.valueOf(4));
\r
570 tfmr = txFactory.newTransformer();
\r
571 } catch (TransformerConfigurationException ex) {
\r
572 throw new RuntimeException("JAXP Configuration Failed.", ex);
\r
574 tfmr.setOutputProperty(OutputKeys.INDENT, "yes");
\r
576 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4504745
\r
577 final String encoding = "UTF-8";
\r
578 tfmr.setOutputProperty("encoding", encoding);
\r
580 tfmr.transform(new DOMSource(doc), new StreamResult(
\r
581 new OutputStreamWriter(outstm, Charset.forName(encoding))));
\r
583 } catch (TransformerException ex) {
\r
584 IOException ex2 = new IOException("XML Convert failed.");
\r