OSDN Git Service

キャラクターデータのXMLの読み書き部を分離独立させた。
authorseraphy <seraphy@5b6e9025-a2e8-4882-b233-f889982098c5>
Sun, 6 Oct 2013 17:57:20 +0000 (17:57 +0000)
committerseraphy <seraphy@5b6e9025-a2e8-4882-b233-f889982098c5>
Sun, 6 Oct 2013 17:57:20 +0000 (17:57 +0000)
git-svn-id: https://svn.sourceforge.jp/svnroot/charactermanaj/trunk@52 5b6e9025-a2e8-4882-b233-f889982098c5

src/charactermanaj/model/io/AbstractCharacterDataArchiveFile.java
src/charactermanaj/model/io/AbstractCharacterDataArchivedFileWriter.java
src/charactermanaj/model/io/CharacterDataPersistent.java
src/charactermanaj/model/io/CharacterDataXMLReader.java [new file with mode: 0644]
src/charactermanaj/model/io/CharacterDataXMLWriter.java [new file with mode: 0644]
src/charactermanaj/model/util/MakeEmbeddedResource.java
src/charactermanaj/ui/ProfileSelectorDialog.java
unitTest/charactermanaj/model/CharacterDataPersistentTest.java

index b27f847..bb81a2c 100644 (file)
@@ -353,7 +353,7 @@ public abstract class AbstractCharacterDataArchiveFile
                        return null;\r
                }\r
 \r
