import java.io.IOException;\r
import java.io.InputStream;\r
import java.io.OutputStream;\r
-import java.io.OutputStreamWriter;\r
import java.net.URI;\r
import java.net.URL;\r
-import java.nio.charset.Charset;\r
import java.text.SimpleDateFormat;\r
import java.util.ArrayList;\r
-import java.util.Collection;\r
import java.util.Collections;\r
import java.util.Date;\r
-import java.util.HashMap;\r
import java.util.Iterator;\r
-import java.util.LinkedList;\r
import java.util.List;\r
-import java.util.Locale;\r
import java.util.NoSuchElementException;\r
import java.util.concurrent.ExecutionException;\r
import java.util.concurrent.ExecutorService;\r
import java.util.logging.Level;\r
import java.util.logging.Logger;\r
\r
-import javax.xml.XMLConstants;\r
-import javax.xml.namespace.NamespaceContext;\r
-import javax.xml.parsers.DocumentBuilder;\r
-import javax.xml.parsers.DocumentBuilderFactory;\r
-import javax.xml.parsers.ParserConfigurationException;\r
-import javax.xml.parsers.SAXParser;\r
-import javax.xml.parsers.SAXParserFactory;\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
-import javax.xml.validation.Schema;\r
-import javax.xml.validation.SchemaFactory;\r
-import javax.xml.xpath.XPath;\r
-import javax.xml.xpath.XPathFactory;\r
-\r
-import org.w3c.dom.Attr;\r
-import org.w3c.dom.Document;\r
-import org.w3c.dom.Element;\r
import org.w3c.dom.Node;\r
import org.w3c.dom.NodeList;\r
-import org.xml.sax.Attributes;\r
-import org.xml.sax.ErrorHandler;\r
-import org.xml.sax.SAXException;\r
-import org.xml.sax.SAXParseException;\r
-import org.xml.sax.helpers.DefaultHandler;\r
\r
import charactermanaj.graphics.io.FileImageResource;\r
import charactermanaj.graphics.io.ImageLoader;\r
import charactermanaj.model.AppConfig;\r
import charactermanaj.model.CharacterData;\r
import charactermanaj.model.Layer;\r
-import charactermanaj.model.PartsAuthorInfo;\r
import charactermanaj.model.PartsCategory;\r
-import charactermanaj.model.PartsManageData;\r
-import charactermanaj.model.PartsManageData.PartsKey;\r
import charactermanaj.ui.MainFrame;\r
import charactermanaj.util.DirectoryConfig;\r
import charactermanaj.util.FileNameNormalizer;\r
*/\r
private final CharacterDataXMLReader characterDataXmlReader = new CharacterDataXMLReader();\r
\r
+ /**\r
+ * キャラクターデータを格納したXMLのライタ\r
+ */\r
private final CharacterDataXMLWriter characterDataXmlWriter = new CharacterDataXMLWriter();\r
\r
/**\r
*/\r
public static final String VERSION_SIG_1_0 = "1.0";\r
\r
- /**\r
- * キャラクター定義XMLファイルの名前空間\r
- */\r
- public static final String NS = "http://charactermanaj.sourceforge.jp/schema/charactermanaj";\r
-\r
- /**\r
- * パーツ定義XMLファイルの名前空間\r
- */\r
- public static final String NS_PARTSDEF = "http://charactermanaj.sourceforge.jp/schema/charactermanaj-partsdef";\r
-\r
- /**\r
- * キャラクター定義XML用のスキーマ定義リソース名\r
- */\r
- private static final String CHARACTER_XML_SCHEMA = "/schema/character.xsd";\r
-\r
- /**\r
- * キャラクター定義XML用のスキーマ定義リソース名\r
- */\r
- private static final String CHARACTER_XML_SCHEMA_0_8 = "/schema/0.8/character.xsd";\r
-\r
- /**\r
- * パーツセット定義XMLのスキーマ定義リソース名\r
- */\r
- private static final String PARTSSET_XML_SCHEMA = "/schema/partsset.xsd";\r
-\r
- /**\r
- * パーツセット定義XMLのスキーマ定義リソース名\r
- */\r
- private static final String PARTSSET_XML_SCHEMA_0_8 = "/schema/0.8/partsset.xsd";\r
-\r
- /**\r
- * XMLのデータ形式.<br>\r
- * SchemaのバリデージョンチェックとDOMの解析を始める前にSAXで流し込んで、\r
- * 最初のエレメント名や使用している名前空間、バージョンを読み込んで、 スキーマをきりかえられるようにするためのもの.\r
- * \r
- * @author seraphy\r
- */\r
- public static class DocInfo {\r
-\r
- private String firstElementName;\r
-\r
- private String version;\r
-\r
- private String namespace;\r
-\r
- public void setFirstElementName(String firstElementName) {\r
- this.firstElementName = firstElementName;\r
- }\r
-\r
- /**\r
- * 最初の要素のqName\r
- * \r
- * @return\r
- */\r
- public String getFirstElementName() {\r
- return firstElementName;\r
- }\r
-\r
- public void setNamespace(String namespace) {\r
- this.namespace = namespace;\r
- }\r
-\r
- public void setVersion(String version) {\r
- this.version = version;\r
- }\r
-\r
- /**\r
- * 最初の要素に指定されているxmlns属性の値\r
- * \r
- * @param namespace\r
- */\r
- public String getNamespace() {\r
- return namespace;\r
- }\r
-\r
- /**\r
- * 最初の要素に指定されているversion属性の値\r
- * \r
- * @return\r
- */\r
- public String getVersion() {\r
- return version;\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return firstElementName + " /version: " + version + " /namespace:"\r
- + namespace;\r
- }\r
- }\r
\r
/**\r
* プロファイルの列挙時のエラーハンドラ.<br>\r
}\r
\r
/**\r
- * プロファイル列挙時のデフォルトのエラーハンドラ.<br>\r
- * 標準エラー出力にメッセージをプリントするだけで何もしない.<br>\r
- */\r
- public static final ProfileListErrorHandler DEFAULT_ERROR_HANDLER = new ProfileListErrorHandler() {\r
- public void occureException(File baseDir, Throwable ex) {\r
- logger.log(Level.WARNING, "invalid profile. :" + baseDir, ex);\r
- }\r
- };\r
-\r
- /**\r
- * スキーマのキャッシュ.\r
- */\r
- private HashMap<String, Schema> schemaMap = new HashMap<String, Schema>();\r
-\r
- /**\r
- * JAXPで使用するデフォルトのエラーハンドラ\r
- */\r
- private static final ErrorHandler errorHandler = new ErrorHandler() {\r
- public void error(SAXParseException exception) throws SAXException {\r
- throw exception;\r
- }\r
- public void fatalError(SAXParseException exception) throws SAXException {\r
- throw exception;\r
- }\r
- public void warning(SAXParseException exception) throws SAXException {\r
- throw exception;\r
- }\r
- };\r
-\r
- /**\r
* プライベートコンストラクタ.<br>\r
* シングルトン実装であるため、一度だけ呼び出される.\r
*/\r
return characterData;\r
}\r
\r
-\r
- /**\r
- * XMLの最初の要素と、その要素の属性にあるversionとxmlnsを取得して返す.<br>\r
- * XMLとして不正などの理由で取得できない場合はnullを返す.<br>\r
- * 読み込みそのものに失敗した場合は例外を返す.<br>\r
- * \r
- * @param is\r
- * XMLコンテンツと想定される入力ストリーム\r
- * @return DocInfo情報、もしくはnull\r
- * @throws IOException\r
- * 読み込みに失敗した場合\r
- */\r
- public DocInfo readDocumentType(InputStream is) throws IOException {\r
-\r
- SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();\r
- SAXParser saxParser;\r
- try {\r
- saxParser = saxParserFactory.newSAXParser();\r
- } catch (ParserConfigurationException ex) {\r
- throw new RuntimeException("JAXP Configuration Exception.", ex);\r
- } catch (SAXException ex) {\r
- throw new RuntimeException("JAXP Configuration Exception.", ex);\r
- }\r
-\r
- try {\r
- final DocInfo[] result = new DocInfo[1];\r
- saxParser.parse(is, new DefaultHandler() {\r
- private int elmCount = 0;\r
- @Override\r
- public void startElement(String uri, String localName,\r
- String qName, Attributes attributes)\r
- throws SAXException {\r
- if (elmCount == 0) {\r
- String version = attributes.getValue("version");\r
- String namespace = attributes.getValue("xmlns");\r
- DocInfo docInfo = new DocInfo();\r
- docInfo.setFirstElementName(qName);\r
- docInfo.setVersion(version);\r
- docInfo.setNamespace(namespace);\r
- result[0] = docInfo;\r
- }\r
- elmCount++;\r
- }\r
- });\r
- return result[0];\r
-\r
- } catch (SAXException ex) {\r
- logger.log(Level.INFO, "character.xml check failed.", ex);\r
- }\r
- return null;\r
- }\r
-\r
-\r
protected void saveCharacterDataToXML(CharacterData characterData)\r
throws IOException {\r
if (characterData == null) {\r
UserData favoritesData = getFavoritesUserData(characterData);\r
OutputStream os = favoritesData.getOutputStream();\r
try {\r
- saveFavorites(characterData, os);\r
+ characterDataXmlWriter.saveFavorites(characterData, os);\r
\r
} finally {\r
os.close();\r
return new FileUserData(new File(characterDir, "favorites.xml"));\r
}\r
\r
- protected void saveFavorites(CharacterData characterData,\r
- OutputStream outstm) throws IOException {\r
- if (characterData == null || outstm == null) {\r
- throw new IllegalArgumentException();\r
- }\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
-\r
- } catch (ParserConfigurationException ex) {\r
- throw new RuntimeException("JAXP Configuration Exception.", ex);\r
- }\r
-\r
- Element root = doc.createElementNS(NS, "partssets");\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 + " partsset.xsd");\r
- doc.appendChild(root);\r
-\r
- // presetsのelementを構築する.(Presetは除く)\r
- characterDataXmlWriter.writePartsSetElements(doc, root, characterData,\r
- false, true);\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
/**\r
* お気に入り(Favorites)を読み込む.<br>\r
};\r
}\r
\r
- protected Schema loadSchema(DocInfo docInfo) throws IOException {\r
- if (docInfo == null) {\r
- throw new IllegalArgumentException();\r
- }\r
-\r
- String schemaName = null;\r
- if ("character".equals(docInfo.getFirstElementName())) {\r
- if ("http://com.exmaple/charactermanaj".equals(docInfo\r
- .getNamespace())) {\r
- schemaName = CHARACTER_XML_SCHEMA_0_8;\r
- } else if ("http://charactermanaj.sourceforge.jp/schema/charactermanaj"\r
- .equals(docInfo.getNamespace())) {\r
- schemaName = CHARACTER_XML_SCHEMA;\r
- }\r
- } else if ("partssets".equals(docInfo.getFirstElementName())) {\r
- if ("http://com.exmaple/charactermanaj".equals(docInfo\r
- .getNamespace())) {\r
- schemaName = PARTSSET_XML_SCHEMA_0_8;\r
- } else if ("http://charactermanaj.sourceforge.jp/schema/charactermanaj"\r
- .equals(docInfo.getNamespace())) {\r
- schemaName = PARTSSET_XML_SCHEMA;\r
- }\r
- }\r
- if (schemaName == null) {\r
- throw new IOException("unsupported namespace: " + docInfo);\r
- }\r
-\r
- Schema schema = schemaMap.get(schemaName);\r
- if (schema != null) {\r
- return schema;\r
- }\r
-\r
- URL schemaURL = null;\r
- try {\r
- SchemaFactory schemaFactory = SchemaFactory\r
- .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);\r
- schemaFactory.setErrorHandler(errorHandler);\r
- schemaURL = getEmbeddedResourceURL(schemaName);\r
- schema = schemaFactory.newSchema(schemaURL);\r
- schemaMap.put(schemaName, schema);\r
- return schema;\r
-\r
- } catch (Exception ex) {\r
- throw new RuntimeException("schema creation failed. :" + schemaURL,\r
- ex);\r
- }\r
- }\r
-\r
protected URL getEmbeddedResourceURL(String schemaName) {\r
return this.getClass().getResource(schemaName);\r
}\r
\r
- protected XPath createXPath(DocInfo docInfo) {\r
- if (docInfo == null) {\r
- throw new IllegalArgumentException();\r
- }\r
-\r
- final String namespace;\r
- if (docInfo.getNamespace() != null\r
- && docInfo.getNamespace().length() > 0) {\r
- namespace = docInfo.getNamespace();\r
- } else {\r
- namespace = NS;\r
- }\r
-\r
- XPathFactory xpathFactory = XPathFactory.newInstance();\r
- XPath xpath = xpathFactory.newXPath();\r
- xpath.setNamespaceContext(new NamespaceContext() {\r
- public String getNamespaceURI(String prefix) {\r
- if (prefix == null) {\r
- throw new IllegalArgumentException();\r
- }\r
- if (prefix.equals("pre")) {\r
- return namespace;\r
- }\r
- if (prefix.equals("xml")) {\r
- return XMLConstants.XML_NS_URI;\r
- }\r
- return XMLConstants.NULL_NS_URI;\r
- }\r
- public Iterator<?> getPrefixes(String namespaceURI) {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- public String getPrefix(String namespaceURI) {\r
- throw new UnsupportedOperationException();\r
- }\r
- });\r
- return xpath;\r
- }\r
-\r
/**\r
* サンプルピクチャを読み込む.<br>\r
* ピクチャが存在しなければnullを返す. キャラクター定義がValidでない場合は常にnullを返す.<br>\r
}\r
}\r
\r
- /**\r
- * パーツ管理情報をDocBaseと同じフォルダ上のparts-info.xmlに書き出す.<br>\r
- * XML生成中に失敗した場合は既存の管理情報は残される.<br>\r
- * (管理情報の書き込み中にI/O例外が発生した場合は管理情報は破壊される.)<br>\r
- * \r
- * @param docBase\r
- * character.xmlの位置\r
- * @param partsManageData\r
- * パーツ管理情報\r
- * @throws IOException\r
- * 出力に失敗した場合\r
- */\r
- public void savePartsManageData(URI docBase, PartsManageData partsManageData)\r
- throws IOException {\r
- if (docBase == null || partsManageData == null) {\r
- throw new IllegalArgumentException();\r
- }\r
-\r
- if (!"file".equals(docBase.getScheme())) {\r
- throw new IOException("ファイル以外はサポートしていません: " + docBase);\r
- }\r
- File docBaseFile = new File(docBase);\r
- File baseDir = docBaseFile.getParentFile();\r
-\r
- // データからXMLを構築してストリームに出力する.\r
- // 完全に成功したXMLのみ書き込むようにするため、一旦バッファする。\r
- ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
- try {\r
- savePartsManageData(partsManageData, bos);\r
- } finally {\r
- bos.close();\r
- }\r
-\r
- // バッファされたXMLデータを実際のファイルに書き込む\r
- File partsInfoXML = new File(baseDir, "parts-info.xml");\r
- FileOutputStream os = new FileOutputStream(partsInfoXML);\r
- try {\r
- os.write(bos.toByteArray());\r
- } finally {\r
- os.close();\r
- }\r
- }\r
-\r
- /**\r
- * パーツ管理情報をXMLとしてストリームに書き出す.<br>\r
- * \r
- * @param partsManageData\r
- * パーツ管理データ\r
- * @param outstm\r
- * 出力先ストリーム\r
- * @throws IOException\r
- * 出力に失敗した場合\r
- */\r
- public void savePartsManageData(PartsManageData partsManageData,\r
- OutputStream outstm) throws IOException {\r
- if (partsManageData == null || outstm == null) {\r
- throw new IllegalArgumentException();\r
- }\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
-\r
- } catch (ParserConfigurationException ex) {\r
- throw new RuntimeException("JAXP Configuration Exception.", ex);\r
- }\r
-\r
- Locale locale = Locale.getDefault();\r
- String lang = locale.getLanguage();\r
-\r
- Element root = doc.createElementNS(NS_PARTSDEF, "parts-definition");\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_PARTSDEF\r
- + " parts-definition.xsd");\r
- doc.appendChild(root);\r
-\r
- // 作者情報を取得する\r
- Collection<PartsAuthorInfo> partsAuthors = partsManageData\r
- .getAuthorInfos();\r
- for (PartsAuthorInfo partsAuthorInfo : partsAuthors) {\r
- String author = partsAuthorInfo.getAuthor();\r
- if (author == null || author.length() == 0) {\r
- continue;\r
- }\r
-\r
- // 作者情報の登録\r
- Element nodeAuthor = doc.createElementNS(NS_PARTSDEF, "author");\r
- Element nodeAuthorName = doc.createElementNS(NS_PARTSDEF, "name");\r
- Attr attrLang = doc.createAttributeNS(XMLConstants.XML_NS_URI,\r
- "lang");\r
- attrLang.setValue(lang);\r
- nodeAuthorName.setAttributeNodeNS(attrLang);\r
- nodeAuthorName.setTextContent(author);\r
- nodeAuthor.appendChild(nodeAuthorName);\r
-\r
- String homepageURL = partsAuthorInfo.getHomePage();\r
- if (homepageURL != null && homepageURL.length() > 0) {\r
- Element nodeHomepage = doc.createElementNS(NS_PARTSDEF,\r
- "home-page");\r
- Attr attrHomepageLang = doc.createAttributeNS(\r
- XMLConstants.XML_NS_URI, "lang");\r
- attrHomepageLang.setValue(lang);\r
- nodeHomepage.setAttributeNodeNS(attrHomepageLang);\r
- nodeHomepage.setTextContent(homepageURL);\r
- nodeAuthor.appendChild(nodeHomepage);\r
- }\r
-\r
- root.appendChild(nodeAuthor);\r
-\r
- Collection<PartsKey> partsKeys = partsManageData\r
- .getPartsKeysByAuthor(author);\r
-\r
- // ダウンロード別にパーツキーの集約\r
- HashMap<String, List<PartsKey>> downloadMap = new HashMap<String, List<PartsKey>>();\r
- for (PartsKey partsKey : partsKeys) {\r
- PartsManageData.PartsVersionInfo versionInfo = partsManageData\r
- .getVersionStrict(partsKey);\r
- String downloadURL = versionInfo.getDownloadURL();\r
- if (downloadURL == null) {\r
- downloadURL = "";\r
- }\r
- List<PartsKey> partsKeyGrp = downloadMap.get(downloadURL);\r
- if (partsKeyGrp == null) {\r
- partsKeyGrp = new ArrayList<PartsKey>();\r
- downloadMap.put(downloadURL, partsKeyGrp);\r
- }\r
- partsKeyGrp.add(partsKey);\r
- }\r
-\r
- // ダウンロード別にパーツ情報の登録\r
- ArrayList<String> downloadURLs = new ArrayList<String>(\r
- downloadMap.keySet());\r
- Collections.sort(downloadURLs);\r
-\r
- for (String downloadURL : downloadURLs) {\r
- List<PartsKey> partsKeyGrp = downloadMap.get(downloadURL);\r
- Collections.sort(partsKeyGrp);\r
-\r
- Element nodeDownload = doc.createElementNS(NS_PARTSDEF,\r
- "download-url");\r
- nodeDownload.setTextContent(downloadURL);\r
- root.appendChild(nodeDownload);\r
-\r
- for (PartsKey partsKey : partsKeyGrp) {\r
- PartsManageData.PartsVersionInfo versionInfo = partsManageData\r
- .getVersionStrict(partsKey);\r
-\r
- Element nodeParts = doc.createElementNS(NS_PARTSDEF,\r
- "parts");\r
-\r
- nodeParts.setAttribute("name", partsKey.getPartsName());\r
- if (partsKey.getCategoryId() != null) {\r
- nodeParts.setAttribute("category",\r
- partsKey.getCategoryId());\r
- }\r
- if (versionInfo.getVersion() > 0) {\r
- nodeParts.setAttribute("version",\r
- Double.toString(versionInfo.getVersion()));\r
- }\r
-\r
- String localizedName = partsManageData\r
- .getLocalizedName(partsKey);\r
- if (localizedName != null\r
- && localizedName.trim().length() > 0) {\r
- Element nodeLocalizedName = doc.createElementNS(\r
- NS_PARTSDEF, "local-name");\r
- Attr attrLocalizedNameLang = doc.createAttributeNS(\r
- XMLConstants.XML_NS_URI, "lang");\r
- attrLocalizedNameLang.setValue(lang);\r
- nodeLocalizedName\r
- .setAttributeNodeNS(attrLocalizedNameLang);\r
- nodeLocalizedName.setTextContent(localizedName);\r
- nodeParts.appendChild(nodeLocalizedName);\r
- }\r
-\r
- root.appendChild(nodeParts);\r
- }\r
- }\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
- * 指定したDocBaseと同じフォルダにあるparts-info.xmlからパーツ管理情報を取得して返す.<br>\r
- * ファイルが存在しない場合は空のインスタンスを返す.<br>\r
- * 返されるインスタンスは編集可能です.<br>\r
- * \r
- * @param docBase\r
- * character.xmlの位置\r
- * @return パーツ管理情報、存在しない場合は空のインスタンス\r
- * @throws IOException\r
- * 読み込み中に失敗した場合\r
- */\r
- public PartsManageData loadPartsManageData(URI docBase) throws IOException {\r
- if (docBase == null) {\r
- throw new IllegalArgumentException();\r
- }\r
- if (!"file".equals(docBase.getScheme())) {\r
- throw new IOException("ファイル以外はサポートしていません。:" + docBase);\r
- }\r
- File docBaseFile = new File(docBase);\r
- File baseDir = docBaseFile.getParentFile();\r
-\r
- // パーツ管理情報ファイルの確認\r
- final File partsInfoXML = new File(baseDir, "parts-info.xml");\r
- if (!partsInfoXML.exists()) {\r
- // ファイルが存在しなければ空を返す.\r
- return new PartsManageData();\r
- }\r
-\r
- PartsManageData partsManageData;\r
- InputStream is = new FileInputStream(partsInfoXML);\r
- try {\r
- partsManageData = loadPartsManageData(is);\r
- } finally {\r
- is.close();\r
- }\r
- return partsManageData;\r
- }\r
-\r
- public PartsManageData loadPartsManageData(InputStream is)\r
- throws IOException {\r
- if (is == null) {\r
- throw new IllegalArgumentException();\r
- }\r
-\r
- // パーツ管理情報\r
- final PartsManageData partsManageData = new PartsManageData();\r
-\r
- // SAXParserの準備\r
- SAXParser saxParser;\r
- try {\r
- SAXParserFactory saxPartserFactory = SAXParserFactory.newInstance();\r
- saxPartserFactory.setNamespaceAware(true);\r
- saxParser = saxPartserFactory.newSAXParser();\r
- } catch (Exception ex) {\r
- throw new RuntimeException("JAXP Configuration failed.", ex);\r
- }\r
-\r
- // デフォルトのロケールから言語を取得\r
- final Locale locale = Locale.getDefault();\r
- final String lang = locale.getLanguage();\r
-\r
- try {\r
- // 要素のスタック\r
- final LinkedList<String> stack = new LinkedList<String>();\r
-\r
- // DOMではなくSAXで読み流す.\r
- saxParser.parse(is, new DefaultHandler() {\r
- private StringBuilder buf = new StringBuilder();\r
-\r
- private PartsAuthorInfo partsAuthorInfo;\r
-\r
- private String authorName;\r
- private String homepageURL;\r
- private String authorNameLang;\r
- private String homepageLang;\r
- private String downloadURL;\r
-\r
- private String partsLocalNameLang;\r
- private String partsLocalName;\r
- private String partsCategoryId;\r
- private String partsName;\r
- private double partsVersion;\r
-\r
- @Override\r
- public void startDocument() throws SAXException {\r
- logger.log(Level.FINEST, "parts-info : start");\r
- }\r
-\r
- @Override\r
- public void endDocument() throws SAXException {\r
- logger.log(Level.FINEST, "parts-info : end");\r
- }\r
-\r
- @Override\r
- public void characters(char[] ch, int start, int length)\r
- throws SAXException {\r
- buf.append(ch, start, length);\r
- }\r
- @Override\r
- public void startElement(String uri, String localName,\r
- String qName, Attributes attributes)\r
- throws SAXException {\r
- stack.addFirst(qName);\r
- int mx = stack.size();\r
- if (mx >= 2 && stack.get(1).equals("parts")) {\r
- if ("local-name".equals(qName)) {\r
- partsLocalNameLang = attributes.getValue(\r
- XMLConstants.XML_NS_URI, "lang");\r
- }\r
-\r
- } else if (mx >= 2 && stack.get(1).equals("author")) {\r
- if ("name".equals(qName)) {\r
- authorNameLang = attributes.getValue(\r
- XMLConstants.XML_NS_URI, "lang");\r
-\r
- } else if ("home-page".equals(qName)) {\r
- homepageLang = attributes.getValue(\r
- XMLConstants.XML_NS_URI, "lang");\r
- }\r
-\r
- } else if ("author".equals(qName)) {\r
- partsAuthorInfo = null;\r
- authorName = null;\r
- authorNameLang = null;\r
- homepageURL = null;\r
- homepageLang = null;\r
-\r
- } else if ("download-url".equals(qName)) {\r
- downloadURL = null;\r
-\r
- } else if ("parts".equals(qName)) {\r
- partsLocalName = null;\r
- partsLocalNameLang = null;\r
- partsCategoryId = attributes.getValue("category");\r
- partsName = attributes.getValue("name");\r
- String strVersion = attributes.getValue("version");\r
- try {\r
- if (strVersion == null || strVersion.length() == 0) {\r
- partsVersion = 0.;\r
-\r
- } else {\r
- partsVersion = Double.parseDouble(strVersion);\r
- if (partsVersion < 0) {\r
- partsVersion = 0;\r
- }\r
- }\r
-\r
- } catch (Exception ex) {\r
- logger.log(Level.INFO,\r
- "parts-info.xml: invalid version."\r
- + strVersion);\r
- partsVersion = 0;\r
- }\r
- }\r
-\r
- buf = new StringBuilder();\r
- }\r
- @Override\r
- public void endElement(String uri, String localName,\r
- String qName) throws SAXException {\r
-\r
- int mx = stack.size();\r
-\r
- if (mx >= 2 && "parts".equals(stack.get(1))) {\r
- if ("local-name".equals(qName)) {\r
- if (partsLocalName == null\r
- || lang.equals(partsLocalNameLang)) {\r
- partsLocalName = buf.toString();\r
- }\r
- }\r
-\r
- } else if (mx >= 2 && "author".equals(stack.get(1))) {\r
- if ("name".equals(qName)) {\r
- if (authorName == null\r
- || lang.equals(authorNameLang)) {\r
- authorName = buf.toString();\r
- }\r
-\r
- } else if ("home-page".equals(qName)) {\r
- if (homepageURL == null\r
- || lang.equals(homepageLang)) {\r
- homepageURL = buf.toString();\r
- }\r
- }\r
-\r
- } else if ("author".equals(qName)) {\r
- logger.log(Level.FINE, "parts-info: author: "\r
- + authorName + " /homepage:" + homepageURL);\r
- if (authorName != null && authorName.length() > 0) {\r
- partsAuthorInfo = new PartsAuthorInfo();\r
- partsAuthorInfo.setAuthor(authorName);\r
- partsAuthorInfo.setHomePage(homepageURL);\r
-\r
- } else {\r
- partsAuthorInfo = null;\r
- }\r
-\r
- } else if ("download-url".equals(qName)) {\r
- downloadURL = buf.toString();\r
- logger.log(Level.FINE, "parts-info: download-url: "\r
- + downloadURL);\r
-\r
- } else if ("parts".equals(qName)) {\r
- if (logger.isLoggable(Level.FINE)) {\r
- logger.log(Level.FINE,\r
- "parts-info.xml: parts-name: " + partsName\r
- + " /category: " + partsCategoryId\r
- + " /parts-local-name: "\r
- + partsLocalName + " /version:"\r
- + partsVersion);\r
- }\r
-\r
- PartsManageData.PartsVersionInfo versionInfo = new PartsManageData.PartsVersionInfo();\r
- versionInfo.setVersion(partsVersion);\r
- versionInfo.setDownloadURL(downloadURL);\r
\r
- PartsManageData.PartsKey partsKey = new PartsManageData.PartsKey(\r
- partsName, partsCategoryId);\r
-\r
- partsManageData.putPartsInfo(partsKey, partsLocalName,\r
- partsAuthorInfo, versionInfo);\r
-\r
- }\r
- stack.removeFirst();\r
- }\r
- });\r
-\r
- } catch (SAXException ex) {\r
- IOException ex2 = new IOException("parts-info.xml read failed.");\r
- ex2.initCause(ex);\r
- throw ex2;\r
- }\r
-\r
- return partsManageData;\r
- }\r
\r
\r
/**\r
--- /dev/null
+package charactermanaj.model.io;\r
+\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.net.URI;\r
+import java.util.LinkedList;\r
+import java.util.Locale;\r
+import java.util.logging.Level;\r
+import java.util.logging.Logger;\r
+\r
+import javax.xml.XMLConstants;\r
+import javax.xml.parsers.SAXParser;\r
+import javax.xml.parsers.SAXParserFactory;\r
+\r
+import org.xml.sax.Attributes;\r
+import org.xml.sax.SAXException;\r
+import org.xml.sax.helpers.DefaultHandler;\r
+\r
+import charactermanaj.model.PartsAuthorInfo;\r
+import charactermanaj.model.PartsManageData;\r
+\r
+/**\r
+ * パーツ管理情報のXMLの読み込み用クラス.\r
+ * \r
+ * @author seraphy\r
+ */\r
+public class PartsInfoXMLReader {\r
+\r
+ /**\r
+ * ロガー\r
+ */\r
+ private static final Logger logger = Logger\r
+ .getLogger(PartsInfoXMLReader.class.getName());\r
+\r
+ /**\r
+ * 指定したDocBaseと同じフォルダにあるparts-info.xmlからパーツ管理情報を取得して返す.<br>\r
+ * ファイルが存在しない場合は空のインスタンスを返す.<br>\r
+ * 返されるインスタンスは編集可能です.<br>\r
+ * \r
+ * @param docBase\r
+ * character.xmlの位置\r
+ * @return パーツ管理情報、存在しない場合は空のインスタンス\r
+ * @throws IOException\r
+ * 読み込み中に失敗した場合\r
+ */\r
+ public PartsManageData loadPartsManageData(URI docBase) throws IOException {\r
+ if (docBase == null) {\r
+ throw new IllegalArgumentException();\r
+ }\r
+ if (!"file".equals(docBase.getScheme())) {\r
+ throw new IOException("ファイル以外はサポートしていません。:" + docBase);\r
+ }\r
+ File docBaseFile = new File(docBase);\r
+ File baseDir = docBaseFile.getParentFile();\r
+\r
+ // パーツ管理情報ファイルの確認\r
+ final File partsInfoXML = new File(baseDir, "parts-info.xml");\r
+ if (!partsInfoXML.exists()) {\r
+ // ファイルが存在しなければ空を返す.\r
+ return new PartsManageData();\r
+ }\r
+\r
+ PartsManageData partsManageData;\r
+ InputStream is = new FileInputStream(partsInfoXML);\r
+ try {\r
+ partsManageData = loadPartsManageData(is);\r
+ } finally {\r
+ is.close();\r
+ }\r
+ return partsManageData;\r
+ }\r
+\r
+ public PartsManageData loadPartsManageData(InputStream is)\r
+ throws IOException {\r
+ if (is == null) {\r
+ throw new IllegalArgumentException();\r
+ }\r
+\r
+ // パーツ管理情報\r
+ final PartsManageData partsManageData = new PartsManageData();\r
+\r
+ // SAXParserの準備\r
+ SAXParser saxParser;\r
+ try {\r
+ SAXParserFactory saxPartserFactory = SAXParserFactory.newInstance();\r
+ saxPartserFactory.setNamespaceAware(true);\r
+ saxParser = saxPartserFactory.newSAXParser();\r
+ } catch (Exception ex) {\r
+ throw new RuntimeException("JAXP Configuration failed.", ex);\r
+ }\r
+\r
+ // デフォルトのロケールから言語を取得\r
+ final Locale locale = Locale.getDefault();\r
+ final String lang = locale.getLanguage();\r
+\r
+ try {\r
+ // 要素のスタック\r
+ final LinkedList<String> stack = new LinkedList<String>();\r
+\r
+ // DOMではなくSAXで読み流す.\r
+ saxParser.parse(is, new DefaultHandler() {\r
+ private StringBuilder buf = new StringBuilder();\r
+\r
+ private PartsAuthorInfo partsAuthorInfo;\r
+\r
+ private String authorName;\r
+ private String homepageURL;\r
+ private String authorNameLang;\r
+ private String homepageLang;\r
+ private String downloadURL;\r
+\r
+ private String partsLocalNameLang;\r
+ private String partsLocalName;\r
+ private String partsCategoryId;\r
+ private String partsName;\r
+ private double partsVersion;\r
+\r
+ @Override\r
+ public void startDocument() throws SAXException {\r
+ logger.log(Level.FINEST, "parts-info : start");\r
+ }\r
+\r
+ @Override\r
+ public void endDocument() throws SAXException {\r
+ logger.log(Level.FINEST, "parts-info : end");\r
+ }\r
+\r
+ @Override\r
+ public void characters(char[] ch, int start, int length)\r
+ throws SAXException {\r
+ buf.append(ch, start, length);\r
+ }\r
+ @Override\r
+ public void startElement(String uri, String localName,\r
+ String qName, Attributes attributes)\r
+ throws SAXException {\r
+ stack.addFirst(qName);\r
+ int mx = stack.size();\r
+ if (mx >= 2 && stack.get(1).equals("parts")) {\r
+ if ("local-name".equals(qName)) {\r
+ partsLocalNameLang = attributes.getValue(\r
+ XMLConstants.XML_NS_URI, "lang");\r
+ }\r
+\r
+ } else if (mx >= 2 && stack.get(1).equals("author")) {\r
+ if ("name".equals(qName)) {\r
+ authorNameLang = attributes.getValue(\r
+ XMLConstants.XML_NS_URI, "lang");\r
+\r
+ } else if ("home-page".equals(qName)) {\r
+ homepageLang = attributes.getValue(\r
+ XMLConstants.XML_NS_URI, "lang");\r
+ }\r
+\r
+ } else if ("author".equals(qName)) {\r
+ partsAuthorInfo = null;\r
+ authorName = null;\r
+ authorNameLang = null;\r
+ homepageURL = null;\r
+ homepageLang = null;\r
+\r
+ } else if ("download-url".equals(qName)) {\r
+ downloadURL = null;\r
+\r
+ } else if ("parts".equals(qName)) {\r
+ partsLocalName = null;\r
+ partsLocalNameLang = null;\r
+ partsCategoryId = attributes.getValue("category");\r
+ partsName = attributes.getValue("name");\r
+ String strVersion = attributes.getValue("version");\r
+ try {\r
+ if (strVersion == null || strVersion.length() == 0) {\r
+ partsVersion = 0.;\r
+\r
+ } else {\r
+ partsVersion = Double.parseDouble(strVersion);\r
+ if (partsVersion < 0) {\r
+ partsVersion = 0;\r
+ }\r
+ }\r
+\r
+ } catch (Exception ex) {\r
+ logger.log(Level.INFO,\r
+ "parts-info.xml: invalid version."\r
+ + strVersion);\r
+ partsVersion = 0;\r
+ }\r
+ }\r
+\r
+ buf = new StringBuilder();\r
+ }\r
+ @Override\r
+ public void endElement(String uri, String localName,\r
+ String qName) throws SAXException {\r
+\r
+ int mx = stack.size();\r
+\r
+ if (mx >= 2 && "parts".equals(stack.get(1))) {\r
+ if ("local-name".equals(qName)) {\r
+ if (partsLocalName == null\r
+ || lang.equals(partsLocalNameLang)) {\r
+ partsLocalName = buf.toString();\r
+ }\r
+ }\r
+\r
+ } else if (mx >= 2 && "author".equals(stack.get(1))) {\r
+ if ("name".equals(qName)) {\r
+ if (authorName == null\r
+ || lang.equals(authorNameLang)) {\r
+ authorName = buf.toString();\r
+ }\r
+\r
+ } else if ("home-page".equals(qName)) {\r
+ if (homepageURL == null\r
+ || lang.equals(homepageLang)) {\r
+ homepageURL = buf.toString();\r
+ }\r
+ }\r
+\r
+ } else if ("author".equals(qName)) {\r
+ logger.log(Level.FINE, "parts-info: author: "\r
+ + authorName + " /homepage:" + homepageURL);\r
+ if (authorName != null && authorName.length() > 0) {\r
+ partsAuthorInfo = new PartsAuthorInfo();\r
+ partsAuthorInfo.setAuthor(authorName);\r
+ partsAuthorInfo.setHomePage(homepageURL);\r
+\r
+ } else {\r
+ partsAuthorInfo = null;\r
+ }\r
+\r
+ } else if ("download-url".equals(qName)) {\r
+ downloadURL = buf.toString();\r
+ logger.log(Level.FINE, "parts-info: download-url: "\r
+ + downloadURL);\r
+\r
+ } else if ("parts".equals(qName)) {\r
+ if (logger.isLoggable(Level.FINE)) {\r
+ logger.log(Level.FINE,\r
+ "parts-info.xml: parts-name: " + partsName\r
+ + " /category: " + partsCategoryId\r
+ + " /parts-local-name: "\r
+ + partsLocalName + " /version:"\r
+ + partsVersion);\r
+ }\r
+\r
+ PartsManageData.PartsVersionInfo versionInfo = new PartsManageData.PartsVersionInfo();\r
+ versionInfo.setVersion(partsVersion);\r
+ versionInfo.setDownloadURL(downloadURL);\r
+\r
+ PartsManageData.PartsKey partsKey = new PartsManageData.PartsKey(\r
+ partsName, partsCategoryId);\r
+\r
+ partsManageData.putPartsInfo(partsKey, partsLocalName,\r
+ partsAuthorInfo, versionInfo);\r
+\r
+ }\r
+ stack.removeFirst();\r
+ }\r
+ });\r
+\r
+ } catch (SAXException ex) {\r
+ IOException ex2 = new IOException("parts-info.xml read failed.");\r
+ ex2.initCause(ex);\r
+ throw ex2;\r
+ }\r
+\r
+ return partsManageData;\r
+ }\r
+}\r
--- /dev/null
+package charactermanaj.model.io;\r
+\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.File;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.io.OutputStreamWriter;\r
+import java.net.URI;\r
+import java.nio.charset.Charset;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Locale;\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.model.PartsAuthorInfo;\r
+import charactermanaj.model.PartsManageData;\r
+import charactermanaj.model.PartsManageData.PartsKey;\r
+\r
+public class PartsInfoXMLWriter {\r
+\r
+ /**\r
+ * パーツ定義XMLファイルの名前空間\r
+ */\r
+ public static final String NS_PARTSDEF = "http://charactermanaj.sourceforge.jp/schema/charactermanaj-partsdef";\r
+\r
+ /**\r
+ * パーツ管理情報をDocBaseと同じフォルダ上のparts-info.xmlに書き出す.<br>\r
+ * XML生成中に失敗した場合は既存の管理情報は残される.<br>\r
+ * (管理情報の書き込み中にI/O例外が発生した場合は管理情報は破壊される.)<br>\r
+ * \r
+ * @param docBase\r
+ * character.xmlの位置\r
+ * @param partsManageData\r
+ * パーツ管理情報\r
+ * @throws IOException\r
+ * 出力に失敗した場合\r
+ */\r
+ public void savePartsManageData(URI docBase, PartsManageData partsManageData)\r
+ throws IOException {\r
+ if (docBase == null || partsManageData == null) {\r
+ throw new IllegalArgumentException();\r
+ }\r
+\r
+ if (!"file".equals(docBase.getScheme())) {\r
+ throw new IOException("ファイル以外はサポートしていません: " + docBase);\r
+ }\r
+ File docBaseFile = new File(docBase);\r
+ File baseDir = docBaseFile.getParentFile();\r
+\r
+ // データからXMLを構築してストリームに出力する.\r
+ // 完全に成功したXMLのみ書き込むようにするため、一旦バッファする。\r
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
+ try {\r
+ savePartsManageData(partsManageData, bos);\r
+ } finally {\r
+ bos.close();\r
+ }\r
+\r
+ // バッファされたXMLデータを実際のファイルに書き込む\r
+ File partsInfoXML = new File(baseDir, "parts-info.xml");\r
+ FileOutputStream os = new FileOutputStream(partsInfoXML);\r
+ try {\r
+ os.write(bos.toByteArray());\r
+ } finally {\r
+ os.close();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * パーツ管理情報をXMLとしてストリームに書き出す.<br>\r
+ * \r
+ * @param partsManageData\r
+ * パーツ管理データ\r
+ * @param outstm\r
+ * 出力先ストリーム\r
+ * @throws IOException\r
+ * 出力に失敗した場合\r
+ */\r
+ public void savePartsManageData(PartsManageData partsManageData,\r
+ OutputStream outstm) throws IOException {\r
+ if (partsManageData == null || outstm == null) {\r
+ throw new IllegalArgumentException();\r
+ }\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
+\r
+ } catch (ParserConfigurationException ex) {\r
+ throw new RuntimeException("JAXP Configuration Exception.", ex);\r
+ }\r
+\r
+ Locale locale = Locale.getDefault();\r
+ String lang = locale.getLanguage();\r
+\r
+ Element root = doc.createElementNS(NS_PARTSDEF, "parts-definition");\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_PARTSDEF\r
+ + " parts-definition.xsd");\r
+ doc.appendChild(root);\r
+\r
+ // 作者情報を取得する\r
+ Collection<PartsAuthorInfo> partsAuthors = partsManageData\r
+ .getAuthorInfos();\r
+ for (PartsAuthorInfo partsAuthorInfo : partsAuthors) {\r
+ String author = partsAuthorInfo.getAuthor();\r
+ if (author == null || author.length() == 0) {\r
+ continue;\r
+ }\r
+\r
+ // 作者情報の登録\r
+ Element nodeAuthor = doc.createElementNS(NS_PARTSDEF, "author");\r
+ Element nodeAuthorName = doc.createElementNS(NS_PARTSDEF, "name");\r
+ Attr attrLang = doc.createAttributeNS(XMLConstants.XML_NS_URI,\r
+ "lang");\r
+ attrLang.setValue(lang);\r
+ nodeAuthorName.setAttributeNodeNS(attrLang);\r
+ nodeAuthorName.setTextContent(author);\r
+ nodeAuthor.appendChild(nodeAuthorName);\r
+\r
+ String homepageURL = partsAuthorInfo.getHomePage();\r
+ if (homepageURL != null && homepageURL.length() > 0) {\r
+ Element nodeHomepage = doc.createElementNS(NS_PARTSDEF,\r
+ "home-page");\r
+ Attr attrHomepageLang = doc.createAttributeNS(\r
+ XMLConstants.XML_NS_URI, "lang");\r
+ attrHomepageLang.setValue(lang);\r
+ nodeHomepage.setAttributeNodeNS(attrHomepageLang);\r
+ nodeHomepage.setTextContent(homepageURL);\r
+ nodeAuthor.appendChild(nodeHomepage);\r
+ }\r
+\r
+ root.appendChild(nodeAuthor);\r
+\r
+ Collection<PartsKey> partsKeys = partsManageData\r
+ .getPartsKeysByAuthor(author);\r
+\r
+ // ダウンロード別にパーツキーの集約\r
+ HashMap<String, List<PartsKey>> downloadMap = new HashMap<String, List<PartsKey>>();\r
+ for (PartsKey partsKey : partsKeys) {\r
+ PartsManageData.PartsVersionInfo versionInfo = partsManageData\r
+ .getVersionStrict(partsKey);\r
+ String downloadURL = versionInfo.getDownloadURL();\r
+ if (downloadURL == null) {\r
+ downloadURL = "";\r
+ }\r
+ List<PartsKey> partsKeyGrp = downloadMap.get(downloadURL);\r
+ if (partsKeyGrp == null) {\r
+ partsKeyGrp = new ArrayList<PartsKey>();\r
+ downloadMap.put(downloadURL, partsKeyGrp);\r
+ }\r
+ partsKeyGrp.add(partsKey);\r
+ }\r
+\r
+ // ダウンロード別にパーツ情報の登録\r
+ ArrayList<String> downloadURLs = new ArrayList<String>(\r
+ downloadMap.keySet());\r
+ Collections.sort(downloadURLs);\r
+\r
+ for (String downloadURL : downloadURLs) {\r
+ List<PartsKey> partsKeyGrp = downloadMap.get(downloadURL);\r
+ Collections.sort(partsKeyGrp);\r
+\r
+ Element nodeDownload = doc.createElementNS(NS_PARTSDEF,\r
+ "download-url");\r
+ nodeDownload.setTextContent(downloadURL);\r
+ root.appendChild(nodeDownload);\r
+\r
+ for (PartsKey partsKey : partsKeyGrp) {\r
+ PartsManageData.PartsVersionInfo versionInfo = partsManageData\r
+ .getVersionStrict(partsKey);\r
+\r
+ Element nodeParts = doc.createElementNS(NS_PARTSDEF,\r
+ "parts");\r
+\r
+ nodeParts.setAttribute("name", partsKey.getPartsName());\r
+ if (partsKey.getCategoryId() != null) {\r
+ nodeParts.setAttribute("category",\r
+ partsKey.getCategoryId());\r
+ }\r
+ if (versionInfo.getVersion() > 0) {\r
+ nodeParts.setAttribute("version",\r
+ Double.toString(versionInfo.getVersion()));\r
+ }\r
+\r
+ String localizedName = partsManageData\r
+ .getLocalizedName(partsKey);\r
+ if (localizedName != null\r
+ && localizedName.trim().length() > 0) {\r
+ Element nodeLocalizedName = doc.createElementNS(\r
+ NS_PARTSDEF, "local-name");\r
+ Attr attrLocalizedNameLang = doc.createAttributeNS(\r
+ XMLConstants.XML_NS_URI, "lang");\r
+ attrLocalizedNameLang.setValue(lang);\r
+ nodeLocalizedName\r
+ .setAttributeNodeNS(attrLocalizedNameLang);\r
+ nodeLocalizedName.setTextContent(localizedName);\r
+ nodeParts.appendChild(nodeLocalizedName);\r
+ }\r
+\r
+ root.appendChild(nodeParts);\r
+ }\r
+ }\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