• R/O
  • SSH
  • HTTPS

charactermanaj: コミット


コミットメタ情報

リビジョン89 (tree)
日時2013-12-05 01:33:26
作者seraphy

ログメッセージ

ワーキングセットをXMLで出力できるようにした。(読み込みは未対応)

変更サマリ

差分

--- trunk/src/charactermanaj/model/CharacterData.java (revision 88)
+++ trunk/src/charactermanaj/model/CharacterData.java (revision 89)
@@ -400,6 +400,60 @@
400400 }
401401
402402 /**
403+ * キャラクターデータの構造を表す文字列を返す.<br>
404+ * カテゴリ、レイヤー、色グループのみで構成される.<br>
405+ * id, revなどは含まない.<br>
406+ * @return キャラクターデータの構造を表す文字列
407+ */
408+ public String toStructureString() {
409+ // カラーグループ
410+ StringBuilder buf = new StringBuilder();
411+ buf.append("{colorGroup:[");
412+ for (ColorGroup colorGroup : getColorGroups()) {
413+ buf.append(colorGroup.getId());
414+ buf.append(",");
415+ }
416+ buf.append("],");
417+
418+ // カテゴリ
419+ buf.append("category:[");
420+ for (PartsCategory category : getPartsCategories()) {
421+ buf.append("{id:");
422+ buf.append(category.getCategoryId());
423+
424+ buf.append(",layer:[");
425+ for (Layer layer : category.getLayers()) {
426+ buf.append("{id:");
427+ buf.append(layer.getId());
428+ buf.append(",dir:");
429+ buf.append(layer.getDir());
430+ buf.append("},");
431+ }
432+ buf.append("]},");
433+ }
434+ buf.append("]}");
435+
436+ return buf.toString();
437+ }
438+
439+ /**
440+ * キャラクターデータのID, REVと構造を識別するシグネチャの文字列を返す.<br>
441+ * (構造はカテゴリ、レイヤー、色グループのみ).<br>
442+ * @return シグネチャの文字列
443+ */
444+ public String toSignatureString() {
445+ StringBuilder buf = new StringBuilder();
446+ buf.append("{id:");
447+ buf.append(getId());
448+ buf.append(",rev:");
449+ buf.append(getRev());
450+ buf.append(",structure:");
451+ buf.append(toStructureString());
452+ buf.append("}");
453+ return buf.toString();
454+ }
455+
456+ /**
403457 * デシリアライズする.
404458 * @param stream 入力もと
405459 * @throws IOException 失敗
--- trunk/src/charactermanaj/model/io/CharacterDataXMLWriter.java (revision 88)
+++ trunk/src/charactermanaj/model/io/CharacterDataXMLWriter.java (revision 89)
@@ -54,8 +54,18 @@
5454 /**
5555 * キャラクター定義XMLファイルの名前空間
5656 */
57- private static final String NS = "http://charactermanaj.sourceforge.jp/schema/charactermanaj";
57+ private static final String DEFAULT_NS = "http://charactermanaj.sourceforge.jp/schema/charactermanaj";
5858
59+ private final String NS;
60+
61+ public CharacterDataXMLWriter() {
62+ this(DEFAULT_NS);
63+ }
64+
65+ public CharacterDataXMLWriter(String ns) {
66+ this.NS = ns;
67+ }
68+
5969 /**
6070 * キャラクターデータのXMLの書き込み.
6171 *
@@ -87,8 +97,7 @@
8797 root.setAttribute("version", VERSION_SIG_1_0);
8898
8999 root.setAttribute("xmlns:xml", XMLConstants.XML_NS_URI);
90- root.setAttribute("xmlns:xsi",
91- "http://www.w3.org/2001/XMLSchema-instance");
100+ root.setAttribute("xmlns:xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
92101 root.setAttribute("xsi:schemaLocation", NS + " character.xsd");
93102 root.setAttribute("id", characterData.getId());
94103 root.setAttribute("rev", characterData.getRev());
@@ -316,6 +325,7 @@
316325 }
317326 tfmr.setOutputProperty(OutputKeys.INDENT, "yes");
318327
328+ // JDK-4504745 : javax.xml.transform.Transformer encoding does not work properly
319329 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4504745
320330 final String encoding = "UTF-8";
321331 tfmr.setOutputProperty("encoding", encoding);
@@ -370,177 +380,216 @@
370380 continue;
371381 }
372382
373- String partsSetId = partsSet.getPartsSetId();
374- String localizedName = partsSet.getLocalizedName();
375-
376- Element nodePreset = doc.createElementNS(NS, "preset");
377- nodePreset.setAttribute("id", partsSetId);
383+ Element nodePreset = createPartsSetXML(doc, lang, partsSet);
378384 baseElement.appendChild(nodePreset);
379385 registeredPartsSetMap.put(partsSet.getPartsSetId(), partsSet);
386+ }
380387
381- // display-name
382- Element nodeName = doc.createElementNS(NS, "display-name");
383- Attr attrLang = doc.createAttributeNS(XMLConstants.XML_NS_URI,
384- "lang");
385- attrLang.setValue(lang);
386- nodeName.setAttributeNode(attrLang);
387- nodeName.setTextContent(localizedName);
388- nodePreset.appendChild(nodeName);
389-
390- // bgColor
391- Color bgColor = partsSet.getBgColor();
392- if (bgColor != null) {
393- Element nodeBgColor = doc.createElementNS(NS,
394- "background-color");
395- nodeBgColor.setAttribute("color",
396- "#" + Integer.toHexString(bgColor.getRGB() & 0xffffff));
397- nodePreset.appendChild(nodeBgColor);
388+ // プリセット登録時はデフォルトのプリセットIDがあれば、それも登録する.
389+ // (ただし、該当パーツセットが書き込み済みである場合のみ)
390+ if (writePresets) {
391+ String defaultPresetId = characterData.getDefaultPartsSetId();
392+ if (defaultPresetId != null && defaultPresetId.length() > 0) {
393+ PartsSet defaultPartsSet = registeredPartsSetMap
394+ .get(defaultPresetId);
395+ if (defaultPartsSet != null && defaultPartsSet.isPresetParts()) {
396+ baseElement.setAttribute("default-preset", defaultPresetId);
397+ }
398398 }
399+ }
399400
400- // affine transform parameter
401- double[] affineTransformParameter = partsSet
402- .getAffineTransformParameter();
403- if (affineTransformParameter != null) {
404- Element nodeAffineTransform = doc.createElementNS(NS,
405- "affine-transform-parameter");
406- StringBuilder tmp = new StringBuilder();
407- for (double affineItem : affineTransformParameter) {
408- if (tmp.length() > 0) {
409- tmp.append(" ");
410- }
411- tmp.append(Double.toString(affineItem));
401+ return registeredPartsSetMap.size();
402+ }
403+
404+ /**
405+ * パーツセットのXM要素を生成して返す.
406+ * @param doc ノードを生成するためのファクトリ
407+ * @param lang 言語識別用(パーツセット名などの登録時のlang属性に必要)
408+ * @param partsSet パーツセット、nullの場合はxsi:nul="true"が返される.
409+ * @return パーツセット1つ分のXML要素
410+ */
411+ public Element createPartsSetXML(Document doc, String lang, PartsSet partsSet) {
412+ if (doc == null || lang == null) {
413+ throw new IllegalArgumentException();
414+ }
415+
416+ String partsSetId = partsSet.getPartsSetId();
417+ String localizedName = partsSet.getLocalizedName();
418+
419+ Element nodePreset = doc.createElementNS(NS, "preset");
420+ if (partsSet == null || partsSet.isEmpty()) {
421+ // 指定されていないか有効でない場合は無しとみなす.
422+ nodePreset.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");
423+ return nodePreset;
424+ }
425+
426+ nodePreset.setAttribute("id", partsSetId);
427+
428+ // display-name
429+ Element nodeName = doc.createElementNS(NS, "display-name");
430+ Attr attrLang = doc.createAttributeNS(XMLConstants.XML_NS_URI,
431+ "lang");
432+ attrLang.setValue(lang);
433+ nodeName.setAttributeNode(attrLang);
434+ nodeName.setTextContent(localizedName);
435+ nodePreset.appendChild(nodeName);
436+
437+ // bgColor
438+ Color bgColor = partsSet.getBgColor();
439+ if (bgColor != null) {
440+ Element nodeBgColor = doc.createElementNS(NS,
441+ "background-color");
442+ nodeBgColor.setAttribute("color",
443+ "#" + Integer.toHexString(bgColor.getRGB() & 0xffffff));
444+ nodePreset.appendChild(nodeBgColor);
445+ }
446+
447+ // affine transform parameter
448+ double[] affineTransformParameter = partsSet
449+ .getAffineTransformParameter();
450+ if (affineTransformParameter != null) {
451+ Element nodeAffineTransform = doc.createElementNS(NS,
452+ "affine-transform-parameter");
453+ StringBuilder tmp = new StringBuilder();
454+ for (double affineItem : affineTransformParameter) {
455+ if (tmp.length() > 0) {
456+ tmp.append(" ");
412457 }
413- nodeAffineTransform.setTextContent(tmp.toString());
414- nodePreset.appendChild(nodeAffineTransform);
458+ tmp.append(Double.toString(affineItem));
415459 }
460+ nodeAffineTransform.setTextContent(tmp.toString());
461+ nodePreset.appendChild(nodeAffineTransform);
462+ }
416463
417- // categories
418- for (Map.Entry<PartsCategory, List<PartsIdentifier>> entry : partsSet
419- .entrySet()) {
420- PartsCategory partsCategory = entry.getKey();
464+ // categories
465+ for (Map.Entry<PartsCategory, List<PartsIdentifier>> entry : partsSet
466+ .entrySet()) {
467+ PartsCategory partsCategory = entry.getKey();
421468
422- // category
423- Element nodeCategory = doc.createElementNS(NS, "category");
424- nodeCategory.setAttribute("refid",
425- partsCategory.getCategoryId());
426- nodePreset.appendChild(nodeCategory);
469+ // category
470+ Element nodeCategory = doc.createElementNS(NS, "category");
471+ nodeCategory.setAttribute("refid",
472+ partsCategory.getCategoryId());
473+ nodePreset.appendChild(nodeCategory);
427474
428- List<PartsIdentifier> partsIdentifiers = entry.getValue();
429- for (PartsIdentifier partsIdentifier : partsIdentifiers) {
430- String partsName = partsIdentifier.getPartsName();
431- Element nodeParts = doc.createElementNS(NS, "parts");
432- nodeParts.setAttribute("name", partsName);
433- nodeCategory.appendChild(nodeParts);
475+ List<PartsIdentifier> partsIdentifiers = entry.getValue();
476+ for (PartsIdentifier partsIdentifier : partsIdentifiers) {
477+ String partsName = partsIdentifier.getPartsName();
478+ Element nodeParts = doc.createElementNS(NS, "parts");
479+ nodeParts.setAttribute("name", partsName);
480+ nodeCategory.appendChild(nodeParts);
434481
435- PartsColorInfo partsColorInfo = partsSet
436- .getColorInfo(partsIdentifier);
437- if (partsColorInfo != null) {
438- Element nodeColor = doc.createElementNS(NS, "color");
439- nodeParts.appendChild(nodeColor);
482+ PartsColorInfo partsColorInfo = partsSet
483+ .getColorInfo(partsIdentifier);
484+ if (partsColorInfo != null) {
485+ Element nodeColor = createPartsColorInfoXML(doc, partsColorInfo);
486+ nodeParts.appendChild(nodeColor);
487+ }
488+ }
489+ }
490+
491+ return nodePreset;
492+ }
493+
494+ /**
495+ * パーツカラー情報のXML要素を生成して返す.<br>
496+ * @param doc 要素を作成するためのファクトリ
497+ * @param partsColorInfo パーツカラー情報
498+ * @return パーツカラー情報の要素
499+ */
500+ public Element createPartsColorInfoXML(Document doc, PartsColorInfo partsColorInfo) {
501+ if (doc == null || partsColorInfo == null) {
502+ throw new IllegalArgumentException();
503+ }
440504
441- for (Map.Entry<Layer, ColorInfo> colorInfoEntry : partsColorInfo
442- .entrySet()) {
443- Layer layer = colorInfoEntry.getKey();
444- ColorInfo colorInfo = colorInfoEntry.getValue();
505+ Element nodeColor = doc.createElementNS(NS, "color");
445506
446- Element nodeLayer = doc
447- .createElementNS(NS, "layer");
448- nodeLayer.setAttribute("refid", layer.getId());
449- nodeColor.appendChild(nodeLayer);
507+ for (Map.Entry<Layer, ColorInfo> colorInfoEntry : partsColorInfo
508+ .entrySet()) {
509+ Layer layer = colorInfoEntry.getKey();
510+ ColorInfo colorInfo = colorInfoEntry.getValue();
450511
451- // ColorGroup
452- ColorGroup colorGroup = colorInfo.getColorGroup();
453- boolean colorSync = colorInfo.isSyncColorGroup();
512+ Element nodeLayer = doc
513+ .createElementNS(NS, "layer");
514+ nodeLayer.setAttribute("refid", layer.getId());
515+ nodeColor.appendChild(nodeLayer);
454516
455- if (colorGroup.isEnabled()) {
456- Element nodeColorGroup = doc.createElementNS(
457- NS, "color-group");
458- nodeColorGroup.setAttribute("group",
459- colorGroup.getId());
460- nodeColorGroup.setAttribute("synchronized",
461- colorSync ? "true" : "false");
462- nodeLayer.appendChild(nodeColorGroup);
463- }
517+ // ColorGroup
518+ ColorGroup colorGroup = colorInfo.getColorGroup();
519+ boolean colorSync = colorInfo.isSyncColorGroup();
464520
465- // RGB
466- ColorConvertParameter param = colorInfo
467- .getColorParameter();
521+ if (colorGroup.isEnabled()) {
522+ Element nodeColorGroup = doc.createElementNS(
523+ NS, "color-group");
524+ nodeColorGroup.setAttribute("group",
525+ colorGroup.getId());
526+ nodeColorGroup.setAttribute("synchronized",
527+ colorSync ? "true" : "false");
528+ nodeLayer.appendChild(nodeColorGroup);
529+ }
468530
469- Element nodeRGB = doc.createElementNS(NS, "rgb");
470- Object[][] rgbArgss = {
471- {"red", param.getOffsetR(),
472- param.getFactorR(),
473- param.getGammaR()},
474- {"green", param.getOffsetG(),
475- param.getFactorG(),
476- param.getGammaG()},
477- {"blue", param.getOffsetB(),
478- param.getFactorB(),
479- param.getGammaB()},
480- {"alpha", param.getOffsetA(),
481- param.getFactorA(),
482- param.getGammaA()},};
483- for (Object[] rgbArgs : rgbArgss) {
484- Element nodeRGBItem = doc.createElementNS(NS,
485- rgbArgs[0].toString());
486- nodeRGBItem.setAttribute("offset",
487- rgbArgs[1].toString());
488- nodeRGBItem.setAttribute("factor",
489- rgbArgs[2].toString());
490- nodeRGBItem.setAttribute("gamma",
491- rgbArgs[3].toString());
492- nodeRGB.appendChild(nodeRGBItem);
493- }
494- nodeLayer.appendChild(nodeRGB);
531+ // RGB
532+ ColorConvertParameter param = colorInfo
533+ .getColorParameter();
495534
496- // HSB
497- Element nodeHSB = doc.createElementNS(NS, "hsb");
498- nodeHSB.setAttribute("hue",
499- Float.toString(param.getHue()));
500- nodeHSB.setAttribute("saturation",
501- Float.toString(param.getSaturation()));
502- nodeHSB.setAttribute("brightness",
503- Float.toString(param.getBrightness()));
504- if (param.getContrast() != 0.f) {
505- // ver0.96追加、optional
506- // ぴったり0.0fだったら省略する.
507- nodeHSB.setAttribute("contrast",
508- Float.toString(param.getContrast()));
509- }
510- nodeLayer.appendChild(nodeHSB);
535+ Element nodeRGB = doc.createElementNS(NS, "rgb");
536+ Object[][] rgbArgss = {
537+ {"red", param.getOffsetR(),
538+ param.getFactorR(),
539+ param.getGammaR()},
540+ {"green", param.getOffsetG(),
541+ param.getFactorG(),
542+ param.getGammaG()},
543+ {"blue", param.getOffsetB(),
544+ param.getFactorB(),
545+ param.getGammaB()},
546+ {"alpha", param.getOffsetA(),
547+ param.getFactorA(),
548+ param.getGammaA()},};
549+ for (Object[] rgbArgs : rgbArgss) {
550+ Element nodeRGBItem = doc.createElementNS(NS,
551+ rgbArgs[0].toString());
552+ nodeRGBItem.setAttribute("offset",
553+ rgbArgs[1].toString());
554+ nodeRGBItem.setAttribute("factor",
555+ rgbArgs[2].toString());
556+ nodeRGBItem.setAttribute("gamma",
557+ rgbArgs[3].toString());
558+ nodeRGB.appendChild(nodeRGBItem);
559+ }
560+ nodeLayer.appendChild(nodeRGB);
511561
512- // RGB Replace
513- Element nodeRGBReplace = doc.createElementNS(NS,
514- "rgb-replace");
515- ColorConv colorConv = param.getColorReplace();
516- if (colorConv == null) {
517- colorConv = ColorConv.NONE;
518- }
519- nodeRGBReplace.setAttribute("replace-type",
520- colorConv.name());
521- nodeRGBReplace.setAttribute("gray",
522- Float.toString(param.getGrayLevel()));
523- nodeLayer.appendChild(nodeRGBReplace);
524- }
525- }
526- }
562+ // HSB
563+ Element nodeHSB = doc.createElementNS(NS, "hsb");
564+ nodeHSB.setAttribute("hue",
565+ Float.toString(param.getHue()));
566+ nodeHSB.setAttribute("saturation",
567+ Float.toString(param.getSaturation()));
568+ nodeHSB.setAttribute("brightness",
569+ Float.toString(param.getBrightness()));
570+ if (param.getContrast() != 0.f) {
571+ // ver0.96追加、optional
572+ // ぴったり0.0fだったら省略する.
573+ nodeHSB.setAttribute("contrast",
574+ Float.toString(param.getContrast()));
527575 }
528- }
576+ nodeLayer.appendChild(nodeHSB);
529577
530- // プリセット登録時はデフォルトのプリセットIDがあれば、それも登録する.
531- // (ただし、該当パーツセットが書き込み済みである場合のみ)
532- if (writePresets) {
533- String defaultPresetId = characterData.getDefaultPartsSetId();
534- if (defaultPresetId != null && defaultPresetId.length() > 0) {
535- PartsSet defaultPartsSet = registeredPartsSetMap
536- .get(defaultPresetId);
537- if (defaultPartsSet != null && defaultPartsSet.isPresetParts()) {
538- baseElement.setAttribute("default-preset", defaultPresetId);
539- }
578+ // RGB Replace
579+ Element nodeRGBReplace = doc.createElementNS(NS,
580+ "rgb-replace");
581+ ColorConv colorConv = param.getColorReplace();
582+ if (colorConv == null) {
583+ colorConv = ColorConv.NONE;
540584 }
585+ nodeRGBReplace.setAttribute("replace-type",
586+ colorConv.name());
587+ nodeRGBReplace.setAttribute("gray",
588+ Float.toString(param.getGrayLevel()));
589+ nodeLayer.appendChild(nodeRGBReplace);
541590 }
542-
543- return registeredPartsSetMap.size();
591+
592+ return nodeColor;
544593 }
545594
546595 public void saveFavorites(CharacterData characterData,
--- trunk/src/charactermanaj/model/io/WorkingSetXMLWriter.java (nonexistent)
+++ trunk/src/charactermanaj/model/io/WorkingSetXMLWriter.java (revision 89)
@@ -0,0 +1,311 @@
1+package charactermanaj.model.io;
2+
3+import java.awt.Color;
4+import java.io.File;
5+import java.io.IOException;
6+import java.io.OutputStream;
7+import java.io.OutputStreamWriter;
8+import java.net.URI;
9+import java.nio.charset.Charset;
10+import java.util.LinkedHashMap;
11+import java.util.Locale;
12+import java.util.Map;
13+
14+import javax.xml.XMLConstants;
15+import javax.xml.parsers.DocumentBuilder;
16+import javax.xml.parsers.DocumentBuilderFactory;
17+import javax.xml.parsers.ParserConfigurationException;
18+import javax.xml.transform.OutputKeys;
19+import javax.xml.transform.Transformer;
20+import javax.xml.transform.TransformerConfigurationException;
21+import javax.xml.transform.TransformerException;
22+import javax.xml.transform.TransformerFactory;
23+import javax.xml.transform.dom.DOMSource;
24+import javax.xml.transform.stream.StreamResult;
25+
26+import org.w3c.dom.Document;
27+import org.w3c.dom.Element;
28+
29+import charactermanaj.model.CharacterData;
30+import charactermanaj.model.PartsColorInfo;
31+import charactermanaj.model.PartsIdentifier;
32+import charactermanaj.model.PartsSet;
33+import charactermanaj.model.WorkingSet;
34+import charactermanaj.ui.model.WallpaperInfo;
35+import charactermanaj.ui.model.WallpaperInfo.WallpaperResourceType;
36+
37+/**
38+ * WorkingSetのXMLへの書き込み
39+ */
40+public class WorkingSetXMLWriter {
41+
42+ /**
43+ * WorkingSetのバージョン
44+ */
45+ private static final String VERSION_SIG_1_0 = "1.0";
46+
47+ /**
48+ * WorkingSetのXMLファイルの名前空間
49+ */
50+ private static final String NS = "http://charactermanaj.sourceforge.jp/schema/charactermanaj-workingset";
51+
52+ /**
53+ * キャラクターデータのXML化
54+ */
55+ private CharacterDataXMLWriter characterDataXmlWriter =
56+ new CharacterDataXMLWriter(NS);
57+
58+ /**
59+ * ワーキングセットをXML表現で出力ストリームに出力します.<br>
60+ * @param ws ワーキングセット
61+ * @param outstm 出力先ストリーム
62+ * @throws IOException 失敗
63+ */
64+ public void writeWorkingSet(WorkingSet ws, OutputStream outstm) throws IOException {
65+ if (ws == null || outstm == null) {
66+ throw new IllegalArgumentException();
67+ }
68+
69+ Document doc = createWorkingSetXML(ws);
70+
71+ // output xml
72+ TransformerFactory txFactory = TransformerFactory.newInstance();
73+ txFactory.setAttribute("indent-number", Integer.valueOf(4));
74+ Transformer tfmr;
75+ try {
76+ tfmr = txFactory.newTransformer();
77+ } catch (TransformerConfigurationException ex) {
78+ throw new RuntimeException("JAXP Configuration Failed.", ex);
79+ }
80+ tfmr.setOutputProperty(OutputKeys.INDENT, "yes");
81+
82+ // JDK-4504745 : javax.xml.transform.Transformer encoding does not work properly
83+ // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4504745
84+ final String encoding = "UTF-8";
85+ tfmr.setOutputProperty("encoding", encoding);
86+ try {
87+ tfmr.transform(new DOMSource(doc), new StreamResult(
88+ new OutputStreamWriter(outstm, Charset.forName(encoding))));
89+
90+ } catch (TransformerException ex) {
91+ IOException ex2 = new IOException("XML Convert failed.");
92+ ex2.initCause(ex);
93+ throw ex2;
94+ }
95+ }
96+
97+ /**
98+ * ワーキングセットのXMLドキュメントを生成します.
99+ * @param ws ワーキングセット
100+ * @return XMLドキュメント
101+ */
102+ public Document createWorkingSetXML(WorkingSet ws) {
103+ if (ws == null) {
104+ throw new IllegalArgumentException();
105+ }
106+
107+ Document doc;
108+ try {
109+ DocumentBuilderFactory factory = DocumentBuilderFactory
110+ .newInstance();
111+ factory.setNamespaceAware(true);
112+ DocumentBuilder builder = factory.newDocumentBuilder();
113+ doc = builder.newDocument();
114+ } catch (ParserConfigurationException ex) {
115+ throw new RuntimeException("JAXP Configuration failed.", ex);
116+ }
117+
118+ Locale locale = Locale.getDefault();
119+ String lang = locale.getLanguage();
120+
121+ Element root = doc.createElementNS(NS, "character-workingset");
122+ root.setAttribute("version", VERSION_SIG_1_0);
123+
124+ root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:xsi",
125+ XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
126+ root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:xml",
127+ XMLConstants.XML_NS_URI);
128+ root.setAttribute("xsi:schemaLocation", NS + " character_ws.xsd");
129+
130+ // ドキュメントベース
131+ URI docbase = ws.getCharacterDocBase();
132+ root.setAttribute("characterDocBase", docbase == null ? "" : docbase.toString());
133+
134+ // キャラクターデータのシグネチャ
135+ CharacterData cd = ws.getCharacterData();
136+ Element characterDataSigElm = doc.createElementNS(NS, "characterDataSig");
137+ if (cd == null || !cd.isValid()) {
138+ // 指定されていないか有効でない場合は無しとみなす.
139+ characterDataSigElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");
140+ } else {
141+ characterDataSigElm.setTextContent(cd.toSignatureString());
142+ }
143+ root.appendChild(characterDataSigElm);
144+
145+ // パーツカラー情報
146+ root.appendChild(writePartsColorInfoMap(doc, ws.getPartsColorInfoMap()));
147+
148+ // パーツセット
149+ PartsSet partsSet = ws.getPartsSet();
150+ Element partsSetElm = doc.createElementNS(NS, "partsSet");
151+ if (partsSet == null || partsSet.isEmpty()) {
152+ partsSetElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");
153+
154+ } else {
155+ Element elm = characterDataXmlWriter.createPartsSetXML(doc, lang, partsSet);
156+ partsSetElm.appendChild(elm);
157+ }
158+ root.appendChild(partsSetElm);
159+
160+ // 最後に使用した保存先ディレクトリ
161+ Element lastUsedSaveDirElm = doc.createElementNS(NS, "lastUsedSaveDir");
162+ File lastUsedSaveDir = ws.getLastUsedSaveDir();
163+ if (lastUsedSaveDir == null) {
164+ lastUsedSaveDirElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");
165+
166+ } else {
167+ lastUsedSaveDirElm.setTextContent(lastUsedSaveDir.getPath());
168+ }
169+ root.appendChild(lastUsedSaveDirElm);
170+
171+ // 最後に使用したエクスポート先ディレクトリ
172+ Element lastUsedExportDirElm = doc.createElementNS(NS, "lastUsedExportDir");
173+ File lastUsedExportDir = ws.getLastUsedExportDir();
174+ if (lastUsedExportDir == null) {
175+ lastUsedExportDirElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");
176+
177+ } else {
178+ lastUsedExportDirElm.setTextContent(lastUsedExportDir.getPath());
179+ }
180+ root.appendChild(lastUsedExportDirElm);
181+
182+ // 最後に使用したパーツセット情報、なければnull
183+ PartsSet lastUsePresetParts = ws.getLastUsePresetParts();
184+ Element lastUsePresetPartsElm = doc.createElementNS(NS, "lastUsePresetParts");
185+ if (lastUsePresetParts == null || lastUsePresetParts.isEmpty()) {
186+ lastUsePresetPartsElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");
187+
188+ } else {
189+ Element elm = characterDataXmlWriter.createPartsSetXML(doc, lang, lastUsePresetParts);
190+ lastUsePresetPartsElm.appendChild(elm);
191+ }
192+ root.appendChild(lastUsePresetPartsElm);
193+
194+ // 壁紙情報
195+ root.appendChild(writeWallpaper(doc, ws.getWallpaperInfo()));
196+
197+ doc.appendChild(root);
198+ return doc;
199+ }
200+
201+ /**
202+ * パーツごとのカラー情報のXML要素を生成して返します.
203+ * @param doc 要素のファクトリ
204+ * @param partsColorMap パーツごとのカラー情報のマップ
205+ * @return パーツごとのカラー情報のXML要素
206+ */
207+ public Element writePartsColorInfoMap(Document doc, Map<PartsIdentifier, PartsColorInfo> partsColorMap) {
208+ Element partsColorInfoMapElm = doc.createElementNS(NS, "partsColorInfoMap");
209+ if (partsColorMap != null) {
210+ // 使用しているカラーの設定ごとに番号を振る
211+ // (同じカラー設定であれば同じ番号とする.)
212+ LinkedHashMap<PartsColorInfo, String> colorMap = new LinkedHashMap<PartsColorInfo, String>();
213+ for (Map.Entry<PartsIdentifier, PartsColorInfo> partsColorEntry : partsColorMap.entrySet()) {
214+ PartsColorInfo partsColorInfo = partsColorEntry.getValue();
215+ if (partsColorInfo != null && !partsColorInfo.isEmpty()) {
216+ if (!colorMap.containsKey(partsColorInfo)) {
217+ colorMap.put(partsColorInfo, Integer.toString(colorMap.size() + 1));
218+ }
219+ }
220+ }
221+
222+ // すべてのカラー設定を出力する.
223+ Element colorsElm = doc.createElementNS(NS, "colors");
224+ for (Map.Entry<PartsColorInfo, String> colorMapEntry : colorMap.entrySet()) {
225+ PartsColorInfo partsColorInfo = colorMapEntry.getKey();
226+ String id = colorMapEntry.getValue();
227+ Element partsColorElm = characterDataXmlWriter.createPartsColorInfoXML(doc, partsColorInfo);
228+ partsColorElm.setAttribute("id", id);
229+ colorsElm.appendChild(partsColorElm);
230+ }
231+ partsColorInfoMapElm.appendChild(colorsElm);
232+
233+ // パーツと、そのパーツのカラー設定番号の一覧を出力する.
234+ Element partsListElm = doc.createElementNS(NS, "partsList");
235+ for (Map.Entry<PartsIdentifier, PartsColorInfo> partsColorEntry : partsColorMap.entrySet()) {
236+ PartsIdentifier partsIdentifier = partsColorEntry.getKey();
237+ PartsColorInfo partsColorInfo = partsColorEntry.getValue();
238+ if (partsColorInfo != null && !partsColorInfo.isEmpty()) {
239+ String colorId = colorMap.get(partsColorInfo);
240+ if (colorId == null) {
241+ throw new RuntimeException("colorMapが不整合です");
242+ }
243+ Element partsElm = doc.createElementNS(NS, "partsIdentifier");
244+ String categoryId = partsIdentifier.getPartsCategory().getCategoryId();
245+ partsElm.setAttribute("categoryId", categoryId);
246+ partsElm.setAttribute("name", partsIdentifier.getPartsName());
247+ partsElm.setAttribute("colorId", colorId);
248+ partsListElm.appendChild(partsElm);
249+ }
250+ }
251+ partsColorInfoMapElm.appendChild(partsListElm);
252+ }
253+ return partsColorInfoMapElm;
254+ }
255+
256+ /**
257+ * 壁紙情報をXML要素として生成する.
258+ * @param doc XML要素のファクトリ
259+ * @param wallpaperInfo 壁紙情報
260+ * @return 壁紙情報のXML要素
261+ */
262+ public Element writeWallpaper(Document doc, WallpaperInfo wallpaperInfo) {
263+ Element elm = doc.createElementNS(NS, "wallpaperInfo");
264+
265+ if (wallpaperInfo == null) {
266+ elm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");
267+
268+ } else {
269+ // タイプ
270+ WallpaperResourceType typ = wallpaperInfo.getType();
271+ Element typElm = doc.createElementNS(NS, "type");
272+ typElm.setTextContent(typ.name());
273+ elm.appendChild(typElm);
274+
275+ // リソース
276+ String res = wallpaperInfo.getResource();
277+ Element resElm = doc.createElementNS(NS, "resource");
278+ if (res == null || res.trim().length() == 0) {
279+ resElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");
280+ } else {
281+ resElm.setTextContent(res);
282+ }
283+ elm.appendChild(resElm);
284+
285+ // ファイル
286+ File file = wallpaperInfo.getFile();
287+ Element fileElm = doc.createElementNS(NS, "file");
288+ if (file == null) {
289+ fileElm.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:nil", "true");
290+ } else {
291+ fileElm.setTextContent(file.getPath());
292+ }
293+ elm.appendChild(fileElm);
294+
295+ // アルファ
296+ float alpha = wallpaperInfo.getAlpha();
297+ Element alphaElm = doc.createElementNS(NS, "alpha");
298+ alphaElm.setTextContent(Float.toString(alpha));
299+ elm.appendChild(alphaElm);
300+
301+ // 背景色
302+ Color backgroundColor = wallpaperInfo.getBackgroundColor();
303+ Element bgColorElm = doc.createElementNS(NS, "backgroundColor");
304+ bgColorElm.setTextContent("#" + Integer.toHexString(backgroundColor.getRGB() & 0xffffff));
305+ elm.appendChild(bgColorElm);
306+ }
307+
308+ return elm;
309+ }
310+
311+}
--- trunk/src/charactermanaj/model/WorkingSet.java (revision 88)
+++ trunk/src/charactermanaj/model/WorkingSet.java (revision 89)
@@ -3,9 +3,9 @@
33 import java.io.File;
44 import java.io.IOException;
55 import java.io.ObjectInputStream;
6+import java.io.ObjectInputStream.GetField;
67 import java.io.ObjectStreamClass;
78 import java.io.Serializable;
8-import java.io.ObjectInputStream.GetField;
99 import java.net.URI;
1010 import java.net.URL;
1111 import java.util.Map;
@@ -92,6 +92,12 @@
9292 this.characterDataRev = characterDataRev;
9393 }
9494
95+ /**
96+ * REV情報.<br>
97+ * キャラクターデータが設定されていない場合に使用される.<br>
98+ * (ver0.96以前旧シリアライズデータ互換用)<br>
99+ * @return
100+ */
95101 public String getCharacterDataRev() {
96102 return characterDataRev;
97103 }
@@ -139,6 +145,7 @@
139145
140146 /**
141147 * 最後に使用したお気に入りの情報.<br>
148+ * 一度もプリセットを使ってなければnull.<br>
142149 * ver0.94以前には存在しなかったため、nullになりえます。
143150 * @return
144151 */
@@ -145,7 +152,14 @@
145152 public PartsSet getLastUsePresetParts() {
146153 return lastUsePresetParts;
147154 }
148-
155+
156+ /**
157+ /**
158+ * 最後に使用したお気に入りの情報.<br>
159+ * 一度もプリセットを使ってなければnull.<br>
160+ * (ver0.94以前には存在しなかったため、nullになりえます。)
161+ * @param lastUsePresetParts
162+ */
149163 public void setLastUsePresetParts(PartsSet lastUsePresetParts) {
150164 this.lastUsePresetParts = lastUsePresetParts;
151165 }
--- trunk/src/charactermanaj/ui/MainFrame.java (revision 88)
+++ trunk/src/charactermanaj/ui/MainFrame.java (revision 89)
@@ -1,7 +1,6 @@
11 package charactermanaj.ui;
22
3-import static java.lang.Math.max;
4-import static java.lang.Math.min;
3+import static java.lang.Math.*;
54
65 import java.awt.BorderLayout;
76 import java.awt.Color;
@@ -23,6 +22,7 @@
2322 import java.awt.image.BufferedImage;
2423 import java.io.File;
2524 import java.io.IOException;
25+import java.io.OutputStream;
2626 import java.lang.reflect.InvocationTargetException;
2727 import java.util.ArrayList;
2828 import java.util.Collections;
@@ -80,6 +80,7 @@
8080 import charactermanaj.model.io.PartsImageDirectoryWatchEvent;
8181 import charactermanaj.model.io.PartsImageDirectoryWatchListener;
8282 import charactermanaj.model.io.RecentDataPersistent;
83+import charactermanaj.model.io.WorkingSetXMLWriter;
8384 import charactermanaj.ui.ImageSelectPanel.ImageSelectPanelEvent;
8485 import charactermanaj.ui.ImageSelectPanel.ImageSelectPanelListener;
8586 import charactermanaj.ui.ManageFavoriteDialog.FavoriteManageCallback;
@@ -1865,6 +1866,17 @@
18651866 UserData workingSetStore = getWorkingSetUserData(false);
18661867 workingSetStore.save(workingSet);
18671868
1869+ // XML形式でのワーキングセットの保存
1870+ UserDataFactory userDataFactory = UserDataFactory.getInstance();
1871+ UserData xmlData = userDataFactory.getMangledNamedUserData(characterData.getDocBase(), "workingset.xml");
1872+ OutputStream outstm = xmlData.getOutputStream();
1873+ try {
1874+ WorkingSetXMLWriter workingSetXmlWriter = new WorkingSetXMLWriter();
1875+ workingSetXmlWriter.writeWorkingSet(workingSet, outstm);
1876+ } finally {
1877+ outstm.close();
1878+ }
1879+
18681880 } catch (Exception ex) {
18691881 ErrorMessageHelper.showErrorDialog(this, ex);
18701882 }
--- trunk/src/charactermanaj/util/UserDataFactory.java (revision 88)
+++ trunk/src/charactermanaj/util/UserDataFactory.java (revision 89)
@@ -53,14 +53,25 @@
5353 File userDataDir = ConfigurationDirUtilities.getUserDataDir();
5454
5555 if (name != null && name.length() > 0) {
56- int pos = name.lastIndexOf('.');
57- if (pos >= 0) {
58- String ext = name.substring(pos + 1);
59- if (ext.length() > 0) {
60- if ("ser".equals(ext)) {
61- userDataDir = new File(userDataDir, "caches");
62- } else {
63- userDataDir = new File(userDataDir, ext + "s");
56+ int seppos = name.lastIndexOf('-');
57+ if (name.endsWith(".xml") && seppos >= 0) {
58+ // 「foo-????.xml」形式の場合は「????」でグループ化する
59+ String groupName = name.substring(seppos + 1, name.length() - 4);
60+ if (groupName.length() > 0) {
61+ userDataDir = new File(userDataDir, groupName);
62+ }
63+
64+ } else {
65+ // 拡張子によるグループ化
66+ int pos = name.lastIndexOf('.');
67+ if (pos >= 0) {
68+ String ext = name.substring(pos + 1);
69+ if (ext.length() > 0) {
70+ if ("ser".equals(ext)) {
71+ userDataDir = new File(userDataDir, "caches");
72+ } else {
73+ userDataDir = new File(userDataDir, ext + "s");
74+ }
6475 }
6576 }
6677 }
旧リポジトリブラウザで表示