-               CharacterDataPersistent persist = CharacterDataPersistent.getInstance();\r
+               CharacterDataXMLReader xmlReader = new CharacterDataXMLReader();\r
 \r
                try {\r
                        // character.xmlを読み込む\r
@@ -362,7 +362,7 @@ public abstract class AbstractCharacterDataArchiveFile
                        try {\r
                                URI docBase = getContentURI(rootPrefix\r
                                                + CharacterDataPersistent.CONFIG_FILE);\r
-                               cd = persist.loadCharacterDataFromXML(is, docBase);\r
+                               cd = xmlReader.loadCharacterDataFromXML(is, docBase);\r
 \r
                        } finally {\r
                                is.close();\r
@@ -453,13 +453,13 @@ public abstract class AbstractCharacterDataArchiveFile
                        return;\r
                }\r
 \r
-               CharacterDataPersistent persist = CharacterDataPersistent.getInstance();\r
+               CharacterDataXMLReader xmlReader = new CharacterDataXMLReader();\r
 \r
                try {\r
                        // favorites.xmlを読み込む\r
                        InputStream is = favoritesXml.openStream();\r
                        try {\r
-                               persist.loadPartsSet(characterData, is);\r
+                               xmlReader.loadPartsSet(characterData, is);\r
 \r
                        } catch (Exception ex) {\r
                                logger.log(Level.INFO, "favorites.xml load failed.", ex);\r
index 83ee552..e4174a3 100644 (file)
@@ -51,11 +51,11 @@ public abstract class AbstractCharacterDataArchivedFileWriter extends AbstractCh
        @Override\r
        protected void internalWriteCharacterData(CharacterData characterData)\r
                        throws IOException {\r
-               CharacterDataPersistent persist = CharacterDataPersistent.getInstance();\r
+               CharacterDataXMLWriter xmlWriter = new CharacterDataXMLWriter();\r
                \r
                // character.xmlの出力\r
                putNextEntry(CharacterDataPersistent.CONFIG_FILE, 0);\r
-               persist.writeXMLCharacterData(characterData, getOutputStream());\r
+               xmlWriter.writeXMLCharacterData(characterData, getOutputStream());\r
                closeEntry();\r
                \r
                // character.iniの出力\r
@@ -64,8 +64,11 @@ public abstract class AbstractCharacterDataArchivedFileWriter extends AbstractCh
 \r
        /**\r
         * character.iniを出力します.<br>\r
-        * @param characterData キャラクターデータ\r
-        * @throws IOException 出力に失敗した場合\r
+        * \r
+        * @param characterData\r
+        *            キャラクターデータ\r
+        * @throws IOException\r
+        *             出力に失敗した場合\r
         */\r
        protected void internalWriteCharacterIni(CharacterData characterData) throws IOException {\r
                StringBuilder buf = new StringBuilder();\r
index 9d14d78..f09ff52 100644 (file)
@@ -1,10 +1,5 @@
 package charactermanaj.model.io;\r
 \r
-import static charactermanaj.util.XMLUtilities.getChildElements;\r
-import static charactermanaj.util.XMLUtilities.getElementText;\r
-import static charactermanaj.util.XMLUtilities.getFirstChildElement;\r
-import static charactermanaj.util.XMLUtilities.getLocalizedElementText;\r
-\r
 import java.awt.Color;\r
 import java.awt.Dimension;\r
 import java.awt.image.BufferedImage;\r
@@ -57,7 +52,6 @@ import javax.xml.transform.stream.StreamResult;
 import javax.xml.validation.Schema;\r
 import javax.xml.validation.SchemaFactory;\r
 import javax.xml.xpath.XPath;\r
-import javax.xml.xpath.XPathExpressionException;\r
 import javax.xml.xpath.XPathFactory;\r
 \r
 import org.w3c.dom.Attr;\r
@@ -71,32 +65,24 @@ import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;\r
 import org.xml.sax.helpers.DefaultHandler;\r
 \r
-import charactermanaj.graphics.colormodel.ColorModels;\r
-import charactermanaj.graphics.filters.ColorConv;\r
-import charactermanaj.graphics.filters.ColorConvertParameter;\r
 import charactermanaj.graphics.io.FileImageResource;\r
 import charactermanaj.graphics.io.ImageLoader;\r
 import charactermanaj.graphics.io.ImageSaveHelper;\r
 import charactermanaj.graphics.io.LoadedImage;\r
 import charactermanaj.model.AppConfig;\r
 import charactermanaj.model.CharacterData;\r
-import charactermanaj.model.ColorGroup;\r
-import charactermanaj.model.ColorInfo;\r
 import charactermanaj.model.Layer;\r
 import charactermanaj.model.PartsAuthorInfo;\r
 import charactermanaj.model.PartsCategory;\r
-import charactermanaj.model.PartsColorInfo;\r
 import charactermanaj.model.PartsIdentifier;\r
 import charactermanaj.model.PartsManageData;\r
 import charactermanaj.model.PartsManageData.PartsKey;\r
 import charactermanaj.model.PartsSet;\r
-import charactermanaj.model.RecommendationURL;\r
 import charactermanaj.ui.MainFrame;\r
 import charactermanaj.util.DirectoryConfig;\r
 import charactermanaj.util.FileNameNormalizer;\r
 import charactermanaj.util.FileUserData;\r
 import charactermanaj.util.UserData;\r
-import charactermanaj.util.XMLUtilities;\r
 \r
 public class CharacterDataPersistent {\r
 \r
@@ -117,6 +103,13 @@ public class CharacterDataPersistent {
                        .getLogger(CharacterDataPersistent.class.getName());\r
 \r
        /**\r
+        * キャラクターデータを格納したXMLのリーダー\r
+        */\r
+       private final CharacterDataXMLReader characterDataXmlReader = new CharacterDataXMLReader();\r
+\r
+       private final CharacterDataXMLWriter characterDataXmlWriter = new CharacterDataXMLWriter();\r
+\r
+       /**\r
         * サンプルイメージファイル名\r
         */\r
        public static final String SAMPLE_IMAGE_FILENAME = "preview.png";\r
@@ -626,7 +619,8 @@ public class CharacterDataPersistent {
                // }\r
 \r
                // XMLから読み取る\r
-               CharacterData characterData = loadCharacterDataFromXML(docBase);\r
+               CharacterData characterData = characterDataXmlReader\r
+                               .loadCharacterDataFromXML(docBase);\r
 \r
                // // XMLの読み取り結果をシリアライズする.\r
                // try {\r
@@ -641,34 +635,6 @@ public class CharacterDataPersistent {
                return characterData;\r
        }\r
 \r
-       /**\r
-        * キャラクター定義(プロファイル)をロードする.\r
-        * \r
-        * @param docBase\r
-        *            対象xml\r
-        * @return キャラクターデータ\r
-        * @throws IOException\r
-        */\r
-       public CharacterData loadCharacterDataFromXML(URI docBase)\r
-                       throws IOException {\r
-               if (docBase == null) {\r
-                       throw new IllegalArgumentException();\r
-               }\r
-\r
-               URL docBaseURL = docBase.toURL();\r
-               CharacterData cd;\r
-               InputStream is = docBaseURL.openStream();\r
-               try {\r
-                       long st = System.currentTimeMillis();\r
-                       cd = loadCharacterDataFromXML(is, docBase);\r
-                       long en = System.currentTimeMillis();\r
-                       System.out.println("所要時間: " + (en - st));\r
-\r
-               } finally {\r
-                       is.close();\r
-               }\r
-               return cd;\r
-       }\r
 \r
        /**\r
         * XMLの最初の要素と、その要素の属性にあるversionとxmlnsを取得して返す.<br>\r
@@ -780,7 +746,7 @@ public class CharacterDataPersistent {
                URL defaultCharacter = getEmbeddedResourceURL(DEFAULT_CHARACTER_XML);\r
                InputStream is = defaultCharacter.openStream();\r
                try {\r
-                       cd = loadCharacterDataFromXML(is, null);\r
+                       cd = characterDataXmlReader.loadCharacterDataFromXML(is, null);\r
 \r
                } finally {\r
                        is.close();\r
@@ -840,508 +806,7 @@ public class CharacterDataPersistent {
                return null;\r
        }\r
 \r
-       /**\r
-        * XMLコンテンツに対する入力ストリームからキャラクターデータを取り出す.<br>\r
-        * docbaseはXMLファイルの位置を示すものであり、XMLデータ中には含まれず、キャラクターデータのロード時にセットされる.<br>\r
-        * そのため引数としてdocbaseを引き渡す.<br>\r
-        * 読み取りは現在のデフォルトロケールで行われる.<br>\r
-        * \r
-        * @param is\r
-        *            入力ストリーム\r
-        * @param docBase\r
-        *            XMLファイルの位置を示すURI、nullの場合はnullが設定される。\r
-        * @param docInfo\r
-        *            ドキュメントのタイプ\r
-        * @return 読み取られたプロファイル\r
-        * @throws IOException\r
-        *             読み取りに失敗\r
-        */\r
-       public CharacterData loadCharacterDataFromXML(InputStream is, URI docBase)\r
-                       throws IOException {\r
-               return loadCharacterDataFromXML(is, docBase, Locale.getDefault());\r
-       }\r
-\r
-       /**\r
-        * XMLコンテンツに対する入力ストリームからキャラクターデータを取り出す.<br>\r
-        * docbaseはXMLファイルの位置を示すものであり、XMLデータ中には含まれず、キャラクターデータのロード時にセットされる.<br>\r
-        * そのため引数としてdocbaseを引き渡す.<br>\r
-        * 設定ファイル中の表示文字列にロケール指定がある場合、引数に指定したロケールに合致する言語の情報を取得する.<br>\r
-        * 合致するものがなければ最初のものを使用する.<br>\r
-        * \r
-        * @param is\r
-        *            入力ストリーム\r
-        * @param docBase\r
-        *            XMLファイルの位置を示すURI、nullの場合はnullが設定される。\r
-        * @param docInfo\r
-        *            ドキュメントのタイプ\r
-        * @param locale\r
-        *            読み取るロケール\r
-        * @return 読み取られたプロファイル\r
-        * @throws IOException\r
-        *             読み取りに失敗\r
-        */\r
-       public CharacterData loadCharacterDataFromXML(InputStream is, URI docBase,\r
-                       Locale locale) throws IOException {\r
-               if (is == null || locale == null) {\r
-                       throw new IllegalArgumentException();\r
-               }\r
-\r
-               Document doc = XMLUtilities.loadDocument(is);\r
-\r
-               CharacterData characterData = new CharacterData();\r
-               characterData.setDocBase(docBase);\r
-\r
-               try {\r
-                       Element docElm = doc.getDocumentElement();\r
-                       if (!"character".equals(docElm.getNodeName())) {\r
-                               throw new IOException("Invalid Format.");\r
-                       }\r
 \r
-                       String docVersion = docElm.getAttribute("version").trim();\r
-                       if (!"1.0".equals(docVersion)) {\r
-                               throw new IOException("unsupported version: " + docVersion);\r
-                       }\r
-                       String characterId = docElm.getAttribute("id").trim();\r
-                       String characterRev = docElm.getAttribute("rev").trim();\r
-\r
-                       characterData.setId(characterId);\r
-                       characterData.setRev(characterRev);\r
-\r
-                       // language\r
-                       String lang = locale.getLanguage();\r
-\r
-                       // name\r
-                       String characterName = getLocalizedElementText(docElm, "name", lang);\r
-                       if (characterName == null) {\r
-                               characterName = "default";\r
-                       }\r
-                       characterData.setName(characterName.trim());\r
-\r
-                       // information/author, information/description\r
-                       String author = null;\r
-                       String description = null;\r
-                       for (Element infoElm : getChildElements(docElm, "information")) {\r
-                               if (author == null) {\r
-                                       author = getLocalizedElementText(infoElm, "author", lang);\r
-                               }\r
-                               if (description == null) {\r
-                                       description = getLocalizedElementText(infoElm,\r
-                                                       "description", lang);\r
-                               }\r
-                       }\r
-                       if (author == null) {\r
-                               author = "";\r
-                       }\r
-                       characterData.setAuthor(author.trim());\r
-\r
-                       if (description == null) {\r
-                               description = null;\r
-                       }\r
-                       characterData.setDescription(description);\r
-\r
-                       // image-size/width, image-size/height\r
-                       int width = 0;\r
-                       int height = 0;\r
-\r
-                       for (Element sizeElm : getChildElements(docElm, "image-size")) {\r
-                               String tmpWidth = getLocalizedElementText(sizeElm, "width",\r
-                                               lang);\r
-                               if (tmpWidth != null && tmpWidth.trim().length() > 0) {\r
-                                       width = Integer.parseInt(tmpWidth.trim());\r
-                               }\r
-                               String tmpHeight = getLocalizedElementText(sizeElm, "Height",\r
-                                               lang);\r
-                               if (tmpHeight != null && tmpHeight.trim().length() > 0) {\r
-                                       height = Integer.parseInt(tmpHeight.trim());\r
-                               }\r
-                               break;\r
-                       }\r
-                       if (width <= 0) {\r
-                               width = 300;\r
-                       }\r
-                       if (height <= 0) {\r
-                               height = 400;\r
-                       }\r
-                       characterData.setImageSize(new Dimension(width, height));\r
-\r
-                       // settings\r
-                       for (Element settingElm : getChildElements(docElm, "settings")) {\r
-                               for (Element entElm : getChildElements(settingElm, "entry")) {\r
-                                       String key = entElm.getAttribute("key").trim();\r
-                                       String val = entElm.getTextContent();\r
-                                       characterData.setProperty(key, val);\r
-                               }\r
-                       }\r
-\r
-                       // colorGroups/colorGroup\r
-                       ArrayList<ColorGroup> colorGroups = new ArrayList<ColorGroup>();\r
-                       for (Element colorGroupsElm : getChildElements(docElm,\r
-                                       "colorGroups")) {\r
-                               for (Element colorGroupElm : getChildElements(colorGroupsElm,\r
-                                               "colorGroup")) {\r
-                                       String colorGroupId = colorGroupElm.getAttribute("id")\r
-                                                       .trim();\r
-                                       String colorGroupDisplayName = getLocalizedElementText(\r
-                                                       colorGroupElm, "display-name", lang);\r
-\r
-                                       ColorGroup colorGroup = new ColorGroup(colorGroupId,\r
-                                                       colorGroupDisplayName);\r
-                                       colorGroups.add(colorGroup);\r
-                               }\r
-                       }\r
-                       characterData.setColorGroups(colorGroups);\r
-\r
-                       // categories/category\r
-                       ArrayList<PartsCategory> categories = new ArrayList<PartsCategory>();\r
-                       for (Element catsElm : getChildElements(docElm, "categories")) {\r
-                               for (Element catElm : getChildElements(catsElm, "category")) {\r
-                                       String categoryId = catElm.getAttribute("id").trim();\r
-                                       boolean multipleSelectable = Boolean.parseBoolean(catElm\r
-                                                       .getAttribute("multipleSelectable"));\r
-\r
-                                       String categoryDisplayName = getLocalizedElementText(\r
-                                                       catElm, "display-name", lang);\r
-\r
-                                       int visibleRows = 0;\r
-                                       String tmpVisibleRows = getLocalizedElementText(catElm,\r
-                                                       "visible-rows", lang);\r
-                                       if (tmpVisibleRows != null\r
-                                                       && tmpVisibleRows.trim().length() > 0) {\r
-                                               visibleRows = Integer.parseInt(tmpVisibleRows.trim());\r
-                                       }\r
-                                       if (visibleRows <= 0) {\r
-                                               visibleRows = 0;\r
-                                       }\r
-\r
-                                       // layers/layer\r
-                                       ArrayList<Layer> layers = new ArrayList<Layer>();\r
-                                       for (Element layersElm : getChildElements(catElm, "layers")) {\r
-                                               for (Element layerElm : getChildElements(layersElm,\r
-                                                               "layer")) {\r
-                                                       String layerId = layerElm.getAttribute("id");\r
-                                                       String layerDisplayName = getLocalizedElementText(\r
-                                                                       layerElm, "display-name", lang);\r
-\r
-                                                       // レイヤーの重ね順\r
-                                                       String strOrder = getElementText(layerElm, "order");\r
-                                                       int order = layers.size();\r
-                                                       if (strOrder != null\r
-                                                                       && strOrder.trim().length() > 0) {\r
-                                                               order = Integer.parseInt(strOrder.trim());\r
-                                                       }\r
-\r
-                                                       // レイヤーの画像ディレクトリ名\r
-                                                       String layerDir = getElementText(layerElm, "dir");\r
-                                                       if (layerDir == null\r
-                                                                       || layerDir.trim().length() == 0) {\r
-                                                               throw new IOException("layer's dir is null");\r
-                                                       }\r
-\r
-                                                       // カラーモデル(省略可)\r
-                                                       String colorModelName = getElementText(layerElm,\r
-                                                                       "colorModel");\r
-                                                       if (colorModelName == null\r
-                                                                       || colorModelName.length() == 0) {\r
-                                                               // 省略時はデフォルトのカラーモデル名を使用する.\r
-                                                               colorModelName = ColorModels.DEFAULT.name();\r
-                                                       }\r
-\r
-                                                       // layer/colorGroup カラーグループ\r
-                                                       boolean initSync = false;\r
-                                                       ColorGroup colorGroup = null;\r
-                                                       Element lcgElm = getFirstChildElement(layerElm,\r
-                                                                       "colorGroup");\r
-                                                       if (lcgElm != null) {\r
-                                                               String tmpInitSync = lcgElm\r
-                                                                               .getAttribute("init-sync");\r
-                                                               if (tmpInitSync.trim().length() > 0) {\r
-                                                                       initSync = Boolean.parseBoolean(tmpInitSync\r
-                                                                                       .trim());\r
-                                                               }\r
-                                                               if (colorGroup == null) {\r
-                                                                       String colorGroupRefId = lcgElm\r
-                                                                                       .getAttribute("color-hair").trim();\r
-                                                                       colorGroup = characterData\r
-                                                                                       .getColorGroup(colorGroupRefId);\r
-                                                               }\r
-                                                       }\r
-\r
-                                                       Layer layer = new Layer(layerId, layerDisplayName,\r
-                                                                       order, colorGroup, initSync, layerDir,\r
-                                                                       colorModelName);\r
-                                                       layers.add(layer);\r
-                                               }\r
-                                       }\r
-\r
-                                       PartsCategory category = new PartsCategory(\r
-                                                       categories.size(), categoryId, categoryDisplayName,\r
-                                                       multipleSelectable, visibleRows,\r
-                                                       layers.toArray(new Layer[layers.size()]));\r
-                                       categories.add(category);\r
-                               }\r
-                       }\r
-                       characterData.setPartsCategories(categories\r
-                                       .toArray(new PartsCategory[categories.size()]));\r
-\r
-                       // presets\r
-                       for (Element presetssElm : getChildElements(docElm, "presets")) {\r
-                               loadPartsSet(characterData, presetssElm, true, lang);\r
-                       }\r
-\r
-                       // recommendations\r
-                       List<RecommendationURL> recommendationURLList = null; // お勧めノードがない場合はnull\r
-                       for (Element recmsElm : getChildElements(docElm, "recommendations")) {\r
-                               for (Element recmElm : getChildElements(recmsElm,\r
-                                               "recommendation")) {\r
-                                       String recommentDescription = getLocalizedElementText(\r
-                                                       recmElm, "description", lang);\r
-                                       String url = getLocalizedElementText(recmElm, "URL", lang);\r
-\r
-                                       if (recommentDescription != null) {\r
-                                               recommentDescription = recommentDescription.trim();\r
-                                       }\r
-                                       if (url != null) {\r
-                                               url = url.trim();\r
-                                       }\r
-\r
-                                       RecommendationURL recommendationURL = new RecommendationURL();\r
-                                       recommendationURL.setDisplayName(recommentDescription);\r
-                                       recommendationURL.setUrl(url);\r
-\r
-                                       if (recommendationURLList == null) {\r
-                                               recommendationURLList = new ArrayList<RecommendationURL>();\r
-                                       }\r
-                                       recommendationURLList.add(recommendationURL);\r
-                               }\r
-                       }\r
-\r
-               } catch (RuntimeException ex) {\r
-                       IOException ex2 = new IOException("CharacterData invalid format.");\r
-                       ex2.initCause(ex);\r
-                       throw ex2;\r
-               }\r
-\r
-               return characterData;\r
-       }\r
-\r
-       /**\r
-        * CharacterDataのプリセットまたはFavoritesのパーツセットのXMLからパーツセットを読み取って登録する.<br>\r
-        * \r
-        * @param characterData\r
-        *            キャラクターデータ\r
-        * @param nodePartssets\r
-        *            パーツセットのノード、プリセットまたはパーツセットノード\r
-        * @param presetParts\r
-        *            ロードしたパーツセットにプリセットフラグをたてる場合はtrue\r
-        * @param lang\r
-        *            言語\r
-        * @throws XPathExpressionException\r
-        */\r
-       protected void loadPartsSet(CharacterData characterData,\r
-                       Element nodePartssets, boolean presetParts, String lang) {\r
-\r
-               // デフォルトのパーツセットID\r
-               String defaultPresetId = nodePartssets.getAttribute("default-preset")\r
-                               .trim();\r
-\r
-               // パーツセットリストの読み込み\r
-               for (Element presetElm : getChildElements(nodePartssets, "preset")) {\r
-                       String partsSetId = presetElm.getAttribute("id").trim();\r
-                       if (defaultPresetId == null || defaultPresetId.length() == 0) {\r
-                               defaultPresetId = partsSetId;\r
-                       }\r
-                       String displayName = getLocalizedElementText(presetElm,\r
-                                       "display-name", lang);\r
-\r
-                       PartsSet partsSet = new PartsSet();\r
-\r
-                       partsSet.setPartsSetId(partsSetId);\r
-                       partsSet.setLocalizedName(displayName);\r
-                       partsSet.setPresetParts(presetParts);\r
-\r
-                       // bgColor\r
-                       Element bgColorElm = getFirstChildElement(presetElm,\r
-                                       "background-color");\r
-                       if (bgColorElm != null) {\r
-                               String tmpBgColor = bgColorElm.getAttribute("color");\r
-                               try {\r
-                                       Color bgColor = Color.decode(tmpBgColor);\r
-                                       partsSet.setBgColor(bgColor);\r
-\r
-                               } catch (Exception ex) {\r
-                                       logger.log(Level.WARNING, "bgColor parameter is invalid. :"\r
-                                                       + tmpBgColor, ex);\r
-                                       // 無視する\r
-                               }\r
-                       }\r
-\r
-                       // affine-transform-parameter\r
-                       String tmpAffienTrans = getElementText(presetElm,\r
-                                       "affine-transform-parameter");\r
-                       if (tmpAffienTrans != null && tmpAffienTrans.trim().length() > 0) {\r
-                               try {\r
-                                       ArrayList<Double> affineTransformParameterArr = new ArrayList<Double>();\r
-                                       for (String strParam : tmpAffienTrans.split("\\s+")) {\r
-                                               affineTransformParameterArr.add(Double\r
-                                                               .valueOf(strParam));\r
-                                       }\r
-                                       double[] affineTransformParameter = new double[affineTransformParameterArr\r
-                                                       .size()];\r
-                                       int idx = 0;\r
-                                       for (double aaffineItem : affineTransformParameterArr) {\r
-                                               affineTransformParameter[idx++] = aaffineItem;\r
-                                       }\r
-                                       partsSet.setAffineTransformParameter(affineTransformParameter);\r
-\r
-                               } catch (Exception ex) {\r
-                                       logger.log(Level.WARNING,\r
-                                                       "affine transform parameter is invalid. :"\r
-                                                                       + tmpAffienTrans, ex);\r
-                                       // 無視する.\r
-                               }\r
-                       }\r
-\r
-                       // Category\r
-                       for (Element catElm : getChildElements(presetElm, "category")) {\r
-                               String categoryId = catElm.getAttribute("refid").trim();\r
-                               PartsCategory category = characterData\r
-                                               .getPartsCategory(categoryId);\r
-                               if (category == null) {\r
-                                       System.err.println("undefined category: " + categoryId);\r
-                                       continue;\r
-                               }\r
-\r
-                               // Parts\r
-                               for (Element partsElm : getChildElements(catElm, "parts")) {\r
-                                       String partsName = partsElm.getAttribute("name").trim();\r
-\r
-                                       PartsIdentifier partsIdentifier = new PartsIdentifier(\r
-                                                       category, partsName, partsName);\r
-\r
-                                       // Color/Layer\r
-                                       PartsColorInfo partsColorInfo = null;\r
-                                       for (Element colorElm : getChildElements(partsElm, "color")) {\r
-                                               for (Element layerElm : getChildElements(colorElm,\r
-                                                               "layer")) {\r
-                                                       String layerId = layerElm.getAttribute("refid")\r
-                                                                       .trim();\r
-                                                       Layer layer = category.getLayer(layerId);\r
-                                                       if (layer == null) {\r
-                                                               logger.log(Level.WARNING, "undefined layer: "\r
-                                                                               + layerId);\r
-                                                               continue;\r
-                                                       }\r
-\r
-                                                       if (partsColorInfo == null) {\r
-                                                               partsColorInfo = new PartsColorInfo(category);\r
-                                                       }\r
-                                                       ColorInfo colorInfo = partsColorInfo.get(layer);\r
-\r
-                                                       // color-group\r
-                                                       Element colorGroupElm = getFirstChildElement(\r
-                                                                       layerElm, "color-group");\r
-                                                       if (colorGroupElm != null) {\r
-                                                               ColorGroup colorGroup = characterData\r
-                                                                               .getColorGroup(colorGroupElm\r
-                                                                                               .getAttribute("group").trim());\r
-                                                               boolean syncColorGroup = Boolean\r
-                                                                               .parseBoolean(colorGroupElm\r
-                                                                                               .getAttribute("synchronized")\r
-                                                                                               .trim());\r
-                                                               colorInfo.setColorGroup(colorGroup);\r
-                                                               colorInfo.setSyncColorGroup(syncColorGroup);\r
-                                                       }\r
-\r
-                                                       // rgb\r
-                                                       ColorConvertParameter param = colorInfo\r
-                                                                       .getColorParameter();\r
-                                                       Element nodeRgb = getFirstChildElement(layerElm,\r
-                                                                       "rgb");\r
-                                                       if (nodeRgb != null) {\r
-                                                               for (Element elmRgb : getChildElements(nodeRgb,\r
-                                                                               null)) {\r
-                                                                       String rgbName = elmRgb.getNodeName();\r
-                                                                       int offset = Integer.parseInt(elmRgb\r
-                                                                                       .getAttribute("offset"));\r
-                                                                       float factor = Float.parseFloat(elmRgb\r
-                                                                                       .getAttribute("factor"));\r
-                                                                       float gamma = Float.parseFloat(elmRgb\r
-                                                                                       .getAttribute("gamma"));\r
-                                                                       if ("red".equals(rgbName)) {\r
-                                                                               param.setOffsetR(offset);\r
-                                                                               param.setFactorR(factor);\r
-                                                                               param.setGammaR(gamma);\r
-                                                                       } else if ("green".equals(rgbName)) {\r
-                                                                               param.setOffsetG(offset);\r
-                                                                               param.setFactorG(factor);\r
-                                                                               param.setGammaG(gamma);\r
-                                                                       } else if ("blue".equals(rgbName)) {\r
-                                                                               param.setOffsetB(offset);\r
-                                                                               param.setFactorB(factor);\r
-                                                                               param.setGammaB(gamma);\r
-                                                                       } else if ("alpha".equals(rgbName)) {\r
-                                                                               param.setOffsetA(offset);\r
-                                                                               param.setFactorA(factor);\r
-                                                                               param.setGammaA(gamma);\r
-                                                                       }\r
-                                                               }\r
-                                                       }\r
-\r
-                                                       // hsb\r
-                                                       Element elmHsb = getFirstChildElement(layerElm,\r
-                                                                       "hsb");\r
-                                                       if (elmHsb != null) {\r
-                                                               float hue = Float.parseFloat(elmHsb\r
-                                                                               .getAttribute("hue"));\r
-                                                               float saturation = Float.parseFloat(elmHsb\r
-                                                                               .getAttribute("saturation"));\r
-                                                               float brightness = Float.parseFloat(elmHsb\r
-                                                                               .getAttribute("brightness"));\r
-                                                               String strContrast = elmHsb.getAttribute(\r
-                                                                               "contrast").trim();\r
-                                                               param.setHue(hue);\r
-                                                               param.setSaturation(saturation);\r
-                                                               param.setBrightness(brightness);\r
-                                                               if (strContrast != null\r
-                                                                               && strContrast.length() > 0) {\r
-                                                                       // ver0.96追加 optional\r
-                                                                       float contrast = Float\r
-                                                                                       .parseFloat(strContrast);\r
-                                                                       param.setContrast(contrast);\r
-                                                               }\r
-                                                       }\r
-\r
-                                                       // rgb-replace\r
-                                                       Element elmRgbReplace = getFirstChildElement(\r
-                                                                       layerElm, "rgb-replace");\r
-                                                       if (elmRgbReplace != null) {\r
-                                                               Float grayLevel = Float\r
-                                                                               .parseFloat(elmRgbReplace\r
-                                                                                               .getAttribute("gray"));\r
-                                                               ColorConv colorType = ColorConv\r
-                                                                               .valueOf(elmRgbReplace\r
-                                                                                               .getAttribute("replace-type"));\r
-                                                               param.setGrayLevel(grayLevel);\r
-                                                               param.setColorReplace(colorType);\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       partsSet.appendParts(category, partsIdentifier,\r
-                                                       partsColorInfo);\r
-                               }\r
-                       }\r
-\r
-                       characterData.addPartsSet(partsSet);\r
-               }\r
-\r
-               if (presetParts) {\r
-                       if (defaultPresetId.length() == 0) {\r
-                               // デフォルトパーツセットがないことを示すためのnull\r
-                               defaultPresetId = null;\r
-                       }\r
-                       characterData.setDefaultPartsSetId(defaultPresetId);\r
-               }\r
-       }\r
 \r
        protected void saveCharacterDataToXML(CharacterData characterData)\r
                        throws IOException {\r
@@ -1362,7 +827,7 @@ public class CharacterDataPersistent {
                // XML形式で保存(メモリへ)\r
                ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
                try {\r
-                       writeXMLCharacterData(characterData, bos);\r
+                       characterDataXmlWriter.writeXMLCharacterData(characterData, bos);\r
                } finally {\r
                        bos.close();\r
                }\r
@@ -1401,272 +866,7 @@ public class CharacterDataPersistent {
        // }\r
        // }\r
 \r
-       public void writeXMLCharacterData(CharacterData characterData,\r
-                       OutputStream outstm) throws IOException {\r
-               if (outstm == null || characterData == null) {\r
-                       throw new IllegalArgumentException();\r
-               }\r
-\r
-               Locale locale = Locale.getDefault();\r
-               String lang = locale.getLanguage();\r
-\r
-               Document doc;\r
-               try {\r
-                       DocumentBuilderFactory factory = DocumentBuilderFactory\r
-                                       .newInstance();\r
-                       factory.setNamespaceAware(true);\r
-                       DocumentBuilder builder = factory.newDocumentBuilder();\r
-                       doc = builder.newDocument();\r
-               } catch (ParserConfigurationException ex) {\r
-                       throw new RuntimeException("JAXP Configuration failed.", ex);\r
-               }\r
-\r
-               Element root = doc.createElementNS(NS, "character");\r
-               root.setAttribute("version", VERSION_SIG_1_0);\r
-\r
-               root.setAttribute("xmlns:xml", XMLConstants.XML_NS_URI);\r
-               root.setAttribute("xmlns:xsi",\r
-                               "http://www.w3.org/2001/XMLSchema-instance");\r
-               root.setAttribute("xsi:schemaLocation", NS + " character.xsd");\r
-               root.setAttribute("id", characterData.getId());\r
-               root.setAttribute("rev", characterData.getRev());\r
-               doc.appendChild(root);\r
-\r
-               // name\r
-               Element nodeName = doc.createElementNS(NS, "name");\r
-               Attr attrLang = doc.createAttributeNS(XMLConstants.XML_NS_URI, "lang");\r
-               attrLang.setValue(lang);\r
-               nodeName.setAttributeNodeNS(attrLang);\r
-               nodeName.setTextContent(characterData.getName());\r
-               root.appendChild(nodeName);\r
-\r
-               // information\r
-               String author = characterData.getAuthor();\r
-               String description = characterData.getDescription();\r
-               if ((author != null && author.length() > 0)\r
-                               || (description != null && description.length() > 0)) {\r
-                       Element nodeInfomation = doc.createElementNS(NS, "information");\r
-                       if (author != null && author.length() > 0) {\r
-                               Element nodeAuthor = doc.createElementNS(NS, "author");\r
-                               Attr attrNodeAuthorLang = doc.createAttributeNS(\r
-                                               XMLConstants.XML_NS_URI, "lang");\r
-                               attrNodeAuthorLang.setValue(lang);\r
-                               nodeAuthor.setAttributeNodeNS(attrNodeAuthorLang);\r
-                               nodeAuthor.setTextContent(author);\r
-                               nodeInfomation.appendChild(nodeAuthor);\r
-                       }\r
-                       if (description != null && description.length() > 0) {\r
-\r
-                               // 説明の改行コードはXML上ではLFとする.\r
-                               description = description.replace("\r\n", "\n");\r
-                               description = description.replace("\r", "\n");\r
-\r
-                               Element nodeDescription = doc\r
-                                               .createElementNS(NS, "description");\r
-                               Attr attrNodeDescriptionLang = doc.createAttributeNS(\r
-                                               XMLConstants.XML_NS_URI, "lang");\r
-                               attrNodeDescriptionLang.setValue(lang);\r
-                               nodeDescription.setAttributeNodeNS(attrNodeDescriptionLang);\r
-                               nodeDescription.setTextContent(description);\r
-                               nodeInfomation.appendChild(nodeDescription);\r
-                       }\r
-                       root.appendChild(nodeInfomation);\r
-               }\r
-\r
-               // size\r
-               Element nodeSize = doc.createElementNS(NS, "image-size");\r
-               Element nodeWidth = doc.createElementNS(NS, "width");\r
-               nodeWidth.setTextContent(Integer.toString((int) characterData\r
-                               .getImageSize().getWidth()));\r
-               Element nodeHeight = doc.createElementNS(NS, "height");\r
-               nodeHeight.setTextContent(Integer.toString((int) characterData\r
-                               .getImageSize().getHeight()));\r
-               nodeSize.appendChild(nodeWidth);\r
-               nodeSize.appendChild(nodeHeight);\r
-               root.appendChild(nodeSize);\r
-\r
-               // settings\r
-               Element nodeSettings = doc.createElementNS(NS, "settings");\r
-               root.appendChild(nodeSettings);\r
-               for (String settingsEntryName : characterData.getPropertyNames()) {\r
-                       String value = characterData.getProperty(settingsEntryName);\r
-                       if (value != null) {\r
-                               Element nodeEntry = doc.createElementNS(NS, "entry");\r
-                               nodeEntry.setAttribute("key", settingsEntryName);\r
-                               nodeEntry.setTextContent(value);\r
-                               nodeSettings.appendChild(nodeEntry);\r
-                       }\r
-               }\r
-\r
-               // categories\r
-               Element nodeCategories = doc.createElementNS(NS, "categories");\r
-               for (PartsCategory category : characterData.getPartsCategories()) {\r
-                       // category\r
-                       Element nodeCategory = doc.createElementNS(NS, "category");\r
-                       nodeCategory.setAttribute("id", category.getCategoryId());\r
-                       nodeCategory.setAttribute("multipleSelectable",\r
-                                       category.isMultipleSelectable() ? "true" : "false");\r
-\r
-                       // visible-rows\r
-                       Element nodeVisibleRows = doc.createElementNS(NS, "visible-rows");\r
-                       nodeVisibleRows.setTextContent(Integer.toString(category\r
-                                       .getVisibleRows()));\r
-                       nodeCategory.appendChild(nodeVisibleRows);\r
-\r
-                       // category name\r
-                       Element nodeCategoryName = doc.createElementNS(NS, "display-name");\r
-                       Attr attrCategoryNameLang = doc.createAttributeNS(\r
-                                       XMLConstants.XML_NS_URI, "lang");\r
-                       attrCategoryNameLang.setValue(lang);\r
-                       nodeCategoryName.setAttributeNodeNS(attrCategoryNameLang);\r
-                       nodeCategoryName\r
-                                       .setTextContent(category.getLocalizedCategoryName());\r
-                       nodeCategory.appendChild(nodeCategoryName);\r
-\r
-                       // layers\r
-                       Element nodeLayers = doc.createElementNS(NS, "layers");\r
-                       for (Layer layer : category.getLayers()) {\r
-                               // layer\r
-                               Element nodeLayer = doc.createElementNS(NS, "layer");\r
-                               nodeLayer.setAttribute("id", layer.getId());\r
-\r
-                               Element nodeLayerName = doc.createElementNS(NS, "display-name");\r
-                               Attr attrLayerNameLang = doc.createAttributeNS(\r
-                                               XMLConstants.XML_NS_URI, "lang");\r
-                               attrLayerNameLang.setValue(lang);\r
-                               nodeLayerName.setAttributeNodeNS(attrLayerNameLang);\r
-                               nodeLayerName.setTextContent(layer.getLocalizedName());\r
-                               nodeLayer.appendChild(nodeLayerName);\r
-\r
-                               Element nodeOrder = doc.createElementNS(NS, "order");\r
-                               nodeOrder.setTextContent(Integer.toString(layer.getOrder()));\r
-                               nodeLayer.appendChild(nodeOrder);\r
-\r
-                               ColorGroup colorGroup = layer.getColorGroup();\r
-                               if (colorGroup != null && colorGroup.isEnabled()) {\r
-                                       Element nodeColorGroup = doc.createElementNS(NS,\r
-                                                       "colorGroup");\r
-                                       nodeColorGroup.setAttribute("refid", colorGroup.getId());\r
-                                       nodeColorGroup.setAttribute("init-sync", layer.isInitSync()\r
-                                                       ? "true"\r
-                                                       : "false");\r
-                                       nodeLayer.appendChild(nodeColorGroup);\r
-                               }\r
-\r
-                               Element nodeDir = doc.createElementNS(NS, "dir");\r
-                               nodeDir.setTextContent(layer.getDir());\r
-                               nodeLayer.appendChild(nodeDir);\r
-\r
-                               String colorModelName = layer.getColorModelName();\r
-                               if (colorModelName != null && colorModelName.length() > 0) {\r
-                                       Element nodeColorModel = doc.createElementNS(NS,\r
-                                                       "colorModel");\r
-                                       nodeColorModel.setTextContent(layer.getColorModelName());\r
-                                       nodeLayer.appendChild(nodeColorModel);\r
-                               }\r
-\r
-                               nodeLayers.appendChild(nodeLayer);\r
-                       }\r
-                       nodeCategory.appendChild(nodeLayers);\r
-\r
-                       nodeCategories.appendChild(nodeCategory);\r
-               }\r
-               root.appendChild(nodeCategories);\r
-\r
-               // ColorGroupを構築する\r
-               Collection<ColorGroup> colorGroups = characterData.getColorGroups();\r
-               if (colorGroups.size() > 0) {\r
-                       Element nodeColorGroups = doc.createElementNS(NS, "colorGroups");\r
-                       int colorGroupCount = 0;\r
-                       for (ColorGroup colorGroup : colorGroups) {\r
-                               if (!colorGroup.isEnabled()) {\r
-                                       continue;\r
-                               }\r
-                               Element nodeColorGroup = doc.createElementNS(NS, "colorGroup");\r
-                               nodeColorGroup.setAttribute("id", colorGroup.getId());\r
-                               Element nodeColorGroupName = doc.createElementNS(NS,\r
-                                               "display-name");\r
-                               Attr attrColorGroupNameLang = doc.createAttributeNS(\r
-                                               XMLConstants.XML_NS_URI, "lang");\r
-                               attrColorGroupNameLang.setValue(lang);\r
-                               nodeColorGroupName.setAttributeNodeNS(attrColorGroupNameLang);\r
-                               nodeColorGroupName\r
-                                               .setTextContent(colorGroup.getLocalizedName());\r
-                               nodeColorGroup.appendChild(nodeColorGroupName);\r
-                               nodeColorGroups.appendChild(nodeColorGroup);\r
-                               colorGroupCount++;\r
-                       }\r
-                       if (colorGroupCount > 0) {\r
-                               root.appendChild(nodeColorGroups);\r
-                       }\r
-               }\r
-\r
-               // Recommendations\r
-               List<RecommendationURL> recommendations = characterData\r
-                               .getRecommendationURLList();\r
-               if (recommendations != null) {\r
-                       Element nodeRecommendations = doc.createElementNS(NS,\r
-                                       "recommendations");\r
-                       for (RecommendationURL recommendation : recommendations) {\r
-                               Element nodeRecommendation = doc.createElementNS(NS,\r
-                                               "recommendation");\r
-                               String displayName = recommendation.getDisplayName();\r
-                               String url = recommendation.getUrl();\r
-\r
-                               Element nodeDescription = doc\r
-                                               .createElementNS(NS, "description");\r
-                               Attr attrRecommendationDescriptionLang = doc.createAttributeNS(\r
-                                               XMLConstants.XML_NS_URI, "lang");\r
-                               attrRecommendationDescriptionLang.setValue(lang);\r
-                               nodeDescription\r
-                                               .setAttributeNodeNS(attrRecommendationDescriptionLang);\r
-                               nodeDescription.setTextContent(displayName);\r
-\r
-                               Element nodeURL = doc.createElementNS(NS, "URL");\r
-                               Attr attrRecommendationURLLang = doc.createAttributeNS(\r
-                                               XMLConstants.XML_NS_URI, "lang");\r
-                               attrRecommendationURLLang.setValue(lang);\r
-                               nodeURL.setAttributeNodeNS(attrRecommendationURLLang);\r
-                               nodeURL.setTextContent(url);\r
-\r
-                               nodeRecommendation.appendChild(nodeDescription);\r
-                               nodeRecommendation.appendChild(nodeURL);\r
-\r
-                               nodeRecommendations.appendChild(nodeRecommendation);\r
-                       }\r
-                       root.appendChild(nodeRecommendations);\r
-               }\r
-\r
-               // presetsのelementを構築する.\r
-               Element nodePresets = doc.createElementNS(NS, "presets");\r
-               if (writePartsSetElements(doc, nodePresets, characterData, true, false) > 0) {\r
-                       root.appendChild(nodePresets);\r
-               }\r
-\r
-               // output xml\r
-               TransformerFactory txFactory = TransformerFactory.newInstance();\r
-               txFactory.setAttribute("indent-number", Integer.valueOf(4));\r
-               Transformer tfmr;\r
-               try {\r
-                       tfmr = txFactory.newTransformer();\r
-               } catch (TransformerConfigurationException ex) {\r
-                       throw new RuntimeException("JAXP Configuration Failed.", ex);\r
-               }\r
-               tfmr.setOutputProperty(OutputKeys.INDENT, "yes");\r
-\r
-               // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4504745\r
-               final String encoding = "UTF-8";\r
-               tfmr.setOutputProperty("encoding", encoding);\r
-               try {\r
-                       tfmr.transform(new DOMSource(doc), new StreamResult(\r
-                                       new OutputStreamWriter(outstm, Charset.forName(encoding))));\r
 \r
-               } catch (TransformerException ex) {\r
-                       IOException ex2 = new IOException("XML Convert failed.");\r
-                       ex2.initCause(ex);\r
-                       throw ex2;\r
-               }\r
-       }\r
 \r
        public void saveFavorites(CharacterData characterData) throws IOException {\r
                if (characterData == null) {\r
@@ -1722,7 +922,8 @@ public class CharacterDataPersistent {
                doc.appendChild(root);\r
 \r
                // presetsのelementを構築する.(Presetは除く)\r
-               writePartsSetElements(doc, root, characterData, false, true);\r
+               characterDataXmlWriter.writePartsSetElements(doc, root, characterData,\r
+                               false, true);\r
 \r
                // output xml\r
                TransformerFactory txFactory = TransformerFactory.newInstance();\r
@@ -1749,218 +950,7 @@ public class CharacterDataPersistent {
                }\r
        }\r
 \r
-       /**\r
-        * キャラクターデータ内のPresetおよびFavotiesのPartssetの双方共通のパーツセット要素のリストを構築する.\r
-        * \r
-        * @param doc\r
-        *            ドキュメントオブジェクト(createElementNS用)\r
-        * @param baseElement\r
-        *            親要素、キャラクターデータの場合はPreset、Favoritesの場合はPartssetを示す要素\r
-        * @param characterData\r
-        *            キャラクターデータ\r
-        * @param writePresets\r
-        *            Preset属性のパーツセットを登録する場合はtrue、Preset属性時はデフォルトプリセット属性も(あれば)登録される\r
-        * @param writeFavorites\r
-        *            Preset属性のないパーツセットを登録する場合はtrue\r
-        * @return 登録したパーツセットの個数\r
-        */\r
-       protected int writePartsSetElements(Document doc, Element baseElement,\r
-                       CharacterData characterData, boolean writePresets,\r
-                       boolean writeFavorites) {\r
-               Map<String, PartsSet> partsSetMap = characterData.getPartsSets();\r
-\r
-               Locale locale = Locale.getDefault();\r
-               String lang = locale.getLanguage();\r
-\r
-               HashMap<String, PartsSet> registeredPartsSetMap = new HashMap<String, PartsSet>();\r
-\r
-               for (Map.Entry<String, PartsSet> partsSetsEntry : partsSetMap\r
-                               .entrySet()) {\r
-                       PartsSet partsSet = partsSetsEntry.getValue();\r
-                       if (partsSet.isPresetParts() && !writePresets) {\r
-                               continue;\r
-                       }\r
-                       if (!partsSet.isPresetParts() && !writeFavorites) {\r
-                               continue;\r
-                       }\r
-\r
-                       if (partsSet.isEmpty()) {\r
-                               // 空のパーツセットは登録しない.\r
-                               continue;\r
-                       }\r
 \r
-                       String partsSetId = partsSet.getPartsSetId();\r
-                       String localizedName = partsSet.getLocalizedName();\r
-\r
-                       Element nodePreset = doc.createElementNS(NS, "preset");\r
-                       nodePreset.setAttribute("id", partsSetId);\r
-                       baseElement.appendChild(nodePreset);\r
-                       registeredPartsSetMap.put(partsSet.getPartsSetId(), partsSet);\r
-\r
-                       // display-name\r
-                       Element nodeName = doc.createElementNS(NS, "display-name");\r
-                       Attr attrLang = doc.createAttributeNS(XMLConstants.XML_NS_URI,\r
-                                       "lang");\r
-                       attrLang.setValue(lang);\r
-                       nodeName.setAttributeNode(attrLang);\r
-                       nodeName.setTextContent(localizedName);\r
-                       nodePreset.appendChild(nodeName);\r
-\r
-                       // bgColor\r
-                       Color bgColor = partsSet.getBgColor();\r
-                       if (bgColor != null) {\r
-                               Element nodeBgColor = doc.createElementNS(NS,\r
-                                               "background-color");\r
-                               nodeBgColor.setAttribute("color",\r
-                                               "#" + Integer.toHexString(bgColor.getRGB() & 0xffffff));\r
-                               nodePreset.appendChild(nodeBgColor);\r
-                       }\r
-\r
-                       // affine transform parameter\r
-                       double[] affineTransformParameter = partsSet\r
-                                       .getAffineTransformParameter();\r
-                       if (affineTransformParameter != null) {\r
-                               Element nodeAffineTransform = doc.createElementNS(NS,\r
-                                               "affine-transform-parameter");\r
-                               StringBuilder tmp = new StringBuilder();\r
-                               for (double affineItem : affineTransformParameter) {\r
-                                       if (tmp.length() > 0) {\r
-                                               tmp.append(" ");\r
-                                       }\r
-                                       tmp.append(Double.toString(affineItem));\r
-                               }\r
-                               nodeAffineTransform.setTextContent(tmp.toString());\r
-                               nodePreset.appendChild(nodeAffineTransform);\r
-                       }\r
-\r
-                       // categories\r
-                       for (Map.Entry<PartsCategory, List<PartsIdentifier>> entry : partsSet\r
-                                       .entrySet()) {\r
-                               PartsCategory partsCategory = entry.getKey();\r
-\r
-                               // category\r
-                               Element nodeCategory = doc.createElementNS(NS, "category");\r
-                               nodeCategory.setAttribute("refid",\r
-                                               partsCategory.getCategoryId());\r
-                               nodePreset.appendChild(nodeCategory);\r
-\r
-                               List<PartsIdentifier> partsIdentifiers = entry.getValue();\r
-                               for (PartsIdentifier partsIdentifier : partsIdentifiers) {\r
-                                       String partsName = partsIdentifier.getPartsName();\r
-                                       Element nodeParts = doc.createElementNS(NS, "parts");\r
-                                       nodeParts.setAttribute("name", partsName);\r
-                                       nodeCategory.appendChild(nodeParts);\r
-\r
-                                       PartsColorInfo partsColorInfo = partsSet\r
-                                                       .getColorInfo(partsIdentifier);\r
-                                       if (partsColorInfo != null) {\r
-                                               Element nodeColor = doc.createElementNS(NS, "color");\r
-                                               nodeParts.appendChild(nodeColor);\r
-\r
-                                               for (Map.Entry<Layer, ColorInfo> colorInfoEntry : partsColorInfo\r
-                                                               .entrySet()) {\r
-                                                       Layer layer = colorInfoEntry.getKey();\r
-                                                       ColorInfo colorInfo = colorInfoEntry.getValue();\r
-\r
-                                                       Element nodeLayer = doc\r
-                                                                       .createElementNS(NS, "layer");\r
-                                                       nodeLayer.setAttribute("refid", layer.getId());\r
-                                                       nodeColor.appendChild(nodeLayer);\r
-\r
-                                                       // ColorGroup\r
-                                                       ColorGroup colorGroup = colorInfo.getColorGroup();\r
-                                                       boolean colorSync = colorInfo.isSyncColorGroup();\r
-\r
-                                                       if (colorGroup.isEnabled()) {\r
-                                                               Element nodeColorGroup = doc.createElementNS(\r
-                                                                               NS, "color-group");\r
-                                                               nodeColorGroup.setAttribute("group",\r
-                                                                               colorGroup.getId());\r
-                                                               nodeColorGroup.setAttribute("synchronized",\r
-                                                                               colorSync ? "true" : "false");\r
-                                                               nodeLayer.appendChild(nodeColorGroup);\r
-                                                       }\r
-\r
-                                                       // RGB\r
-                                                       ColorConvertParameter param = colorInfo\r
-                                                                       .getColorParameter();\r
-\r
-                                                       Element nodeRGB = doc.createElementNS(NS, "rgb");\r
-                                                       Object[][] rgbArgss = {\r
-                                                                       {"red", param.getOffsetR(),\r
-                                                                                       param.getFactorR(),\r
-                                                                                       param.getGammaR()},\r
-                                                                       {"green", param.getOffsetG(),\r
-                                                                                       param.getFactorG(),\r
-                                                                                       param.getGammaG()},\r
-                                                                       {"blue", param.getOffsetB(),\r
-                                                                                       param.getFactorB(),\r
-                                                                                       param.getGammaB()},\r
-                                                                       {"alpha", param.getOffsetA(),\r
-                                                                                       param.getFactorA(),\r
-                                                                                       param.getGammaA()},};\r
-                                                       for (Object[] rgbArgs : rgbArgss) {\r
-                                                               Element nodeRGBItem = doc.createElementNS(NS,\r
-                                                                               rgbArgs[0].toString());\r
-                                                               nodeRGBItem.setAttribute("offset",\r
-                                                                               rgbArgs[1].toString());\r
-                                                               nodeRGBItem.setAttribute("factor",\r
-                                                                               rgbArgs[2].toString());\r
-                                                               nodeRGBItem.setAttribute("gamma",\r
-                                                                               rgbArgs[3].toString());\r
-                                                               nodeRGB.appendChild(nodeRGBItem);\r
-                                                       }\r
-                                                       nodeLayer.appendChild(nodeRGB);\r
-\r
-                                                       // HSB\r
-                                                       Element nodeHSB = doc.createElementNS(NS, "hsb");\r
-                                                       nodeHSB.setAttribute("hue",\r
-                                                                       Float.toString(param.getHue()));\r
-                                                       nodeHSB.setAttribute("saturation",\r
-                                                                       Float.toString(param.getSaturation()));\r
-                                                       nodeHSB.setAttribute("brightness",\r
-                                                                       Float.toString(param.getBrightness()));\r
-                                                       if (param.getContrast() != 0.f) {\r
-                                                               // ver0.96追加、optional\r
-                                                               // ぴったり0.0fだったら省略する.\r
-                                                               nodeHSB.setAttribute("contrast",\r
-                                                                               Float.toString(param.getContrast()));\r
-                                                       }\r
-                                                       nodeLayer.appendChild(nodeHSB);\r
-\r
-                                                       // RGB Replace\r
-                                                       Element nodeRGBReplace = doc.createElementNS(NS,\r
-                                                                       "rgb-replace");\r
-                                                       ColorConv colorConv = param.getColorReplace();\r
-                                                       if (colorConv == null) {\r
-                                                               colorConv = ColorConv.NONE;\r
-                                                       }\r
-                                                       nodeRGBReplace.setAttribute("replace-type",\r
-                                                                       colorConv.name());\r
-                                                       nodeRGBReplace.setAttribute("gray",\r
-                                                                       Float.toString(param.getGrayLevel()));\r
-                                                       nodeLayer.appendChild(nodeRGBReplace);\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-\r
-               // プリセット登録時はデフォルトのプリセットIDがあれば、それも登録する.\r
-               // (ただし、該当パーツセットが書き込み済みである場合のみ)\r
-               if (writePresets) {\r
-                       String defaultPresetId = characterData.getDefaultPartsSetId();\r
-                       if (defaultPresetId != null && defaultPresetId.length() > 0) {\r
-                               PartsSet defaultPartsSet = registeredPartsSetMap\r
-                                               .get(defaultPresetId);\r
-                               if (defaultPartsSet != null && defaultPartsSet.isPresetParts()) {\r
-                                       baseElement.setAttribute("default-preset", defaultPresetId);\r
-                               }\r
-                       }\r
-               }\r
-\r
-               return registeredPartsSetMap.size();\r
-       }\r
        /**\r
         * お気に入り(Favorites)を読み込む.<br>\r
         * 現在のパーツセットに追加する形で読み込まれ、同じパーツセットIDのものは上書きされます.<br>\r
@@ -1979,7 +969,7 @@ public class CharacterDataPersistent {
                if (favoritesXml.exists()) {\r
                        InputStream is = favoritesXml.openStream();\r
                        try {\r
-                               loadPartsSet(characterData, is);\r
+                               characterDataXmlReader.loadPartsSet(characterData, is);\r
 \r
                        } finally {\r
                                is.close();\r
@@ -1987,33 +977,6 @@ public class CharacterDataPersistent {
                }\r
        }\r
 \r
-       /**\r
-        * 入力ストリームからパーツセット定義(Favorites.xml)を読み込んで、 characterDataに追加登録する.<br>\r
-        * \r
-        * @param characterData\r
-        *            お気に入りを登録されるキャラクターデータ\r
-        * @param inpstm\r
-        *            お気に入りのxmlへの入力ストリーム\r
-        * @param docInfo\r
-        *            ドキュメントタイプ\r
-        * @throws IOException\r
-        *             読み込みに失敗した場合\r
-        */\r
-       protected void loadPartsSet(CharacterData characterData, InputStream inpstm)\r
-                       throws IOException {\r
-               if (characterData == null || inpstm == null) {\r
-                       throw new IllegalArgumentException();\r
-               }\r
-\r
-               Document doc = XMLUtilities.loadDocument(inpstm);\r
-               Element docElm = doc.getDocumentElement();\r
-               if (!"partssets".equals(docElm.getNodeName())) {\r
-                       logger.log(Level.WARNING, "invalid partsets format.");\r
-                       return;\r
-               }\r
-               String lang = Locale.getDefault().getLanguage();\r
-               loadPartsSet(characterData, docElm, false, lang);\r
-       }\r
 \r
        /**\r
         * 既存のキャラクター定義を削除する.<br>\r
@@ -2988,7 +1951,8 @@ public class CharacterDataPersistent {
                try {\r
                        FileOutputStream outstm = new FileOutputStream(characterXmlFile);\r
                        try {\r
-                               writeXMLCharacterData(characterData, outstm);\r
+                               characterDataXmlWriter.writeXMLCharacterData(characterData,\r
+                                               outstm);\r
                        } finally {\r
                                outstm.close();\r
                        }\r
diff --git a/src/charactermanaj/model/io/CharacterDataXMLReader.java b/src/charactermanaj/model/io/CharacterDataXMLReader.java
new file mode 100644 (file)
index 0000000..ef769f0
--- /dev/null
@@ -0,0 +1,612 @@
+package charactermanaj.model.io;\r
+\r
+import static charactermanaj.util.XMLUtilities.getChildElements;\r
+import static charactermanaj.util.XMLUtilities.getElementText;\r
+import static charactermanaj.util.XMLUtilities.getFirstChildElement;\r
+import static charactermanaj.util.XMLUtilities.getLocalizedElementText;\r
+\r
+import java.awt.Color;\r
+import java.awt.Dimension;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.net.URI;\r
+import java.net.URL;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Locale;\r
+import java.util.logging.Level;\r
+import java.util.logging.Logger;\r
+\r
+import javax.xml.xpath.XPathExpressionException;\r
+\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+import charactermanaj.graphics.colormodel.ColorModels;\r
+import charactermanaj.graphics.filters.ColorConv;\r
+import charactermanaj.graphics.filters.ColorConvertParameter;\r
+import charactermanaj.model.CharacterData;\r
+import charactermanaj.model.ColorGroup;\r
+import charactermanaj.model.ColorInfo;\r
+import charactermanaj.model.Layer;\r
+import charactermanaj.model.PartsCategory;\r
+import charactermanaj.model.PartsColorInfo;\r
+import charactermanaj.model.PartsIdentifier;\r
+import charactermanaj.model.PartsSet;\r
+import charactermanaj.model.RecommendationURL;\r
+import charactermanaj.util.XMLUtilities;\r
+\r
+/**\r
+ * キャラクターデータを格納したXMLを読み込むためのクラス.\r
+ * \r
+ * @author seraphy\r
+ */\r
+public class CharacterDataXMLReader {\r
+\r
+       /**\r
+        * ロガー\r
+        */\r
+       private static final Logger logger = Logger\r
+                       .getLogger(CharacterDataXMLReader.class.getName());\r
+\r
+       /**\r
+        * キャラクター定義(プロファイル)をロードする.\r
+        * \r
+        * @param docBase\r
+        *            対象xml\r
+        * @return キャラクターデータ\r
+        * @throws IOException\r
+        */\r
+       public CharacterData loadCharacterDataFromXML(URI docBase)\r
+                       throws IOException {\r
+               if (docBase == null) {\r
+                       throw new IllegalArgumentException();\r
+               }\r
+\r
+               URL docBaseURL = docBase.toURL();\r
+               CharacterData cd;\r
+               InputStream is = docBaseURL.openStream();\r
+               try {\r
+                       long st = System.currentTimeMillis();\r
+                       cd = loadCharacterDataFromXML(is, docBase);\r
+                       long en = System.currentTimeMillis();\r
+                       System.out.println("所要時間: " + (en - st));\r
+\r
+               } finally {\r
+                       is.close();\r
+               }\r
+               return cd;\r
+       }\r
+\r
+       /**\r
+        * XMLコンテンツに対する入力ストリームからキャラクターデータを取り出す.<br>\r
+        * docbaseはXMLファイルの位置を示すものであり、XMLデータ中には含まれず、キャラクターデータのロード時にセットされる.<br>\r
+        * そのため引数としてdocbaseを引き渡す.<br>\r
+        * 読み取りは現在のデフォルトロケールで行われる.<br>\r
+        * \r
+        * @param is\r
+        *            入力ストリーム\r
+        * @param docBase\r
+        *            XMLファイルの位置を示すURI、nullの場合はnullが設定される。\r
+        * @param docInfo\r
+        *            ドキュメントのタイプ\r
+        * @return 読み取られたプロファイル\r
+        * @throws IOException\r
+        *             読み取りに失敗\r
+        */\r
+       public CharacterData loadCharacterDataFromXML(InputStream is, URI docBase)\r
+                       throws IOException {\r
+               return loadCharacterDataFromXML(is, docBase, Locale.getDefault());\r
+       }\r
+\r
+       /**\r
+        * XMLコンテンツに対する入力ストリームからキャラクターデータを取り出す.<br>\r
+        * docbaseはXMLファイルの位置を示すものであり、XMLデータ中には含まれず、キャラクターデータのロード時にセットされる.<br>\r
+        * そのため引数としてdocbaseを引き渡す.<br>\r
+        * 設定ファイル中の表示文字列にロケール指定がある場合、引数に指定したロケールに合致する言語の情報を取得する.<br>\r
+        * 合致するものがなければ最初のものを使用する.<br>\r
+        * \r
+        * @param is\r
+        *            入力ストリーム\r
+        * @param docBase\r
+        *            XMLファイルの位置を示すURI、nullの場合はnullが設定される。\r
+        * @param docInfo\r
+        *            ドキュメントのタイプ\r
+        * @param locale\r
+        *            読み取るロケール\r
+        * @return 読み取られたプロファイル\r
+        * @throws IOException\r
+        *             読み取りに失敗\r
+        */\r
+       public CharacterData loadCharacterDataFromXML(InputStream is, URI docBase,\r
+                       Locale locale) throws IOException {\r
+               if (is == null || locale == null) {\r
+                       throw new IllegalArgumentException();\r
+               }\r
+\r
+               Document doc = XMLUtilities.loadDocument(is);\r
+\r
+               CharacterData characterData = new CharacterData();\r
+               characterData.setDocBase(docBase);\r
+\r
+               try {\r
+                       Element docElm = doc.getDocumentElement();\r
+                       if (!"character".equals(docElm.getNodeName())) {\r
+                               throw new IOException("Invalid Format.");\r
+                       }\r
+\r
+                       String docVersion = docElm.getAttribute("version").trim();\r
+                       if (!"1.0".equals(docVersion)) {\r
+                               throw new IOException("unsupported version: " + docVersion);\r
+                       }\r
+                       String characterId = docElm.getAttribute("id").trim();\r
+                       String characterRev = docElm.getAttribute("rev").trim();\r
+\r
+                       characterData.setId(characterId);\r
+                       characterData.setRev(characterRev);\r
+\r
+                       // language\r
+                       String lang = locale.getLanguage();\r
+\r
+                       // name\r
+                       String characterName = getLocalizedElementText(docElm, "name", lang);\r
+                       if (characterName == null) {\r
+                               characterName = "default";\r
+                       }\r
+                       characterData.setName(characterName.trim());\r
+\r
+                       // information/author, information/description\r
+                       String author = null;\r
+                       String description = null;\r
+                       for (Element infoElm : getChildElements(docElm, "information")) {\r
+                               if (author == null) {\r
+                                       author = getLocalizedElementText(infoElm, "author", lang);\r
+                               }\r
+                               if (description == null) {\r
+                                       description = getLocalizedElementText(infoElm,\r
+                                                       "description", lang);\r
+                               }\r
+                       }\r
+                       if (author == null) {\r
+                               author = "";\r
+                       }\r
+                       characterData.setAuthor(author.trim());\r
+\r
+                       if (description == null) {\r
+                               description = null;\r
+                       }\r
+                       characterData.setDescription(description);\r
+\r
+                       // image-size/width, image-size/height\r
+                       int width = 0;\r
+                       int height = 0;\r
+\r
+                       for (Element sizeElm : getChildElements(docElm, "image-size")) {\r
+                               String tmpWidth = getLocalizedElementText(sizeElm, "width",\r
+                                               lang);\r
+                               if (tmpWidth != null && tmpWidth.trim().length() > 0) {\r
+                                       width = Integer.parseInt(tmpWidth.trim());\r
+                               }\r
+                               String tmpHeight = getLocalizedElementText(sizeElm, "Height",\r
+                                               lang);\r
+                               if (tmpHeight != null && tmpHeight.trim().length() > 0) {\r
+                                       height = Integer.parseInt(tmpHeight.trim());\r
+                               }\r
+                               break;\r
+                       }\r
+                       if (width <= 0) {\r
+                               width = 300;\r
+                       }\r
+                       if (height <= 0) {\r
+                               height = 400;\r
+                       }\r
+                       characterData.setImageSize(new Dimension(width, height));\r
+\r
+                       // settings\r
+                       for (Element settingElm : getChildElements(docElm, "settings")) {\r
+                               for (Element entElm : getChildElements(settingElm, "entry")) {\r
+                                       String key = entElm.getAttribute("key").trim();\r
+                                       String val = entElm.getTextContent();\r
+                                       characterData.setProperty(key, val);\r
+                               }\r
+                       }\r
+\r
+                       // colorGroups/colorGroup\r
+                       ArrayList<ColorGroup> colorGroups = new ArrayList<ColorGroup>();\r
+                       for (Element colorGroupsElm : getChildElements(docElm,\r
+                                       "colorGroups")) {\r
+                               for (Element colorGroupElm : getChildElements(colorGroupsElm,\r
+                                               "colorGroup")) {\r
+                                       String colorGroupId = colorGroupElm.getAttribute("id")\r
+                                                       .trim();\r
+                                       String colorGroupDisplayName = getLocalizedElementText(\r
+                                                       colorGroupElm, "display-name", lang);\r
+\r
+                                       ColorGroup colorGroup = new ColorGroup(colorGroupId,\r
+                                                       colorGroupDisplayName);\r
+                                       colorGroups.add(colorGroup);\r
+                               }\r
+                       }\r
+                       characterData.setColorGroups(colorGroups);\r
+\r
+                       // categories/category\r
+                       ArrayList<PartsCategory> categories = new ArrayList<PartsCategory>();\r
+                       for (Element catsElm : getChildElements(docElm, "categories")) {\r
+                               for (Element catElm : getChildElements(catsElm, "category")) {\r
+                                       String categoryId = catElm.getAttribute("id").trim();\r
+                                       boolean multipleSelectable = Boolean.parseBoolean(catElm\r
+                                                       .getAttribute("multipleSelectable"));\r
+\r
+                                       String categoryDisplayName = getLocalizedElementText(\r
+                                                       catElm, "display-name", lang);\r
+\r
+                                       int visibleRows = 0;\r
+                                       String tmpVisibleRows = getLocalizedElementText(catElm,\r
+                                                       "visible-rows", lang);\r
+                                       if (tmpVisibleRows != null\r
+                                                       && tmpVisibleRows.trim().length() > 0) {\r
+                                               visibleRows = Integer.parseInt(tmpVisibleRows.trim());\r
+                                       }\r
+                                       if (visibleRows <= 0) {\r
+                                               visibleRows = 0;\r
+                                       }\r
+\r
+                                       // layers/layer\r
+                                       ArrayList<Layer> layers = new ArrayList<Layer>();\r
+                                       for (Element layersElm : getChildElements(catElm, "layers")) {\r
+                                               for (Element layerElm : getChildElements(layersElm,\r
+                                                               "layer")) {\r
+                                                       String layerId = layerElm.getAttribute("id");\r
+                                                       String layerDisplayName = getLocalizedElementText(\r
+                                                                       layerElm, "display-name", lang);\r
+\r
+                                                       // レイヤーの重ね順\r
+                                                       String strOrder = getElementText(layerElm, "order");\r
+                                                       int order = layers.size();\r
+                                                       if (strOrder != null\r
+                                                                       && strOrder.trim().length() > 0) {\r
+                                                               order = Integer.parseInt(strOrder.trim());\r
+                                                       }\r
+\r
+                                                       // レイヤーの画像ディレクトリ名\r
+                                                       String layerDir = getElementText(layerElm, "dir");\r
+                                                       if (layerDir == null\r
+                                                                       || layerDir.trim().length() == 0) {\r
+                                                               throw new IOException("layer's dir is null");\r
+                                                       }\r
+\r
+                                                       // カラーモデル(省略可)\r
+                                                       String colorModelName = getElementText(layerElm,\r
+                                                                       "colorModel");\r
+                                                       if (colorModelName == null\r
+                                                                       || colorModelName.length() == 0) {\r
+                                                               // 省略時はデフォルトのカラーモデル名を使用する.\r
+                                                               colorModelName = ColorModels.DEFAULT.name();\r
+                                                       }\r
+\r
+                                                       // layer/colorGroup カラーグループ\r
+                                                       boolean initSync = false;\r
+                                                       ColorGroup colorGroup = null;\r
+                                                       Element lcgElm = getFirstChildElement(layerElm,\r
+                                                                       "colorGroup");\r
+                                                       if (lcgElm != null) {\r
+                                                               String tmpInitSync = lcgElm\r
+                                                                               .getAttribute("init-sync");\r
+                                                               if (tmpInitSync.trim().length() > 0) {\r
+                                                                       initSync = Boolean.parseBoolean(tmpInitSync\r
+                                                                                       .trim());\r
+                                                               }\r
+                                                               if (colorGroup == null) {\r
+                                                                       String colorGroupRefId = lcgElm\r
+                                                                                       .getAttribute("color-hair").trim();\r
+                                                                       colorGroup = characterData\r
+                                                                                       .getColorGroup(colorGroupRefId);\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       Layer layer = new Layer(layerId, layerDisplayName,\r
+                                                                       order, colorGroup, initSync, layerDir,\r
+                                                                       colorModelName);\r
+                                                       layers.add(layer);\r
+                                               }\r
+                                       }\r
+\r
+                                       PartsCategory category = new PartsCategory(\r
+                                                       categories.size(), categoryId, categoryDisplayName,\r
+                                                       multipleSelectable, visibleRows,\r
+                                                       layers.toArray(new Layer[layers.size()]));\r
+                                       categories.add(category);\r
+                               }\r
+                       }\r
+                       characterData.setPartsCategories(categories\r
+                                       .toArray(new PartsCategory[categories.size()]));\r
+\r
+                       // presets\r
+                       for (Element presetssElm : getChildElements(docElm, "presets")) {\r
+                               loadPartsSet(characterData, presetssElm, true, lang);\r
+                       }\r
+\r
+                       // recommendations\r
+                       List<RecommendationURL> recommendationURLList = null; // お勧めノードがない場合はnull\r
+                       for (Element recmsElm : getChildElements(docElm, "recommendations")) {\r
+                               for (Element recmElm : getChildElements(recmsElm,\r
+                                               "recommendation")) {\r
+                                       String recommentDescription = getLocalizedElementText(\r
+                                                       recmElm, "description", lang);\r
+                                       String url = getLocalizedElementText(recmElm, "URL", lang);\r
+\r
+                                       if (recommentDescription != null) {\r
+                                               recommentDescription = recommentDescription.trim();\r
+                                       }\r
+                                       if (url != null) {\r
+                                               url = url.trim();\r
+                                       }\r
+\r
+                                       RecommendationURL recommendationURL = new RecommendationURL();\r
+                                       recommendationURL.setDisplayName(recommentDescription);\r
+                                       recommendationURL.setUrl(url);\r
+\r
+                                       if (recommendationURLList == null) {\r
+                                               recommendationURLList = new ArrayList<RecommendationURL>();\r
+                                       }\r
+                                       recommendationURLList.add(recommendationURL);\r
+                               }\r
+                       }\r
+\r
+               } catch (RuntimeException ex) {\r
+                       IOException ex2 = new IOException("CharacterData invalid format.");\r
+                       ex2.initCause(ex);\r
+                       throw ex2;\r
+               }\r
+\r
+               return characterData;\r
+       }\r
+\r
+       /**\r
+        * 入力ストリームからパーツセット定義(Favorites.xml)を読み込んで、 characterDataに追加登録する.<br>\r
+        * \r
+        * @param characterData\r
+        *            お気に入りを登録されるキャラクターデータ\r
+        * @param inpstm\r
+        *            お気に入りのxmlへの入力ストリーム\r
+        * @param docInfo\r
+        *            ドキュメントタイプ\r
+        * @throws IOException\r
+        *             読み込みに失敗した場合\r
+        */\r
+       public void loadPartsSet(CharacterData characterData, InputStream inpstm)\r
+                       throws IOException {\r
+               if (characterData == null || inpstm == null) {\r
+                       throw new IllegalArgumentException();\r
+               }\r
+\r
+               Document doc = XMLUtilities.loadDocument(inpstm);\r
+               Element docElm = doc.getDocumentElement();\r
+               if (!"partssets".equals(docElm.getNodeName())) {\r
+                       logger.log(Level.WARNING, "invalid partsets format.");\r
+                       return;\r
+               }\r
+               String lang = Locale.getDefault().getLanguage();\r
+               loadPartsSet(characterData, docElm, false, lang);\r
+       }\r
+\r
+       /**\r
+        * CharacterDataのプリセットまたはFavoritesのパーツセットのXMLからパーツセットを読み取って登録する.<br>\r
+        * \r
+        * @param characterData\r
+        *            キャラクターデータ\r
+        * @param nodePartssets\r
+        *            パーツセットのノード、プリセットまたはパーツセットノード\r
+        * @param presetParts\r
+        *            ロードしたパーツセットにプリセットフラグをたてる場合はtrue\r
+        * @param lang\r
+        *            言語\r
+        * @throws XPathExpressionException\r
+        */\r
+       protected void loadPartsSet(CharacterData characterData,\r
+                       Element nodePartssets, boolean presetParts, String lang) {\r
+\r
+               // デフォルトのパーツセットID\r
+               String defaultPresetId = nodePartssets.getAttribute("default-preset")\r
+                               .trim();\r
+\r
+               // パーツセットリストの読み込み\r
+               for (Element presetElm : getChildElements(nodePartssets, "preset")) {\r
+                       String partsSetId = presetElm.getAttribute("id").trim();\r
+                       if (defaultPresetId == null || defaultPresetId.length() == 0) {\r
+                               defaultPresetId = partsSetId;\r
+                       }\r
+                       String displayName = getLocalizedElementText(presetElm,\r
+                                       "display-name", lang);\r
+\r
+                       PartsSet partsSet = new PartsSet();\r
+\r
+                       partsSet.setPartsSetId(partsSetId);\r
+                       partsSet.setLocalizedName(displayName);\r
+                       partsSet.setPresetParts(presetParts);\r
+\r
+                       // bgColor\r
+                       Element bgColorElm = getFirstChildElement(presetElm,\r
+                                       "background-color");\r
+                       if (bgColorElm != null) {\r
+                               String tmpBgColor = bgColorElm.getAttribute("color");\r
+                               try {\r
+                                       Color bgColor = Color.decode(tmpBgColor);\r
+                                       partsSet.setBgColor(bgColor);\r
+\r
+                               } catch (Exception ex) {\r
+                                       logger.log(Level.WARNING, "bgColor parameter is invalid. :"\r
+                                                       + tmpBgColor, ex);\r
+                                       // 無視する\r
+                               }\r
+                       }\r
+\r
+                       // affine-transform-parameter\r
+                       String tmpAffienTrans = getElementText(presetElm,\r
+                                       "affine-transform-parameter");\r
+                       if (tmpAffienTrans != null && tmpAffienTrans.trim().length() > 0) {\r
+                               try {\r
+                                       ArrayList<Double> affineTransformParameterArr = new ArrayList<Double>();\r
+                                       for (String strParam : tmpAffienTrans.split("\\s+")) {\r
+                                               affineTransformParameterArr.add(Double\r
+                                                               .valueOf(strParam));\r
+                                       }\r
+                                       double[] affineTransformParameter = new double[affineTransformParameterArr\r
+                                                       .size()];\r
+                                       int idx = 0;\r
+                                       for (double aaffineItem : affineTransformParameterArr) {\r
+                                               affineTransformParameter[idx++] = aaffineItem;\r
+                                       }\r
+                                       partsSet.setAffineTransformParameter(affineTransformParameter);\r
+\r
+                               } catch (Exception ex) {\r
+                                       logger.log(Level.WARNING,\r
+                                                       "affine transform parameter is invalid. :"\r
+                                                                       + tmpAffienTrans, ex);\r
+                                       // 無視する.\r
+                               }\r
+                       }\r
+\r
+                       // Category\r
+                       for (Element catElm : getChildElements(presetElm, "category")) {\r
+                               String categoryId = catElm.getAttribute("refid").trim();\r
+                               PartsCategory category = characterData\r
+                                               .getPartsCategory(categoryId);\r
+                               if (category == null) {\r
+                                       System.err.println("undefined category: " + categoryId);\r
+                                       continue;\r
+                               }\r
+\r
+                               // Parts\r
+                               for (Element partsElm : getChildElements(catElm, "parts")) {\r
+                                       String partsName = partsElm.getAttribute("name").trim();\r
+\r
+                                       PartsIdentifier partsIdentifier = new PartsIdentifier(\r
+                                                       category, partsName, partsName);\r
+\r
+                                       // Color/Layer\r
+                                       PartsColorInfo partsColorInfo = null;\r
+                                       for (Element colorElm : getChildElements(partsElm, "color")) {\r
+                                               for (Element layerElm : getChildElements(colorElm,\r
+                                                               "layer")) {\r
+                                                       String layerId = layerElm.getAttribute("refid")\r
+                                                                       .trim();\r
+                                                       Layer layer = category.getLayer(layerId);\r
+                                                       if (layer == null) {\r
+                                                               logger.log(Level.WARNING, "undefined layer: "\r
+                                                                               + layerId);\r
+                                                               continue;\r
+                                                       }\r
+\r
+                                                       if (partsColorInfo == null) {\r
+                                                               partsColorInfo = new PartsColorInfo(category);\r
+                                                       }\r
+                                                       ColorInfo colorInfo = partsColorInfo.get(layer);\r
+\r
+                                                       // color-group\r
+                                                       Element colorGroupElm = getFirstChildElement(\r
+                                                                       layerElm, "color-group");\r
+                                                       if (colorGroupElm != null) {\r
+                                                               ColorGroup colorGroup = characterData\r
+                                                                               .getColorGroup(colorGroupElm\r
+                                                                                               .getAttribute("group").trim());\r
+                                                               boolean syncColorGroup = Boolean\r
+                                                                               .parseBoolean(colorGroupElm\r
+                                                                                               .getAttribute("synchronized")\r
+                                                                                               .trim());\r
+                                                               colorInfo.setColorGroup(colorGroup);\r
+                                                               colorInfo.setSyncColorGroup(syncColorGroup);\r
+                                                       }\r
+\r
+                                                       // rgb\r
+                                                       ColorConvertParameter param = colorInfo\r
+                                                                       .getColorParameter();\r
+                                                       Element nodeRgb = getFirstChildElement(layerElm,\r
+                                                                       "rgb");\r
+                                                       if (nodeRgb != null) {\r
+                                                               for (Element elmRgb : getChildElements(nodeRgb,\r
+                                                                               null)) {\r
+                                                                       String rgbName = elmRgb.getNodeName();\r
+                                                                       int offset = Integer.parseInt(elmRgb\r
+                                                                                       .getAttribute("offset"));\r
+                                                                       float factor = Float.parseFloat(elmRgb\r
+                                                                                       .getAttribute("factor"));\r
+                                                                       float gamma = Float.parseFloat(elmRgb\r
+                                                                                       .getAttribute("gamma"));\r
+                                                                       if ("red".equals(rgbName)) {\r
+                                                                               param.setOffsetR(offset);\r
+                                                                               param.setFactorR(factor);\r
+                                                                               param.setGammaR(gamma);\r
+                                                                       } else if ("green".equals(rgbName)) {\r
+                                                                               param.setOffsetG(offset);\r
+                                                                               param.setFactorG(factor);\r
+                                                                               param.setGammaG(gamma);\r
+                                                                       } else if ("blue".equals(rgbName)) {\r
+                                                                               param.setOffsetB(offset);\r
+                                                                               param.setFactorB(factor);\r
+                                                                               param.setGammaB(gamma);\r
+                                                                       } else if ("alpha".equals(rgbName)) {\r
+                                                                               param.setOffsetA(offset);\r
+                                                                               param.setFactorA(factor);\r
+                                                                               param.setGammaA(gamma);\r
+                                                                       }\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       // hsb\r
+                                                       Element elmHsb = getFirstChildElement(layerElm,\r
+                                                                       "hsb");\r
+                                                       if (elmHsb != null) {\r
+                                                               float hue = Float.parseFloat(elmHsb\r
+                                                                               .getAttribute("hue"));\r
+                                                               float saturation = Float.parseFloat(elmHsb\r
+                                                                               .getAttribute("saturation"));\r
+                                                               float brightness = Float.parseFloat(elmHsb\r
+                                                                               .getAttribute("brightness"));\r
+                                                               String strContrast = elmHsb.getAttribute(\r
+                                                                               "contrast").trim();\r
+                                                               param.setHue(hue);\r
+                                                               param.setSaturation(saturation);\r
+                                                               param.setBrightness(brightness);\r
+                                                               if (strContrast != null\r
+                                                                               && strContrast.length() > 0) {\r
+                                                                       // ver0.96追加 optional\r
+                                                                       float contrast = Float\r
+                                                                                       .parseFloat(strContrast);\r
+                                                                       param.setContrast(contrast);\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       // rgb-replace\r
+                                                       Element elmRgbReplace = getFirstChildElement(\r
+                                                                       layerElm, "rgb-replace");\r
+                                                       if (elmRgbReplace != null) {\r
+                                                               Float grayLevel = Float\r
+                                                                               .parseFloat(elmRgbReplace\r
+                                                                                               .getAttribute("gray"));\r
+                                                               ColorConv colorType = ColorConv\r
+                                                                               .valueOf(elmRgbReplace\r
+                                                                                               .getAttribute("replace-type"));\r
+                                                               param.setGrayLevel(grayLevel);\r
+                                                               param.setColorReplace(colorType);\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       partsSet.appendParts(category, partsIdentifier,\r
+                                                       partsColorInfo);\r
+                               }\r
+                       }\r
+\r
+                       characterData.addPartsSet(partsSet);\r
+               }\r
+\r
+               if (presetParts) {\r
+                       if (defaultPresetId.length() == 0) {\r
+                               // デフォルトパーツセットがないことを示すためのnull\r
+                               defaultPresetId = null;\r
+                       }\r
+                       characterData.setDefaultPartsSetId(defaultPresetId);\r
+               }\r
+       }\r
+\r
+}\r
diff --git a/src/charactermanaj/model/io/CharacterDataXMLWriter.java b/src/charactermanaj/model/io/CharacterDataXMLWriter.java
new file mode 100644 (file)
index 0000000..65bbf0b
--- /dev/null
@@ -0,0 +1,526 @@
+package charactermanaj.model.io;\r
+\r
+import static charactermanaj.model.io.CharacterDataPersistent.NS;\r
+import static charactermanaj.model.io.CharacterDataPersistent.VERSION_SIG_1_0;\r
+\r
+import java.awt.Color;\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.io.OutputStreamWriter;\r
+import java.nio.charset.Charset;\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Locale;\r
+import java.util.Map;\r
+\r
+import javax.xml.XMLConstants;\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import javax.xml.parsers.ParserConfigurationException;\r
+import javax.xml.transform.OutputKeys;\r
+import javax.xml.transform.Transformer;\r
+import javax.xml.transform.TransformerConfigurationException;\r
+import javax.xml.transform.TransformerException;\r
+import javax.xml.transform.TransformerFactory;\r
+import javax.xml.transform.dom.DOMSource;\r
+import javax.xml.transform.stream.StreamResult;\r
+\r
+import org.w3c.dom.Attr;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+import charactermanaj.graphics.filters.ColorConv;\r
+import charactermanaj.graphics.filters.ColorConvertParameter;\r
+import charactermanaj.model.CharacterData;\r
+import charactermanaj.model.ColorGroup;\r
+import charactermanaj.model.ColorInfo;\r
+import charactermanaj.model.Layer;\r
+import charactermanaj.model.PartsCategory;\r
+import charactermanaj.model.PartsColorInfo;\r
+import charactermanaj.model.PartsIdentifier;\r
+import charactermanaj.model.PartsSet;\r
+import charactermanaj.model.RecommendationURL;\r
+\r
+public class CharacterDataXMLWriter {\r
+\r
+       public void writeXMLCharacterData(CharacterData characterData,\r
+                       OutputStream outstm) throws IOException {\r
+               if (outstm == null || characterData == null) {\r
+                       throw new IllegalArgumentException();\r
+               }\r
+\r
+               Locale locale = Locale.getDefault();\r
+               String lang = locale.getLanguage();\r
+\r
+               Document doc;\r
+               try {\r
+                       DocumentBuilderFactory factory = DocumentBuilderFactory\r
+                                       .newInstance();\r
+                       factory.setNamespaceAware(true);\r
+                       DocumentBuilder builder = factory.newDocumentBuilder();\r
+                       doc = builder.newDocument();\r
+               } catch (ParserConfigurationException ex) {\r
+                       throw new RuntimeException("JAXP Configuration failed.", ex);\r
+               }\r
+\r
+               Element root = doc.createElementNS(NS, "character");\r
+               root.setAttribute("version", VERSION_SIG_1_0);\r
+\r
+               root.setAttribute("xmlns:xml", XMLConstants.XML_NS_URI);\r
+               root.setAttribute("xmlns:xsi",\r
+                               "http://www.w3.org/2001/XMLSchema-instance");\r
+               root.setAttribute("xsi:schemaLocation", NS + " character.xsd");\r
+               root.setAttribute("id", characterData.getId());\r
+               root.setAttribute("rev", characterData.getRev());\r
+               doc.appendChild(root);\r
+\r
+               // name\r
+               Element nodeName = doc.createElementNS(NS, "name");\r
+               Attr attrLang = doc.createAttributeNS(XMLConstants.XML_NS_URI, "lang");\r
+               attrLang.setValue(lang);\r
+               nodeName.setAttributeNodeNS(attrLang);\r
+               nodeName.setTextContent(characterData.getName());\r
+               root.appendChild(nodeName);\r
+\r
+               // information\r
+               String author = characterData.getAuthor();\r
+               String description = characterData.getDescription();\r
+               if ((author != null && author.length() > 0)\r
+                               || (description != null && description.length() > 0)) {\r
+                       Element nodeInfomation = doc.createElementNS(NS, "information");\r
+                       if (author != null && author.length() > 0) {\r
+                               Element nodeAuthor = doc.createElementNS(NS, "author");\r
+                               Attr attrNodeAuthorLang = doc.createAttributeNS(\r
+                                               XMLConstants.XML_NS_URI, "lang");\r
+                               attrNodeAuthorLang.setValue(lang);\r
+                               nodeAuthor.setAttributeNodeNS(attrNodeAuthorLang);\r
+                               nodeAuthor.setTextContent(author);\r
+                               nodeInfomation.appendChild(nodeAuthor);\r
+                       }\r
+                       if (description != null && description.length() > 0) {\r
+\r
+                               // 説明の改行コードはXML上ではLFとする.\r
+                               description = description.replace("\r\n", "\n");\r
+                               description = description.replace("\r", "\n");\r
+\r
+                               Element nodeDescription = doc\r
+                                               .createElementNS(NS, "description");\r
+                               Attr attrNodeDescriptionLang = doc.createAttributeNS(\r
+                                               XMLConstants.XML_NS_URI, "lang");\r
+                               attrNodeDescriptionLang.setValue(lang);\r
+                               nodeDescription.setAttributeNodeNS(attrNodeDescriptionLang);\r
+                               nodeDescription.setTextContent(description);\r
+                               nodeInfomation.appendChild(nodeDescription);\r
+                       }\r
+                       root.appendChild(nodeInfomation);\r
+               }\r
+\r
+               // size\r
+               Element nodeSize = doc.createElementNS(NS, "image-size");\r
+               Element nodeWidth = doc.createElementNS(NS, "width");\r
+               nodeWidth.setTextContent(Integer.toString((int) characterData\r
+                               .getImageSize().getWidth()));\r
+               Element nodeHeight = doc.createElementNS(NS, "height");\r
+               nodeHeight.setTextContent(Integer.toString((int) characterData\r
+                               .getImageSize().getHeight()));\r
+               nodeSize.appendChild(nodeWidth);\r
+               nodeSize.appendChild(nodeHeight);\r
+               root.appendChild(nodeSize);\r
+\r
+               // settings\r
+               Element nodeSettings = doc.createElementNS(NS, "settings");\r
+               root.appendChild(nodeSettings);\r
+               for (String settingsEntryName : characterData.getPropertyNames()) {\r
+                       String value = characterData.getProperty(settingsEntryName);\r
+                       if (value != null) {\r
+                               Element nodeEntry = doc.createElementNS(NS, "entry");\r
+                               nodeEntry.setAttribute("key", settingsEntryName);\r
+                               nodeEntry.setTextContent(value);\r
+                               nodeSettings.appendChild(nodeEntry);\r
+                       }\r
+               }\r
+\r
+               // categories\r
+               Element nodeCategories = doc.createElementNS(NS, "categories");\r
+               for (PartsCategory category : characterData.getPartsCategories()) {\r
+                       // category\r
+                       Element nodeCategory = doc.createElementNS(NS, "category");\r
+                       nodeCategory.setAttribute("id", category.getCategoryId());\r
+                       nodeCategory.setAttribute("multipleSelectable",\r
+                                       category.isMultipleSelectable() ? "true" : "false");\r
+\r
+                       // visible-rows\r
+                       Element nodeVisibleRows = doc.createElementNS(NS, "visible-rows");\r
+                       nodeVisibleRows.setTextContent(Integer.toString(category\r
+                                       .getVisibleRows()));\r
+                       nodeCategory.appendChild(nodeVisibleRows);\r
+\r
+                       // category name\r
+                       Element nodeCategoryName = doc.createElementNS(NS, "display-name");\r
+                       Attr attrCategoryNameLang = doc.createAttributeNS(\r
+                                       XMLConstants.XML_NS_URI, "lang");\r
+                       attrCategoryNameLang.setValue(lang);\r
+                       nodeCategoryName.setAttributeNodeNS(attrCategoryNameLang);\r
+                       nodeCategoryName\r
+                                       .setTextContent(category.getLocalizedCategoryName());\r
+                       nodeCategory.appendChild(nodeCategoryName);\r
+\r
+                       // layers\r
+                       Element nodeLayers = doc.createElementNS(NS, "layers");\r
+                       for (Layer layer : category.getLayers()) {\r
+                               // layer\r
+                               Element nodeLayer = doc.createElementNS(NS, "layer");\r
+                               nodeLayer.setAttribute("id", layer.getId());\r
+\r
+                               Element nodeLayerName = doc.createElementNS(NS, "display-name");\r
+                               Attr attrLayerNameLang = doc.createAttributeNS(\r
+                                               XMLConstants.XML_NS_URI, "lang");\r
+                               attrLayerNameLang.setValue(lang);\r
+                               nodeLayerName.setAttributeNodeNS(attrLayerNameLang);\r
+                               nodeLayerName.setTextContent(layer.getLocalizedName());\r
+                               nodeLayer.appendChild(nodeLayerName);\r
+\r
+                               Element nodeOrder = doc.createElementNS(NS, "order");\r
+                               nodeOrder.setTextContent(Integer.toString(layer.getOrder()));\r
+                               nodeLayer.appendChild(nodeOrder);\r
+\r
+                               ColorGroup colorGroup = layer.getColorGroup();\r
+                               if (colorGroup != null && colorGroup.isEnabled()) {\r
+                                       Element nodeColorGroup = doc.createElementNS(NS,\r
+                                                       "colorGroup");\r
+                                       nodeColorGroup.setAttribute("refid", colorGroup.getId());\r
+                                       nodeColorGroup.setAttribute("init-sync", layer.isInitSync()\r
+                                                       ? "true"\r
+                                                       : "false");\r
+                                       nodeLayer.appendChild(nodeColorGroup);\r
+                               }\r
+\r
+                               Element nodeDir = doc.createElementNS(NS, "dir");\r
+                               nodeDir.setTextContent(layer.getDir());\r
+                               nodeLayer.appendChild(nodeDir);\r
+\r
+                               String colorModelName = layer.getColorModelName();\r
+                               if (colorModelName != null && colorModelName.length() > 0) {\r
+                                       Element nodeColorModel = doc.createElementNS(NS,\r
+                                                       "colorModel");\r
+                                       nodeColorModel.setTextContent(layer.getColorModelName());\r
+                                       nodeLayer.appendChild(nodeColorModel);\r
+                               }\r
+\r
+                               nodeLayers.appendChild(nodeLayer);\r
+                       }\r
+                       nodeCategory.appendChild(nodeLayers);\r
+\r
+                       nodeCategories.appendChild(nodeCategory);\r
+               }\r
+               root.appendChild(nodeCategories);\r
+\r
+               // ColorGroupを構築する\r
+               Collection<ColorGroup> colorGroups = characterData.getColorGroups();\r
+               if (colorGroups.size() > 0) {\r
+                       Element nodeColorGroups = doc.createElementNS(NS, "colorGroups");\r
+                       int colorGroupCount = 0;\r
+                       for (ColorGroup colorGroup : colorGroups) {\r
+                               if (!colorGroup.isEnabled()) {\r
+                                       continue;\r
+                               }\r
+                               Element nodeColorGroup = doc.createElementNS(NS, "colorGroup");\r
+                               nodeColorGroup.setAttribute("id", colorGroup.getId());\r
+                               Element nodeColorGroupName = doc.createElementNS(NS,\r
+                                               "display-name");\r
+                               Attr attrColorGroupNameLang = doc.createAttributeNS(\r
+                                               XMLConstants.XML_NS_URI, "lang");\r
+                               attrColorGroupNameLang.setValue(lang);\r
+                               nodeColorGroupName.setAttributeNodeNS(attrColorGroupNameLang);\r
+                               nodeColorGroupName\r
+                                               .setTextContent(colorGroup.getLocalizedName());\r
+                               nodeColorGroup.appendChild(nodeColorGroupName);\r
+                               nodeColorGroups.appendChild(nodeColorGroup);\r
+                               colorGroupCount++;\r
+                       }\r
+                       if (colorGroupCount > 0) {\r
+                               root.appendChild(nodeColorGroups);\r
+                       }\r
+               }\r
+\r
+               // Recommendations\r
+               List<RecommendationURL> recommendations = characterData\r
+                               .getRecommendationURLList();\r
+               if (recommendations != null) {\r
+                       Element nodeRecommendations = doc.createElementNS(NS,\r
+                                       "recommendations");\r
+                       for (RecommendationURL recommendation : recommendations) {\r
+                               Element nodeRecommendation = doc.createElementNS(NS,\r
+                                               "recommendation");\r
+                               String displayName = recommendation.getDisplayName();\r
+                               String url = recommendation.getUrl();\r
+\r
+                               Element nodeDescription = doc\r
+                                               .createElementNS(NS, "description");\r
+                               Attr attrRecommendationDescriptionLang = doc.createAttributeNS(\r
+                                               XMLConstants.XML_NS_URI, "lang");\r
+                               attrRecommendationDescriptionLang.setValue(lang);\r
+                               nodeDescription\r
+                                               .setAttributeNodeNS(attrRecommendationDescriptionLang);\r
+                               nodeDescription.setTextContent(displayName);\r
+\r
+                               Element nodeURL = doc.createElementNS(NS, "URL");\r
+                               Attr attrRecommendationURLLang = doc.createAttributeNS(\r
+                                               XMLConstants.XML_NS_URI, "lang");\r
+                               attrRecommendationURLLang.setValue(lang);\r
+                               nodeURL.setAttributeNodeNS(attrRecommendationURLLang);\r
+                               nodeURL.setTextContent(url);\r
+\r
+                               nodeRecommendation.appendChild(nodeDescription);\r
+                               nodeRecommendation.appendChild(nodeURL);\r
+\r
+                               nodeRecommendations.appendChild(nodeRecommendation);\r
+                       }\r
+                       root.appendChild(nodeRecommendations);\r
+               }\r
+\r
+               // presetsのelementを構築する.\r
+               Element nodePresets = doc.createElementNS(NS, "presets");\r
+               if (writePartsSetElements(doc, nodePresets, characterData, true, false) > 0) {\r
+                       root.appendChild(nodePresets);\r
+               }\r
+\r
+               // output xml\r
+               TransformerFactory txFactory = TransformerFactory.newInstance();\r
+               txFactory.setAttribute("indent-number", Integer.valueOf(4));\r
+               Transformer tfmr;\r
+               try {\r
+                       tfmr = txFactory.newTransformer();\r
+               } catch (TransformerConfigurationException ex) {\r
+                       throw new RuntimeException("JAXP Configuration Failed.", ex);\r
+               }\r
+               tfmr.setOutputProperty(OutputKeys.INDENT, "yes");\r
+\r
+               // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4504745\r
+               final String encoding = "UTF-8";\r
+               tfmr.setOutputProperty("encoding", encoding);\r
+               try {\r
+                       tfmr.transform(new DOMSource(doc), new StreamResult(\r
+                                       new OutputStreamWriter(outstm, Charset.forName(encoding))));\r
+\r
+               } catch (TransformerException ex) {\r
+                       IOException ex2 = new IOException("XML Convert failed.");\r
+                       ex2.initCause(ex);\r
+                       throw ex2;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * キャラクターデータ内のPresetおよびFavotiesのPartssetの双方共通のパーツセット要素のリストを構築する.\r
+        * \r
+        * @param doc\r
+        *            ドキュメントオブジェクト(createElementNS用)\r
+        * @param baseElement\r
+        *            親要素、キャラクターデータの場合はPreset、Favoritesの場合はPartssetを示す要素\r
+        * @param characterData\r
+        *            キャラクターデータ\r
+        * @param writePresets\r
+        *            Preset属性のパーツセットを登録する場合はtrue、Preset属性時はデフォルトプリセット属性も(あれば)登録される\r
+        * @param writeFavorites\r
+        *            Preset属性のないパーツセットを登録する場合はtrue\r
+        * @return 登録したパーツセットの個数\r
+        */\r
+       protected int writePartsSetElements(Document doc, Element baseElement,\r
+                       CharacterData characterData, boolean writePresets,\r
+                       boolean writeFavorites) {\r
+               Map<String, PartsSet> partsSetMap = characterData.getPartsSets();\r
+\r
+               Locale locale = Locale.getDefault();\r
+               String lang = locale.getLanguage();\r
+\r
+               HashMap<String, PartsSet> registeredPartsSetMap = new HashMap<String, PartsSet>();\r
+\r
+               for (Map.Entry<String, PartsSet> partsSetsEntry : partsSetMap\r
+                               .entrySet()) {\r
+                       PartsSet partsSet = partsSetsEntry.getValue();\r
+                       if (partsSet.isPresetParts() && !writePresets) {\r
+                               continue;\r
+                       }\r
+                       if (!partsSet.isPresetParts() && !writeFavorites) {\r
+                               continue;\r
+                       }\r
+\r
+                       if (partsSet.isEmpty()) {\r
+                               // 空のパーツセットは登録しない.\r
+                               continue;\r
+                       }\r
+\r
+                       String partsSetId = partsSet.getPartsSetId();\r
+                       String localizedName = partsSet.getLocalizedName();\r
+\r
+                       Element nodePreset = doc.createElementNS(NS, "preset");\r
+                       nodePreset.setAttribute("id", partsSetId);\r
+                       baseElement.appendChild(nodePreset);\r
+                       registeredPartsSetMap.put(partsSet.getPartsSetId(), partsSet);\r
+\r
+                       // display-name\r
+                       Element nodeName = doc.createElementNS(NS, "display-name");\r
+                       Attr attrLang = doc.createAttributeNS(XMLConstants.XML_NS_URI,\r
+                                       "lang");\r
+                       attrLang.setValue(lang);\r
+                       nodeName.setAttributeNode(attrLang);\r
+                       nodeName.setTextContent(localizedName);\r
+                       nodePreset.appendChild(nodeName);\r
+\r
+                       // bgColor\r
+                       Color bgColor = partsSet.getBgColor();\r
+                       if (bgColor != null) {\r
+                               Element nodeBgColor = doc.createElementNS(NS,\r
+                                               "background-color");\r
+                               nodeBgColor.setAttribute("color",\r
+                                               "#" + Integer.toHexString(bgColor.getRGB() & 0xffffff));\r
+                               nodePreset.appendChild(nodeBgColor);\r
+                       }\r
+\r
+                       // affine transform parameter\r
+                       double[] affineTransformParameter = partsSet\r
+                                       .getAffineTransformParameter();\r
+                       if (affineTransformParameter != null) {\r
+                               Element nodeAffineTransform = doc.createElementNS(NS,\r
+                                               "affine-transform-parameter");\r
+                               StringBuilder tmp = new StringBuilder();\r
+                               for (double affineItem : affineTransformParameter) {\r
+                                       if (tmp.length() > 0) {\r
+                                               tmp.append(" ");\r
+                                       }\r
+                                       tmp.append(Double.toString(affineItem));\r
+                               }\r
+                               nodeAffineTransform.setTextContent(tmp.toString());\r
+                               nodePreset.appendChild(nodeAffineTransform);\r
+                       }\r
+\r
+                       // categories\r
+                       for (Map.Entry<PartsCategory, List<PartsIdentifier>> entry : partsSet\r
+                                       .entrySet()) {\r
+                               PartsCategory partsCategory = entry.getKey();\r
+\r
+                               // category\r
+                               Element nodeCategory = doc.createElementNS(NS, "category");\r
+                               nodeCategory.setAttribute("refid",\r
+                                               partsCategory.getCategoryId());\r
+                               nodePreset.appendChild(nodeCategory);\r
+\r
+                               List<PartsIdentifier> partsIdentifiers = entry.getValue();\r
+                               for (PartsIdentifier partsIdentifier : partsIdentifiers) {\r
+                                       String partsName = partsIdentifier.getPartsName();\r
+                                       Element nodeParts = doc.createElementNS(NS, "parts");\r
+                                       nodeParts.setAttribute("name", partsName);\r
+                                       nodeCategory.appendChild(nodeParts);\r
+\r
+                                       PartsColorInfo partsColorInfo = partsSet\r
+                                                       .getColorInfo(partsIdentifier);\r
+                                       if (partsColorInfo != null) {\r
+                                               Element nodeColor = doc.createElementNS(NS, "color");\r
+                                               nodeParts.appendChild(nodeColor);\r
+\r
+                                               for (Map.Entry<Layer, ColorInfo> colorInfoEntry : partsColorInfo\r
+                                                               .entrySet()) {\r
+                                                       Layer layer = colorInfoEntry.getKey();\r
+                                                       ColorInfo colorInfo = colorInfoEntry.getValue();\r
+\r
+                                                       Element nodeLayer = doc\r
+                                                                       .createElementNS(NS, "layer");\r
+                                                       nodeLayer.setAttribute("refid", layer.getId());\r
+                                                       nodeColor.appendChild(nodeLayer);\r
+\r
+                                                       // ColorGroup\r
+                                                       ColorGroup colorGroup = colorInfo.getColorGroup();\r
+                                                       boolean colorSync = colorInfo.isSyncColorGroup();\r
+\r
+                                                       if (colorGroup.isEnabled()) {\r
+                                                               Element nodeColorGroup = doc.createElementNS(\r
+                                                                               NS, "color-group");\r
+                                                               nodeColorGroup.setAttribute("group",\r
+                                                                               colorGroup.getId());\r
+                                                               nodeColorGroup.setAttribute("synchronized",\r
+                                                                               colorSync ? "true" : "false");\r
+                                                               nodeLayer.appendChild(nodeColorGroup);\r
+                                                       }\r
+\r
+                                                       // RGB\r
+                                                       ColorConvertParameter param = colorInfo\r
+                                                                       .getColorParameter();\r
+\r
+                                                       Element nodeRGB = doc.createElementNS(NS, "rgb");\r
+                                                       Object[][] rgbArgss = {\r
+                                                                       {"red", param.getOffsetR(),\r
+                                                                                       param.getFactorR(),\r
+                                                                                       param.getGammaR()},\r
+                                                                       {"green", param.getOffsetG(),\r
+                                                                                       param.getFactorG(),\r
+                                                                                       param.getGammaG()},\r
+                                                                       {"blue", param.getOffsetB(),\r
+                                                                                       param.getFactorB(),\r
+                                                                                       param.getGammaB()},\r
+                                                                       {"alpha", param.getOffsetA(),\r
+                                                                                       param.getFactorA(),\r
+                                                                                       param.getGammaA()},};\r
+                                                       for (Object[] rgbArgs : rgbArgss) {\r
+                                                               Element nodeRGBItem = doc.createElementNS(NS,\r
+                                                                               rgbArgs[0].toString());\r
+                                                               nodeRGBItem.setAttribute("offset",\r
+                                                                               rgbArgs[1].toString());\r
+                                                               nodeRGBItem.setAttribute("factor",\r
+                                                                               rgbArgs[2].toString());\r
+                                                               nodeRGBItem.setAttribute("gamma",\r
+                                                                               rgbArgs[3].toString());\r
+                                                               nodeRGB.appendChild(nodeRGBItem);\r
+                                                       }\r
+                                                       nodeLayer.appendChild(nodeRGB);\r
+\r
+                                                       // HSB\r
+                                                       Element nodeHSB = doc.createElementNS(NS, "hsb");\r
+                                                       nodeHSB.setAttribute("hue",\r
+                                                                       Float.toString(param.getHue()));\r
+                                                       nodeHSB.setAttribute("saturation",\r
+                                                                       Float.toString(param.getSaturation()));\r
+                                                       nodeHSB.setAttribute("brightness",\r
+                                                                       Float.toString(param.getBrightness()));\r
+                                                       if (param.getContrast() != 0.f) {\r
+                                                               // ver0.96追加、optional\r
+                                                               // ぴったり0.0fだったら省略する.\r
+                                                               nodeHSB.setAttribute("contrast",\r
+                                                                               Float.toString(param.getContrast()));\r
+                                                       }\r
+                                                       nodeLayer.appendChild(nodeHSB);\r
+\r
+                                                       // RGB Replace\r
+                                                       Element nodeRGBReplace = doc.createElementNS(NS,\r
+                                                                       "rgb-replace");\r
+                                                       ColorConv colorConv = param.getColorReplace();\r
+                                                       if (colorConv == null) {\r
+                                                               colorConv = ColorConv.NONE;\r
+                                                       }\r
+                                                       nodeRGBReplace.setAttribute("replace-type",\r
+                                                                       colorConv.name());\r
+                                                       nodeRGBReplace.setAttribute("gray",\r
+                                                                       Float.toString(param.getGrayLevel()));\r
+                                                       nodeLayer.appendChild(nodeRGBReplace);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               // プリセット登録時はデフォルトのプリセットIDがあれば、それも登録する.\r
+               // (ただし、該当パーツセットが書き込み済みである場合のみ)\r
+               if (writePresets) {\r
+                       String defaultPresetId = characterData.getDefaultPartsSetId();\r
+                       if (defaultPresetId != null && defaultPresetId.length() > 0) {\r
+                               PartsSet defaultPartsSet = registeredPartsSetMap\r
+                                               .get(defaultPresetId);\r
+                               if (defaultPartsSet != null && defaultPartsSet.isPresetParts()) {\r
+                                       baseElement.setAttribute("default-preset", defaultPresetId);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               return registeredPartsSetMap.size();\r
+       }\r
+}\r
index 0f38ea4..916e73d 100644 (file)
@@ -14,6 +14,7 @@ import java.util.Locale;
 \r
 import charactermanaj.model.CharacterData;\r
 import charactermanaj.model.io.CharacterDataPersistent;\r
+import charactermanaj.model.io.CharacterDataXMLReader;\r
 \r
 /**\r
  * 埋め込みリソースを生成するためのビルド時のヘルパ.<br>\r
@@ -136,9 +137,8 @@ public class MakeEmbeddedResource {
                URL defaultCharacter = getEmbeddedResourceURL(CharacterDataPersistent.DEFAULT_CHARACTER_XML);\r
                InputStream is = defaultCharacter.openStream();\r
                try {\r
-                       CharacterDataPersistent persist = CharacterDataPersistent\r
-                                       .getInstance();\r
-                       cd = persist.loadCharacterDataFromXML(is, null, locale);\r
+                       CharacterDataXMLReader xmlReader = new CharacterDataXMLReader();\r
+                       cd = xmlReader.loadCharacterDataFromXML(is, null, locale);\r
 \r
                } finally {\r
                        is.close();\r
index d2f8954..7cf40e7 100644 (file)
@@ -81,6 +81,7 @@ import charactermanaj.util.UIHelper;
 \r
 /**\r
  * プロファイルを選択するためのダイアログ、およびデフォルトプロファイルを開く\r
+ * \r
  * @author seraphy\r
  */\r
 public class ProfileSelectorDialog extends JDialog {\r
@@ -150,8 +151,11 @@ public class ProfileSelectorDialog extends JDialog {
        \r
        /**\r
         * プロファイルの選択ダイアログを構築する.\r
-        * @param parent 親フレーム、もしくはnull\r
-        * @param characterDatas プロファイルのリスト\r
+        * \r
+        * @param parent\r
+        *            親フレーム、もしくはnull\r
+        * @param characterDatas\r
+        *            プロファイルのリスト\r
         */\r
        public ProfileSelectorDialog(JFrame parent, List<CharacterData> characterDatas) {\r
                super(parent, true);\r
@@ -206,7 +210,12 @@ public class ProfileSelectorDialog extends JDialog {
                });\r
                characterList.addListSelectionListener(new ListSelectionListener() {\r
                        public void valueChanged(ListSelectionEvent e) {\r
-                               updateUIState();\r
+                               if (!e.getValueIsAdjusting()) {\r
+                                       long st = System.currentTimeMillis();\r
+                                       updateUIState();\r
+                                       long en = System.currentTimeMillis();\r
+                                       System.out.println("★切り替え所要時間:" + (en - st));\r
+                               }\r
                        }\r
                });\r
                characterList.addMouseListener(new MouseAdapter() {\r
@@ -612,7 +621,9 @@ public class ProfileSelectorDialog extends JDialog {
        \r
        /**\r
         * サンプルピクチャパネルにドロップされた画像ファイルをサンプルピクチャとしてコピーします.<br>\r
-        * @param dtde ドロップイベント\r
+        * \r
+        * @param dtde\r
+        *            ドロップイベント\r
         */\r
        protected void onDrop(Collection<File> dropFiles) {\r
                Toolkit tk = Toolkit.getDefaultToolkit();\r
@@ -688,7 +699,9 @@ public class ProfileSelectorDialog extends JDialog {
        \r
        /**\r
         * プロファイルの作成\r
-        * @param makeDefault デフォルトのプロファイルで作成する場合\r
+        * \r
+        * @param makeDefault\r
+        *            デフォルトのプロファイルで作成する場合\r
         */\r
        protected void onProfileNew(boolean makeDefault) {\r
                CharacterDataPersistent persist = CharacterDataPersistent.getInstance();\r
index b14b2e7..d8d1c56 100644 (file)
@@ -2,7 +2,7 @@ package charactermanaj.model;
 \r
 import java.net.URI;\r
 \r
-import charactermanaj.model.io.CharacterDataPersistent;\r
+import charactermanaj.model.io.CharacterDataXMLReader;\r
 \r
 public class CharacterDataPersistentTest {\r
 \r
@@ -13,8 +13,7 @@ public class CharacterDataPersistentTest {
        public void run() {\r
                try {\r
                        URI uri = getClass().getResource("character.xml").toURI();\r
-                       CharacterDataPersistent persist = CharacterDataPersistent\r
-                                       .getInstance();\r
+                       CharacterDataXMLReader persist = new CharacterDataXMLReader();\r
                        CharacterData cd = persist.loadCharacterDataFromXML(uri);\r
                        System.out.println("result=" + cd);\r
 \r