--- /dev/null
+[patterns]
+
+**.txt = native
+
+**.java = native
+**.properties = LF
+
+**.xml = LF
+**.xsd = LF
+
+**.css = LF
+**.html = LF
+**.png = BIN
-[UTF-8 Japanese]\r
-\r
-\r
-JinArchiver 変更履歴\r
-\r
-\r
-1.502.2 (2011-04-21)\r
- ・110421版スキーマに対応。\r
-\r
-1.501.2 (2011-04-20)\r
- ・G国に対応。vanish,checkout,shortMember,counting2,executionタグの追加。\r
- ・JinParser 1.407.2版に対応。\r
- ・SCMをSubversionからMercurialに移行\r
-\r
-1.401.2 (2009-10-26)\r
- ・初回リリース。\r
-\r
---- EOF ---\r
+[UTF-8 Japanese]
+
+
+JinArchiver 変更履歴
+
+
+1.502.2 (2011-04-21)
+ ・110421版スキーマに対応。
+
+1.501.2 (2011-04-20)
+ ・G国に対応。vanish,checkout,shortMember,counting2,executionタグの追加。
+ ・JinParser 1.407.2版に対応。
+ ・SCMをSubversionからMercurialに移行
+
+1.401.2 (2009-10-26)
+ ・初回リリース。
+
+--- EOF ---
-[UTF-8 Japanese]\r
-\r
-The MIT License\r
-\r
-\r
-Copyright(c) 2009 olyutorskii\r
-\r
-\r
-Permission is hereby granted, free of charge, to any person obtaining a copy\r
-of this software and associated documentation files (the "Software"), to deal\r
-in the Software without restriction, including without limitation the rights\r
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
-copies of the Software, and to permit persons to whom the Software is\r
-furnished to do so, subject to the following conditions:\r
-\r
-The above copyright notice and this permission notice shall be included in\r
-all copies or substantial portions of the Software.\r
-\r
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
-THE SOFTWARE.\r
-\r
-\r
-JinArchiver作者自身からのコメント:\r
-\r
- ※ 少なくともこのソフトウェアの実行、複製、配布、改造は自由です。\r
- ※ 少なくともこのソフトウェアは無保証です。\r
-\r
---- EOF ---\r
+[UTF-8 Japanese]
+
+The MIT License
+
+
+Copyright(c) 2009 olyutorskii
+
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+JinArchiver作者自身からのコメント:
+
+ ※ 少なくともこのソフトウェアの実行、複製、配布、改造は自由です。
+ ※ 少なくともこのソフトウェアは無保証です。
+
+--- EOF ---
-[UTF-8 Japanese]\r
-\r
- JinArchiver\r
- README\r
-\r
- Copyright(c) 2009 olyutorskii\r
-\r
-\r
-=== JinArchiverとは ===\r
-\r
-\r
- JinArchiverは、人狼BBSの過去ログを独自のXML形式でローカルディスクに\r
-保存するためのツールです。\r
-\r
-※ このアーカイブにはJindolfの実行バイナリは含まれていません。\r
- Jindolfを動かしたい方は、jindolfで始まり拡張子が*.jarであるファイルを\r
- 別途入手してください。\r
-※ 人狼BBSのURLは [ http://homepage2.nifty.com/ninjinia/ ] まで\r
-※ 人狼BBSを主催するninjin氏は、JinArchiverの製作に一切関与していません。\r
- JinArchiverに関する問い合わせををninjin氏へ投げかけないように!約束だよ!\r
-\r
-\r
-=== 使い方 ===\r
-\r
-例) ※ F国 1507村 のアーカイブをディレクトリ/tmpに作りたい場合。\r
-\r
-java -jar jinarchiver-X.X.X.jar -land wolff -vid 1507 -outdir /tmp\r
-\r
-オプション詳細は-helpオプションで確認してください。\r
-\r
-\r
-=== ソースコードに関して ===\r
-\r
- - JinArchiverはJava言語(JLS3)で記述されたプログラムです。\r
- - JinArchiverはJRE1.5に準拠したJava実行環境で利用できるように作られています。\r
- 原則として、JRE1.5に準拠した実行系であれば、プラットフォームを選びません。\r
-\r
-\r
-=== アーカイブ管理体制 ===\r
-\r
- このアーカイブは、UTF-8による開発環境を前提として構成されています。\r
- このアーカイブの原本となる開発資産は、\r
- http://hg.sourceforge.jp/view/jindolf/JinArchiver/\r
- を上位に持つMercurialリポジトリで管理されています。\r
- アーカイブの代わりにMercurialを通じて開発資産にアクセスすることにより、\r
- 任意の文字コードに変換されたJavaソースファイルや各種リソースを\r
- 容易に入手することが可能です。\r
-\r
-\r
-=== 開発プロジェクト運営元 ===\r
-\r
- http://sourceforge.jp/projects/jindolf/ まで。\r
-\r
-\r
-=== ディレクトリ内訳構成 ===\r
-\r
-./README.txt\r
- あなたが今見てるこれ。\r
-\r
-./CHANGELOG.txt\r
- 変更履歴。\r
-\r
-./LICENSE.txt\r
- ライセンスに関して。\r
-\r
-./src/\r
- Javaのソースコード。XMLなどの各種リソース。\r
-\r
-./test/\r
- JUnit 4.* 用のテストコード。\r
-\r
-./pom.xml\r
- Maven2用プロジェクト構成定義ファイル。\r
-\r
-./build.xml\r
- Ant用追加タスク。\r
-\r
-./src/main/java/\r
- Javaのソースコード。\r
-\r
-./src/main/resources/\r
- プロパティファイルなどの各種リソース。\r
-\r
-./src/test/java/\r
- JUnit 4.* 用のユニットテストコード。\r
-\r
-./src/main/config/checks.xml\r
- Checkstyle用configファイル。\r
-\r
-./src/main/config/pmdrules.xml\r
- PMD用ルール定義ファイル。\r
-\r
-./src/main/assembly/descriptor.xml\r
- ソースアーカイブ構成定義ファイル。\r
-\r
-\r
---- EOF ---\r
+[UTF-8 Japanese]
+
+ JinArchiver
+ README
+
+ Copyright(c) 2009 olyutorskii
+
+
+=== JinArchiverとは ===
+
+
+ JinArchiverは、人狼BBSの過去ログを独自のXML形式でローカルディスクに
+保存するためのツールです。
+
+※ このアーカイブにはJindolfの実行バイナリは含まれていません。
+ Jindolfを動かしたい方は、jindolfで始まり拡張子が*.jarであるファイルを
+ 別途入手してください。
+※ 人狼BBSのURLは [ http://homepage2.nifty.com/ninjinia/ ] まで
+※ 人狼BBSを主催するninjin氏は、JinArchiverの製作に一切関与していません。
+ JinArchiverに関する問い合わせををninjin氏へ投げかけないように!約束だよ!
+
+
+=== 使い方 ===
+
+例) ※ F国 1507村 のアーカイブをディレクトリ/tmpに作りたい場合。
+
+java -jar jinarchiver-X.X.X.jar -land wolff -vid 1507 -outdir /tmp
+
+オプション詳細は-helpオプションで確認してください。
+
+
+=== ソースコードに関して ===
+
+ - JinArchiverはJava言語(JLS3)で記述されたプログラムです。
+ - JinArchiverはJRE1.5に準拠したJava実行環境で利用できるように作られています。
+ 原則として、JRE1.5に準拠した実行系であれば、プラットフォームを選びません。
+
+
+=== アーカイブ管理体制 ===
+
+ このアーカイブは、UTF-8による開発環境を前提として構成されています。
+ このアーカイブの原本となる開発資産は、
+ http://hg.sourceforge.jp/view/jindolf/JinArchiver/
+ を上位に持つMercurialリポジトリで管理されています。
+ アーカイブの代わりにMercurialを通じて開発資産にアクセスすることにより、
+ 任意の文字コードに変換されたJavaソースファイルや各種リソースを
+ 容易に入手することが可能です。
+
+
+=== 開発プロジェクト運営元 ===
+
+ http://sourceforge.jp/projects/jindolf/ まで。
+
+
+=== ディレクトリ内訳構成 ===
+
+./README.txt
+ あなたが今見てるこれ。
+
+./CHANGELOG.txt
+ 変更履歴。
+
+./LICENSE.txt
+ ライセンスに関して。
+
+./src/
+ Javaのソースコード。XMLなどの各種リソース。
+
+./test/
+ JUnit 4.* 用のテストコード。
+
+./pom.xml
+ Maven2用プロジェクト構成定義ファイル。
+
+./build.xml
+ Ant用追加タスク。
+
+./src/main/java/
+ Javaのソースコード。
+
+./src/main/resources/
+ プロパティファイルなどの各種リソース。
+
+./src/test/java/
+ JUnit 4.* 用のユニットテストコード。
+
+./src/main/config/checks.xml
+ Checkstyle用configファイル。
+
+./src/main/config/pmdrules.xml
+ PMD用ルール定義ファイル。
+
+./src/main/assembly/descriptor.xml
+ ソースアーカイブ構成定義ファイル。
+
+
+--- EOF ---
-/*\r
- * avatar model\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.IOException;\r
-import java.io.Writer;\r
-import java.util.List;\r
-import javax.xml.parsers.DocumentBuilder;\r
-import javax.xml.parsers.DocumentBuilderFactory;\r
-import javax.xml.parsers.ParserConfigurationException;\r
-import jp.sourceforge.jindolf.corelib.PreDefAvatar;\r
-import org.xml.sax.SAXException;\r
-\r
-/**\r
- * Avatarモデル。\r
- */\r
-public class AvatarData{\r
-\r
- private static final List<PreDefAvatar> PREDEF_AVATAR_LIST;\r
-\r
- static{\r
- DocumentBuilderFactory factory =\r
- DocumentBuilderFactory.newInstance();\r
- try{\r
- DocumentBuilder builder = factory.newDocumentBuilder();\r
- PREDEF_AVATAR_LIST = PreDefAvatar.buildPreDefAvatarList(builder);\r
- }catch(ParserConfigurationException e){\r
- throw new ExceptionInInitializerError(e);\r
- }catch(IOException e){\r
- throw new ExceptionInInitializerError(e);\r
- }catch(SAXException e){\r
- throw new ExceptionInInitializerError(e);\r
- }\r
- }\r
-\r
-\r
- private String fullName;\r
- private String shortName;\r
- private String avatarId;\r
- private String faceIconUri;\r
-\r
-\r
- /**\r
- * コンストラクタ。\r
- */\r
- public AvatarData(){\r
- super();\r
- return;\r
- }\r
-\r
- /**\r
- * コンストラクタ。\r
- * @param predefAvatar プリセット済みAvatar\r
- */\r
- public AvatarData(PreDefAvatar predefAvatar){\r
- this();\r
-\r
- this.fullName = predefAvatar.getFullName();\r
- this.shortName = predefAvatar.getShortName();\r
- this.avatarId = predefAvatar.getAvatarId();\r
- this.faceIconUri = null;\r
-\r
- return;\r
- }\r
-\r
-\r
- /**\r
- * プリセット済みAvatarをフルネームを用いて取得する。\r
- * @param seq フルネーム\r
- * @return 見つかったプリセット済みAvatar。見つからなければnull。\r
- */\r
- public static PreDefAvatar getPreDefAvatar(CharSequence seq){\r
- for(PreDefAvatar avatar : PREDEF_AVATAR_LIST){\r
- String fullName = avatar.getFullName();\r
- if(fullName.contentEquals(seq)){\r
- return avatar;\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- /**\r
- * フルネームを取得する。\r
- * @return フルネーム\r
- */\r
- public String getFullName(){\r
- return this.fullName;\r
- }\r
-\r
- /**\r
- * フルネームを設定する。\r
- * @param fullName フルネーム\r
- */\r
- public void setFullName(String fullName){\r
- this.fullName = fullName;\r
- return;\r
- }\r
-\r
- /**\r
- * 短縮名を取得する。\r
- * @return 短縮名\r
- */\r
- public String getShortName(){\r
- return this.shortName;\r
- }\r
-\r
- /**\r
- * 短縮名を設定する。\r
- * @param shortName 短縮名\r
- */\r
- public void setShortName(String shortName){\r
- this.shortName = shortName;\r
- return;\r
- }\r
-\r
- /**\r
- * Avatar識別子を取得する。\r
- * @return Avatar識別子\r
- */\r
- public String getAvatarId(){\r
- return this.avatarId;\r
- }\r
-\r
- /**\r
- * Avatar識別子を設定する。\r
- * @param avatarId Avatar識別子\r
- */\r
- public void setAvatarId(String avatarId){\r
- this.avatarId = avatarId;\r
- return;\r
- }\r
-\r
- /**\r
- * 顔アイコンURI文字列を取得する。\r
- * @return 顔アイコンURI文字列\r
- */\r
- public String getFaceIconUri(){\r
- return this.faceIconUri;\r
- }\r
-\r
- /**\r
- * 顔アイコンURI文字列を設定する。\r
- * @param faceIconUri 顔アイコンURI文字列\r
- */\r
- public void setFaceIconUri(String faceIconUri){\r
- this.faceIconUri = faceIconUri;\r
- return;\r
- }\r
-\r
- /**\r
- * avatar要素をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpXml(Writer writer) throws IOException{\r
- writer.append("<avatar\n");\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "avatarId", this.avatarId);\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "fullName", this.fullName);\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "shortName", this.shortName);\r
- writer.append('\n');\r
-\r
- if(this.faceIconUri != null){\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "faceIconURI", this.faceIconUri);\r
- writer.append('\n');\r
- // F1014対策\r
- }\r
-\r
- writer.append("/>\n");\r
- writer.flush();\r
-\r
- return;\r
- }\r
-\r
-}\r
+/*
+ * avatar model
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import jp.sourceforge.jindolf.corelib.PreDefAvatar;
+import org.xml.sax.SAXException;
+
+/**
+ * Avatarモデル。
+ */
+public class AvatarData{
+
+ private static final List<PreDefAvatar> PREDEF_AVATAR_LIST;
+
+ static{
+ DocumentBuilderFactory factory =
+ DocumentBuilderFactory.newInstance();
+ try{
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ PREDEF_AVATAR_LIST = PreDefAvatar.buildPreDefAvatarList(builder);
+ }catch(ParserConfigurationException e){
+ throw new ExceptionInInitializerError(e);
+ }catch(IOException e){
+ throw new ExceptionInInitializerError(e);
+ }catch(SAXException e){
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+
+ private String fullName;
+ private String shortName;
+ private String avatarId;
+ private String faceIconUri;
+
+
+ /**
+ * コンストラクタ。
+ */
+ public AvatarData(){
+ super();
+ return;
+ }
+
+ /**
+ * コンストラクタ。
+ * @param predefAvatar プリセット済みAvatar
+ */
+ public AvatarData(PreDefAvatar predefAvatar){
+ this();
+
+ this.fullName = predefAvatar.getFullName();
+ this.shortName = predefAvatar.getShortName();
+ this.avatarId = predefAvatar.getAvatarId();
+ this.faceIconUri = null;
+
+ return;
+ }
+
+
+ /**
+ * プリセット済みAvatarをフルネームを用いて取得する。
+ * @param seq フルネーム
+ * @return 見つかったプリセット済みAvatar。見つからなければnull。
+ */
+ public static PreDefAvatar getPreDefAvatar(CharSequence seq){
+ for(PreDefAvatar avatar : PREDEF_AVATAR_LIST){
+ String fullName = avatar.getFullName();
+ if(fullName.contentEquals(seq)){
+ return avatar;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * フルネームを取得する。
+ * @return フルネーム
+ */
+ public String getFullName(){
+ return this.fullName;
+ }
+
+ /**
+ * フルネームを設定する。
+ * @param fullName フルネーム
+ */
+ public void setFullName(String fullName){
+ this.fullName = fullName;
+ return;
+ }
+
+ /**
+ * 短縮名を取得する。
+ * @return 短縮名
+ */
+ public String getShortName(){
+ return this.shortName;
+ }
+
+ /**
+ * 短縮名を設定する。
+ * @param shortName 短縮名
+ */
+ public void setShortName(String shortName){
+ this.shortName = shortName;
+ return;
+ }
+
+ /**
+ * Avatar識別子を取得する。
+ * @return Avatar識別子
+ */
+ public String getAvatarId(){
+ return this.avatarId;
+ }
+
+ /**
+ * Avatar識別子を設定する。
+ * @param avatarId Avatar識別子
+ */
+ public void setAvatarId(String avatarId){
+ this.avatarId = avatarId;
+ return;
+ }
+
+ /**
+ * 顔アイコンURI文字列を取得する。
+ * @return 顔アイコンURI文字列
+ */
+ public String getFaceIconUri(){
+ return this.faceIconUri;
+ }
+
+ /**
+ * 顔アイコンURI文字列を設定する。
+ * @param faceIconUri 顔アイコンURI文字列
+ */
+ public void setFaceIconUri(String faceIconUri){
+ this.faceIconUri = faceIconUri;
+ return;
+ }
+
+ /**
+ * avatar要素をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpXml(Writer writer) throws IOException{
+ writer.append("<avatar\n");
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "avatarId", this.avatarId);
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "fullName", this.fullName);
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "shortName", this.shortName);
+ writer.append('\n');
+
+ if(this.faceIconUri != null){
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "faceIconURI", this.faceIconUri);
+ writer.append('\n');
+ // F1014対策
+ }
+
+ writer.append("/>\n");
+ writer.flush();
+
+ return;
+ }
+
+}
-/*\r
- * information builder from input\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.net.URL;\r
-import java.net.URLConnection;\r
-import java.nio.charset.Charset;\r
-import jp.sourceforge.jindolf.parser.ContentBuilder;\r
-import jp.sourceforge.jindolf.parser.ContentBuilderSJ;\r
-import jp.sourceforge.jindolf.parser.ContentBuilderUCS2;\r
-import jp.sourceforge.jindolf.parser.DecodeException;\r
-import jp.sourceforge.jindolf.parser.DecodedContent;\r
-import jp.sourceforge.jindolf.parser.HtmlParseException;\r
-import jp.sourceforge.jindolf.parser.HtmlParser;\r
-import jp.sourceforge.jindolf.parser.SjisDecoder;\r
-import jp.sourceforge.jindolf.parser.StreamDecoder;\r
-\r
-/**\r
- * 入力から内部構造を生成する。\r
- */\r
-public final class Builder{\r
-\r
- private static final int BUF_SZ = 100 * 1024;\r
-\r
-\r
- /**\r
- * 隠れコンストラクタ。\r
- */\r
- private Builder(){\r
- super();\r
- return;\r
- }\r
-\r
-\r
- /**\r
- * 入力ストリームをデコードする。\r
- * @param charset 文字コード指定\r
- * @param istream 入力ストリーム\r
- * @return デコード結果\r
- * @throws IOException 入力エラー\r
- * @throws DecodeException デコードエラー\r
- */\r
- public static DecodedContent contentFromStream(Charset charset,\r
- InputStream istream)\r
- throws IOException, DecodeException{\r
- StreamDecoder decoder;\r
- ContentBuilder builder;\r
-\r
- if(charset.name().equalsIgnoreCase("Shift_JIS")){\r
- decoder = new SjisDecoder();\r
- builder = new ContentBuilderSJ(BUF_SZ);\r
- }else if(charset.name().equalsIgnoreCase("UTF-8")){\r
- decoder = new StreamDecoder(charset.newDecoder());\r
- builder = new ContentBuilderUCS2(BUF_SZ);\r
- }else{\r
- assert false;\r
- return null;\r
- }\r
-\r
- decoder.setDecodeHandler(builder);\r
-\r
- decoder.decode(istream);\r
-\r
- DecodedContent content = builder.getContent();\r
-\r
- return content;\r
- }\r
-\r
- /**\r
- * 村の各日々をロードしパースする。\r
- * @param villageData 村情報\r
- * @throws IOException 入力エラー\r
- * @throws DecodeException デコードエラー\r
- * @throws HtmlParseException パースエラー\r
- */\r
- public static void fillVillageData(VillageData villageData)\r
- throws IOException, DecodeException, HtmlParseException {\r
- HtmlParser parser = new HtmlParser();\r
- Handler handler = new Handler();\r
- parser.setBasicHandler (handler);\r
- parser.setTalkHandler (handler);\r
- parser.setSysEventHandler(handler);\r
-\r
- handler.initVillageData(villageData);\r
-\r
- Charset charset = villageData.getLandDef().getEncoding();\r
-\r
- for(PeriodResource resource : villageData.getPeriodResourceList()){\r
- handler.initPeriodResource(resource);\r
- URL url;\r
- url = resource.getResourceUrl();\r
- if(url == null){\r
- url = new URL(resource.getOrigUrlText());\r
- }\r
- URLConnection conn = url.openConnection();\r
- InputStream istream = conn.getInputStream();\r
- if(resource.getDownTimeMs() <= 0){\r
- long downTimeMs = conn.getDate();\r
- resource.setDownTimeMs(downTimeMs);\r
- }\r
- DecodedContent content = contentFromStream(charset, istream);\r
- istream.close();\r
- parser.parseAutomatic(content);\r
- }\r
-\r
- return;\r
- }\r
-\r
-}\r
+/*
+ * information builder from input
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.Charset;
+import jp.sourceforge.jindolf.parser.ContentBuilder;
+import jp.sourceforge.jindolf.parser.ContentBuilderSJ;
+import jp.sourceforge.jindolf.parser.ContentBuilderUCS2;
+import jp.sourceforge.jindolf.parser.DecodeException;
+import jp.sourceforge.jindolf.parser.DecodedContent;
+import jp.sourceforge.jindolf.parser.HtmlParseException;
+import jp.sourceforge.jindolf.parser.HtmlParser;
+import jp.sourceforge.jindolf.parser.SjisDecoder;
+import jp.sourceforge.jindolf.parser.StreamDecoder;
+
+/**
+ * 入力から内部構造を生成する。
+ */
+public final class Builder{
+
+ private static final int BUF_SZ = 100 * 1024;
+
+
+ /**
+ * 隠れコンストラクタ。
+ */
+ private Builder(){
+ super();
+ return;
+ }
+
+
+ /**
+ * 入力ストリームをデコードする。
+ * @param charset 文字コード指定
+ * @param istream 入力ストリーム
+ * @return デコード結果
+ * @throws IOException 入力エラー
+ * @throws DecodeException デコードエラー
+ */
+ public static DecodedContent contentFromStream(Charset charset,
+ InputStream istream)
+ throws IOException, DecodeException{
+ StreamDecoder decoder;
+ ContentBuilder builder;
+
+ if(charset.name().equalsIgnoreCase("Shift_JIS")){
+ decoder = new SjisDecoder();
+ builder = new ContentBuilderSJ(BUF_SZ);
+ }else if(charset.name().equalsIgnoreCase("UTF-8")){
+ decoder = new StreamDecoder(charset.newDecoder());
+ builder = new ContentBuilderUCS2(BUF_SZ);
+ }else{
+ assert false;
+ return null;
+ }
+
+ decoder.setDecodeHandler(builder);
+
+ decoder.decode(istream);
+
+ DecodedContent content = builder.getContent();
+
+ return content;
+ }
+
+ /**
+ * 村の各日々をロードしパースする。
+ * @param villageData 村情報
+ * @throws IOException 入力エラー
+ * @throws DecodeException デコードエラー
+ * @throws HtmlParseException パースエラー
+ */
+ public static void fillVillageData(VillageData villageData)
+ throws IOException, DecodeException, HtmlParseException {
+ HtmlParser parser = new HtmlParser();
+ Handler handler = new Handler();
+ parser.setBasicHandler (handler);
+ parser.setTalkHandler (handler);
+ parser.setSysEventHandler(handler);
+
+ handler.initVillageData(villageData);
+
+ Charset charset = villageData.getLandDef().getEncoding();
+
+ for(PeriodResource resource : villageData.getPeriodResourceList()){
+ handler.initPeriodResource(resource);
+ URL url;
+ url = resource.getResourceUrl();
+ if(url == null){
+ url = new URL(resource.getOrigUrlText());
+ }
+ URLConnection conn = url.openConnection();
+ InputStream istream = conn.getInputStream();
+ if(resource.getDownTimeMs() <= 0){
+ long downTimeMs = conn.getDate();
+ resource.setDownTimeMs(downTimeMs);
+ }
+ DecodedContent content = contentFromStream(charset, istream);
+ istream.close();
+ parser.parseAutomatic(content);
+ }
+
+ return;
+ }
+
+}
-/*\r
- * system event\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.IOException;\r
-import java.io.Writer;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import jp.sourceforge.jindolf.corelib.GameRole;\r
-import jp.sourceforge.jindolf.corelib.SysEventType;\r
-import jp.sourceforge.jindolf.parser.DecodedContent;\r
-\r
-/**\r
- * システムイベント モデル。\r
- */\r
-public class EventData extends TopicData{\r
-\r
- private SysEventType eventType = null;\r
-\r
- private final List<AvatarData> avatarList = new LinkedList<AvatarData>();\r
- private final List<Integer> intList = new LinkedList<Integer>();\r
- private final List<GameRole> roleList = new LinkedList<GameRole>();\r
- private final List<DecodedContent> strList =\r
- new LinkedList<DecodedContent>();\r
-\r
-\r
- /**\r
- * コンストラクタ。\r
- * @param periodData 所属元Period\r
- */\r
- public EventData(PeriodData periodData){\r
- super();\r
- return;\r
- }\r
-\r
-\r
- /**\r
- * イベント種別からXML要素名を取得する。\r
- * @param type イベント種別\r
- * @return 要素名\r
- */\r
- public static String getTagName(SysEventType type){\r
- String tagName;\r
-\r
- switch(type){\r
- case STARTENTRY: tagName = "startEntry"; break;\r
- case ONSTAGE: tagName = "onStage"; break;\r
- case STARTMIRROR: tagName = "startMirror"; break;\r
- case OPENROLE: tagName = "openRole"; break;\r
- case MURDERED: tagName = "murdered"; break;\r
- case STARTASSAULT: tagName = "startAssault"; break;\r
- case SURVIVOR: tagName = "survivor"; break;\r
- case COUNTING: tagName = "counting"; break;\r
- case NOMURDER: tagName = "noMurder"; break;\r
- case SUDDENDEATH: tagName = "suddenDeath"; break;\r
- case WINVILLAGE: tagName = "winVillage"; break;\r
- case WINWOLF: tagName = "winWolf"; break;\r
- case WINHAMSTER: tagName = "winHamster"; break;\r
- case PLAYERLIST: tagName = "playerList"; break;\r
- case PANIC: tagName = "panic"; break;\r
- case EXECUTION: tagName = "execution"; break;\r
- case VANISH: tagName = "vanish"; break;\r
- case CHECKOUT: tagName = "checkout"; break;\r
- case SHORTMEMBER: tagName = "shortMember"; break;\r
- case ASKENTRY: tagName = "askEntry"; break;\r
- case ASKCOMMIT: tagName = "askCommit"; break;\r
- case NOCOMMENT: tagName = "noComment"; break;\r
- case STAYEPILOGUE: tagName = "stayEpilogue"; break;\r
- case GAMEOVER: tagName = "gameOver"; break;\r
- case GUARD: tagName = "guard"; break;\r
- case JUDGE: tagName = "judge"; break;\r
- case COUNTING2: tagName = "counting2"; break;\r
- case ASSAULT: tagName = "assault"; break;\r
- default: throw new IllegalArgumentException();\r
- }\r
-\r
- return tagName;\r
- }\r
-\r
- /**\r
- * 役職からXMLシンボル名を取得する。\r
- * @param role 役職\r
- * @return XMLシンボル名\r
- */\r
- public static String getRoleAttrValue(GameRole role){\r
- String roleName;\r
-\r
- switch(role){\r
- case INNOCENT: roleName = "innocent"; break;\r
- case WOLF: roleName = "wolf"; break;\r
- case SEER: roleName = "seer"; break;\r
- case SHAMAN: roleName = "shaman"; break;\r
- case MADMAN: roleName = "madman"; break;\r
- case HUNTER: roleName = "hunter"; break;\r
- case FRATER: roleName = "frater"; break;\r
- case HAMSTER: roleName = "hamster"; break;\r
- default: throw new IllegalArgumentException();\r
- }\r
-\r
- return roleName;\r
- }\r
-\r
- /**\r
- * avatarRef要素をXML出力する。\r
- * @param writer 出力先\r
- * @param avatar Avatar\r
- * @throws IOException 出力エラー\r
- */\r
- public static void dumpAvatarRef(Writer writer, AvatarData avatar)\r
- throws IOException{\r
- writer.append("<avatarRef");\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "avatarId", avatar.getAvatarId());\r
- writer.append(" />\n");\r
- return;\r
- }\r
-\r
- /**\r
- * システムイベント種別を取得する。\r
- * @return システムイベント種別\r
- */\r
- public SysEventType getEventType(){\r
- return this.eventType;\r
- }\r
-\r
- /**\r
- * システムイベント種別を設定する。\r
- * @param eventType システムイベント種別\r
- */\r
- public void setEventType(SysEventType eventType){\r
- this.eventType = eventType;\r
- return;\r
- }\r
-\r
- /**\r
- * Avatar情報を追加する。\r
- * @param avatarData Avatar情報\r
- */\r
- public void addAvatarData(AvatarData avatarData){\r
- this.avatarList.add(avatarData);\r
- return;\r
- }\r
-\r
- /**\r
- * 整数情報を追加する。\r
- * @param intVal 整数情報\r
- */\r
- public void addInteger(int intVal){\r
- this.intList.add(intVal);\r
- return;\r
- }\r
-\r
- /**\r
- * 役職情報を追加する。\r
- * @param role 役職情報\r
- */\r
- public void addGameRole(GameRole role){\r
- this.roleList.add(role);\r
- return;\r
- }\r
-\r
- /**\r
- * 文字列情報を追加する。\r
- * @param seq 文字列情報\r
- */\r
- public void addDecodedContent(DecodedContent seq){\r
- this.strList.add(seq);\r
- return;\r
- }\r
-\r
- /**\r
- * ONSTAGE属性値をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpOnstageAttr(Writer writer) throws IOException{\r
- int entryNo = this.intList.get(0);\r
- AvatarData avatarData = this.avatarList.get(0);\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "entryNo", Integer.toString(entryNo));\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "avatarId", avatarData.getAvatarId());\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * avatarId属性値をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpSingleAvatarAttr(Writer writer) throws IOException{\r
- AvatarData avatarData = this.avatarList.get(0);\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "avatarId", avatarData.getAvatarId());\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * COUNTINGのvictim属性値をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpCountingAttr(Writer writer) throws IOException{\r
- int total = this.avatarList.size();\r
- if(total % 2 != 0){\r
- AvatarData victim = this.avatarList.get(total - 1);\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "victim", victim.getAvatarId());\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * EXECUTIONのvictim属性値をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpExecutionAttr(Writer writer) throws IOException{\r
- int totalAvatar = this.avatarList.size();\r
- int totalVotes = this.intList.size();\r
- if(totalAvatar != totalVotes){\r
- AvatarData victim = this.avatarList.get(totalAvatar - 1);\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "victim", victim.getAvatarId());\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * ASKENTRY属性値をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpAskEntryAttr(Writer writer) throws IOException{\r
- int hour = this.intList.get(0);\r
- int minute = this.intList.get(1);\r
- int minLimit = this.intList.get(2);\r
- int maxLimit = this.intList.get(3);\r
-\r
- writer.append(' ');\r
- XmlUtils.timeAttrOut(writer, "commitTime", hour, minute);\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "minMembers", Integer.toString(minLimit));\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "maxMembers", Integer.toString(maxLimit));\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * ASKCOMMIT属性値をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpAskCommitAttr(Writer writer) throws IOException{\r
- int hour = this.intList.get(0);\r
- int minute = this.intList.get(1);\r
-\r
- writer.append(' ');\r
- XmlUtils.timeAttrOut(writer, "limitVote", hour, minute);\r
-\r
- writer.append(' ');\r
- XmlUtils.timeAttrOut(writer, "limitSpecial", hour, minute);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * STAYEPILOGUE属性値をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpStayEpilogueAttr(Writer writer) throws IOException{\r
- GameRole role = this.roleList.get(0);\r
- int hour = this.intList.get(0);\r
- int minute = this.intList.get(1);\r
-\r
- String winner;\r
- switch(role){\r
- case INNOCENT: winner = "village"; break;\r
- case WOLF: winner = "wolf"; break;\r
- case HAMSTER: winner = "hamster"; break;\r
- default: throw new IllegalArgumentException();\r
- }\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "maxMembers", winner);\r
-\r
- writer.append(' ');\r
- XmlUtils.timeAttrOut(writer, "limitTime", hour, minute);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * openRole子要素をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpOpenroleElem(Writer writer) throws IOException{\r
- int num = this.roleList.size();\r
- for(int index = 0; index < num; index++){\r
- int heads = this.intList.get(index);\r
- GameRole role = this.roleList.get(index);\r
- String roleName = getRoleAttrValue(role);\r
-\r
- writer.append("<roleHeads");\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "role", roleName);\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "heads", Integer.toString(heads));\r
- writer.append(" />\n");\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * murdered子要素をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpMurderedElem(Writer writer) throws IOException{\r
- for(AvatarData avatar : this.avatarList){\r
- dumpAvatarRef(writer, avatar);\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * survivor子要素をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpSurvivorElem(Writer writer) throws IOException{\r
- for(AvatarData avatar : this.avatarList){\r
- dumpAvatarRef(writer, avatar);\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * nocomment子要素をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpNoCommentElem(Writer writer) throws IOException{\r
- for(AvatarData avatar : this.avatarList){\r
- dumpAvatarRef(writer, avatar);\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * counting子要素をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpCountingElem(Writer writer) throws IOException{\r
- int total = this.avatarList.size();\r
- total = total / 2 * 2;\r
- for(int index = 0; index < total; index += 2){\r
- AvatarData voteBy = this.avatarList.get(index);\r
- AvatarData voteTo = this.avatarList.get(index + 1);\r
- writer.append("<vote");\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "byWhom", voteBy.getAvatarId());\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "target", voteTo.getAvatarId());\r
- writer.append(" />\n");\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * execution子要素をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpExecutionElem(Writer writer) throws IOException{\r
- int total = this.intList.size();\r
- for(int index = 0; index < total; index++){\r
- AvatarData voteTo = this.avatarList.get(index);\r
- int count = this.intList.get(index);\r
- writer.append("<nominated");\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "avatarId", voteTo.getAvatarId());\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "count", "" + count);\r
- writer.append(" />\n");\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * playerlist子要素をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpPlayerlistElem(Writer writer) throws IOException{\r
- int num = this.avatarList.size();\r
-\r
- for(int index = 0; index < num; index++){\r
- AvatarData avatar = this.avatarList.get(index);\r
- DecodedContent uri = this.strList.get(index * 2);\r
- DecodedContent account = this.strList.get(index * 2 + 1);\r
- int isLiving = this.intList.get(index);\r
- String survive;\r
- if(isLiving == 0) survive = "false";\r
- else survive = "true";\r
- GameRole role = this.roleList.get(index);\r
- String roleName = getRoleAttrValue(role);\r
-\r
- writer.append("<playerInfo");\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "playerId", account.toString());\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "avatarId", avatar.getAvatarId());\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "survive", survive);\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "role", roleName);\r
-\r
- String uriStr = uri.toString();\r
- uriStr = uriStr.replaceAll("^[\\s]+", "");\r
- uriStr = uriStr.replaceAll("[\\s]+$", "");\r
- uriStr = uriStr.replaceAll("[\\s]+", "\u0020");\r
- if(uriStr.length() > 0){\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "uri", uriStr);\r
- }\r
-\r
- writer.append(" />\n");\r
- }\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * Avatar間関係の属性値をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpByWhomAttr(Writer writer) throws IOException{\r
- AvatarData by = this.avatarList.get(0);\r
- AvatarData to = this.avatarList.get(1);\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "byWhom", by.getAvatarId());\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "target", to.getAvatarId());\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * ASSAULT属性値をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpAssaultAttr(Writer writer) throws IOException{\r
- AvatarData by = this.avatarList.get(0);\r
- AvatarData to = this.avatarList.get(1);\r
-\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "byWhom", by.getAvatarId());\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "target", to.getAvatarId());\r
- writer.append('\n');\r
-\r
- DecodedContent xname = this.strList.get(0);\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "xname", xname);\r
-\r
- int hour = this.intList.get(0);\r
- int minute = this.intList.get(1);\r
- writer.append(' ');\r
- XmlUtils.timeAttrOut(writer, "time", hour, minute);\r
- writer.append('\n');\r
-\r
- String icon = this.strList.get(1).toString();\r
- if( ! icon.equals(by.getFaceIconUri()) ){\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "faceIconURI", icon);\r
- writer.append('\n');\r
- }\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * システムイベント各種要素のXML出力を行う。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpXml(Writer writer) throws IOException{\r
- String tagName = getTagName(this.eventType);\r
-\r
- writer.append("<");\r
- writer.append(tagName);\r
-\r
- boolean hasAttr = true;\r
- switch(this.eventType){\r
- case ONSTAGE:\r
- dumpOnstageAttr(writer);\r
- break;\r
- case COUNTING:\r
- dumpCountingAttr(writer);\r
- break;\r
- case EXECUTION:\r
- dumpExecutionAttr(writer);\r
- break;\r
- case SUDDENDEATH:\r
- case VANISH:\r
- case CHECKOUT:\r
- dumpSingleAvatarAttr(writer);\r
- break;\r
- case ASKENTRY:\r
- dumpAskEntryAttr(writer);\r
- break;\r
- case ASKCOMMIT:\r
- dumpAskCommitAttr(writer);\r
- break;\r
- case STAYEPILOGUE:\r
- dumpStayEpilogueAttr(writer);\r
- break;\r
- case JUDGE:\r
- case GUARD:\r
- dumpByWhomAttr(writer);\r
- break;\r
- case ASSAULT:\r
- dumpAssaultAttr(writer);\r
- break;\r
- default:\r
- hasAttr = false;\r
- break;\r
- }\r
-\r
- if(hasAttr) writer.append(' ');\r
- writer.append(">\n");\r
-\r
- dumpLines(writer);\r
-\r
- switch(this.eventType){\r
- case OPENROLE:\r
- dumpOpenroleElem(writer);\r
- break;\r
- case MURDERED:\r
- dumpMurderedElem(writer);\r
- break;\r
- case SURVIVOR:\r
- dumpSurvivorElem(writer);\r
- break;\r
- case COUNTING:\r
- case COUNTING2:\r
- dumpCountingElem(writer);\r
- break;\r
- case EXECUTION:\r
- dumpExecutionElem(writer);\r
- break;\r
- case PLAYERLIST:\r
- dumpPlayerlistElem(writer);\r
- break;\r
- case NOCOMMENT:\r
- dumpNoCommentElem(writer);\r
- break;\r
- default:\r
- break;\r
- }\r
-\r
- writer.append("</");\r
- writer.append(tagName);\r
- writer.append(">\n");\r
-\r
- return;\r
- }\r
-\r
-}\r
+/*
+ * system event
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.LinkedList;
+import java.util.List;
+import jp.sourceforge.jindolf.corelib.GameRole;
+import jp.sourceforge.jindolf.corelib.SysEventType;
+import jp.sourceforge.jindolf.parser.DecodedContent;
+
+/**
+ * システムイベント モデル。
+ */
+public class EventData extends TopicData{
+
+ private SysEventType eventType = null;
+
+ private final List<AvatarData> avatarList = new LinkedList<AvatarData>();
+ private final List<Integer> intList = new LinkedList<Integer>();
+ private final List<GameRole> roleList = new LinkedList<GameRole>();
+ private final List<DecodedContent> strList =
+ new LinkedList<DecodedContent>();
+
+
+ /**
+ * コンストラクタ。
+ * @param periodData 所属元Period
+ */
+ public EventData(PeriodData periodData){
+ super();
+ return;
+ }
+
+
+ /**
+ * イベント種別からXML要素名を取得する。
+ * @param type イベント種別
+ * @return 要素名
+ */
+ public static String getTagName(SysEventType type){
+ String tagName;
+
+ switch(type){
+ case STARTENTRY: tagName = "startEntry"; break;
+ case ONSTAGE: tagName = "onStage"; break;
+ case STARTMIRROR: tagName = "startMirror"; break;
+ case OPENROLE: tagName = "openRole"; break;
+ case MURDERED: tagName = "murdered"; break;
+ case STARTASSAULT: tagName = "startAssault"; break;
+ case SURVIVOR: tagName = "survivor"; break;
+ case COUNTING: tagName = "counting"; break;
+ case NOMURDER: tagName = "noMurder"; break;
+ case SUDDENDEATH: tagName = "suddenDeath"; break;
+ case WINVILLAGE: tagName = "winVillage"; break;
+ case WINWOLF: tagName = "winWolf"; break;
+ case WINHAMSTER: tagName = "winHamster"; break;
+ case PLAYERLIST: tagName = "playerList"; break;
+ case PANIC: tagName = "panic"; break;
+ case EXECUTION: tagName = "execution"; break;
+ case VANISH: tagName = "vanish"; break;
+ case CHECKOUT: tagName = "checkout"; break;
+ case SHORTMEMBER: tagName = "shortMember"; break;
+ case ASKENTRY: tagName = "askEntry"; break;
+ case ASKCOMMIT: tagName = "askCommit"; break;
+ case NOCOMMENT: tagName = "noComment"; break;
+ case STAYEPILOGUE: tagName = "stayEpilogue"; break;
+ case GAMEOVER: tagName = "gameOver"; break;
+ case GUARD: tagName = "guard"; break;
+ case JUDGE: tagName = "judge"; break;
+ case COUNTING2: tagName = "counting2"; break;
+ case ASSAULT: tagName = "assault"; break;
+ default: throw new IllegalArgumentException();
+ }
+
+ return tagName;
+ }
+
+ /**
+ * 役職からXMLシンボル名を取得する。
+ * @param role 役職
+ * @return XMLシンボル名
+ */
+ public static String getRoleAttrValue(GameRole role){
+ String roleName;
+
+ switch(role){
+ case INNOCENT: roleName = "innocent"; break;
+ case WOLF: roleName = "wolf"; break;
+ case SEER: roleName = "seer"; break;
+ case SHAMAN: roleName = "shaman"; break;
+ case MADMAN: roleName = "madman"; break;
+ case HUNTER: roleName = "hunter"; break;
+ case FRATER: roleName = "frater"; break;
+ case HAMSTER: roleName = "hamster"; break;
+ default: throw new IllegalArgumentException();
+ }
+
+ return roleName;
+ }
+
+ /**
+ * avatarRef要素をXML出力する。
+ * @param writer 出力先
+ * @param avatar Avatar
+ * @throws IOException 出力エラー
+ */
+ public static void dumpAvatarRef(Writer writer, AvatarData avatar)
+ throws IOException{
+ writer.append("<avatarRef");
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "avatarId", avatar.getAvatarId());
+ writer.append(" />\n");
+ return;
+ }
+
+ /**
+ * システムイベント種別を取得する。
+ * @return システムイベント種別
+ */
+ public SysEventType getEventType(){
+ return this.eventType;
+ }
+
+ /**
+ * システムイベント種別を設定する。
+ * @param eventType システムイベント種別
+ */
+ public void setEventType(SysEventType eventType){
+ this.eventType = eventType;
+ return;
+ }
+
+ /**
+ * Avatar情報を追加する。
+ * @param avatarData Avatar情報
+ */
+ public void addAvatarData(AvatarData avatarData){
+ this.avatarList.add(avatarData);
+ return;
+ }
+
+ /**
+ * 整数情報を追加する。
+ * @param intVal 整数情報
+ */
+ public void addInteger(int intVal){
+ this.intList.add(intVal);
+ return;
+ }
+
+ /**
+ * 役職情報を追加する。
+ * @param role 役職情報
+ */
+ public void addGameRole(GameRole role){
+ this.roleList.add(role);
+ return;
+ }
+
+ /**
+ * 文字列情報を追加する。
+ * @param seq 文字列情報
+ */
+ public void addDecodedContent(DecodedContent seq){
+ this.strList.add(seq);
+ return;
+ }
+
+ /**
+ * ONSTAGE属性値をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpOnstageAttr(Writer writer) throws IOException{
+ int entryNo = this.intList.get(0);
+ AvatarData avatarData = this.avatarList.get(0);
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "entryNo", Integer.toString(entryNo));
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "avatarId", avatarData.getAvatarId());
+
+ return;
+ }
+
+ /**
+ * avatarId属性値をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpSingleAvatarAttr(Writer writer) throws IOException{
+ AvatarData avatarData = this.avatarList.get(0);
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "avatarId", avatarData.getAvatarId());
+
+ return;
+ }
+
+ /**
+ * COUNTINGのvictim属性値をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpCountingAttr(Writer writer) throws IOException{
+ int total = this.avatarList.size();
+ if(total % 2 != 0){
+ AvatarData victim = this.avatarList.get(total - 1);
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "victim", victim.getAvatarId());
+ }
+ return;
+ }
+
+ /**
+ * EXECUTIONのvictim属性値をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpExecutionAttr(Writer writer) throws IOException{
+ int totalAvatar = this.avatarList.size();
+ int totalVotes = this.intList.size();
+ if(totalAvatar != totalVotes){
+ AvatarData victim = this.avatarList.get(totalAvatar - 1);
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "victim", victim.getAvatarId());
+ }
+ return;
+ }
+
+ /**
+ * ASKENTRY属性値をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpAskEntryAttr(Writer writer) throws IOException{
+ int hour = this.intList.get(0);
+ int minute = this.intList.get(1);
+ int minLimit = this.intList.get(2);
+ int maxLimit = this.intList.get(3);
+
+ writer.append(' ');
+ XmlUtils.timeAttrOut(writer, "commitTime", hour, minute);
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "minMembers", Integer.toString(minLimit));
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "maxMembers", Integer.toString(maxLimit));
+
+ return;
+ }
+
+ /**
+ * ASKCOMMIT属性値をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpAskCommitAttr(Writer writer) throws IOException{
+ int hour = this.intList.get(0);
+ int minute = this.intList.get(1);
+
+ writer.append(' ');
+ XmlUtils.timeAttrOut(writer, "limitVote", hour, minute);
+
+ writer.append(' ');
+ XmlUtils.timeAttrOut(writer, "limitSpecial", hour, minute);
+
+ return;
+ }
+
+ /**
+ * STAYEPILOGUE属性値をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpStayEpilogueAttr(Writer writer) throws IOException{
+ GameRole role = this.roleList.get(0);
+ int hour = this.intList.get(0);
+ int minute = this.intList.get(1);
+
+ String winner;
+ switch(role){
+ case INNOCENT: winner = "village"; break;
+ case WOLF: winner = "wolf"; break;
+ case HAMSTER: winner = "hamster"; break;
+ default: throw new IllegalArgumentException();
+ }
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "maxMembers", winner);
+
+ writer.append(' ');
+ XmlUtils.timeAttrOut(writer, "limitTime", hour, minute);
+
+ return;
+ }
+
+ /**
+ * openRole子要素をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpOpenroleElem(Writer writer) throws IOException{
+ int num = this.roleList.size();
+ for(int index = 0; index < num; index++){
+ int heads = this.intList.get(index);
+ GameRole role = this.roleList.get(index);
+ String roleName = getRoleAttrValue(role);
+
+ writer.append("<roleHeads");
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "role", roleName);
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "heads", Integer.toString(heads));
+ writer.append(" />\n");
+ }
+ return;
+ }
+
+ /**
+ * murdered子要素をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpMurderedElem(Writer writer) throws IOException{
+ for(AvatarData avatar : this.avatarList){
+ dumpAvatarRef(writer, avatar);
+ }
+ return;
+ }
+
+ /**
+ * survivor子要素をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpSurvivorElem(Writer writer) throws IOException{
+ for(AvatarData avatar : this.avatarList){
+ dumpAvatarRef(writer, avatar);
+ }
+ return;
+ }
+
+ /**
+ * nocomment子要素をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpNoCommentElem(Writer writer) throws IOException{
+ for(AvatarData avatar : this.avatarList){
+ dumpAvatarRef(writer, avatar);
+ }
+ return;
+ }
+
+ /**
+ * counting子要素をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpCountingElem(Writer writer) throws IOException{
+ int total = this.avatarList.size();
+ total = total / 2 * 2;
+ for(int index = 0; index < total; index += 2){
+ AvatarData voteBy = this.avatarList.get(index);
+ AvatarData voteTo = this.avatarList.get(index + 1);
+ writer.append("<vote");
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "byWhom", voteBy.getAvatarId());
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "target", voteTo.getAvatarId());
+ writer.append(" />\n");
+ }
+ return;
+ }
+
+ /**
+ * execution子要素をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpExecutionElem(Writer writer) throws IOException{
+ int total = this.intList.size();
+ for(int index = 0; index < total; index++){
+ AvatarData voteTo = this.avatarList.get(index);
+ int count = this.intList.get(index);
+ writer.append("<nominated");
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "avatarId", voteTo.getAvatarId());
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "count", "" + count);
+ writer.append(" />\n");
+ }
+ return;
+ }
+
+ /**
+ * playerlist子要素をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpPlayerlistElem(Writer writer) throws IOException{
+ int num = this.avatarList.size();
+
+ for(int index = 0; index < num; index++){
+ AvatarData avatar = this.avatarList.get(index);
+ DecodedContent uri = this.strList.get(index * 2);
+ DecodedContent account = this.strList.get(index * 2 + 1);
+ int isLiving = this.intList.get(index);
+ String survive;
+ if(isLiving == 0) survive = "false";
+ else survive = "true";
+ GameRole role = this.roleList.get(index);
+ String roleName = getRoleAttrValue(role);
+
+ writer.append("<playerInfo");
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "playerId", account.toString());
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "avatarId", avatar.getAvatarId());
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "survive", survive);
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "role", roleName);
+
+ String uriStr = uri.toString();
+ uriStr = uriStr.replaceAll("^[\\s]+", "");
+ uriStr = uriStr.replaceAll("[\\s]+$", "");
+ uriStr = uriStr.replaceAll("[\\s]+", "\u0020");
+ if(uriStr.length() > 0){
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "uri", uriStr);
+ }
+
+ writer.append(" />\n");
+ }
+
+ return;
+ }
+
+ /**
+ * Avatar間関係の属性値をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpByWhomAttr(Writer writer) throws IOException{
+ AvatarData by = this.avatarList.get(0);
+ AvatarData to = this.avatarList.get(1);
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "byWhom", by.getAvatarId());
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "target", to.getAvatarId());
+
+ return;
+ }
+
+ /**
+ * ASSAULT属性値をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpAssaultAttr(Writer writer) throws IOException{
+ AvatarData by = this.avatarList.get(0);
+ AvatarData to = this.avatarList.get(1);
+
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "byWhom", by.getAvatarId());
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "target", to.getAvatarId());
+ writer.append('\n');
+
+ DecodedContent xname = this.strList.get(0);
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "xname", xname);
+
+ int hour = this.intList.get(0);
+ int minute = this.intList.get(1);
+ writer.append(' ');
+ XmlUtils.timeAttrOut(writer, "time", hour, minute);
+ writer.append('\n');
+
+ String icon = this.strList.get(1).toString();
+ if( ! icon.equals(by.getFaceIconUri()) ){
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "faceIconURI", icon);
+ writer.append('\n');
+ }
+
+ return;
+ }
+
+ /**
+ * システムイベント各種要素のXML出力を行う。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpXml(Writer writer) throws IOException{
+ String tagName = getTagName(this.eventType);
+
+ writer.append("<");
+ writer.append(tagName);
+
+ boolean hasAttr = true;
+ switch(this.eventType){
+ case ONSTAGE:
+ dumpOnstageAttr(writer);
+ break;
+ case COUNTING:
+ dumpCountingAttr(writer);
+ break;
+ case EXECUTION:
+ dumpExecutionAttr(writer);
+ break;
+ case SUDDENDEATH:
+ case VANISH:
+ case CHECKOUT:
+ dumpSingleAvatarAttr(writer);
+ break;
+ case ASKENTRY:
+ dumpAskEntryAttr(writer);
+ break;
+ case ASKCOMMIT:
+ dumpAskCommitAttr(writer);
+ break;
+ case STAYEPILOGUE:
+ dumpStayEpilogueAttr(writer);
+ break;
+ case JUDGE:
+ case GUARD:
+ dumpByWhomAttr(writer);
+ break;
+ case ASSAULT:
+ dumpAssaultAttr(writer);
+ break;
+ default:
+ hasAttr = false;
+ break;
+ }
+
+ if(hasAttr) writer.append(' ');
+ writer.append(">\n");
+
+ dumpLines(writer);
+
+ switch(this.eventType){
+ case OPENROLE:
+ dumpOpenroleElem(writer);
+ break;
+ case MURDERED:
+ dumpMurderedElem(writer);
+ break;
+ case SURVIVOR:
+ dumpSurvivorElem(writer);
+ break;
+ case COUNTING:
+ case COUNTING2:
+ dumpCountingElem(writer);
+ break;
+ case EXECUTION:
+ dumpExecutionElem(writer);
+ break;
+ case PLAYERLIST:
+ dumpPlayerlistElem(writer);
+ break;
+ case NOCOMMENT:
+ dumpNoCommentElem(writer);
+ break;
+ default:
+ break;
+ }
+
+ writer.append("</");
+ writer.append(tagName);
+ writer.append(">\n");
+
+ return;
+ }
+
+}
-/*\r
- * file archive utilities\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.File;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.io.InputStreamReader;\r
-import java.io.LineNumberReader;\r
-import java.io.Reader;\r
-import java.net.MalformedURLException;\r
-import java.net.URI;\r
-import java.net.URL;\r
-import java.text.DateFormat;\r
-import java.text.ParseException;\r
-import java.text.SimpleDateFormat;\r
-import java.util.Date;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.Locale;\r
-import java.util.regex.Matcher;\r
-import java.util.regex.Pattern;\r
-import jp.sourceforge.jindolf.corelib.LandDef;\r
-import jp.sourceforge.jindolf.corelib.PeriodType;\r
-\r
-/**\r
- * ファイルシステム上に納められた\r
- * 生XHTMLデータおよびログファイルへのアクセス諸々。\r
- */\r
-public final class FileArchive{\r
-\r
- private static final Pattern LINE_PATTERN;\r
- private static final DateFormat ISO_FORMAT;\r
-\r
- static{\r
- String fnameRegex =\r
- "(jin_([^_]+)_(\\d+)_(\\d+)_"\r
- +"(?:(prologue)|(progress)|(epilogue))"\r
- +"\\.html)";\r
- LINE_PATTERN = Pattern.compile(\r
- "^" + fnameRegex + "\\s+(\\S+)\\s+(\\S+)\\s+(\\d)" + "$");\r
-\r
- ISO_FORMAT =\r
- new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.JAPAN);\r
- }\r
-\r
-\r
- /**\r
- * 隠れコンストラクタ。\r
- */\r
- private FileArchive(){\r
- throw new Error();\r
- }\r
-\r
-\r
- /**\r
- * ISO形式の日付時刻情報をパースする。\r
- * @param text 日付表記\r
- * @return エポック秒(ms)\r
- */\r
- public static long parseISODate(String text){\r
- Date date;\r
- try{\r
- synchronized(ISO_FORMAT){\r
- date = ISO_FORMAT.parse(text);\r
- }\r
- }catch(ParseException e){\r
- throw new IllegalArgumentException(e);\r
- }\r
- return date.getTime();\r
- }\r
-\r
- /**\r
- * ログ記述からリソース情報を生成する。\r
- * @param logLine 1行に納められたログ記述\r
- * @return リソース情報\r
- */\r
- public static PeriodResource parseDownLogLine(CharSequence logLine){\r
- PeriodResource result;\r
-\r
- Matcher matcher = LINE_PATTERN.matcher(logLine);\r
- if( ! matcher.matches() ) throw new IllegalArgumentException();\r
-\r
- String fname = matcher.group(1);\r
- String landId = matcher.group(2);\r
- int villageId = Integer.parseInt(matcher.group(3));\r
- int day = Integer.parseInt(matcher.group(4));\r
-\r
- PeriodType periodType;\r
- if (matcher.start(5) >= 0) periodType = PeriodType.PROLOGUE;\r
- else if(matcher.start(6) >= 0) periodType = PeriodType.PROGRESS;\r
- else if(matcher.start(7) >= 0) periodType = PeriodType.EPILOGUE;\r
- else throw new IllegalArgumentException();\r
-\r
- String uriText = matcher.group(8);\r
- String dateText = matcher.group(9);\r
- int hasError = Integer.parseInt(matcher.group(10));\r
- if(hasError != 0) throw new IllegalArgumentException();\r
-\r
- long dateMs = parseISODate(dateText);\r
-\r
- if(landId.equals("wolf0")) landId = "wolf";\r
- if(landId.equals("wolf1")) landId = "wolf0";\r
- LandDef landDef = JinArchiver.getLandDef(landId);\r
-\r
- File file = new File(fname);\r
- URI fileUri = file.toURI();\r
- URL fileUrl;\r
- try{\r
- fileUrl = fileUri.toURL();\r
- }catch(MalformedURLException e){\r
- throw new IllegalArgumentException(e);\r
- }\r
-\r
- result = new PeriodResource(landDef,\r
- villageId,\r
- periodType,\r
- day,\r
- uriText,\r
- dateMs,\r
- fileUrl );\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * ログファイルからリソース列を抽出する。\r
- * @param reader ログファイルの内容\r
- * @return リソース列\r
- * @throws IOException 入力エラー\r
- */\r
- public static List<PeriodResource> parseDownList(LineNumberReader reader)\r
- throws IOException{\r
- List<PeriodResource> result = new LinkedList<PeriodResource>();\r
-\r
- for(;;){\r
- String line = reader.readLine();\r
- if(line == null) break;\r
- PeriodResource info = parseDownLogLine(line);\r
- if(info == null){\r
- throw new IllegalArgumentException();\r
- }\r
- result.add(info);\r
- }\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * ログファイルからリソース列を抽出する。\r
- * @param istream ログファイルの内容\r
- * @return リソース列\r
- * @throws IOException 入力エラー\r
- */\r
- public static List<PeriodResource> parseDownloadLog(InputStream istream)\r
- throws IOException{\r
- Reader reader = new InputStreamReader(istream, "US-ASCII");\r
- LineNumberReader lineReader = new LineNumberReader(reader);\r
- List<PeriodResource> result = parseDownList(lineReader);\r
- lineReader.close();\r
- return result;\r
- }\r
-\r
-}\r
+/*
+ * file archive utilities
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.io.Reader;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import jp.sourceforge.jindolf.corelib.LandDef;
+import jp.sourceforge.jindolf.corelib.PeriodType;
+
+/**
+ * ファイルシステム上に納められた
+ * 生XHTMLデータおよびログファイルへのアクセス諸々。
+ */
+public final class FileArchive{
+
+ private static final Pattern LINE_PATTERN;
+ private static final DateFormat ISO_FORMAT;
+
+ static{
+ String fnameRegex =
+ "(jin_([^_]+)_(\\d+)_(\\d+)_"
+ +"(?:(prologue)|(progress)|(epilogue))"
+ +"\\.html)";
+ LINE_PATTERN = Pattern.compile(
+ "^" + fnameRegex + "\\s+(\\S+)\\s+(\\S+)\\s+(\\d)" + "$");
+
+ ISO_FORMAT =
+ new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.JAPAN);
+ }
+
+
+ /**
+ * 隠れコンストラクタ。
+ */
+ private FileArchive(){
+ throw new Error();
+ }
+
+
+ /**
+ * ISO形式の日付時刻情報をパースする。
+ * @param text 日付表記
+ * @return エポック秒(ms)
+ */
+ public static long parseISODate(String text){
+ Date date;
+ try{
+ synchronized(ISO_FORMAT){
+ date = ISO_FORMAT.parse(text);
+ }
+ }catch(ParseException e){
+ throw new IllegalArgumentException(e);
+ }
+ return date.getTime();
+ }
+
+ /**
+ * ログ記述からリソース情報を生成する。
+ * @param logLine 1行に納められたログ記述
+ * @return リソース情報
+ */
+ public static PeriodResource parseDownLogLine(CharSequence logLine){
+ PeriodResource result;
+
+ Matcher matcher = LINE_PATTERN.matcher(logLine);
+ if( ! matcher.matches() ) throw new IllegalArgumentException();
+
+ String fname = matcher.group(1);
+ String landId = matcher.group(2);
+ int villageId = Integer.parseInt(matcher.group(3));
+ int day = Integer.parseInt(matcher.group(4));
+
+ PeriodType periodType;
+ if (matcher.start(5) >= 0) periodType = PeriodType.PROLOGUE;
+ else if(matcher.start(6) >= 0) periodType = PeriodType.PROGRESS;
+ else if(matcher.start(7) >= 0) periodType = PeriodType.EPILOGUE;
+ else throw new IllegalArgumentException();
+
+ String uriText = matcher.group(8);
+ String dateText = matcher.group(9);
+ int hasError = Integer.parseInt(matcher.group(10));
+ if(hasError != 0) throw new IllegalArgumentException();
+
+ long dateMs = parseISODate(dateText);
+
+ if(landId.equals("wolf0")) landId = "wolf";
+ if(landId.equals("wolf1")) landId = "wolf0";
+ LandDef landDef = JinArchiver.getLandDef(landId);
+
+ File file = new File(fname);
+ URI fileUri = file.toURI();
+ URL fileUrl;
+ try{
+ fileUrl = fileUri.toURL();
+ }catch(MalformedURLException e){
+ throw new IllegalArgumentException(e);
+ }
+
+ result = new PeriodResource(landDef,
+ villageId,
+ periodType,
+ day,
+ uriText,
+ dateMs,
+ fileUrl );
+
+ return result;
+ }
+
+ /**
+ * ログファイルからリソース列を抽出する。
+ * @param reader ログファイルの内容
+ * @return リソース列
+ * @throws IOException 入力エラー
+ */
+ public static List<PeriodResource> parseDownList(LineNumberReader reader)
+ throws IOException{
+ List<PeriodResource> result = new LinkedList<PeriodResource>();
+
+ for(;;){
+ String line = reader.readLine();
+ if(line == null) break;
+ PeriodResource info = parseDownLogLine(line);
+ if(info == null){
+ throw new IllegalArgumentException();
+ }
+ result.add(info);
+ }
+
+ return result;
+ }
+
+ /**
+ * ログファイルからリソース列を抽出する。
+ * @param istream ログファイルの内容
+ * @return リソース列
+ * @throws IOException 入力エラー
+ */
+ public static List<PeriodResource> parseDownloadLog(InputStream istream)
+ throws IOException{
+ Reader reader = new InputStreamReader(istream, "US-ASCII");
+ LineNumberReader lineReader = new LineNumberReader(reader);
+ List<PeriodResource> result = parseDownList(lineReader);
+ lineReader.close();
+ return result;
+ }
+
+}
-/*\r
- * parse handler\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.util.regex.Matcher;\r
-import java.util.regex.Pattern;\r
-import jp.sourceforge.jindolf.corelib.DisclosureType;\r
-import jp.sourceforge.jindolf.corelib.EventFamily;\r
-import jp.sourceforge.jindolf.corelib.GameRole;\r
-import jp.sourceforge.jindolf.corelib.LandDef;\r
-import jp.sourceforge.jindolf.corelib.PeriodType;\r
-import jp.sourceforge.jindolf.corelib.SysEventType;\r
-import jp.sourceforge.jindolf.corelib.TalkType;\r
-import jp.sourceforge.jindolf.corelib.Team;\r
-import jp.sourceforge.jindolf.corelib.VillageTag;\r
-import jp.sourceforge.jindolf.parser.DecodedContent;\r
-import jp.sourceforge.jindolf.parser.EntityConverter;\r
-import jp.sourceforge.jindolf.parser.HtmlAdapter;\r
-import jp.sourceforge.jindolf.parser.HtmlParseException;\r
-import jp.sourceforge.jindolf.parser.PageType;\r
-import jp.sourceforge.jindolf.parser.SeqRange;\r
-\r
-/**\r
- * パーサ用ハンドラ。\r
- */\r
-public class Handler extends HtmlAdapter{\r
-\r
- private static final Pattern MURDER_PATTERN =\r
- Pattern.compile("^(.*)\u0020!\u0020今日がお前の命日だ!$");\r
-\r
- private final EntityConverter converter = new EntityConverter();\r
-\r
- private VillageData villageData = null;\r
- private String pageTitle = null;\r
-\r
- private PeriodData currentPeriod = null;\r
- private PeriodResource currentResource = null;\r
-\r
- private TalkData currentTalk = null;\r
- private EventData currentEvent = null;\r
-\r
- /**\r
- * コンストラクタ。\r
- */\r
- public Handler(){\r
- super();\r
- return;\r
- }\r
-\r
- /**\r
- * 村情報を初期化。\r
- * @param villageDataArg 村情報\r
- */\r
- public void initVillageData(VillageData villageDataArg){\r
- this.villageData = villageDataArg;\r
- this.currentPeriod = null;\r
- this.pageTitle = null;\r
- return;\r
- }\r
-\r
- /**\r
- * Periodリソース情報を初期化。\r
- * @param resource リソース情報\r
- */\r
- public void initPeriodResource(PeriodResource resource){\r
- this.currentResource = resource;\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void startParse(DecodedContent content) throws HtmlParseException{\r
- if(this.villageData == null) throw new HtmlParseException();\r
- this.currentPeriod =\r
- new PeriodData(this.villageData, this.currentResource);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param titleRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void pageTitle(DecodedContent content, SeqRange titleRange)\r
- throws HtmlParseException{\r
- DecodedContent title = this.converter.convert(content, titleRange);\r
- if(this.pageTitle == null){\r
- this.pageTitle = title.toString();\r
- }else{\r
- if( ! this.pageTitle.contentEquals(title) ){\r
- throw new HtmlParseException();\r
- }\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param loginRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void loginName(DecodedContent content, SeqRange loginRange)\r
- throws HtmlParseException{\r
- DecodedContent account = this.converter.convert(content, loginRange);\r
- this.currentPeriod.setLoginName(account);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param type {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void pageType(PageType type) throws HtmlParseException{\r
- if(type != PageType.PERIOD_PAGE) throw new HtmlParseException();\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param villageRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void villageName(DecodedContent content, SeqRange villageRange)\r
- throws HtmlParseException{\r
- String vName =\r
- this.converter.convert(content, villageRange).toString();\r
- String fullName = this.villageData.getFullName();\r
- if(fullName.length() <= 0){\r
- if( ! this.pageTitle.endsWith(vName) ){\r
- throw new HtmlParseException();\r
- }\r
- Pattern ptn = Pattern.compile("^([^0-9]*)([0-9]+)\\s+(\\S+)$");\r
- Matcher matcher = ptn.matcher(vName);\r
- if( ! matcher.matches() ) throw new HtmlParseException();\r
- String prefix = matcher.group(1);\r
- String vid = matcher.group(2);\r
- String vtag = matcher.group(3);\r
- LandDef landDef = this.villageData.getLandDef();\r
- if( ! prefix.equals(landDef.getLandPrefix()) ){\r
- throw new HtmlParseException();\r
- }\r
- if( Integer.parseInt(vid) != this.villageData.getVillageId() ){\r
- throw new HtmlParseException();\r
- }\r
- matcher.reset(vtag);\r
- if(VillageTag.lookingAtVillageTag(matcher) == null){\r
- throw new HtmlParseException();\r
- }\r
- this.villageData.setFullName(vName);\r
- }else{\r
- if( ! vName.equals(fullName) ) throw new HtmlParseException();\r
- }\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param month {@inheritDoc}\r
- * @param day {@inheritDoc}\r
- * @param hour {@inheritDoc}\r
- * @param minute {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void commitTime(int month, int day, int hour, int minute)\r
- throws HtmlParseException{\r
- int commitHour = this.villageData.getCommitHour();\r
- int commitMinute = this.villageData.getCommitMinute();\r
-\r
- if(commitHour < 0){\r
- this.villageData.setCommitHour(hour);\r
- }else{\r
- if(hour != commitHour) throw new HtmlParseException();\r
- }\r
-\r
- if(commitMinute < 0){\r
- this.villageData.setCommitMinute(minute);\r
- }else{\r
- if(minute != commitMinute) throw new HtmlParseException();\r
- }\r
-\r
- this.currentPeriod.setCommitMonth(month);\r
- this.currentPeriod.setCommitDay(day);\r
- this.currentPeriod.setCommitHour(hour);\r
- this.currentPeriod.setCommitMinute(minute);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param anchorRange {@inheritDoc}\r
- * @param periodType {@inheritDoc}\r
- * @param day {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void periodLink(DecodedContent content,\r
- SeqRange anchorRange,\r
- PeriodType periodType,\r
- int day)\r
- throws HtmlParseException{\r
- if(anchorRange.isValid()){\r
- DisclosureType newType;\r
-\r
- if(periodType == null){\r
- newType = DisclosureType.COMPLETE;\r
- }else if(periodType == PeriodType.EPILOGUE\r
- && this.currentResource.getPeriodType()\r
- != PeriodType.EPILOGUE){\r
- newType = DisclosureType.COMPLETE;\r
- }else if( periodType != PeriodType.PROLOGUE\r
- && this.currentResource.getPeriodType()\r
- == PeriodType.PROLOGUE){\r
- newType = DisclosureType.COMPLETE;\r
- }else{\r
- newType = DisclosureType.UNCOMPLETE;\r
- }\r
-\r
- this.currentPeriod.setDisclosureType(newType);\r
-\r
- return;\r
- }\r
-\r
- if(periodType != this.currentResource.getPeriodType()){\r
- throw new HtmlParseException();\r
- }\r
-\r
- if(periodType == PeriodType.PROGRESS\r
- && day != this.currentResource.getDay()){\r
- throw new HtmlParseException();\r
- }\r
-\r
- this.currentPeriod.setDisclosureType(DisclosureType.HOT);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void startTalk() throws HtmlParseException{\r
- this.currentTalk = new TalkData();\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param avatarRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void talkAvatar(DecodedContent content, SeqRange avatarRange)\r
- throws HtmlParseException{\r
- DecodedContent avatarName =\r
- this.converter.convert(content, avatarRange);\r
- AvatarData avatar = this.villageData.getAvatarData(avatarName);\r
- this.currentTalk.setAvatarData(avatar);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param urlRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void talkIconUrl(DecodedContent content, SeqRange urlRange)\r
- throws HtmlParseException{\r
- DecodedContent faceIcon = this.converter.convert(content, urlRange);\r
- this.currentTalk.setFaceIconUri(faceIcon.toString());\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param idRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void talkId(DecodedContent content, SeqRange idRange)\r
- throws HtmlParseException{\r
- DecodedContent xname = this.converter.convert(content, idRange);\r
- this.currentTalk.setXName(xname.toString());\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param hour {@inheritDoc}\r
- * @param minute {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void talkTime(int hour, int minute) throws HtmlParseException{\r
- this.currentTalk.setHour(hour);\r
- this.currentTalk.setMinute(minute);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param type {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void talkType(TalkType type) throws HtmlParseException{\r
- this.currentTalk.setTalkType(type);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param textRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void talkText(DecodedContent content, SeqRange textRange)\r
- throws HtmlParseException{\r
- DecodedContent line = this.converter.convert(content, textRange);\r
- this.currentTalk.addLine(line);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void talkBreak() throws HtmlParseException{\r
- this.currentTalk.addBreak();\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void endTalk() throws HtmlParseException{\r
- String faceIcon = this.currentTalk.getFaceIconUri();\r
- if(this.currentTalk.getTalkType() == TalkType.GRAVE){\r
- this.villageData.setGraveIconUri(faceIcon);\r
- }else{\r
- AvatarData avatar = this.currentTalk.getAvatarData();\r
- if(avatar.getFaceIconUri() == null){\r
- avatar.setFaceIconUri(faceIcon);\r
- }\r
- }\r
-\r
- if( ! this.currentPeriod.hasMurderResult()\r
- && this.currentTalk.getTalkType() == TalkType.WOLFONLY\r
- && this.currentTalk.getLineNum() == 1){\r
- DecodedContent line1st = this.currentTalk.get1stLine();\r
- Matcher matcher = MURDER_PATTERN.matcher(line1st);\r
- if(matcher.matches()){\r
- AvatarData byWhom = this.currentTalk.getAvatarData();\r
- String avatarName = matcher.group(1);\r
- AvatarData target =\r
- this.villageData.getAvatarData(avatarName);\r
- String xname = this.currentTalk.getXName();\r
- int hour = this.currentTalk.getHour();\r
- int minute = this.currentTalk.getMinute();\r
- String iconUri = this.currentTalk.getFaceIconUri();\r
- EventData event = new EventData(this.currentPeriod);\r
- event.setEventType(SysEventType.ASSAULT);\r
- event.addLine(line1st);\r
- event.addAvatarData(byWhom);\r
- event.addAvatarData(target);\r
- event.addDecodedContent(new DecodedContent(xname));\r
- event.addInteger(hour);\r
- event.addInteger(minute);\r
- event.addDecodedContent(new DecodedContent(iconUri));\r
- if(byWhom.getFaceIconUri() == null){\r
- byWhom.setFaceIconUri(iconUri);\r
- }\r
- this.currentPeriod.addTopicData(event);\r
- this.currentTalk = null;\r
- return;\r
- }\r
- }\r
-\r
- this.currentPeriod.addTopicData(this.currentTalk);\r
- this.currentTalk = null;\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param eventFamily {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void startSysEvent(EventFamily eventFamily)\r
- throws HtmlParseException{\r
- this.currentEvent = new EventData(this.currentPeriod);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param type {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventType(SysEventType type) throws HtmlParseException{\r
- this.currentEvent.setEventType(type);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param contentRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventContent(DecodedContent content,\r
- SeqRange contentRange)\r
- throws HtmlParseException{\r
- DecodedContent line = this.converter.convert(content, contentRange);\r
- this.currentEvent.addLine(line);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param anchorRange {@inheritDoc}\r
- * @param contentRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventContentAnchor(DecodedContent content,\r
- SeqRange anchorRange,\r
- SeqRange contentRange)\r
- throws HtmlParseException{\r
- DecodedContent line = this.converter.convert(content, contentRange);\r
- this.currentEvent.addLine(line);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventContentBreak() throws HtmlParseException{\r
- this.currentEvent.addBreak();\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param entryNo {@inheritDoc}\r
- * @param avatarRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventOnStage(DecodedContent content,\r
- int entryNo,\r
- SeqRange avatarRange)\r
- throws HtmlParseException{\r
- DecodedContent avatarName =\r
- this.converter.convert(content, avatarRange);\r
- AvatarData avatar = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(avatar);\r
- this.currentEvent.addInteger(entryNo);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param role {@inheritDoc}\r
- * @param num {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventOpenRole(GameRole role, int num)\r
- throws HtmlParseException{\r
- this.currentEvent.addGameRole(role);\r
- this.currentEvent.addInteger(num);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param avatarRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventMurdered(DecodedContent content,\r
- SeqRange avatarRange)\r
- throws HtmlParseException{\r
- DecodedContent avatarName =\r
- this.converter.convert(content, avatarRange);\r
- AvatarData avatar = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(avatar);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param avatarRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventSurvivor(DecodedContent content,\r
- SeqRange avatarRange)\r
- throws HtmlParseException{\r
- DecodedContent avatarName =\r
- this.converter.convert(content, avatarRange);\r
- AvatarData avatar = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(avatar);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param voteByRange {@inheritDoc}\r
- * @param voteToRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventCounting(DecodedContent content,\r
- SeqRange voteByRange,\r
- SeqRange voteToRange)\r
- throws HtmlParseException{\r
- AvatarData avatar;\r
-\r
- if(voteByRange.isValid()){\r
- DecodedContent voteBy =\r
- this.converter.convert(content, voteByRange);\r
- avatar = this.villageData.getAvatarData(voteBy);\r
- this.currentEvent.addAvatarData(avatar);\r
- }\r
-\r
- DecodedContent voteTo =\r
- this.converter.convert(content, voteToRange);\r
- avatar = this.villageData.getAvatarData(voteTo);\r
- this.currentEvent.addAvatarData(avatar);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param voteByRange {@inheritDoc}\r
- * @param voteToRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventCounting2(DecodedContent content,\r
- SeqRange voteByRange,\r
- SeqRange voteToRange)\r
- throws HtmlParseException{\r
- AvatarData avatar;\r
-\r
- DecodedContent voteBy =\r
- this.converter.convert(content, voteByRange);\r
- avatar = this.villageData.getAvatarData(voteBy);\r
- this.currentEvent.addAvatarData(avatar);\r
-\r
- DecodedContent voteTo =\r
- this.converter.convert(content, voteToRange);\r
- avatar = this.villageData.getAvatarData(voteTo);\r
- this.currentEvent.addAvatarData(avatar);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param avatarRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventSuddenDeath(DecodedContent content,\r
- SeqRange avatarRange)\r
- throws HtmlParseException{\r
- DecodedContent avatarName =\r
- this.converter.convert(content, avatarRange);\r
- AvatarData avatar = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(avatar);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param avatarRange {@inheritDoc}\r
- * @param anchorRange {@inheritDoc}\r
- * @param loginRange {@inheritDoc}\r
- * @param isLiving {@inheritDoc}\r
- * @param role {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventPlayerList(DecodedContent content,\r
- SeqRange avatarRange,\r
- SeqRange anchorRange,\r
- SeqRange loginRange,\r
- boolean isLiving,\r
- GameRole role)\r
- throws HtmlParseException{\r
- DecodedContent avatarName =\r
- this.converter.convert(content, avatarRange);\r
- AvatarData avatar = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(avatar);\r
-\r
- DecodedContent uri;\r
- if(anchorRange.isValid()){\r
- uri = this.converter.convert(content, anchorRange);\r
- }else{\r
- uri = new DecodedContent("");\r
- }\r
- Win31j.supplyWin31jChar(uri);\r
- this.currentEvent.addDecodedContent(uri);\r
-\r
- DecodedContent account =\r
- this.converter.convert(content, loginRange);\r
- Win31j.supplyWin31jChar(account);\r
- this.currentEvent.addDecodedContent(account);\r
-\r
- if(isLiving) this.currentEvent.addInteger(1);\r
- else this.currentEvent.addInteger(0);\r
-\r
- this.currentEvent.addGameRole(role);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param hour {@inheritDoc}\r
- * @param minute {@inheritDoc}\r
- * @param minLimit {@inheritDoc}\r
- * @param maxLimit {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventAskEntry(int hour, int minute,\r
- int minLimit, int maxLimit)\r
- throws HtmlParseException{\r
- this.currentEvent.addInteger(hour);\r
- this.currentEvent.addInteger(minute);\r
- this.currentEvent.addInteger(minLimit);\r
- this.currentEvent.addInteger(maxLimit);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param hour {@inheritDoc}\r
- * @param minute {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventAskCommit(int hour, int minute)\r
- throws HtmlParseException{\r
- this.currentEvent.addInteger(hour);\r
- this.currentEvent.addInteger(minute);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param avatarRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventNoComment(DecodedContent content,\r
- SeqRange avatarRange)\r
- throws HtmlParseException{\r
- DecodedContent avatarName;\r
- avatarName = this.converter.convert(content, avatarRange);\r
- AvatarData avatar = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(avatar);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param winner {@inheritDoc}\r
- * @param hour {@inheritDoc}\r
- * @param minute {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventStayEpilogue(Team winner,\r
- int hour, int minute)\r
- throws HtmlParseException{\r
- GameRole role;\r
- switch(winner){\r
- case VILLAGE: role = GameRole.INNOCENT; break;\r
- case WOLF: role = GameRole.WOLF; break;\r
- case HAMSTER: role = GameRole.HAMSTER; break;\r
- default: throw new IllegalArgumentException();\r
- }\r
-\r
- this.currentEvent.addGameRole(role);\r
- this.currentEvent.addInteger(hour);\r
- this.currentEvent.addInteger(minute);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param guardByRange {@inheritDoc}\r
- * @param guardToRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventGuard(DecodedContent content,\r
- SeqRange guardByRange,\r
- SeqRange guardToRange)\r
- throws HtmlParseException{\r
- DecodedContent avatarName;\r
-\r
- avatarName = this.converter.convert(content, guardByRange);\r
- AvatarData guardBy = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(guardBy);\r
-\r
- avatarName = this.converter.convert(content, guardToRange);\r
- AvatarData guardTo = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(guardTo);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param judgeByRange {@inheritDoc}\r
- * @param judgeToRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventJudge(DecodedContent content,\r
- SeqRange judgeByRange,\r
- SeqRange judgeToRange)\r
- throws HtmlParseException{\r
- DecodedContent avatarName;\r
-\r
- avatarName = this.converter.convert(content, judgeByRange);\r
- AvatarData judgeBy = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(judgeBy);\r
-\r
- avatarName = this.converter.convert(content, judgeToRange);\r
- AvatarData judgeTo = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(judgeTo);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param avatarRange {@inheritDoc}\r
- * @param votes {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventExecution(DecodedContent content,\r
- SeqRange avatarRange,\r
- int votes)\r
- throws HtmlParseException{\r
- DecodedContent avatarName;\r
- avatarName = this.converter.convert(content, avatarRange);\r
- AvatarData avatar = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(avatar);\r
-\r
- if(votes > 0){\r
- this.currentEvent.addInteger(votes);\r
- }\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param avatarRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventCheckout(DecodedContent content,\r
- SeqRange avatarRange)\r
- throws HtmlParseException{\r
- DecodedContent avatarName;\r
- avatarName = this.converter.convert(content, avatarRange);\r
- AvatarData avatar = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(avatar);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param avatarRange {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void sysEventVanish(DecodedContent content,\r
- SeqRange avatarRange)\r
- throws HtmlParseException{\r
- DecodedContent avatarName;\r
- avatarName = this.converter.convert(content, avatarRange);\r
- AvatarData avatar = this.villageData.getAvatarData(avatarName);\r
- this.currentEvent.addAvatarData(avatar);\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void endSysEvent() throws HtmlParseException{\r
- this.currentPeriod.addTopicData(this.currentEvent);\r
- this.currentEvent = null;\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void endParse() throws HtmlParseException{\r
- this.villageData.addPeriodData(this.currentPeriod);\r
- this.currentPeriod = null;\r
- return;\r
- }\r
-\r
-}\r
+/*
+ * parse handler
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import jp.sourceforge.jindolf.corelib.DisclosureType;
+import jp.sourceforge.jindolf.corelib.EventFamily;
+import jp.sourceforge.jindolf.corelib.GameRole;
+import jp.sourceforge.jindolf.corelib.LandDef;
+import jp.sourceforge.jindolf.corelib.PeriodType;
+import jp.sourceforge.jindolf.corelib.SysEventType;
+import jp.sourceforge.jindolf.corelib.TalkType;
+import jp.sourceforge.jindolf.corelib.Team;
+import jp.sourceforge.jindolf.corelib.VillageTag;
+import jp.sourceforge.jindolf.parser.DecodedContent;
+import jp.sourceforge.jindolf.parser.EntityConverter;
+import jp.sourceforge.jindolf.parser.HtmlAdapter;
+import jp.sourceforge.jindolf.parser.HtmlParseException;
+import jp.sourceforge.jindolf.parser.PageType;
+import jp.sourceforge.jindolf.parser.SeqRange;
+
+/**
+ * パーサ用ハンドラ。
+ */
+public class Handler extends HtmlAdapter{
+
+ private static final Pattern MURDER_PATTERN =
+ Pattern.compile("^(.*)\u0020!\u0020今日がお前の命日だ!$");
+
+ private final EntityConverter converter = new EntityConverter();
+
+ private VillageData villageData = null;
+ private String pageTitle = null;
+
+ private PeriodData currentPeriod = null;
+ private PeriodResource currentResource = null;
+
+ private TalkData currentTalk = null;
+ private EventData currentEvent = null;
+
+ /**
+ * コンストラクタ。
+ */
+ public Handler(){
+ super();
+ return;
+ }
+
+ /**
+ * 村情報を初期化。
+ * @param villageDataArg 村情報
+ */
+ public void initVillageData(VillageData villageDataArg){
+ this.villageData = villageDataArg;
+ this.currentPeriod = null;
+ this.pageTitle = null;
+ return;
+ }
+
+ /**
+ * Periodリソース情報を初期化。
+ * @param resource リソース情報
+ */
+ public void initPeriodResource(PeriodResource resource){
+ this.currentResource = resource;
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void startParse(DecodedContent content) throws HtmlParseException{
+ if(this.villageData == null) throw new HtmlParseException();
+ this.currentPeriod =
+ new PeriodData(this.villageData, this.currentResource);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param titleRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void pageTitle(DecodedContent content, SeqRange titleRange)
+ throws HtmlParseException{
+ DecodedContent title = this.converter.convert(content, titleRange);
+ if(this.pageTitle == null){
+ this.pageTitle = title.toString();
+ }else{
+ if( ! this.pageTitle.contentEquals(title) ){
+ throw new HtmlParseException();
+ }
+ }
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param loginRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void loginName(DecodedContent content, SeqRange loginRange)
+ throws HtmlParseException{
+ DecodedContent account = this.converter.convert(content, loginRange);
+ this.currentPeriod.setLoginName(account);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param type {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void pageType(PageType type) throws HtmlParseException{
+ if(type != PageType.PERIOD_PAGE) throw new HtmlParseException();
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param villageRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void villageName(DecodedContent content, SeqRange villageRange)
+ throws HtmlParseException{
+ String vName =
+ this.converter.convert(content, villageRange).toString();
+ String fullName = this.villageData.getFullName();
+ if(fullName.length() <= 0){
+ if( ! this.pageTitle.endsWith(vName) ){
+ throw new HtmlParseException();
+ }
+ Pattern ptn = Pattern.compile("^([^0-9]*)([0-9]+)\\s+(\\S+)$");
+ Matcher matcher = ptn.matcher(vName);
+ if( ! matcher.matches() ) throw new HtmlParseException();
+ String prefix = matcher.group(1);
+ String vid = matcher.group(2);
+ String vtag = matcher.group(3);
+ LandDef landDef = this.villageData.getLandDef();
+ if( ! prefix.equals(landDef.getLandPrefix()) ){
+ throw new HtmlParseException();
+ }
+ if( Integer.parseInt(vid) != this.villageData.getVillageId() ){
+ throw new HtmlParseException();
+ }
+ matcher.reset(vtag);
+ if(VillageTag.lookingAtVillageTag(matcher) == null){
+ throw new HtmlParseException();
+ }
+ this.villageData.setFullName(vName);
+ }else{
+ if( ! vName.equals(fullName) ) throw new HtmlParseException();
+ }
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param month {@inheritDoc}
+ * @param day {@inheritDoc}
+ * @param hour {@inheritDoc}
+ * @param minute {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void commitTime(int month, int day, int hour, int minute)
+ throws HtmlParseException{
+ int commitHour = this.villageData.getCommitHour();
+ int commitMinute = this.villageData.getCommitMinute();
+
+ if(commitHour < 0){
+ this.villageData.setCommitHour(hour);
+ }else{
+ if(hour != commitHour) throw new HtmlParseException();
+ }
+
+ if(commitMinute < 0){
+ this.villageData.setCommitMinute(minute);
+ }else{
+ if(minute != commitMinute) throw new HtmlParseException();
+ }
+
+ this.currentPeriod.setCommitMonth(month);
+ this.currentPeriod.setCommitDay(day);
+ this.currentPeriod.setCommitHour(hour);
+ this.currentPeriod.setCommitMinute(minute);
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param anchorRange {@inheritDoc}
+ * @param periodType {@inheritDoc}
+ * @param day {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void periodLink(DecodedContent content,
+ SeqRange anchorRange,
+ PeriodType periodType,
+ int day)
+ throws HtmlParseException{
+ if(anchorRange.isValid()){
+ DisclosureType newType;
+
+ if(periodType == null){
+ newType = DisclosureType.COMPLETE;
+ }else if(periodType == PeriodType.EPILOGUE
+ && this.currentResource.getPeriodType()
+ != PeriodType.EPILOGUE){
+ newType = DisclosureType.COMPLETE;
+ }else if( periodType != PeriodType.PROLOGUE
+ && this.currentResource.getPeriodType()
+ == PeriodType.PROLOGUE){
+ newType = DisclosureType.COMPLETE;
+ }else{
+ newType = DisclosureType.UNCOMPLETE;
+ }
+
+ this.currentPeriod.setDisclosureType(newType);
+
+ return;
+ }
+
+ if(periodType != this.currentResource.getPeriodType()){
+ throw new HtmlParseException();
+ }
+
+ if(periodType == PeriodType.PROGRESS
+ && day != this.currentResource.getDay()){
+ throw new HtmlParseException();
+ }
+
+ this.currentPeriod.setDisclosureType(DisclosureType.HOT);
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void startTalk() throws HtmlParseException{
+ this.currentTalk = new TalkData();
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param avatarRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void talkAvatar(DecodedContent content, SeqRange avatarRange)
+ throws HtmlParseException{
+ DecodedContent avatarName =
+ this.converter.convert(content, avatarRange);
+ AvatarData avatar = this.villageData.getAvatarData(avatarName);
+ this.currentTalk.setAvatarData(avatar);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param urlRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void talkIconUrl(DecodedContent content, SeqRange urlRange)
+ throws HtmlParseException{
+ DecodedContent faceIcon = this.converter.convert(content, urlRange);
+ this.currentTalk.setFaceIconUri(faceIcon.toString());
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param idRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void talkId(DecodedContent content, SeqRange idRange)
+ throws HtmlParseException{
+ DecodedContent xname = this.converter.convert(content, idRange);
+ this.currentTalk.setXName(xname.toString());
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param hour {@inheritDoc}
+ * @param minute {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void talkTime(int hour, int minute) throws HtmlParseException{
+ this.currentTalk.setHour(hour);
+ this.currentTalk.setMinute(minute);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param type {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void talkType(TalkType type) throws HtmlParseException{
+ this.currentTalk.setTalkType(type);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param textRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void talkText(DecodedContent content, SeqRange textRange)
+ throws HtmlParseException{
+ DecodedContent line = this.converter.convert(content, textRange);
+ this.currentTalk.addLine(line);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void talkBreak() throws HtmlParseException{
+ this.currentTalk.addBreak();
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void endTalk() throws HtmlParseException{
+ String faceIcon = this.currentTalk.getFaceIconUri();
+ if(this.currentTalk.getTalkType() == TalkType.GRAVE){
+ this.villageData.setGraveIconUri(faceIcon);
+ }else{
+ AvatarData avatar = this.currentTalk.getAvatarData();
+ if(avatar.getFaceIconUri() == null){
+ avatar.setFaceIconUri(faceIcon);
+ }
+ }
+
+ if( ! this.currentPeriod.hasMurderResult()
+ && this.currentTalk.getTalkType() == TalkType.WOLFONLY
+ && this.currentTalk.getLineNum() == 1){
+ DecodedContent line1st = this.currentTalk.get1stLine();
+ Matcher matcher = MURDER_PATTERN.matcher(line1st);
+ if(matcher.matches()){
+ AvatarData byWhom = this.currentTalk.getAvatarData();
+ String avatarName = matcher.group(1);
+ AvatarData target =
+ this.villageData.getAvatarData(avatarName);
+ String xname = this.currentTalk.getXName();
+ int hour = this.currentTalk.getHour();
+ int minute = this.currentTalk.getMinute();
+ String iconUri = this.currentTalk.getFaceIconUri();
+ EventData event = new EventData(this.currentPeriod);
+ event.setEventType(SysEventType.ASSAULT);
+ event.addLine(line1st);
+ event.addAvatarData(byWhom);
+ event.addAvatarData(target);
+ event.addDecodedContent(new DecodedContent(xname));
+ event.addInteger(hour);
+ event.addInteger(minute);
+ event.addDecodedContent(new DecodedContent(iconUri));
+ if(byWhom.getFaceIconUri() == null){
+ byWhom.setFaceIconUri(iconUri);
+ }
+ this.currentPeriod.addTopicData(event);
+ this.currentTalk = null;
+ return;
+ }
+ }
+
+ this.currentPeriod.addTopicData(this.currentTalk);
+ this.currentTalk = null;
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param eventFamily {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void startSysEvent(EventFamily eventFamily)
+ throws HtmlParseException{
+ this.currentEvent = new EventData(this.currentPeriod);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param type {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventType(SysEventType type) throws HtmlParseException{
+ this.currentEvent.setEventType(type);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param contentRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventContent(DecodedContent content,
+ SeqRange contentRange)
+ throws HtmlParseException{
+ DecodedContent line = this.converter.convert(content, contentRange);
+ this.currentEvent.addLine(line);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param anchorRange {@inheritDoc}
+ * @param contentRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventContentAnchor(DecodedContent content,
+ SeqRange anchorRange,
+ SeqRange contentRange)
+ throws HtmlParseException{
+ DecodedContent line = this.converter.convert(content, contentRange);
+ this.currentEvent.addLine(line);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventContentBreak() throws HtmlParseException{
+ this.currentEvent.addBreak();
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param entryNo {@inheritDoc}
+ * @param avatarRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventOnStage(DecodedContent content,
+ int entryNo,
+ SeqRange avatarRange)
+ throws HtmlParseException{
+ DecodedContent avatarName =
+ this.converter.convert(content, avatarRange);
+ AvatarData avatar = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(avatar);
+ this.currentEvent.addInteger(entryNo);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param role {@inheritDoc}
+ * @param num {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventOpenRole(GameRole role, int num)
+ throws HtmlParseException{
+ this.currentEvent.addGameRole(role);
+ this.currentEvent.addInteger(num);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param avatarRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventMurdered(DecodedContent content,
+ SeqRange avatarRange)
+ throws HtmlParseException{
+ DecodedContent avatarName =
+ this.converter.convert(content, avatarRange);
+ AvatarData avatar = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(avatar);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param avatarRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventSurvivor(DecodedContent content,
+ SeqRange avatarRange)
+ throws HtmlParseException{
+ DecodedContent avatarName =
+ this.converter.convert(content, avatarRange);
+ AvatarData avatar = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(avatar);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param voteByRange {@inheritDoc}
+ * @param voteToRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventCounting(DecodedContent content,
+ SeqRange voteByRange,
+ SeqRange voteToRange)
+ throws HtmlParseException{
+ AvatarData avatar;
+
+ if(voteByRange.isValid()){
+ DecodedContent voteBy =
+ this.converter.convert(content, voteByRange);
+ avatar = this.villageData.getAvatarData(voteBy);
+ this.currentEvent.addAvatarData(avatar);
+ }
+
+ DecodedContent voteTo =
+ this.converter.convert(content, voteToRange);
+ avatar = this.villageData.getAvatarData(voteTo);
+ this.currentEvent.addAvatarData(avatar);
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param voteByRange {@inheritDoc}
+ * @param voteToRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventCounting2(DecodedContent content,
+ SeqRange voteByRange,
+ SeqRange voteToRange)
+ throws HtmlParseException{
+ AvatarData avatar;
+
+ DecodedContent voteBy =
+ this.converter.convert(content, voteByRange);
+ avatar = this.villageData.getAvatarData(voteBy);
+ this.currentEvent.addAvatarData(avatar);
+
+ DecodedContent voteTo =
+ this.converter.convert(content, voteToRange);
+ avatar = this.villageData.getAvatarData(voteTo);
+ this.currentEvent.addAvatarData(avatar);
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param avatarRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventSuddenDeath(DecodedContent content,
+ SeqRange avatarRange)
+ throws HtmlParseException{
+ DecodedContent avatarName =
+ this.converter.convert(content, avatarRange);
+ AvatarData avatar = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(avatar);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param avatarRange {@inheritDoc}
+ * @param anchorRange {@inheritDoc}
+ * @param loginRange {@inheritDoc}
+ * @param isLiving {@inheritDoc}
+ * @param role {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventPlayerList(DecodedContent content,
+ SeqRange avatarRange,
+ SeqRange anchorRange,
+ SeqRange loginRange,
+ boolean isLiving,
+ GameRole role)
+ throws HtmlParseException{
+ DecodedContent avatarName =
+ this.converter.convert(content, avatarRange);
+ AvatarData avatar = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(avatar);
+
+ DecodedContent uri;
+ if(anchorRange.isValid()){
+ uri = this.converter.convert(content, anchorRange);
+ }else{
+ uri = new DecodedContent("");
+ }
+ Win31j.supplyWin31jChar(uri);
+ this.currentEvent.addDecodedContent(uri);
+
+ DecodedContent account =
+ this.converter.convert(content, loginRange);
+ Win31j.supplyWin31jChar(account);
+ this.currentEvent.addDecodedContent(account);
+
+ if(isLiving) this.currentEvent.addInteger(1);
+ else this.currentEvent.addInteger(0);
+
+ this.currentEvent.addGameRole(role);
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param hour {@inheritDoc}
+ * @param minute {@inheritDoc}
+ * @param minLimit {@inheritDoc}
+ * @param maxLimit {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventAskEntry(int hour, int minute,
+ int minLimit, int maxLimit)
+ throws HtmlParseException{
+ this.currentEvent.addInteger(hour);
+ this.currentEvent.addInteger(minute);
+ this.currentEvent.addInteger(minLimit);
+ this.currentEvent.addInteger(maxLimit);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param hour {@inheritDoc}
+ * @param minute {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventAskCommit(int hour, int minute)
+ throws HtmlParseException{
+ this.currentEvent.addInteger(hour);
+ this.currentEvent.addInteger(minute);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param avatarRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventNoComment(DecodedContent content,
+ SeqRange avatarRange)
+ throws HtmlParseException{
+ DecodedContent avatarName;
+ avatarName = this.converter.convert(content, avatarRange);
+ AvatarData avatar = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(avatar);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param winner {@inheritDoc}
+ * @param hour {@inheritDoc}
+ * @param minute {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventStayEpilogue(Team winner,
+ int hour, int minute)
+ throws HtmlParseException{
+ GameRole role;
+ switch(winner){
+ case VILLAGE: role = GameRole.INNOCENT; break;
+ case WOLF: role = GameRole.WOLF; break;
+ case HAMSTER: role = GameRole.HAMSTER; break;
+ default: throw new IllegalArgumentException();
+ }
+
+ this.currentEvent.addGameRole(role);
+ this.currentEvent.addInteger(hour);
+ this.currentEvent.addInteger(minute);
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param guardByRange {@inheritDoc}
+ * @param guardToRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventGuard(DecodedContent content,
+ SeqRange guardByRange,
+ SeqRange guardToRange)
+ throws HtmlParseException{
+ DecodedContent avatarName;
+
+ avatarName = this.converter.convert(content, guardByRange);
+ AvatarData guardBy = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(guardBy);
+
+ avatarName = this.converter.convert(content, guardToRange);
+ AvatarData guardTo = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(guardTo);
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param judgeByRange {@inheritDoc}
+ * @param judgeToRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventJudge(DecodedContent content,
+ SeqRange judgeByRange,
+ SeqRange judgeToRange)
+ throws HtmlParseException{
+ DecodedContent avatarName;
+
+ avatarName = this.converter.convert(content, judgeByRange);
+ AvatarData judgeBy = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(judgeBy);
+
+ avatarName = this.converter.convert(content, judgeToRange);
+ AvatarData judgeTo = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(judgeTo);
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param avatarRange {@inheritDoc}
+ * @param votes {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventExecution(DecodedContent content,
+ SeqRange avatarRange,
+ int votes)
+ throws HtmlParseException{
+ DecodedContent avatarName;
+ avatarName = this.converter.convert(content, avatarRange);
+ AvatarData avatar = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(avatar);
+
+ if(votes > 0){
+ this.currentEvent.addInteger(votes);
+ }
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param avatarRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventCheckout(DecodedContent content,
+ SeqRange avatarRange)
+ throws HtmlParseException{
+ DecodedContent avatarName;
+ avatarName = this.converter.convert(content, avatarRange);
+ AvatarData avatar = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(avatar);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param avatarRange {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void sysEventVanish(DecodedContent content,
+ SeqRange avatarRange)
+ throws HtmlParseException{
+ DecodedContent avatarName;
+ avatarName = this.converter.convert(content, avatarRange);
+ AvatarData avatar = this.villageData.getAvatarData(avatarName);
+ this.currentEvent.addAvatarData(avatar);
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void endSysEvent() throws HtmlParseException{
+ this.currentPeriod.addTopicData(this.currentEvent);
+ this.currentEvent = null;
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void endParse() throws HtmlParseException{
+ this.villageData.addPeriodData(this.currentPeriod);
+ this.currentPeriod = null;
+ return;
+ }
+
+}
-/*\r
- * downloader\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.net.URL;\r
-import java.nio.charset.Charset;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import jp.sourceforge.jindolf.corelib.LandDef;\r
-import jp.sourceforge.jindolf.corelib.LandState;\r
-import jp.sourceforge.jindolf.corelib.PeriodType;\r
-import jp.sourceforge.jindolf.parser.DecodeException;\r
-import jp.sourceforge.jindolf.parser.DecodedContent;\r
-import jp.sourceforge.jindolf.parser.HtmlAdapter;\r
-import jp.sourceforge.jindolf.parser.HtmlParseException;\r
-import jp.sourceforge.jindolf.parser.HtmlParser;\r
-import jp.sourceforge.jindolf.parser.PageType;\r
-import jp.sourceforge.jindolf.parser.SeqRange;\r
-\r
-/**\r
- * 人狼HTTPサーバ内のリソース情報を展開する。\r
- */\r
-public final class HttpAccess{\r
-\r
- /**\r
- * 隠しコンストラクタ。\r
- */\r
- private HttpAccess(){\r
- throw new Error();\r
- }\r
-\r
-\r
- /**\r
- * 日一覧ページ(エピローグの翌日)のURLを得る。\r
- * @param landDef 国指定\r
- * @param vid 村番号\r
- * @return 一覧ページへのURL\r
- * @throws IOException 入力エラー\r
- */\r
- public static URL getPeriodListURL(LandDef landDef, int vid)\r
- throws IOException{\r
- StringBuilder urlText = new StringBuilder();\r
-\r
- urlText.append(landDef.getCgiURI().toASCIIString());\r
- urlText.append('?').append("vid=").append(vid);\r
- if(landDef.getLandState() == LandState.ACTIVE){\r
- urlText.append('&').append("meslog=");\r
- }\r
-\r
- URL result = new URL(urlText.toString());\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * 日ページのロード元情報一覧を得る。\r
- * @param landDef 国指定\r
- * @param vid 村番号\r
- * @return ロード元情報一覧\r
- * @throws DecodeException デコードエラー\r
- * @throws HtmlParseException パースエラー\r
- * @throws IOException 入力エラー\r
- */\r
- public static List<PeriodResource> loadResourceList(LandDef landDef,\r
- int vid)\r
- throws DecodeException,\r
- HtmlParseException,\r
- IOException {\r
- URL url = getPeriodListURL(landDef, vid);\r
-\r
- Charset charset = landDef.getEncoding();\r
- InputStream istream = url.openStream();\r
- DecodedContent content = Builder.contentFromStream(charset, istream);\r
- istream.close();\r
-\r
- HtmlParser parser = new HtmlParser();\r
- PeriodListHandler handler = new PeriodListHandler(landDef, vid);\r
- parser.setBasicHandler(handler);\r
- parser.setTalkHandler(handler);\r
- parser.setSysEventHandler(handler);\r
- parser.parseAutomatic(content);\r
-\r
- List<PeriodResource> result = handler.getResourceList();\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * 日一覧パース用ハンドラ。\r
- */\r
- public static class PeriodListHandler extends HtmlAdapter{\r
-\r
- private final LandDef landDef;\r
- private final int vid;\r
-\r
- private List<PeriodResource> resourceList = null;\r
-\r
- private int progressDays;\r
- private boolean hasDone;\r
-\r
- /**\r
- * コンストラクタ。\r
- * @param landDef 国指定\r
- * @param vid 村番号\r
- */\r
- public PeriodListHandler(LandDef landDef, int vid){\r
- super();\r
- this.landDef = landDef;\r
- this.vid = vid;\r
- return;\r
- }\r
-\r
- /**\r
- * 日ページのURL文字列を生成する。\r
- * @param type 日種類\r
- * @param day 日にち\r
- * @return URL文字列\r
- */\r
- public String getURL(PeriodType type, int day){\r
- String base = this.landDef.getCgiURI().toASCIIString();\r
- base += "?vid=" + this.vid;\r
-\r
- if(this.landDef.getLandId().equals("wolfg")){\r
- base += "&meslog=";\r
- String dnum = "000" + (day - 1);\r
- dnum = dnum.substring(dnum.length() - 3);\r
- switch(type){\r
- case PROLOGUE:\r
- base += "000_ready";\r
- break;\r
- case PROGRESS:\r
- base += dnum;\r
- base += "_progress";\r
- break;\r
- case EPILOGUE:\r
- base += dnum;\r
- base += "_party";\r
- break;\r
- default:\r
- assert false;\r
- return null;\r
- }\r
- }else{\r
- base += "&meslog=" + this.vid + "_";\r
- switch(type){\r
- case PROLOGUE:\r
- base += "ready_0";\r
- break;\r
- case PROGRESS:\r
- base += "progress_" + (day - 1);\r
- break;\r
- case EPILOGUE:\r
- base += "party_" + (day - 1);\r
- break;\r
- default:\r
- return null;\r
- }\r
- }\r
-\r
- base += "&mes=all";\r
-\r
- return base;\r
- }\r
-\r
- /**\r
- * PeriodResource一覧を得る。\r
- * @return PeriodResource一覧\r
- */\r
- public List<PeriodResource> getResourceList(){\r
- return this.resourceList;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void startParse(DecodedContent content)\r
- throws HtmlParseException{\r
- this.resourceList = new LinkedList<PeriodResource>();\r
- this.progressDays = 0;\r
- this.hasDone = false;\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param type {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void pageType(PageType type) throws HtmlParseException{\r
- if(type != PageType.PERIOD_PAGE) throw new HtmlParseException();\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param content {@inheritDoc}\r
- * @param anchorRange {@inheritDoc}\r
- * @param periodType {@inheritDoc}\r
- * @param day {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void periodLink(DecodedContent content,\r
- SeqRange anchorRange,\r
- PeriodType periodType,\r
- int day )\r
- throws HtmlParseException{\r
- if(periodType == null){\r
- this.hasDone = true;\r
- }else if(periodType == PeriodType.PROGRESS){\r
- this.progressDays = day;\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @throws HtmlParseException {@inheritDoc}\r
- */\r
- @Override\r
- public void endParse() throws HtmlParseException{\r
- if( ! this.hasDone ) throw new HtmlParseException();\r
-\r
- PeriodResource resource;\r
-\r
- String prologueURI = getURL(PeriodType.PROLOGUE, 0);\r
- resource = new PeriodResource(this.landDef,\r
- this.vid,\r
- PeriodType.PROLOGUE,\r
- 0,\r
- prologueURI,\r
- 0L,\r
- null);\r
- this.resourceList.add(resource);\r
-\r
- for(int day = 1; day <= this.progressDays; day++){\r
- String progressURI = getURL(PeriodType.PROGRESS, day);\r
- resource = new PeriodResource(this.landDef,\r
- this.vid,\r
- PeriodType.PROGRESS,\r
- day,\r
- progressURI,\r
- 0L,\r
- null);\r
- this.resourceList.add(resource);\r
- }\r
-\r
- String epilogueURI = getURL(PeriodType.EPILOGUE,\r
- this.progressDays + 1);\r
- resource = new PeriodResource(this.landDef,\r
- this.vid,\r
- PeriodType.EPILOGUE,\r
- this.progressDays + 1,\r
- epilogueURI,\r
- 0L,\r
- null);\r
- this.resourceList.add(resource);\r
-\r
- return;\r
- }\r
-\r
- }\r
-\r
-}\r
+/*
+ * downloader
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.LinkedList;
+import java.util.List;
+import jp.sourceforge.jindolf.corelib.LandDef;
+import jp.sourceforge.jindolf.corelib.LandState;
+import jp.sourceforge.jindolf.corelib.PeriodType;
+import jp.sourceforge.jindolf.parser.DecodeException;
+import jp.sourceforge.jindolf.parser.DecodedContent;
+import jp.sourceforge.jindolf.parser.HtmlAdapter;
+import jp.sourceforge.jindolf.parser.HtmlParseException;
+import jp.sourceforge.jindolf.parser.HtmlParser;
+import jp.sourceforge.jindolf.parser.PageType;
+import jp.sourceforge.jindolf.parser.SeqRange;
+
+/**
+ * 人狼HTTPサーバ内のリソース情報を展開する。
+ */
+public final class HttpAccess{
+
+ /**
+ * 隠しコンストラクタ。
+ */
+ private HttpAccess(){
+ throw new Error();
+ }
+
+
+ /**
+ * 日一覧ページ(エピローグの翌日)のURLを得る。
+ * @param landDef 国指定
+ * @param vid 村番号
+ * @return 一覧ページへのURL
+ * @throws IOException 入力エラー
+ */
+ public static URL getPeriodListURL(LandDef landDef, int vid)
+ throws IOException{
+ StringBuilder urlText = new StringBuilder();
+
+ urlText.append(landDef.getCgiURI().toASCIIString());
+ urlText.append('?').append("vid=").append(vid);
+ if(landDef.getLandState() == LandState.ACTIVE){
+ urlText.append('&').append("meslog=");
+ }
+
+ URL result = new URL(urlText.toString());
+
+ return result;
+ }
+
+ /**
+ * 日ページのロード元情報一覧を得る。
+ * @param landDef 国指定
+ * @param vid 村番号
+ * @return ロード元情報一覧
+ * @throws DecodeException デコードエラー
+ * @throws HtmlParseException パースエラー
+ * @throws IOException 入力エラー
+ */
+ public static List<PeriodResource> loadResourceList(LandDef landDef,
+ int vid)
+ throws DecodeException,
+ HtmlParseException,
+ IOException {
+ URL url = getPeriodListURL(landDef, vid);
+
+ Charset charset = landDef.getEncoding();
+ InputStream istream = url.openStream();
+ DecodedContent content = Builder.contentFromStream(charset, istream);
+ istream.close();
+
+ HtmlParser parser = new HtmlParser();
+ PeriodListHandler handler = new PeriodListHandler(landDef, vid);
+ parser.setBasicHandler(handler);
+ parser.setTalkHandler(handler);
+ parser.setSysEventHandler(handler);
+ parser.parseAutomatic(content);
+
+ List<PeriodResource> result = handler.getResourceList();
+
+ return result;
+ }
+
+ /**
+ * 日一覧パース用ハンドラ。
+ */
+ public static class PeriodListHandler extends HtmlAdapter{
+
+ private final LandDef landDef;
+ private final int vid;
+
+ private List<PeriodResource> resourceList = null;
+
+ private int progressDays;
+ private boolean hasDone;
+
+ /**
+ * コンストラクタ。
+ * @param landDef 国指定
+ * @param vid 村番号
+ */
+ public PeriodListHandler(LandDef landDef, int vid){
+ super();
+ this.landDef = landDef;
+ this.vid = vid;
+ return;
+ }
+
+ /**
+ * 日ページのURL文字列を生成する。
+ * @param type 日種類
+ * @param day 日にち
+ * @return URL文字列
+ */
+ public String getURL(PeriodType type, int day){
+ String base = this.landDef.getCgiURI().toASCIIString();
+ base += "?vid=" + this.vid;
+
+ if(this.landDef.getLandId().equals("wolfg")){
+ base += "&meslog=";
+ String dnum = "000" + (day - 1);
+ dnum = dnum.substring(dnum.length() - 3);
+ switch(type){
+ case PROLOGUE:
+ base += "000_ready";
+ break;
+ case PROGRESS:
+ base += dnum;
+ base += "_progress";
+ break;
+ case EPILOGUE:
+ base += dnum;
+ base += "_party";
+ break;
+ default:
+ assert false;
+ return null;
+ }
+ }else{
+ base += "&meslog=" + this.vid + "_";
+ switch(type){
+ case PROLOGUE:
+ base += "ready_0";
+ break;
+ case PROGRESS:
+ base += "progress_" + (day - 1);
+ break;
+ case EPILOGUE:
+ base += "party_" + (day - 1);
+ break;
+ default:
+ return null;
+ }
+ }
+
+ base += "&mes=all";
+
+ return base;
+ }
+
+ /**
+ * PeriodResource一覧を得る。
+ * @return PeriodResource一覧
+ */
+ public List<PeriodResource> getResourceList(){
+ return this.resourceList;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void startParse(DecodedContent content)
+ throws HtmlParseException{
+ this.resourceList = new LinkedList<PeriodResource>();
+ this.progressDays = 0;
+ this.hasDone = false;
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param type {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void pageType(PageType type) throws HtmlParseException{
+ if(type != PageType.PERIOD_PAGE) throw new HtmlParseException();
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param content {@inheritDoc}
+ * @param anchorRange {@inheritDoc}
+ * @param periodType {@inheritDoc}
+ * @param day {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void periodLink(DecodedContent content,
+ SeqRange anchorRange,
+ PeriodType periodType,
+ int day )
+ throws HtmlParseException{
+ if(periodType == null){
+ this.hasDone = true;
+ }else if(periodType == PeriodType.PROGRESS){
+ this.progressDays = day;
+ }
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws HtmlParseException {@inheritDoc}
+ */
+ @Override
+ public void endParse() throws HtmlParseException{
+ if( ! this.hasDone ) throw new HtmlParseException();
+
+ PeriodResource resource;
+
+ String prologueURI = getURL(PeriodType.PROLOGUE, 0);
+ resource = new PeriodResource(this.landDef,
+ this.vid,
+ PeriodType.PROLOGUE,
+ 0,
+ prologueURI,
+ 0L,
+ null);
+ this.resourceList.add(resource);
+
+ for(int day = 1; day <= this.progressDays; day++){
+ String progressURI = getURL(PeriodType.PROGRESS, day);
+ resource = new PeriodResource(this.landDef,
+ this.vid,
+ PeriodType.PROGRESS,
+ day,
+ progressURI,
+ 0L,
+ null);
+ this.resourceList.add(resource);
+ }
+
+ String epilogueURI = getURL(PeriodType.EPILOGUE,
+ this.progressDays + 1);
+ resource = new PeriodResource(this.landDef,
+ this.vid,
+ PeriodType.EPILOGUE,
+ this.progressDays + 1,
+ epilogueURI,
+ 0L,
+ null);
+ this.resourceList.add(resource);
+
+ return;
+ }
+
+ }
+
+}
-/*\r
- * main entry\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.BufferedOutputStream;\r
-import java.io.BufferedWriter;\r
-import java.io.File;\r
-import java.io.FileOutputStream;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.io.OutputStream;\r
-import java.io.OutputStreamWriter;\r
-import java.io.Writer;\r
-import java.text.MessageFormat;\r
-import java.util.List;\r
-import java.util.Properties;\r
-import javax.xml.parsers.DocumentBuilder;\r
-import javax.xml.parsers.DocumentBuilderFactory;\r
-import javax.xml.parsers.ParserConfigurationException;\r
-import jp.sourceforge.jindolf.corelib.LandDef;\r
-import jp.sourceforge.jindolf.parser.DecodeException;\r
-import jp.sourceforge.jindolf.parser.HtmlParseException;\r
-import org.xml.sax.SAXException;\r
-\r
-/**\r
- * メインエントリ。\r
- */\r
-public final class JinArchiver{\r
-\r
- /** Generator. */\r
- public static final String GENERATOR;\r
-\r
- /** このClass。 */\r
- private static final Class<?> SELF_KLASS;\r
- /** このPackage。 */\r
- private static final Package SELF_PACKAGE;\r
- /** タイトル。 */\r
- private static final String TITLE;\r
- /** バージョン。 */\r
- private static final String VERSION;\r
-\r
- private static final List<LandDef> LANDDEF_LIST;\r
-\r
- /** バージョン定義リソース。 */\r
- private static final String RES_VERDEF = "resources/version.properties";\r
-\r
- static{\r
- SELF_KLASS = JinArchiver.class;\r
- SELF_PACKAGE = SELF_KLASS.getPackage();\r
-\r
- Properties verProp = loadVersionDefinition(SELF_KLASS);\r
- TITLE = getPackageInfo(verProp, "pkg-title.", "Unknown");\r
- VERSION = getPackageInfo(verProp, "pkg-version.", "0");\r
- GENERATOR = TITLE + " " + VERSION;\r
-\r
- DocumentBuilderFactory factory =\r
- DocumentBuilderFactory.newInstance();\r
- try{\r
- DocumentBuilder builder = factory.newDocumentBuilder();\r
- LANDDEF_LIST = LandDef.buildLandDefList(builder);\r
- }catch(ParserConfigurationException e){\r
- throw new ExceptionInInitializerError(e);\r
- }catch(IOException e){\r
- throw new ExceptionInInitializerError(e);\r
- }catch(SAXException e){\r
- throw new ExceptionInInitializerError(e);\r
- }\r
- }\r
-\r
-\r
- /**\r
- * 隠しコンストラクタ。\r
- */\r
- private JinArchiver(){\r
- throw new Error();\r
- }\r
-\r
-\r
- /**\r
- * リソース上のパッケージ定義プロパティをロードする。\r
- * MANIFEST.MFが参照できない実行環境での代替品。\r
- * @param klass パッケージを構成する任意のクラス\r
- * @return プロパティ\r
- */\r
- private static Properties loadVersionDefinition(Class klass){\r
- Properties result = new Properties();\r
-\r
- InputStream istream = klass.getResourceAsStream(RES_VERDEF);\r
- try{\r
- result.load(istream);\r
- }catch(IOException e){\r
- return result;\r
- }finally{\r
- try{\r
- istream.close();\r
- }catch(IOException e){\r
- return result;\r
- }\r
- }\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * リソース上のプロパティから\r
- * このクラスのパッケージのパッケージ情報を取得する。\r
- * MANIFEST.MFが参照できない実行環境での代替品。\r
- * @param prop プロパティ\r
- * @param prefix 接頭辞\r
- * @param defValue 見つからなかった場合のデフォルト値\r
- * @return パッケージ情報\r
- */\r
- private static String getPackageInfo(Properties prop,\r
- String prefix,\r
- String defValue){\r
- return getPackageInfo(prop, SELF_PACKAGE, prefix, defValue);\r
- }\r
-\r
- /**\r
- * リソース上のプロパティからパッケージ情報を取得する。\r
- * MANIFEST.MFが参照できない実行環境での代替品。\r
- * @param prop プロパティ\r
- * @param pkg 任意のパッケージ\r
- * @param prefix 接頭辞\r
- * @param defValue デフォルト値\r
- * @return 見つからなかった場合のパッケージ情報\r
- */\r
- private static String getPackageInfo(Properties prop,\r
- Package pkg,\r
- String prefix,\r
- String defValue){\r
- String propName = prefix + pkg.getName();\r
- String result = prop.getProperty(propName, defValue);\r
- return result;\r
- }\r
-\r
- /**\r
- * System.err.println()のWrapper。\r
- * @param text 出力テキスト\r
- */\r
- private static void errprintln(CharSequence text){\r
- System.err.println(text);\r
- return;\r
- }\r
-\r
- /**\r
- * プログラムの終了。\r
- * @param code プロセスコード。\r
- */\r
- private static void exit(int code){\r
- System.exit(code);\r
- assert false;\r
- return;\r
- }\r
-\r
- /**\r
- * 国IDから国情報を得る。\r
- * @param landId 国ID\r
- * @return 国情報\r
- */\r
- public static LandDef getLandDef(String landId){\r
- for(LandDef landDef : LANDDEF_LIST){\r
- if(landDef.getLandId().equals(landId)) return landDef;\r
- }\r
- return null;\r
- }\r
-\r
- /**\r
- * ヘルプメッセージ出力。\r
- */\r
- private static void helpMessage(){\r
- errprintln(\r
- "\n" + GENERATOR + " 人狼BBS アーカイブ作成ツール\n\n"\r
- +"-h, -help, -?\n\tヘルプメッセージ\n"\r
- +"-land 国識別子\n"\r
- +"-vid 村番号\n"\r
- +"-outdir 出力ディレクトリ\n"\r
- +"-stdout\n\t標準出力へ出力\n\n"\r
- +"※ -outdir と -stdout は排他指定\n"\r
- );\r
- StringBuilder landList = new StringBuilder();\r
- for(LandDef landDef : LANDDEF_LIST){\r
- landList.append(landDef.getLandId()).append(' ');\r
- }\r
- errprintln("利用可能な国識別子は " + landList + "\n");\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * オプション文字列を解析する。\r
- * @param args オプション文字列\r
- */\r
- private static void parseOption(String[] args){\r
- if(args.length <= 0){\r
- helpMessage();\r
- exit(0);\r
- return;\r
- }\r
-\r
- LandDef landDef = null;\r
- int vid = -1;\r
- String outdir = null;\r
- boolean stdout = false;\r
-\r
- for(int pos = 0; pos < args.length; pos++){\r
- String arg = args[pos];\r
-\r
- if( ! arg.startsWith("-") ){\r
- errprintln("不正なオプションです。 " + arg);\r
- exit(1);\r
- return;\r
- }\r
-\r
- if(arg.equals("-h") || arg.equals("-help") || arg.equals("-?")){\r
- helpMessage();\r
- exit(0);\r
- return;\r
- }\r
-\r
- if(arg.equals("-stdout")){\r
- stdout = true;\r
- outdir = null;\r
- continue;\r
- }\r
-\r
- if(++pos >= args.length){\r
- errprintln(\r
- "オプション " + arg + " に引数がありません。");\r
- exit(1);\r
- return;\r
- }\r
-\r
- String val = args[pos];\r
- if(arg.equals("-land")){\r
- landDef = getLandDef(val);\r
- if(landDef == null){\r
- errprintln("不正な国識別子です。 " + val);\r
- exit(1);\r
- return;\r
- }\r
- }else if(arg.equals("-vid")){\r
- vid = Integer.parseInt(val);\r
- if(vid < 0){\r
- errprintln("不正な村番号です。 " + vid);\r
- exit(1);\r
- return;\r
- }\r
- }else if(arg.equals("-outdir")){\r
- outdir = val;\r
- stdout = false;\r
- }else{\r
- errprintln("不正なオプションです。 " + arg);\r
- exit(1);\r
- return;\r
- }\r
- }\r
-\r
- if(landDef == null){\r
- errprintln(\r
- "-land オプションで国識別子を指定してください。");\r
- exit(1);\r
- return;\r
- }\r
-\r
- if(vid < 0){\r
- errprintln(\r
- "-vid オプションで村番号を指定してください。");\r
- exit(1);\r
- return;\r
- }\r
-\r
- if( (outdir == null && stdout == false)\r
- || (outdir != null && stdout == true) ){\r
- errprintln(\r
- "-outdir か -stdout のどちらか一方を指定してください。");\r
- exit(1);\r
- return;\r
- }\r
-\r
- Writer writer;\r
- if(outdir != null){\r
- writer = getFileWriter(outdir, landDef, vid);\r
- }else{\r
- writer = getStdOutWriter();\r
- }\r
-\r
- writer = ValidateTask.wrapValidator(writer);\r
-\r
- try{\r
- dump(writer, landDef, vid);\r
- }catch(IOException e){\r
- abortWithException(e);\r
- }catch(DecodeException e){\r
- abortWithException(e);\r
- }catch(HtmlParseException e){\r
- abortWithException(e);\r
- }\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 例外によるアプリ終了。\r
- * @param e 例外\r
- */\r
- private static void abortWithException(Exception e){\r
- e.printStackTrace(System.err);\r
- errprintln("処理を続行できません。");\r
- exit(1);\r
- return;\r
- }\r
-\r
- /**\r
- * 主処理。人狼サーバからXHTMLを読み込み。XMLで出力。\r
- * @param writer 出力先\r
- * @param landDef 国情報\r
- * @param vid 村番号\r
- * @throws IOException 入出力エラー\r
- * @throws DecodeException デコードエラー\r
- * @throws HtmlParseException パースエラー\r
- */\r
- public static void dump(Writer writer, LandDef landDef, int vid)\r
- throws IOException, DecodeException, HtmlParseException{\r
- List<PeriodResource> resourceList =\r
- HttpAccess.loadResourceList(landDef, vid);\r
- VillageData village = new VillageData(resourceList);\r
-\r
- Builder.fillVillageData(village);\r
- XmlUtils.dumpVillageData(writer, village);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 標準出力への出力先を得る。\r
- * @return 出力先\r
- */\r
- public static Writer getStdOutWriter(){\r
- OutputStream ostream;\r
- ostream = new BufferedOutputStream(System.out);\r
- Writer writer;\r
- try{\r
- writer = new OutputStreamWriter(ostream, "UTF-8");\r
- writer = new BufferedWriter(writer, 4 * 1024);\r
- }catch(IOException e){\r
- errprintln(\r
- "標準出力に書き込めません。");\r
- exit(1);\r
- return null;\r
- }\r
- return writer;\r
- }\r
-\r
- /**\r
- * ローカルファイルへの出力先を得る。\r
- * @param outdir 出力ディレクトリ\r
- * @param landDef 国情報\r
- * @param vid 村番号\r
- * @return 出力先\r
- */\r
- public static Writer getFileWriter(String outdir,\r
- LandDef landDef,\r
- int vid ){\r
- File outFile = new File(outdir);\r
- if( ! outFile.exists() ){\r
- errprintln(\r
- outdir + " が存在しません。");\r
- exit(1);\r
- return null;\r
- }\r
- if( ! outFile.isDirectory() ){\r
- errprintln(\r
- outdir + " はディレクトリではありません。");\r
- exit(1);\r
- return null;\r
- }\r
- if( ! outFile.canWrite() ){\r
- errprintln(\r
- outdir + " に書き込めません。");\r
- exit(1);\r
- return null;\r
- }\r
- String fname = MessageFormat.format(\r
- "jin_{0}_{1,number,#00000}.xml", landDef.getLandId(), vid);\r
- File xmlFile = new File(outFile, fname);\r
- boolean created;\r
- try{\r
- created = xmlFile.createNewFile();\r
- }catch(IOException e){\r
- errprintln(\r
- xmlFile.getName() + " が作成できません。");\r
- exit(1);\r
- return null;\r
- }\r
- if( ! created ){\r
- errprintln(\r
- fname + " が既に" + outdir + "に存在します。");\r
- exit(1);\r
- return null;\r
- }\r
- /* JRE 1.6 only\r
- xmlFile.setReadable(true);\r
- xmlFile.setWritable(true);\r
- xmlFile.setExecutable(false, false);\r
- */\r
- Writer writer;\r
- try{\r
- OutputStream ostream;\r
- ostream = new FileOutputStream(xmlFile);\r
- ostream = new BufferedOutputStream(ostream, 4 * 1024);\r
- writer = new OutputStreamWriter(ostream, "UTF-8");\r
- writer = new BufferedWriter(writer, 4 * 1024);\r
- }catch(IOException e){\r
- errprintln(\r
- xmlFile.getName() + " に書き込めません。");\r
- exit(1);\r
- return null;\r
- }\r
-\r
- return writer;\r
- }\r
-\r
- /**\r
- * スタートアップエントリ。\r
- * @param args 引数\r
- */\r
- public static void main(String[] args){\r
- parseOption(args);\r
- exit(0);\r
- return;\r
- }\r
-\r
-}\r
+/*
+ * main entry
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.Properties;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import jp.sourceforge.jindolf.corelib.LandDef;
+import jp.sourceforge.jindolf.parser.DecodeException;
+import jp.sourceforge.jindolf.parser.HtmlParseException;
+import org.xml.sax.SAXException;
+
+/**
+ * メインエントリ。
+ */
+public final class JinArchiver{
+
+ /** Generator. */
+ public static final String GENERATOR;
+
+ /** このClass。 */
+ private static final Class<?> SELF_KLASS;
+ /** このPackage。 */
+ private static final Package SELF_PACKAGE;
+ /** タイトル。 */
+ private static final String TITLE;
+ /** バージョン。 */
+ private static final String VERSION;
+
+ private static final List<LandDef> LANDDEF_LIST;
+
+ /** バージョン定義リソース。 */
+ private static final String RES_VERDEF = "resources/version.properties";
+
+ static{
+ SELF_KLASS = JinArchiver.class;
+ SELF_PACKAGE = SELF_KLASS.getPackage();
+
+ Properties verProp = loadVersionDefinition(SELF_KLASS);
+ TITLE = getPackageInfo(verProp, "pkg-title.", "Unknown");
+ VERSION = getPackageInfo(verProp, "pkg-version.", "0");
+ GENERATOR = TITLE + " " + VERSION;
+
+ DocumentBuilderFactory factory =
+ DocumentBuilderFactory.newInstance();
+ try{
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ LANDDEF_LIST = LandDef.buildLandDefList(builder);
+ }catch(ParserConfigurationException e){
+ throw new ExceptionInInitializerError(e);
+ }catch(IOException e){
+ throw new ExceptionInInitializerError(e);
+ }catch(SAXException e){
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+
+ /**
+ * 隠しコンストラクタ。
+ */
+ private JinArchiver(){
+ throw new Error();
+ }
+
+
+ /**
+ * リソース上のパッケージ定義プロパティをロードする。
+ * MANIFEST.MFが参照できない実行環境での代替品。
+ * @param klass パッケージを構成する任意のクラス
+ * @return プロパティ
+ */
+ private static Properties loadVersionDefinition(Class klass){
+ Properties result = new Properties();
+
+ InputStream istream = klass.getResourceAsStream(RES_VERDEF);
+ try{
+ result.load(istream);
+ }catch(IOException e){
+ return result;
+ }finally{
+ try{
+ istream.close();
+ }catch(IOException e){
+ return result;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * リソース上のプロパティから
+ * このクラスのパッケージのパッケージ情報を取得する。
+ * MANIFEST.MFが参照できない実行環境での代替品。
+ * @param prop プロパティ
+ * @param prefix 接頭辞
+ * @param defValue 見つからなかった場合のデフォルト値
+ * @return パッケージ情報
+ */
+ private static String getPackageInfo(Properties prop,
+ String prefix,
+ String defValue){
+ return getPackageInfo(prop, SELF_PACKAGE, prefix, defValue);
+ }
+
+ /**
+ * リソース上のプロパティからパッケージ情報を取得する。
+ * MANIFEST.MFが参照できない実行環境での代替品。
+ * @param prop プロパティ
+ * @param pkg 任意のパッケージ
+ * @param prefix 接頭辞
+ * @param defValue デフォルト値
+ * @return 見つからなかった場合のパッケージ情報
+ */
+ private static String getPackageInfo(Properties prop,
+ Package pkg,
+ String prefix,
+ String defValue){
+ String propName = prefix + pkg.getName();
+ String result = prop.getProperty(propName, defValue);
+ return result;
+ }
+
+ /**
+ * System.err.println()のWrapper。
+ * @param text 出力テキスト
+ */
+ private static void errprintln(CharSequence text){
+ System.err.println(text);
+ return;
+ }
+
+ /**
+ * プログラムの終了。
+ * @param code プロセスコード。
+ */
+ private static void exit(int code){
+ System.exit(code);
+ assert false;
+ return;
+ }
+
+ /**
+ * 国IDから国情報を得る。
+ * @param landId 国ID
+ * @return 国情報
+ */
+ public static LandDef getLandDef(String landId){
+ for(LandDef landDef : LANDDEF_LIST){
+ if(landDef.getLandId().equals(landId)) return landDef;
+ }
+ return null;
+ }
+
+ /**
+ * ヘルプメッセージ出力。
+ */
+ private static void helpMessage(){
+ errprintln(
+ "\n" + GENERATOR + " 人狼BBS アーカイブ作成ツール\n\n"
+ +"-h, -help, -?\n\tヘルプメッセージ\n"
+ +"-land 国識別子\n"
+ +"-vid 村番号\n"
+ +"-outdir 出力ディレクトリ\n"
+ +"-stdout\n\t標準出力へ出力\n\n"
+ +"※ -outdir と -stdout は排他指定\n"
+ );
+ StringBuilder landList = new StringBuilder();
+ for(LandDef landDef : LANDDEF_LIST){
+ landList.append(landDef.getLandId()).append(' ');
+ }
+ errprintln("利用可能な国識別子は " + landList + "\n");
+
+ return;
+ }
+
+ /**
+ * オプション文字列を解析する。
+ * @param args オプション文字列
+ */
+ private static void parseOption(String[] args){
+ if(args.length <= 0){
+ helpMessage();
+ exit(0);
+ return;
+ }
+
+ LandDef landDef = null;
+ int vid = -1;
+ String outdir = null;
+ boolean stdout = false;
+
+ for(int pos = 0; pos < args.length; pos++){
+ String arg = args[pos];
+
+ if( ! arg.startsWith("-") ){
+ errprintln("不正なオプションです。 " + arg);
+ exit(1);
+ return;
+ }
+
+ if(arg.equals("-h") || arg.equals("-help") || arg.equals("-?")){
+ helpMessage();
+ exit(0);
+ return;
+ }
+
+ if(arg.equals("-stdout")){
+ stdout = true;
+ outdir = null;
+ continue;
+ }
+
+ if(++pos >= args.length){
+ errprintln(
+ "オプション " + arg + " に引数がありません。");
+ exit(1);
+ return;
+ }
+
+ String val = args[pos];
+ if(arg.equals("-land")){
+ landDef = getLandDef(val);
+ if(landDef == null){
+ errprintln("不正な国識別子です。 " + val);
+ exit(1);
+ return;
+ }
+ }else if(arg.equals("-vid")){
+ vid = Integer.parseInt(val);
+ if(vid < 0){
+ errprintln("不正な村番号です。 " + vid);
+ exit(1);
+ return;
+ }
+ }else if(arg.equals("-outdir")){
+ outdir = val;
+ stdout = false;
+ }else{
+ errprintln("不正なオプションです。 " + arg);
+ exit(1);
+ return;
+ }
+ }
+
+ if(landDef == null){
+ errprintln(
+ "-land オプションで国識別子を指定してください。");
+ exit(1);
+ return;
+ }
+
+ if(vid < 0){
+ errprintln(
+ "-vid オプションで村番号を指定してください。");
+ exit(1);
+ return;
+ }
+
+ if( (outdir == null && stdout == false)
+ || (outdir != null && stdout == true) ){
+ errprintln(
+ "-outdir か -stdout のどちらか一方を指定してください。");
+ exit(1);
+ return;
+ }
+
+ Writer writer;
+ if(outdir != null){
+ writer = getFileWriter(outdir, landDef, vid);
+ }else{
+ writer = getStdOutWriter();
+ }
+
+ writer = ValidateTask.wrapValidator(writer);
+
+ try{
+ dump(writer, landDef, vid);
+ }catch(IOException e){
+ abortWithException(e);
+ }catch(DecodeException e){
+ abortWithException(e);
+ }catch(HtmlParseException e){
+ abortWithException(e);
+ }
+
+ return;
+ }
+
+ /**
+ * 例外によるアプリ終了。
+ * @param e 例外
+ */
+ private static void abortWithException(Exception e){
+ e.printStackTrace(System.err);
+ errprintln("処理を続行できません。");
+ exit(1);
+ return;
+ }
+
+ /**
+ * 主処理。人狼サーバからXHTMLを読み込み。XMLで出力。
+ * @param writer 出力先
+ * @param landDef 国情報
+ * @param vid 村番号
+ * @throws IOException 入出力エラー
+ * @throws DecodeException デコードエラー
+ * @throws HtmlParseException パースエラー
+ */
+ public static void dump(Writer writer, LandDef landDef, int vid)
+ throws IOException, DecodeException, HtmlParseException{
+ List<PeriodResource> resourceList =
+ HttpAccess.loadResourceList(landDef, vid);
+ VillageData village = new VillageData(resourceList);
+
+ Builder.fillVillageData(village);
+ XmlUtils.dumpVillageData(writer, village);
+
+ return;
+ }
+
+ /**
+ * 標準出力への出力先を得る。
+ * @return 出力先
+ */
+ public static Writer getStdOutWriter(){
+ OutputStream ostream;
+ ostream = new BufferedOutputStream(System.out);
+ Writer writer;
+ try{
+ writer = new OutputStreamWriter(ostream, "UTF-8");
+ writer = new BufferedWriter(writer, 4 * 1024);
+ }catch(IOException e){
+ errprintln(
+ "標準出力に書き込めません。");
+ exit(1);
+ return null;
+ }
+ return writer;
+ }
+
+ /**
+ * ローカルファイルへの出力先を得る。
+ * @param outdir 出力ディレクトリ
+ * @param landDef 国情報
+ * @param vid 村番号
+ * @return 出力先
+ */
+ public static Writer getFileWriter(String outdir,
+ LandDef landDef,
+ int vid ){
+ File outFile = new File(outdir);
+ if( ! outFile.exists() ){
+ errprintln(
+ outdir + " が存在しません。");
+ exit(1);
+ return null;
+ }
+ if( ! outFile.isDirectory() ){
+ errprintln(
+ outdir + " はディレクトリではありません。");
+ exit(1);
+ return null;
+ }
+ if( ! outFile.canWrite() ){
+ errprintln(
+ outdir + " に書き込めません。");
+ exit(1);
+ return null;
+ }
+ String fname = MessageFormat.format(
+ "jin_{0}_{1,number,#00000}.xml", landDef.getLandId(), vid);
+ File xmlFile = new File(outFile, fname);
+ boolean created;
+ try{
+ created = xmlFile.createNewFile();
+ }catch(IOException e){
+ errprintln(
+ xmlFile.getName() + " が作成できません。");
+ exit(1);
+ return null;
+ }
+ if( ! created ){
+ errprintln(
+ fname + " が既に" + outdir + "に存在します。");
+ exit(1);
+ return null;
+ }
+ /* JRE 1.6 only
+ xmlFile.setReadable(true);
+ xmlFile.setWritable(true);
+ xmlFile.setExecutable(false, false);
+ */
+ Writer writer;
+ try{
+ OutputStream ostream;
+ ostream = new FileOutputStream(xmlFile);
+ ostream = new BufferedOutputStream(ostream, 4 * 1024);
+ writer = new OutputStreamWriter(ostream, "UTF-8");
+ writer = new BufferedWriter(writer, 4 * 1024);
+ }catch(IOException e){
+ errprintln(
+ xmlFile.getName() + " に書き込めません。");
+ exit(1);
+ return null;
+ }
+
+ return writer;
+ }
+
+ /**
+ * スタートアップエントリ。
+ * @param args 引数
+ */
+ public static void main(String[] args){
+ parseOption(args);
+ exit(0);
+ return;
+ }
+
+}
-/*\r
- * Multiplex Writer\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.IOException;\r
-import java.io.Writer;\r
-import java.util.Collections;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-\r
-/**\r
- * Writerのマルチプレクサ。\r
- */\r
-public class MultiPlexer extends Writer{\r
-\r
- private final List<Writer> childs = new LinkedList<Writer>();\r
-\r
- /**\r
- * コンストラクタ。\r
- */\r
- public MultiPlexer(){\r
- this(null);\r
- return;\r
- }\r
-\r
- /**\r
- * コンストラクタ。\r
- * @param writer 初期Writer\r
- */\r
- public MultiPlexer(Writer writer){\r
- super();\r
-\r
- if(writer != null){\r
- this.childs.add(writer);\r
- }\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * Writerを追加する。\r
- * @param writer 追加するWriter。nullなら無視。\r
- */\r
- public void addWriter(Writer writer){\r
- if(writer == null) return;\r
- this.childs.add(writer);\r
- return;\r
- }\r
-\r
- /**\r
- * 出力するWriterの一覧を得る。\r
- * @return Writer一覧。\r
- */\r
- public List<Writer> getWriterList(){\r
- return Collections.unmodifiableList(this.childs);\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @throws IOException {@inheritDoc}\r
- */\r
- @Override\r
- public void close() throws IOException{\r
- for(Writer writer : this.childs){\r
- writer.close();\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @throws IOException {@inheritDoc}\r
- */\r
- @Override\r
- public void flush() throws IOException{\r
- for(Writer writer : this.childs){\r
- writer.flush();\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param cbuf {@inheritDoc}\r
- * @param off {@inheritDoc}\r
- * @param len {@inheritDoc}\r
- * @throws IOException {@inheritDoc}\r
- */\r
- @Override\r
- public void write(char[] cbuf, int off, int len) throws IOException{\r
- for(Writer writer : this.childs){\r
- writer.write(cbuf, off, len);\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param csq {@inheritDoc}\r
- * @return {@inheritDoc}\r
- * @throws IOException {@inheritDoc}\r
- */\r
- @Override\r
- public Writer append(CharSequence csq) throws IOException{\r
- for(Writer writer : this.childs){\r
- writer.append(csq);\r
- }\r
- return this;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param csq {@inheritDoc}\r
- * @param start {@inheritDoc}\r
- * @param end {@inheritDoc}\r
- * @return {@inheritDoc}\r
- * @throws IOException {@inheritDoc}\r
- */\r
- @Override\r
- public Writer append(CharSequence csq, int start, int end)\r
- throws IOException{\r
- for(Writer writer : this.childs){\r
- writer.append(csq, start, end);\r
- }\r
- return this;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param c {@inheritDoc}\r
- * @return {@inheritDoc}\r
- * @throws IOException {@inheritDoc}\r
- */\r
- @Override\r
- public Writer append(char c) throws IOException{\r
- for(Writer writer : this.childs){\r
- writer.append(c);\r
- }\r
- return this;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param c {@inheritDoc}\r
- * @throws IOException {@inheritDoc}\r
- */\r
- @Override\r
- public void write(int c) throws IOException{\r
- for(Writer writer : this.childs){\r
- writer.write(c);\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param cbuf {@inheritDoc}\r
- * @throws IOException {@inheritDoc}\r
- */\r
- @Override\r
- public void write(char[] cbuf) throws IOException{\r
- for(Writer writer : this.childs){\r
- writer.write(cbuf);\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param str {@inheritDoc}\r
- * @throws IOException {@inheritDoc}\r
- */\r
- @Override\r
- public void write(String str) throws IOException{\r
- for(Writer writer : this.childs){\r
- writer.write(str);\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * @param str {@inheritDoc}\r
- * @param off {@inheritDoc}\r
- * @param len {@inheritDoc}\r
- * @throws IOException {@inheritDoc}\r
- */\r
- @Override\r
- public void write(String str, int off, int len) throws IOException{\r
- for(Writer writer : this.childs){\r
- writer.write(str, off, len);\r
- }\r
- return;\r
- }\r
-\r
-}\r
+/*
+ * Multiplex Writer
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Writerのマルチプレクサ。
+ */
+public class MultiPlexer extends Writer{
+
+ private final List<Writer> childs = new LinkedList<Writer>();
+
+ /**
+ * コンストラクタ。
+ */
+ public MultiPlexer(){
+ this(null);
+ return;
+ }
+
+ /**
+ * コンストラクタ。
+ * @param writer 初期Writer
+ */
+ public MultiPlexer(Writer writer){
+ super();
+
+ if(writer != null){
+ this.childs.add(writer);
+ }
+
+ return;
+ }
+
+ /**
+ * Writerを追加する。
+ * @param writer 追加するWriter。nullなら無視。
+ */
+ public void addWriter(Writer writer){
+ if(writer == null) return;
+ this.childs.add(writer);
+ return;
+ }
+
+ /**
+ * 出力するWriterの一覧を得る。
+ * @return Writer一覧。
+ */
+ public List<Writer> getWriterList(){
+ return Collections.unmodifiableList(this.childs);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ */
+ @Override
+ public void close() throws IOException{
+ for(Writer writer : this.childs){
+ writer.close();
+ }
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ */
+ @Override
+ public void flush() throws IOException{
+ for(Writer writer : this.childs){
+ writer.flush();
+ }
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param cbuf {@inheritDoc}
+ * @param off {@inheritDoc}
+ * @param len {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ */
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException{
+ for(Writer writer : this.childs){
+ writer.write(cbuf, off, len);
+ }
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param csq {@inheritDoc}
+ * @return {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ */
+ @Override
+ public Writer append(CharSequence csq) throws IOException{
+ for(Writer writer : this.childs){
+ writer.append(csq);
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param csq {@inheritDoc}
+ * @param start {@inheritDoc}
+ * @param end {@inheritDoc}
+ * @return {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ */
+ @Override
+ public Writer append(CharSequence csq, int start, int end)
+ throws IOException{
+ for(Writer writer : this.childs){
+ writer.append(csq, start, end);
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param c {@inheritDoc}
+ * @return {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ */
+ @Override
+ public Writer append(char c) throws IOException{
+ for(Writer writer : this.childs){
+ writer.append(c);
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param c {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ */
+ @Override
+ public void write(int c) throws IOException{
+ for(Writer writer : this.childs){
+ writer.write(c);
+ }
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param cbuf {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ */
+ @Override
+ public void write(char[] cbuf) throws IOException{
+ for(Writer writer : this.childs){
+ writer.write(cbuf);
+ }
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param str {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ */
+ @Override
+ public void write(String str) throws IOException{
+ for(Writer writer : this.childs){
+ writer.write(str);
+ }
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param str {@inheritDoc}
+ * @param off {@inheritDoc}
+ * @param len {@inheritDoc}
+ * @throws IOException {@inheritDoc}
+ */
+ @Override
+ public void write(String str, int off, int len) throws IOException{
+ for(Writer writer : this.childs){
+ writer.write(str, off, len);
+ }
+ return;
+ }
+
+}
-/*\r
- * period model\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.IOException;\r
-import java.io.Writer;\r
-import java.net.URI;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import jp.sourceforge.jindolf.corelib.DisclosureType;\r
-import jp.sourceforge.jindolf.corelib.SysEventType;\r
-import jp.sourceforge.jindolf.parser.DecodedContent;\r
-\r
-/**\r
- * Periodモデル。\r
- */\r
-public class PeriodData{\r
-\r
- private final VillageData parent;\r
- private final PeriodResource resource;\r
- private DecodedContent loginName = new DecodedContent("");\r
- private int commitMonth;\r
- private int commitDay;\r
- private int commitHour;\r
- private int commitMinute;\r
- private DisclosureType disclosureType = DisclosureType.HOT;\r
- private boolean hasMurderResult = false;\r
-\r
- private final List<TopicData> topicList = new LinkedList<TopicData>();\r
-\r
- /**\r
- * コンストラクタ。\r
- * @param parent 所属村\r
- * @param resource ロード元情報\r
- */\r
- public PeriodData(VillageData parent, PeriodResource resource){\r
- super();\r
- this.parent = parent;\r
- this.resource = resource;\r
- return;\r
- }\r
-\r
- /**\r
- * ロード時のログイン名を取得する。\r
- * @return ログイン名\r
- */\r
- public DecodedContent getLoginName(){\r
- return this.loginName;\r
- }\r
-\r
- /**\r
- * ロード時のログイン名を設定する。\r
- * @param loginName ログイン名\r
- */\r
- public void setLoginName(DecodedContent loginName){\r
- this.loginName = loginName;\r
- return;\r
- }\r
-\r
- /**\r
- * コミット月を取得する。\r
- * @return コミット月\r
- */\r
- public int getCommitMonth(){\r
- return this.commitMonth;\r
- }\r
-\r
- /**\r
- * コミット月を設定する。\r
- * @param commitMonth コミット月\r
- */\r
- public void setCommitMonth(int commitMonth){\r
- this.commitMonth = commitMonth;\r
- return;\r
- }\r
-\r
- /**\r
- * コミット日を取得する。\r
- * @return コミット日\r
- */\r
- public int getCommitDay(){\r
- return this.commitDay;\r
- }\r
-\r
- /**\r
- * コミット日を設定する。\r
- * @param commitDay コミット日\r
- */\r
- public void setCommitDay(int commitDay){\r
- this.commitDay = commitDay;\r
- return;\r
- }\r
-\r
- /**\r
- * コミット時を取得する。\r
- * @return コミット時\r
- */\r
- public int getCommitHour(){\r
- return this.commitHour;\r
- }\r
-\r
- /**\r
- * コミット時を設定する。\r
- * @param commitHour コミット時\r
- */\r
- public void setCommitHour(int commitHour){\r
- this.commitHour = commitHour;\r
- return;\r
- }\r
-\r
- /**\r
- * コミット分を取得する。\r
- * @return コミット分\r
- */\r
- public int getCommitMinute(){\r
- return this.commitMinute;\r
- }\r
-\r
- /**\r
- * コミット分を設定する。\r
- * @param commitMinute コミット分\r
- */\r
- public void setCommitMinute(int commitMinute){\r
- this.commitMinute = commitMinute;\r
- return;\r
- }\r
-\r
- /**\r
- * 開示状況を取得する。\r
- * @return 開示状況\r
- */\r
- public DisclosureType getDisclosureType(){\r
- return this.disclosureType;\r
- }\r
-\r
- /**\r
- * 開示状況を設定する。\r
- * @param type 開示状況\r
- */\r
- public void setDisclosureType(DisclosureType type){\r
- this.disclosureType = type;\r
- return;\r
- }\r
-\r
- /**\r
- * 襲撃結果イベントが既に格納されているか確認する。\r
- * @return 襲撃結果があればtrue\r
- */\r
- public boolean hasMurderResult(){\r
- return this.hasMurderResult;\r
- }\r
-\r
- /**\r
- * TopicDataを追加する。\r
- * 襲撃結果の有無も判定される。\r
- * @param topicData TopiData\r
- */\r
- public void addTopicData(TopicData topicData){\r
- this.topicList.add(topicData);\r
-\r
- if(topicData instanceof EventData){\r
- EventData event = (EventData) topicData;\r
- SysEventType type = event.getEventType();\r
- if( type == SysEventType.MURDERED\r
- || type == SysEventType.NOMURDER){\r
- this.hasMurderResult = true;\r
- }\r
- }\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * period要素をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpXml(Writer writer) throws IOException{\r
- writer.append("<period\n");\r
-\r
- String ptype;\r
- switch(this.resource.getPeriodType()){\r
- case PROLOGUE:\r
- ptype = "prologue";\r
- break;\r
- case PROGRESS:\r
- ptype = "progress";\r
- break;\r
- case EPILOGUE:\r
- ptype = "epilogue";\r
- break;\r
- default:\r
- throw new IllegalArgumentException();\r
- }\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "type", ptype);\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer,\r
- "day", Integer.toString(this.resource.getDay()));\r
- writer.append('\n');\r
-\r
- if(this.disclosureType != DisclosureType.COMPLETE){\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer,\r
- "disclosure", this.disclosureType.getXmlName());\r
- writer.append('\n');\r
- }\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.dateAttrOut(writer, "nextCommitDay",\r
- this.commitMonth, this.commitDay);\r
-\r
- writer.append(' ');\r
- XmlUtils.timeAttrOut(writer,\r
- "commitTime",\r
- this.commitHour, this.commitMinute);\r
- writer.append('\n');\r
-\r
- URI baseUri = URI.create(this.parent.getBaseUri());\r
- URI periodUri = URI.create(this.resource.getOrigUrlText());\r
- URI relativeUri = baseUri.relativize(periodUri);\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "sourceURI", relativeUri.toString());\r
- writer.append('\n');\r
-\r
- long downTimeMs = this.resource.getDownTimeMs();\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.dateTimeAttr(writer, "loadedTime", downTimeMs);\r
- writer.append('\n');\r
-\r
- if(this.loginName.length() > 0){\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "loadedBy", this.loginName.toString());\r
- writer.append('\n');\r
- }\r
-\r
- writer.append(">\n\n");\r
-\r
- for(TopicData topic : this.topicList){\r
- topic.dumpXml(writer);\r
- writer.append('\n');\r
- writer.flush();\r
- }\r
-\r
- writer.append("</period>\n");\r
-\r
- return;\r
- }\r
-\r
-}\r
+/*
+ * period model
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.net.URI;
+import java.util.LinkedList;
+import java.util.List;
+import jp.sourceforge.jindolf.corelib.DisclosureType;
+import jp.sourceforge.jindolf.corelib.SysEventType;
+import jp.sourceforge.jindolf.parser.DecodedContent;
+
+/**
+ * Periodモデル。
+ */
+public class PeriodData{
+
+ private final VillageData parent;
+ private final PeriodResource resource;
+ private DecodedContent loginName = new DecodedContent("");
+ private int commitMonth;
+ private int commitDay;
+ private int commitHour;
+ private int commitMinute;
+ private DisclosureType disclosureType = DisclosureType.HOT;
+ private boolean hasMurderResult = false;
+
+ private final List<TopicData> topicList = new LinkedList<TopicData>();
+
+ /**
+ * コンストラクタ。
+ * @param parent 所属村
+ * @param resource ロード元情報
+ */
+ public PeriodData(VillageData parent, PeriodResource resource){
+ super();
+ this.parent = parent;
+ this.resource = resource;
+ return;
+ }
+
+ /**
+ * ロード時のログイン名を取得する。
+ * @return ログイン名
+ */
+ public DecodedContent getLoginName(){
+ return this.loginName;
+ }
+
+ /**
+ * ロード時のログイン名を設定する。
+ * @param loginName ログイン名
+ */
+ public void setLoginName(DecodedContent loginName){
+ this.loginName = loginName;
+ return;
+ }
+
+ /**
+ * コミット月を取得する。
+ * @return コミット月
+ */
+ public int getCommitMonth(){
+ return this.commitMonth;
+ }
+
+ /**
+ * コミット月を設定する。
+ * @param commitMonth コミット月
+ */
+ public void setCommitMonth(int commitMonth){
+ this.commitMonth = commitMonth;
+ return;
+ }
+
+ /**
+ * コミット日を取得する。
+ * @return コミット日
+ */
+ public int getCommitDay(){
+ return this.commitDay;
+ }
+
+ /**
+ * コミット日を設定する。
+ * @param commitDay コミット日
+ */
+ public void setCommitDay(int commitDay){
+ this.commitDay = commitDay;
+ return;
+ }
+
+ /**
+ * コミット時を取得する。
+ * @return コミット時
+ */
+ public int getCommitHour(){
+ return this.commitHour;
+ }
+
+ /**
+ * コミット時を設定する。
+ * @param commitHour コミット時
+ */
+ public void setCommitHour(int commitHour){
+ this.commitHour = commitHour;
+ return;
+ }
+
+ /**
+ * コミット分を取得する。
+ * @return コミット分
+ */
+ public int getCommitMinute(){
+ return this.commitMinute;
+ }
+
+ /**
+ * コミット分を設定する。
+ * @param commitMinute コミット分
+ */
+ public void setCommitMinute(int commitMinute){
+ this.commitMinute = commitMinute;
+ return;
+ }
+
+ /**
+ * 開示状況を取得する。
+ * @return 開示状況
+ */
+ public DisclosureType getDisclosureType(){
+ return this.disclosureType;
+ }
+
+ /**
+ * 開示状況を設定する。
+ * @param type 開示状況
+ */
+ public void setDisclosureType(DisclosureType type){
+ this.disclosureType = type;
+ return;
+ }
+
+ /**
+ * 襲撃結果イベントが既に格納されているか確認する。
+ * @return 襲撃結果があればtrue
+ */
+ public boolean hasMurderResult(){
+ return this.hasMurderResult;
+ }
+
+ /**
+ * TopicDataを追加する。
+ * 襲撃結果の有無も判定される。
+ * @param topicData TopiData
+ */
+ public void addTopicData(TopicData topicData){
+ this.topicList.add(topicData);
+
+ if(topicData instanceof EventData){
+ EventData event = (EventData) topicData;
+ SysEventType type = event.getEventType();
+ if( type == SysEventType.MURDERED
+ || type == SysEventType.NOMURDER){
+ this.hasMurderResult = true;
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * period要素をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpXml(Writer writer) throws IOException{
+ writer.append("<period\n");
+
+ String ptype;
+ switch(this.resource.getPeriodType()){
+ case PROLOGUE:
+ ptype = "prologue";
+ break;
+ case PROGRESS:
+ ptype = "progress";
+ break;
+ case EPILOGUE:
+ ptype = "epilogue";
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "type", ptype);
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer,
+ "day", Integer.toString(this.resource.getDay()));
+ writer.append('\n');
+
+ if(this.disclosureType != DisclosureType.COMPLETE){
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer,
+ "disclosure", this.disclosureType.getXmlName());
+ writer.append('\n');
+ }
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.dateAttrOut(writer, "nextCommitDay",
+ this.commitMonth, this.commitDay);
+
+ writer.append(' ');
+ XmlUtils.timeAttrOut(writer,
+ "commitTime",
+ this.commitHour, this.commitMinute);
+ writer.append('\n');
+
+ URI baseUri = URI.create(this.parent.getBaseUri());
+ URI periodUri = URI.create(this.resource.getOrigUrlText());
+ URI relativeUri = baseUri.relativize(periodUri);
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "sourceURI", relativeUri.toString());
+ writer.append('\n');
+
+ long downTimeMs = this.resource.getDownTimeMs();
+ XmlUtils.indent(writer, 1);
+ XmlUtils.dateTimeAttr(writer, "loadedTime", downTimeMs);
+ writer.append('\n');
+
+ if(this.loginName.length() > 0){
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "loadedBy", this.loginName.toString());
+ writer.append('\n');
+ }
+
+ writer.append(">\n\n");
+
+ for(TopicData topic : this.topicList){
+ topic.dumpXml(writer);
+ writer.append('\n');
+ writer.flush();
+ }
+
+ writer.append("</period>\n");
+
+ return;
+ }
+
+}
-/*\r
- * Period resource\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.net.URL;\r
-import jp.sourceforge.jindolf.corelib.LandDef;\r
-import jp.sourceforge.jindolf.corelib.PeriodType;\r
-\r
-/**\r
- * Periodのロード元情報。\r
- */\r
-public class PeriodResource{\r
-\r
- private final LandDef landDef;\r
- private final int villageId;\r
- private final PeriodType periodType;\r
- private final int day;\r
- private final String origUrlText;\r
- private long downTimeMs;\r
- private URL resourceUrl;\r
-\r
- /**\r
- * コンストラクタ。\r
- * @param landDef 国情報\r
- * @param villageId 村ID\r
- * @param periodType Period種別\r
- * @param day 日付\r
- * @param origUrlText ロード元URI文字列\r
- * @param downTimeMs ロード時刻\r
- * @param resourceUrl ロード元URL\r
- */\r
- public PeriodResource(LandDef landDef,\r
- int villageId,\r
- PeriodType periodType,\r
- int day,\r
- String origUrlText,\r
- long downTimeMs,\r
- URL resourceUrl ) {\r
- super();\r
-\r
- this.landDef = landDef;\r
- this.villageId = villageId;\r
- this.periodType = periodType;\r
- this.day = day;\r
- this.origUrlText = origUrlText;\r
- this.downTimeMs = downTimeMs;\r
- this.resourceUrl = resourceUrl;\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 国情報を取得する。\r
- * @return 国情報\r
- */\r
- public LandDef getLandDef(){\r
- return landDef;\r
- }\r
-\r
- /**\r
- * 村番号を取得する。\r
- * @return 村番号\r
- */\r
- public int getVillageId(){\r
- return villageId;\r
- }\r
-\r
- /**\r
- * Periodの種別を取得する。\r
- * @return Period種別\r
- */\r
- public PeriodType getPeriodType(){\r
- return periodType;\r
- }\r
-\r
- /**\r
- * 日付を取得する。\r
- * @return 日付\r
- */\r
- public int getDay(){\r
- return day;\r
- }\r
-\r
- /**\r
- * オリジナルのダウンロード元URL文字列を取得する。\r
- * @return ダウンロード元URL文字列\r
- */\r
- public String getOrigUrlText(){\r
- return origUrlText;\r
- }\r
-\r
- /**\r
- * オリジナルのダウンロード時刻を取得する。\r
- * @return ダウンロード時刻。エポック秒(ms)\r
- */\r
- public long getDownTimeMs(){\r
- return this.downTimeMs;\r
- }\r
-\r
- /**\r
- * オリジナルのダウンロード時刻を設定する。\r
- * @param downTimeMs ダウンロード時刻。エポック秒(ms)\r
- */\r
- public void setDownTimeMs(long downTimeMs){\r
- this.downTimeMs = downTimeMs;\r
- return;\r
- }\r
-\r
- /**\r
- * XHTML格納先URLを取得する。\r
- * @return 格納先URL\r
- */\r
- public URL getResourceUrl(){\r
- return resourceUrl;\r
- }\r
-\r
- /**\r
- * XHTML格納先URLを設定する。\r
- * @param resourceUrl 格納先URL\r
- */\r
- public void setResourceUrl(URL resourceUrl){\r
- this.resourceUrl = resourceUrl;\r
- return;\r
- }\r
-\r
-}\r
+/*
+ * Period resource
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.net.URL;
+import jp.sourceforge.jindolf.corelib.LandDef;
+import jp.sourceforge.jindolf.corelib.PeriodType;
+
+/**
+ * Periodのロード元情報。
+ */
+public class PeriodResource{
+
+ private final LandDef landDef;
+ private final int villageId;
+ private final PeriodType periodType;
+ private final int day;
+ private final String origUrlText;
+ private long downTimeMs;
+ private URL resourceUrl;
+
+ /**
+ * コンストラクタ。
+ * @param landDef 国情報
+ * @param villageId 村ID
+ * @param periodType Period種別
+ * @param day 日付
+ * @param origUrlText ロード元URI文字列
+ * @param downTimeMs ロード時刻
+ * @param resourceUrl ロード元URL
+ */
+ public PeriodResource(LandDef landDef,
+ int villageId,
+ PeriodType periodType,
+ int day,
+ String origUrlText,
+ long downTimeMs,
+ URL resourceUrl ) {
+ super();
+
+ this.landDef = landDef;
+ this.villageId = villageId;
+ this.periodType = periodType;
+ this.day = day;
+ this.origUrlText = origUrlText;
+ this.downTimeMs = downTimeMs;
+ this.resourceUrl = resourceUrl;
+
+ return;
+ }
+
+ /**
+ * 国情報を取得する。
+ * @return 国情報
+ */
+ public LandDef getLandDef(){
+ return landDef;
+ }
+
+ /**
+ * 村番号を取得する。
+ * @return 村番号
+ */
+ public int getVillageId(){
+ return villageId;
+ }
+
+ /**
+ * Periodの種別を取得する。
+ * @return Period種別
+ */
+ public PeriodType getPeriodType(){
+ return periodType;
+ }
+
+ /**
+ * 日付を取得する。
+ * @return 日付
+ */
+ public int getDay(){
+ return day;
+ }
+
+ /**
+ * オリジナルのダウンロード元URL文字列を取得する。
+ * @return ダウンロード元URL文字列
+ */
+ public String getOrigUrlText(){
+ return origUrlText;
+ }
+
+ /**
+ * オリジナルのダウンロード時刻を取得する。
+ * @return ダウンロード時刻。エポック秒(ms)
+ */
+ public long getDownTimeMs(){
+ return this.downTimeMs;
+ }
+
+ /**
+ * オリジナルのダウンロード時刻を設定する。
+ * @param downTimeMs ダウンロード時刻。エポック秒(ms)
+ */
+ public void setDownTimeMs(long downTimeMs){
+ this.downTimeMs = downTimeMs;
+ return;
+ }
+
+ /**
+ * XHTML格納先URLを取得する。
+ * @return 格納先URL
+ */
+ public URL getResourceUrl(){
+ return resourceUrl;
+ }
+
+ /**
+ * XHTML格納先URLを設定する。
+ * @param resourceUrl 格納先URL
+ */
+ public void setResourceUrl(URL resourceUrl){
+ this.resourceUrl = resourceUrl;
+ return;
+ }
+
+}
-/*\r
- * talk dialog\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.IOException;\r
-import java.io.Writer;\r
-import jp.sourceforge.jindolf.corelib.TalkType;\r
-\r
-/**\r
- * 発言モデル。\r
- */\r
-public class TalkData extends TopicData{\r
-\r
- private TalkType talkType = null;\r
- private AvatarData avatarData = null;\r
- private String xName;\r
- private String faceIconUri = null;\r
- private int hour;\r
- private int minute;\r
-\r
- /**\r
- * コンストラクタ。\r
- */\r
- public TalkData(){\r
- super();\r
- return;\r
- }\r
-\r
- /**\r
- * 発言種別を取得する。\r
- * @return 発言種別\r
- */\r
- public TalkType getTalkType(){\r
- return this.talkType;\r
- }\r
-\r
- /**\r
- * 発言種別を設定する。\r
- * @param talkType 発言種別\r
- */\r
- public void setTalkType(TalkType talkType){\r
- this.talkType = talkType;\r
- return;\r
- }\r
-\r
- /**\r
- * 発言したAvatarを取得する。\r
- * @return 発言Avatar\r
- */\r
- public AvatarData getAvatarData(){\r
- return this.avatarData;\r
- }\r
-\r
- /**\r
- * 発言したAvatarを設定する。\r
- * @param avatarData 発言Avatar\r
- */\r
- public void setAvatarData(AvatarData avatarData){\r
- this.avatarData = avatarData;\r
- return;\r
- }\r
-\r
- /**\r
- * 元発言のname属性値を取得する。\r
- * @return name属性値\r
- */\r
- public String getXName(){\r
- return this.xName;\r
- }\r
-\r
- /**\r
- * 元発言のname属性値を設定する。\r
- * @param xName name属性値\r
- */\r
- public void setXName(String xName){\r
- this.xName = xName;\r
- return;\r
- }\r
-\r
- /**\r
- * 顔アイコン画像URI文字列を取得する。\r
- * @return 顔アイコン画像URI文字列\r
- */\r
- public String getFaceIconUri(){\r
- return this.faceIconUri;\r
- }\r
-\r
- /**\r
- * 顔アイコン画像URI文字列を設定する。\r
- * @param faceIconUri 顔アイコン画像URI文字列\r
- */\r
- public void setFaceIconUri(String faceIconUri){\r
- this.faceIconUri = faceIconUri;\r
- return;\r
- }\r
-\r
- /**\r
- * 発言時を取得する。\r
- * @return 発言時\r
- */\r
- public int getHour(){\r
- return this.hour;\r
- }\r
-\r
- /**\r
- * 発言時を設定する。\r
- * @param hour 発言時\r
- */\r
- public void setHour(int hour){\r
- this.hour = hour;\r
- return;\r
- }\r
-\r
- /**\r
- * 発言分を取得する。\r
- * @return 発言分\r
- */\r
- public int getMinute(){\r
- return this.minute;\r
- }\r
-\r
- /**\r
- * 発言分を設定する。\r
- * @param minute 発言分\r
- */\r
- public void setMinute(int minute){\r
- this.minute = minute;\r
- return;\r
- }\r
-\r
- /**\r
- * talk要素をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- @Override\r
- public void dumpXml(Writer writer) throws IOException{\r
- writer.append("<talk\n");\r
-\r
- String typeStr;\r
- switch(this.talkType){\r
- case PUBLIC:\r
- typeStr = "public";\r
- break;\r
- case WOLFONLY:\r
- typeStr = "wolf";\r
- break;\r
- case PRIVATE:\r
- typeStr = "private";\r
- break;\r
- case GRAVE:\r
- typeStr = "grave";\r
- break;\r
- default:\r
- throw new IllegalArgumentException();\r
- }\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "type", typeStr);\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "avatarId", this.avatarData.getAvatarId());\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "xname", this.xName);\r
-\r
- writer.append(' ');\r
- XmlUtils.timeAttrOut(writer, "time", this.hour, this.minute);\r
- writer.append('\n');\r
-\r
- if( this.talkType != TalkType.GRAVE\r
- && ! this.faceIconUri.equals(this.avatarData.getFaceIconUri()) ){\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "faceIconURI", this.faceIconUri);\r
- writer.append('\n');\r
- }\r
-\r
- writer.append(">\n");\r
-\r
- dumpLines(writer);\r
-\r
- writer.append("</talk>\n");\r
- return;\r
- }\r
-\r
-}\r
+/*
+ * talk dialog
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.IOException;
+import java.io.Writer;
+import jp.sourceforge.jindolf.corelib.TalkType;
+
+/**
+ * 発言モデル。
+ */
+public class TalkData extends TopicData{
+
+ private TalkType talkType = null;
+ private AvatarData avatarData = null;
+ private String xName;
+ private String faceIconUri = null;
+ private int hour;
+ private int minute;
+
+ /**
+ * コンストラクタ。
+ */
+ public TalkData(){
+ super();
+ return;
+ }
+
+ /**
+ * 発言種別を取得する。
+ * @return 発言種別
+ */
+ public TalkType getTalkType(){
+ return this.talkType;
+ }
+
+ /**
+ * 発言種別を設定する。
+ * @param talkType 発言種別
+ */
+ public void setTalkType(TalkType talkType){
+ this.talkType = talkType;
+ return;
+ }
+
+ /**
+ * 発言したAvatarを取得する。
+ * @return 発言Avatar
+ */
+ public AvatarData getAvatarData(){
+ return this.avatarData;
+ }
+
+ /**
+ * 発言したAvatarを設定する。
+ * @param avatarData 発言Avatar
+ */
+ public void setAvatarData(AvatarData avatarData){
+ this.avatarData = avatarData;
+ return;
+ }
+
+ /**
+ * 元発言のname属性値を取得する。
+ * @return name属性値
+ */
+ public String getXName(){
+ return this.xName;
+ }
+
+ /**
+ * 元発言のname属性値を設定する。
+ * @param xName name属性値
+ */
+ public void setXName(String xName){
+ this.xName = xName;
+ return;
+ }
+
+ /**
+ * 顔アイコン画像URI文字列を取得する。
+ * @return 顔アイコン画像URI文字列
+ */
+ public String getFaceIconUri(){
+ return this.faceIconUri;
+ }
+
+ /**
+ * 顔アイコン画像URI文字列を設定する。
+ * @param faceIconUri 顔アイコン画像URI文字列
+ */
+ public void setFaceIconUri(String faceIconUri){
+ this.faceIconUri = faceIconUri;
+ return;
+ }
+
+ /**
+ * 発言時を取得する。
+ * @return 発言時
+ */
+ public int getHour(){
+ return this.hour;
+ }
+
+ /**
+ * 発言時を設定する。
+ * @param hour 発言時
+ */
+ public void setHour(int hour){
+ this.hour = hour;
+ return;
+ }
+
+ /**
+ * 発言分を取得する。
+ * @return 発言分
+ */
+ public int getMinute(){
+ return this.minute;
+ }
+
+ /**
+ * 発言分を設定する。
+ * @param minute 発言分
+ */
+ public void setMinute(int minute){
+ this.minute = minute;
+ return;
+ }
+
+ /**
+ * talk要素をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ @Override
+ public void dumpXml(Writer writer) throws IOException{
+ writer.append("<talk\n");
+
+ String typeStr;
+ switch(this.talkType){
+ case PUBLIC:
+ typeStr = "public";
+ break;
+ case WOLFONLY:
+ typeStr = "wolf";
+ break;
+ case PRIVATE:
+ typeStr = "private";
+ break;
+ case GRAVE:
+ typeStr = "grave";
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "type", typeStr);
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "avatarId", this.avatarData.getAvatarId());
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "xname", this.xName);
+
+ writer.append(' ');
+ XmlUtils.timeAttrOut(writer, "time", this.hour, this.minute);
+ writer.append('\n');
+
+ if( this.talkType != TalkType.GRAVE
+ && ! this.faceIconUri.equals(this.avatarData.getFaceIconUri()) ){
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "faceIconURI", this.faceIconUri);
+ writer.append('\n');
+ }
+
+ writer.append(">\n");
+
+ dumpLines(writer);
+
+ writer.append("</talk>\n");
+ return;
+ }
+
+}
-/*\r
- * topic data\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.IOException;\r
-import java.io.Writer;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import jp.sourceforge.jindolf.parser.DecodedContent;\r
-\r
-/**\r
- * テキスト行の集合。\r
- */\r
-public abstract class TopicData{\r
-\r
- private static final DecodedContent BREAK = new DecodedContent("\n");\r
-\r
- private final List<DecodedContent> lineList =\r
- new LinkedList<DecodedContent>();\r
-\r
- /**\r
- * コンストラクタ。\r
- */\r
- protected TopicData(){\r
- super();\r
- return;\r
- }\r
-\r
- /**\r
- * 行を追加する。\r
- * @param content 行を構成する文字列\r
- */\r
- public void addLine(DecodedContent content){\r
- this.lineList.add(content);\r
- return;\r
- }\r
-\r
- /**\r
- * 行ブレークを追加する。\r
- */\r
- public void addBreak(){\r
- this.lineList.add(BREAK);\r
- return;\r
- }\r
-\r
- /**\r
- * 行数を取得する。\r
- * @return 行数\r
- */\r
- public int getLineNum(){\r
- return this.lineList.size();\r
- }\r
-\r
- /**\r
- * 最初の行を取得する。\r
- * @return 最初の行\r
- */\r
- public DecodedContent get1stLine(){\r
- return this.lineList.get(0);\r
- }\r
-\r
- /**\r
- * 1行li要素をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpLines(Writer writer) throws IOException{\r
- DecodedContent lastLine = null;\r
- DecodedContent lastContent = null;\r
-\r
- for(DecodedContent content : this.lineList){\r
- lastContent = content;\r
- if(content == BREAK){\r
- if(lastLine != null){\r
- writer.append("</li>\n");\r
- lastLine = null;\r
- }else{\r
- writer.append("<li/>\n");\r
- }\r
- }else{\r
- if(lastLine == null){\r
- writer.append("<li>");\r
- }\r
- XmlUtils.dumpDecodedContent(writer, content);\r
- lastLine = content;\r
- }\r
- }\r
-\r
- if(lastLine != null){\r
- writer.append("</li>\n");\r
- }else if(lastContent == BREAK){\r
- writer.append("<li/>\n");\r
- }\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 要素をXML出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public abstract void dumpXml(Writer writer) throws IOException;\r
-\r
-}\r
+/*
+ * topic data
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.LinkedList;
+import java.util.List;
+import jp.sourceforge.jindolf.parser.DecodedContent;
+
+/**
+ * テキスト行の集合。
+ */
+public abstract class TopicData{
+
+ private static final DecodedContent BREAK = new DecodedContent("\n");
+
+ private final List<DecodedContent> lineList =
+ new LinkedList<DecodedContent>();
+
+ /**
+ * コンストラクタ。
+ */
+ protected TopicData(){
+ super();
+ return;
+ }
+
+ /**
+ * 行を追加する。
+ * @param content 行を構成する文字列
+ */
+ public void addLine(DecodedContent content){
+ this.lineList.add(content);
+ return;
+ }
+
+ /**
+ * 行ブレークを追加する。
+ */
+ public void addBreak(){
+ this.lineList.add(BREAK);
+ return;
+ }
+
+ /**
+ * 行数を取得する。
+ * @return 行数
+ */
+ public int getLineNum(){
+ return this.lineList.size();
+ }
+
+ /**
+ * 最初の行を取得する。
+ * @return 最初の行
+ */
+ public DecodedContent get1stLine(){
+ return this.lineList.get(0);
+ }
+
+ /**
+ * 1行li要素をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpLines(Writer writer) throws IOException{
+ DecodedContent lastLine = null;
+ DecodedContent lastContent = null;
+
+ for(DecodedContent content : this.lineList){
+ lastContent = content;
+ if(content == BREAK){
+ if(lastLine != null){
+ writer.append("</li>\n");
+ lastLine = null;
+ }else{
+ writer.append("<li/>\n");
+ }
+ }else{
+ if(lastLine == null){
+ writer.append("<li>");
+ }
+ XmlUtils.dumpDecodedContent(writer, content);
+ lastLine = content;
+ }
+ }
+
+ if(lastLine != null){
+ writer.append("</li>\n");
+ }else if(lastContent == BREAK){
+ writer.append("<li/>\n");
+ }
+
+ return;
+ }
+
+ /**
+ * 要素をXML出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public abstract void dumpXml(Writer writer) throws IOException;
+
+}
-/*\r
- * XML-validation task\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.IOException;\r
-import java.io.PipedReader;\r
-import java.io.PipedWriter;\r
-import java.io.Reader;\r
-import java.io.Writer;\r
-import javax.xml.XMLConstants;\r
-import javax.xml.transform.Source;\r
-import javax.xml.transform.stream.StreamSource;\r
-import javax.xml.validation.Schema;\r
-import javax.xml.validation.SchemaFactory;\r
-import javax.xml.validation.Validator;\r
-import org.xml.sax.SAXException;\r
-\r
-/**\r
- * XML検証タスク。\r
- */\r
-public class ValidateTask implements Runnable{\r
-\r
- private static final SchemaFactory FACTORY =\r
- SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);\r
-\r
- private final Validator validator;\r
- private final Source source;\r
-\r
- /**\r
- * コンストラクタ。\r
- * @param reader 文字入力\r
- * @throws SAXException 内部エラー\r
- */\r
- protected ValidateTask(Reader reader) throws SAXException{\r
- super();\r
- Schema schema = FACTORY.newSchema();\r
- this.validator = schema.newValidator();\r
- this.source = new StreamSource(reader);\r
- return;\r
- }\r
-\r
- /**\r
- * 検証タスク。\r
- * {@inheritDoc}\r
- */\r
- @Override\r
- public void run(){\r
- boolean done = false;\r
- try{\r
- this.validator.validate(this.source);\r
- done = true;\r
- }catch(IOException e){\r
- e.printStackTrace(System.err);\r
- System.err.println("XML検証に失敗しました。");\r
- }catch(SAXException e){\r
- e.printStackTrace(System.err);\r
- System.err.println("XML検証に失敗しました。");\r
- }finally{\r
- if( ! done ) System.exit(1);\r
- }\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 文字出力を横取りしバックグラウンドで検証を行うWriterを生成する。\r
- * @param writer 元出力\r
- * @return 新しい出力\r
- */\r
- public static Writer wrapValidator(Writer writer){\r
- PipedReader reader = new PipedReader();\r
- Writer pipeWriter;\r
- try{\r
- pipeWriter = new PipedWriter(reader);\r
- }catch(IOException e){\r
- e.printStackTrace(System.err);\r
- System.err.println("処理を続行できません。");\r
- System.exit(1);\r
- return null;\r
- }\r
-\r
- MultiPlexer mtplx = new MultiPlexer();\r
- mtplx.addWriter(writer);\r
- mtplx.addWriter(pipeWriter);\r
-\r
- Runnable task;\r
- try{\r
- task = new ValidateTask(reader);\r
- }catch(SAXException e){\r
- e.printStackTrace(System.err);\r
- System.err.println("処理を続行できません。");\r
- System.exit(1);\r
- return null;\r
- }\r
- Thread th = new Thread(task);\r
- th.setDaemon(false);\r
- th.start();\r
-\r
- return mtplx;\r
- }\r
-\r
-}\r
+/*
+ * XML-validation task
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.IOException;
+import java.io.PipedReader;
+import java.io.PipedWriter;
+import java.io.Reader;
+import java.io.Writer;
+import javax.xml.XMLConstants;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+import org.xml.sax.SAXException;
+
+/**
+ * XML検証タスク。
+ */
+public class ValidateTask implements Runnable{
+
+ private static final SchemaFactory FACTORY =
+ SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+
+ private final Validator validator;
+ private final Source source;
+
+ /**
+ * コンストラクタ。
+ * @param reader 文字入力
+ * @throws SAXException 内部エラー
+ */
+ protected ValidateTask(Reader reader) throws SAXException{
+ super();
+ Schema schema = FACTORY.newSchema();
+ this.validator = schema.newValidator();
+ this.source = new StreamSource(reader);
+ return;
+ }
+
+ /**
+ * 検証タスク。
+ * {@inheritDoc}
+ */
+ @Override
+ public void run(){
+ boolean done = false;
+ try{
+ this.validator.validate(this.source);
+ done = true;
+ }catch(IOException e){
+ e.printStackTrace(System.err);
+ System.err.println("XML検証に失敗しました。");
+ }catch(SAXException e){
+ e.printStackTrace(System.err);
+ System.err.println("XML検証に失敗しました。");
+ }finally{
+ if( ! done ) System.exit(1);
+ }
+
+ return;
+ }
+
+ /**
+ * 文字出力を横取りしバックグラウンドで検証を行うWriterを生成する。
+ * @param writer 元出力
+ * @return 新しい出力
+ */
+ public static Writer wrapValidator(Writer writer){
+ PipedReader reader = new PipedReader();
+ Writer pipeWriter;
+ try{
+ pipeWriter = new PipedWriter(reader);
+ }catch(IOException e){
+ e.printStackTrace(System.err);
+ System.err.println("処理を続行できません。");
+ System.exit(1);
+ return null;
+ }
+
+ MultiPlexer mtplx = new MultiPlexer();
+ mtplx.addWriter(writer);
+ mtplx.addWriter(pipeWriter);
+
+ Runnable task;
+ try{
+ task = new ValidateTask(reader);
+ }catch(SAXException e){
+ e.printStackTrace(System.err);
+ System.err.println("処理を続行できません。");
+ System.exit(1);
+ return null;
+ }
+ Thread th = new Thread(task);
+ th.setDaemon(false);
+ th.start();
+
+ return mtplx;
+ }
+
+}
-/*\r
- * village data\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.IOException;\r
-import java.io.Writer;\r
-import java.util.Collections;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import jp.sourceforge.jindolf.corelib.DisclosureType;\r
-import jp.sourceforge.jindolf.corelib.LandDef;\r
-import jp.sourceforge.jindolf.corelib.PeriodType;\r
-import jp.sourceforge.jindolf.corelib.PreDefAvatar;\r
-\r
-/**\r
- * 村のデータモデル。\r
- * villageタグに相当。\r
- */\r
-public class VillageData{\r
-\r
- private final List<PeriodResource> resourceList;\r
-\r
- private final LandDef landDef;\r
- private final int villageId;\r
- private final String baseUri;\r
-\r
- private String fullName = "";\r
- private int commitHour = -1;\r
- private int commitMinute = -1;\r
- private String graveIconUri;\r
-\r
- private final List<AvatarData> avatarList = new LinkedList<AvatarData>();\r
- private int undefAvatarNo = 1;\r
-\r
- private final List<PeriodData> periodList = new LinkedList<PeriodData>();\r
-\r
-\r
- /**\r
- * コンストラクタ。\r
- * @param resourceList PeriodResource並び\r
- */\r
- public VillageData(List<PeriodResource> resourceList){\r
- super();\r
-\r
- validatePeriodResource(resourceList);\r
-\r
- this.resourceList = new LinkedList<PeriodResource>(resourceList);\r
-\r
- PeriodResource resource1st = this.resourceList.get(0);\r
- this.landDef = resource1st.getLandDef();\r
- this.villageId = resource1st.getVillageId();\r
- this.baseUri = getBaseUri(this.resourceList);\r
-\r
- return;\r
- }\r
-\r
-\r
- /**\r
- * PeriodResourceの組が正当かチェックする。\r
- * <ul>\r
- * <li>全て同じ国に属していなければならない\r
- * <li>全て同じ村に属していなければならない\r
- * <li>日付は0から始まる連続した数値でなければならない\r
- * <li>プロローグで始まらなければならない\r
- * <li>エピローグで終わらなければならない\r
- * <li>進行日はプロローグとエピローグに挟まれていなければならない\r
- * </ul>\r
- * @param list PeriodResource並び\r
- * @throws IllegalArgumentException 引数が正当でない\r
- */\r
- public static void validatePeriodResource(List<PeriodResource> list)\r
- throws IllegalArgumentException{\r
- LandDef landDef = null;\r
- int villageId = -1;\r
- int lastDay = -1;\r
- PeriodType periodType = null;\r
-\r
- for(PeriodResource resource : list){\r
- if(landDef == null){\r
- landDef = resource.getLandDef();\r
- }else if(resource.getLandDef() != landDef){\r
- throw new IllegalArgumentException();\r
- }\r
-\r
- if(villageId < 0){\r
- villageId = resource.getVillageId();\r
- }else if(resource.getVillageId() != villageId){\r
- throw new IllegalArgumentException();\r
- }\r
-\r
- if(lastDay < 0){\r
- lastDay = resource.getDay();\r
- if(lastDay != 0) throw new IllegalArgumentException();\r
- }else{\r
- if(resource.getDay() != lastDay + 1){\r
- throw new IllegalArgumentException();\r
- }\r
- lastDay = resource.getDay();\r
- }\r
-\r
- if(periodType == null){\r
- periodType = resource.getPeriodType();\r
- if(periodType != PeriodType.PROLOGUE){\r
- throw new IllegalArgumentException();\r
- }\r
- if(lastDay != 0) throw new IllegalArgumentException();\r
- }else if(periodType == PeriodType.PROLOGUE){\r
- periodType = resource.getPeriodType();\r
- if(periodType != PeriodType.PROGRESS){\r
- throw new IllegalArgumentException();\r
- }\r
- }else if(periodType == PeriodType.PROGRESS){\r
- periodType = resource.getPeriodType();\r
- }else if(periodType == PeriodType.EPILOGUE){\r
- throw new IllegalArgumentException();\r
- }\r
- }\r
-\r
- if(lastDay < 0) throw new IllegalArgumentException();\r
- if(periodType != PeriodType.EPILOGUE){\r
- throw new IllegalArgumentException();\r
- }\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 全PeriodResourceから、共通するベースURIを抽出する。\r
- * @param list PeriodResource並び\r
- * @return ベースURI文字列\r
- * @throws IllegalArgumentException ベースURIが一致していない\r
- */\r
- public static String getBaseUri(List<PeriodResource> list)\r
- throws IllegalArgumentException{\r
- String result = null;\r
-\r
- for(PeriodResource resource : list){\r
- String urlText = resource.getOrigUrlText();\r
- urlText = urlText.replaceAll("[^/]*$", "");\r
- if(result == null){\r
- result = urlText;\r
- }else{\r
- if( ! result.equals(urlText) ){\r
- throw new IllegalArgumentException();\r
- }\r
- }\r
- }\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * 国情報を取得する。\r
- * @return 国情報\r
- */\r
- public LandDef getLandDef(){\r
- return this.landDef;\r
- }\r
-\r
- /**\r
- * 村IDを取得する。\r
- * @return 村ID\r
- */\r
- public int getVillageId(){\r
- return this.villageId;\r
- }\r
-\r
- /**\r
- * ベースURIを取得する。\r
- * @return ベースURI\r
- */\r
- public String getBaseUri(){\r
- return this.baseUri;\r
- }\r
-\r
- /**\r
- * 村フルネームを取得する。\r
- * @return 村フルネーム\r
- */\r
- public String getFullName(){\r
- return this.fullName;\r
- }\r
-\r
- /**\r
- * 村フルネームを設定する。\r
- * @param fullName 村フルネーム\r
- */\r
- public void setFullName(String fullName){\r
- this.fullName = fullName;\r
- return;\r
- }\r
-\r
- /**\r
- * 更新時を取得する。\r
- * @return 更新時\r
- */\r
- public int getCommitHour(){\r
- return this.commitHour;\r
- }\r
-\r
- /**\r
- * 更新時を設定する。\r
- * @param commitHour 更新時\r
- */\r
- public void setCommitHour(int commitHour){\r
- this.commitHour = commitHour;\r
- return;\r
- }\r
-\r
- /**\r
- * 更新分を取得する。\r
- * @return 更新分\r
- */\r
- public int getCommitMinute(){\r
- return this.commitMinute;\r
- }\r
-\r
- /**\r
- * 更新分を設定する。\r
- * @param commitMinute 更新分\r
- */\r
- public void setCommitMinute(int commitMinute){\r
- this.commitMinute = commitMinute;\r
- return;\r
- }\r
-\r
- /**\r
- * 墓アイコンURIを取得する。\r
- * @return 墓アイコンURI文字列\r
- */\r
- public String getGraveIconUri(){\r
- if(this.graveIconUri == null){\r
- return this.landDef.getTombFaceIconURI().toASCIIString();\r
- }\r
- return this.graveIconUri;\r
- }\r
-\r
- /**\r
- * 墓アイコンURI文字列を設定する。\r
- * @param graveIconUri 墓アイコンURI文字列\r
- */\r
- public void setGraveIconUri(String graveIconUri){\r
- this.graveIconUri = graveIconUri;\r
- return;\r
- }\r
-\r
- /**\r
- * 全Periodの開示状況から総合開示状況を算出する。\r
- * @return 公開状況\r
- */\r
- public DisclosureType getDisclosureType(){\r
- DisclosureType result = DisclosureType.COMPLETE;\r
-\r
- for(PeriodData period : this.periodList){\r
- DisclosureType type = period.getDisclosureType();\r
- switch(type){\r
- case HOT:\r
- return DisclosureType.HOT;\r
- case UNCOMPLETE:\r
- result = DisclosureType.UNCOMPLETE;\r
- break;\r
- default:\r
- break;\r
- }\r
- }\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * Periodモデルを追加する。\r
- * @param period Periodモデル\r
- */\r
- public void addPeriodData(PeriodData period){\r
- this.periodList.add(period);\r
- return;\r
- }\r
-\r
- /**\r
- * PeriodResourcenar並びを取得する。\r
- * @return PeriodResource並び\r
- */\r
- public List<PeriodResource> getPeriodResourceList(){\r
- return Collections.unmodifiableList(this.resourceList);\r
- }\r
-\r
- /**\r
- * 未知の新規Avatarを生成する。\r
- * ※ F1556村などへの対処。\r
- * Avatarのフルネーム、短縮名、識別子が設定される。\r
- * @param avfullName Avatarのフルネーム\r
- * @return 新規Avatarモデル\r
- */\r
- public AvatarData createAvatar(String avfullName){\r
- AvatarData avatar = new AvatarData();\r
-\r
- avatar.setFullName(avfullName);\r
-\r
- String[] token = avfullName.split("\\s");\r
- String shortName = token[token.length - 1];\r
- avatar.setShortName(shortName);\r
-\r
- String avatarId = "ukavatar" + this.undefAvatarNo;\r
- this.undefAvatarNo++;\r
- avatar.setAvatarId(avatarId);\r
-\r
- return avatar;\r
- }\r
-\r
- /**\r
- * AvatarフルネームからAvatarを得る。\r
- * まだこの村にいないAvatarならAvatar一覧に登録される。\r
- * @param seq Avatarフルネーム\r
- * @return Avatarモデル\r
- */\r
- public AvatarData getAvatarData(CharSequence seq){\r
- for(AvatarData avatar : this.avatarList){\r
- String avfullName = avatar.getFullName();\r
- if(avfullName.contentEquals(seq)){\r
- return avatar;\r
- }\r
- }\r
-\r
- PreDefAvatar predefAvatar =\r
- AvatarData.getPreDefAvatar(seq);\r
- if(predefAvatar != null){\r
- AvatarData avatar = new AvatarData(predefAvatar);\r
- this.avatarList.add(avatar);\r
- return avatar;\r
- }\r
-\r
- AvatarData avatar = createAvatar(seq.toString());\r
- this.avatarList.add(avatar);\r
-\r
- return avatar;\r
- }\r
-\r
- /**\r
- * avatarList要素のXML出力。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpAvatarList(Writer writer) throws IOException{\r
- writer.append("<avatarList>").append("\n\n");\r
-\r
- for(AvatarData avatar : this.avatarList){\r
- avatar.dumpXml(writer);\r
- writer.append('\n');\r
- }\r
-\r
- writer.append("</avatarList>").append('\n');\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 全period要素のXML出力。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpPeriodList(Writer writer) throws IOException{\r
- for(PeriodData period : this.periodList){\r
- period.dumpXml(writer);\r
- writer.append('\n');\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * village要素のXML出力。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public void dumpXml(Writer writer) throws IOException{\r
- writer.append("<village\n");\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.dumpNameSpaceDecl(writer);\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.dumpSiNameSpaceDecl(writer);\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.dumpSchemeLocation(writer);\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "xml:lang", "ja-JP");\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "xml:base", this.baseUri);\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "fullName", this.fullName);\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "vid", Integer.toString(this.villageId));\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.timeAttrOut(writer,\r
- "commitTime",\r
- this.commitHour, this.commitMinute);\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "state", "gameover");\r
-\r
- DisclosureType type = getDisclosureType();\r
- if(type != DisclosureType.COMPLETE){\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "disclosure", type.getXmlName());\r
- }\r
-\r
- String isValid;\r
- if(this.landDef.isValidVillageId(this.villageId)){\r
- isValid = "true";\r
- }else{\r
- isValid = "false";\r
- }\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "isValid", isValid);\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "landName", this.landDef.getLandName());\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "formalName", this.landDef.getFormalName());\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "landId", this.landDef.getLandId());\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer, "landPrefix", this.landDef.getLandPrefix());\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- String locale = this.landDef.getLocale().toString();\r
- locale = locale.replaceAll("_", "-");\r
- XmlUtils.attrOut(writer, "locale", locale);\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer,\r
- "origencoding", this.landDef.getEncoding().name());\r
-\r
- writer.append(' ');\r
- XmlUtils.attrOut(writer,\r
- "timezone", this.landDef.getTimeZone().getID());\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "graveIconURI", getGraveIconUri());\r
- writer.append('\n');\r
-\r
- XmlUtils.indent(writer, 1);\r
- XmlUtils.attrOut(writer, "generator", JinArchiver.GENERATOR);\r
- writer.append('\n');\r
-\r
- writer.append(">").append('\n');\r
-\r
- writer.append('\n');\r
- dumpAvatarList(writer);\r
-\r
- writer.append('\n');\r
- dumpPeriodList(writer);\r
-\r
- writer.append("</village>").append("\n");\r
-\r
- return;\r
- }\r
-\r
-}\r
+/*
+ * village data
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import jp.sourceforge.jindolf.corelib.DisclosureType;
+import jp.sourceforge.jindolf.corelib.LandDef;
+import jp.sourceforge.jindolf.corelib.PeriodType;
+import jp.sourceforge.jindolf.corelib.PreDefAvatar;
+
+/**
+ * 村のデータモデル。
+ * villageタグに相当。
+ */
+public class VillageData{
+
+ private final List<PeriodResource> resourceList;
+
+ private final LandDef landDef;
+ private final int villageId;
+ private final String baseUri;
+
+ private String fullName = "";
+ private int commitHour = -1;
+ private int commitMinute = -1;
+ private String graveIconUri;
+
+ private final List<AvatarData> avatarList = new LinkedList<AvatarData>();
+ private int undefAvatarNo = 1;
+
+ private final List<PeriodData> periodList = new LinkedList<PeriodData>();
+
+
+ /**
+ * コンストラクタ。
+ * @param resourceList PeriodResource並び
+ */
+ public VillageData(List<PeriodResource> resourceList){
+ super();
+
+ validatePeriodResource(resourceList);
+
+ this.resourceList = new LinkedList<PeriodResource>(resourceList);
+
+ PeriodResource resource1st = this.resourceList.get(0);
+ this.landDef = resource1st.getLandDef();
+ this.villageId = resource1st.getVillageId();
+ this.baseUri = getBaseUri(this.resourceList);
+
+ return;
+ }
+
+
+ /**
+ * PeriodResourceの組が正当かチェックする。
+ * <ul>
+ * <li>全て同じ国に属していなければならない
+ * <li>全て同じ村に属していなければならない
+ * <li>日付は0から始まる連続した数値でなければならない
+ * <li>プロローグで始まらなければならない
+ * <li>エピローグで終わらなければならない
+ * <li>進行日はプロローグとエピローグに挟まれていなければならない
+ * </ul>
+ * @param list PeriodResource並び
+ * @throws IllegalArgumentException 引数が正当でない
+ */
+ public static void validatePeriodResource(List<PeriodResource> list)
+ throws IllegalArgumentException{
+ LandDef landDef = null;
+ int villageId = -1;
+ int lastDay = -1;
+ PeriodType periodType = null;
+
+ for(PeriodResource resource : list){
+ if(landDef == null){
+ landDef = resource.getLandDef();
+ }else if(resource.getLandDef() != landDef){
+ throw new IllegalArgumentException();
+ }
+
+ if(villageId < 0){
+ villageId = resource.getVillageId();
+ }else if(resource.getVillageId() != villageId){
+ throw new IllegalArgumentException();
+ }
+
+ if(lastDay < 0){
+ lastDay = resource.getDay();
+ if(lastDay != 0) throw new IllegalArgumentException();
+ }else{
+ if(resource.getDay() != lastDay + 1){
+ throw new IllegalArgumentException();
+ }
+ lastDay = resource.getDay();
+ }
+
+ if(periodType == null){
+ periodType = resource.getPeriodType();
+ if(periodType != PeriodType.PROLOGUE){
+ throw new IllegalArgumentException();
+ }
+ if(lastDay != 0) throw new IllegalArgumentException();
+ }else if(periodType == PeriodType.PROLOGUE){
+ periodType = resource.getPeriodType();
+ if(periodType != PeriodType.PROGRESS){
+ throw new IllegalArgumentException();
+ }
+ }else if(periodType == PeriodType.PROGRESS){
+ periodType = resource.getPeriodType();
+ }else if(periodType == PeriodType.EPILOGUE){
+ throw new IllegalArgumentException();
+ }
+ }
+
+ if(lastDay < 0) throw new IllegalArgumentException();
+ if(periodType != PeriodType.EPILOGUE){
+ throw new IllegalArgumentException();
+ }
+
+ return;
+ }
+
+ /**
+ * 全PeriodResourceから、共通するベースURIを抽出する。
+ * @param list PeriodResource並び
+ * @return ベースURI文字列
+ * @throws IllegalArgumentException ベースURIが一致していない
+ */
+ public static String getBaseUri(List<PeriodResource> list)
+ throws IllegalArgumentException{
+ String result = null;
+
+ for(PeriodResource resource : list){
+ String urlText = resource.getOrigUrlText();
+ urlText = urlText.replaceAll("[^/]*$", "");
+ if(result == null){
+ result = urlText;
+ }else{
+ if( ! result.equals(urlText) ){
+ throw new IllegalArgumentException();
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * 国情報を取得する。
+ * @return 国情報
+ */
+ public LandDef getLandDef(){
+ return this.landDef;
+ }
+
+ /**
+ * 村IDを取得する。
+ * @return 村ID
+ */
+ public int getVillageId(){
+ return this.villageId;
+ }
+
+ /**
+ * ベースURIを取得する。
+ * @return ベースURI
+ */
+ public String getBaseUri(){
+ return this.baseUri;
+ }
+
+ /**
+ * 村フルネームを取得する。
+ * @return 村フルネーム
+ */
+ public String getFullName(){
+ return this.fullName;
+ }
+
+ /**
+ * 村フルネームを設定する。
+ * @param fullName 村フルネーム
+ */
+ public void setFullName(String fullName){
+ this.fullName = fullName;
+ return;
+ }
+
+ /**
+ * 更新時を取得する。
+ * @return 更新時
+ */
+ public int getCommitHour(){
+ return this.commitHour;
+ }
+
+ /**
+ * 更新時を設定する。
+ * @param commitHour 更新時
+ */
+ public void setCommitHour(int commitHour){
+ this.commitHour = commitHour;
+ return;
+ }
+
+ /**
+ * 更新分を取得する。
+ * @return 更新分
+ */
+ public int getCommitMinute(){
+ return this.commitMinute;
+ }
+
+ /**
+ * 更新分を設定する。
+ * @param commitMinute 更新分
+ */
+ public void setCommitMinute(int commitMinute){
+ this.commitMinute = commitMinute;
+ return;
+ }
+
+ /**
+ * 墓アイコンURIを取得する。
+ * @return 墓アイコンURI文字列
+ */
+ public String getGraveIconUri(){
+ if(this.graveIconUri == null){
+ return this.landDef.getTombFaceIconURI().toASCIIString();
+ }
+ return this.graveIconUri;
+ }
+
+ /**
+ * 墓アイコンURI文字列を設定する。
+ * @param graveIconUri 墓アイコンURI文字列
+ */
+ public void setGraveIconUri(String graveIconUri){
+ this.graveIconUri = graveIconUri;
+ return;
+ }
+
+ /**
+ * 全Periodの開示状況から総合開示状況を算出する。
+ * @return 公開状況
+ */
+ public DisclosureType getDisclosureType(){
+ DisclosureType result = DisclosureType.COMPLETE;
+
+ for(PeriodData period : this.periodList){
+ DisclosureType type = period.getDisclosureType();
+ switch(type){
+ case HOT:
+ return DisclosureType.HOT;
+ case UNCOMPLETE:
+ result = DisclosureType.UNCOMPLETE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Periodモデルを追加する。
+ * @param period Periodモデル
+ */
+ public void addPeriodData(PeriodData period){
+ this.periodList.add(period);
+ return;
+ }
+
+ /**
+ * PeriodResourcenar並びを取得する。
+ * @return PeriodResource並び
+ */
+ public List<PeriodResource> getPeriodResourceList(){
+ return Collections.unmodifiableList(this.resourceList);
+ }
+
+ /**
+ * 未知の新規Avatarを生成する。
+ * ※ F1556村などへの対処。
+ * Avatarのフルネーム、短縮名、識別子が設定される。
+ * @param avfullName Avatarのフルネーム
+ * @return 新規Avatarモデル
+ */
+ public AvatarData createAvatar(String avfullName){
+ AvatarData avatar = new AvatarData();
+
+ avatar.setFullName(avfullName);
+
+ String[] token = avfullName.split("\\s");
+ String shortName = token[token.length - 1];
+ avatar.setShortName(shortName);
+
+ String avatarId = "ukavatar" + this.undefAvatarNo;
+ this.undefAvatarNo++;
+ avatar.setAvatarId(avatarId);
+
+ return avatar;
+ }
+
+ /**
+ * AvatarフルネームからAvatarを得る。
+ * まだこの村にいないAvatarならAvatar一覧に登録される。
+ * @param seq Avatarフルネーム
+ * @return Avatarモデル
+ */
+ public AvatarData getAvatarData(CharSequence seq){
+ for(AvatarData avatar : this.avatarList){
+ String avfullName = avatar.getFullName();
+ if(avfullName.contentEquals(seq)){
+ return avatar;
+ }
+ }
+
+ PreDefAvatar predefAvatar =
+ AvatarData.getPreDefAvatar(seq);
+ if(predefAvatar != null){
+ AvatarData avatar = new AvatarData(predefAvatar);
+ this.avatarList.add(avatar);
+ return avatar;
+ }
+
+ AvatarData avatar = createAvatar(seq.toString());
+ this.avatarList.add(avatar);
+
+ return avatar;
+ }
+
+ /**
+ * avatarList要素のXML出力。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpAvatarList(Writer writer) throws IOException{
+ writer.append("<avatarList>").append("\n\n");
+
+ for(AvatarData avatar : this.avatarList){
+ avatar.dumpXml(writer);
+ writer.append('\n');
+ }
+
+ writer.append("</avatarList>").append('\n');
+
+ return;
+ }
+
+ /**
+ * 全period要素のXML出力。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpPeriodList(Writer writer) throws IOException{
+ for(PeriodData period : this.periodList){
+ period.dumpXml(writer);
+ writer.append('\n');
+ }
+ return;
+ }
+
+ /**
+ * village要素のXML出力。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public void dumpXml(Writer writer) throws IOException{
+ writer.append("<village\n");
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.dumpNameSpaceDecl(writer);
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.dumpSiNameSpaceDecl(writer);
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.dumpSchemeLocation(writer);
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "xml:lang", "ja-JP");
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "xml:base", this.baseUri);
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "fullName", this.fullName);
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "vid", Integer.toString(this.villageId));
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.timeAttrOut(writer,
+ "commitTime",
+ this.commitHour, this.commitMinute);
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "state", "gameover");
+
+ DisclosureType type = getDisclosureType();
+ if(type != DisclosureType.COMPLETE){
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "disclosure", type.getXmlName());
+ }
+
+ String isValid;
+ if(this.landDef.isValidVillageId(this.villageId)){
+ isValid = "true";
+ }else{
+ isValid = "false";
+ }
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "isValid", isValid);
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "landName", this.landDef.getLandName());
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "formalName", this.landDef.getFormalName());
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "landId", this.landDef.getLandId());
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer, "landPrefix", this.landDef.getLandPrefix());
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ String locale = this.landDef.getLocale().toString();
+ locale = locale.replaceAll("_", "-");
+ XmlUtils.attrOut(writer, "locale", locale);
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer,
+ "origencoding", this.landDef.getEncoding().name());
+
+ writer.append(' ');
+ XmlUtils.attrOut(writer,
+ "timezone", this.landDef.getTimeZone().getID());
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "graveIconURI", getGraveIconUri());
+ writer.append('\n');
+
+ XmlUtils.indent(writer, 1);
+ XmlUtils.attrOut(writer, "generator", JinArchiver.GENERATOR);
+ writer.append('\n');
+
+ writer.append(">").append('\n');
+
+ writer.append('\n');
+ dumpAvatarList(writer);
+
+ writer.append('\n');
+ dumpPeriodList(writer);
+
+ writer.append("</village>").append("\n");
+
+ return;
+ }
+
+}
-/*\r
- * windows-31j encoding utilities\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.nio.ByteBuffer;\r
-import java.nio.charset.CharacterCodingException;\r
-import java.nio.charset.Charset;\r
-import java.nio.charset.CharsetDecoder;\r
-import java.nio.charset.CodingErrorAction;\r
-import jp.sourceforge.jindolf.parser.DecodeErrorInfo;\r
-import jp.sourceforge.jindolf.parser.DecodedContent;\r
-\r
-/**\r
- * windows-31jエンコーディング(機種依存文字)に関する諸々。\r
- */\r
-public final class Win31j{\r
-\r
- /** デフォルト置換文字。 */\r
- public static final char REP_CHAR = '\ufffd';\r
-\r
- /** windows-31j Charset. */\r
- public static final Charset CS_WIN31J = Charset.forName("windows-31j");\r
-\r
- private static final CharsetDecoder WIN31JDECODER;\r
- private static final ByteBuffer BYTEBUFFER = ByteBuffer.allocate(2);\r
-\r
- static{\r
- WIN31JDECODER = CS_WIN31J.newDecoder();\r
- WIN31JDECODER.onMalformedInput(CodingErrorAction.REPORT);\r
- WIN31JDECODER.onUnmappableCharacter(CodingErrorAction.REPORT);\r
- WIN31JDECODER.reset();\r
- BYTEBUFFER.clear();\r
- }\r
-\r
-\r
- /**\r
- * 隠しコンストラクタ。\r
- */\r
- private Win31j(){\r
- throw new Error();\r
- }\r
-\r
-\r
- /**\r
- * winsows-31jエンコーディングされたと想定した2バイトデータ\r
- * の復号を試みる。\r
- * 復号に失敗すればU+FFFDを返す。\r
- * @param b1 1バイト目\r
- * @param b2 2バイト目\r
- * @return 復号化された1文字\r
- */\r
- public static synchronized char getWin31jChar(byte b1, byte b2){\r
- char replaced;\r
-\r
- WIN31JDECODER.reset();\r
- BYTEBUFFER.clear();\r
- BYTEBUFFER.put(b1).put(b2);\r
- BYTEBUFFER.flip();\r
-\r
- try{\r
- replaced = WIN31JDECODER.decode(BYTEBUFFER).charAt(0);\r
- }catch(CharacterCodingException e){\r
- replaced = REP_CHAR;\r
- }\r
-\r
- return replaced;\r
- }\r
-\r
- /**\r
- * デコードエラーがwindows-31jに由来する物と仮定して\r
- * 復号を試みる。\r
- * 1バイトエラーもしくは復号に失敗すればU+FFFDを返す。\r
- * @param info デコードエラー\r
- * @return 復号化された1文字\r
- */\r
- public static char getWin31jChar(DecodeErrorInfo info){\r
- if( ! info.has2nd() ) return REP_CHAR;\r
-\r
- byte b1 = info.getRawByte1st();\r
- byte b2 = info.getRawByte2nd();\r
- char replaceChar = getWin31jChar(b1, b2);\r
-\r
- return replaceChar;\r
- }\r
-\r
- /**\r
- * デコードエラーを含む文字列に対し、\r
- * windows-31jによる復号での補完を試みる。\r
- * @param content 文字列\r
- */\r
- public static void supplyWin31jChar(DecodedContent content){\r
- if( ! content.hasDecodeError() ) return;\r
-\r
- for(DecodeErrorInfo info : content.getDecodeErrorList()){\r
- int pos = info.getCharPosition();\r
- char replaceChar = getWin31jChar(info);\r
- content.setCharAt(pos, replaceChar);\r
- }\r
-\r
- return;\r
- }\r
-\r
-}\r
+/*
+ * windows-31j encoding utilities
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
+import jp.sourceforge.jindolf.parser.DecodeErrorInfo;
+import jp.sourceforge.jindolf.parser.DecodedContent;
+
+/**
+ * windows-31jエンコーディング(機種依存文字)に関する諸々。
+ */
+public final class Win31j{
+
+ /** デフォルト置換文字。 */
+ public static final char REP_CHAR = '\ufffd';
+
+ /** windows-31j Charset. */
+ public static final Charset CS_WIN31J = Charset.forName("windows-31j");
+
+ private static final CharsetDecoder WIN31JDECODER;
+ private static final ByteBuffer BYTEBUFFER = ByteBuffer.allocate(2);
+
+ static{
+ WIN31JDECODER = CS_WIN31J.newDecoder();
+ WIN31JDECODER.onMalformedInput(CodingErrorAction.REPORT);
+ WIN31JDECODER.onUnmappableCharacter(CodingErrorAction.REPORT);
+ WIN31JDECODER.reset();
+ BYTEBUFFER.clear();
+ }
+
+
+ /**
+ * 隠しコンストラクタ。
+ */
+ private Win31j(){
+ throw new Error();
+ }
+
+
+ /**
+ * winsows-31jエンコーディングされたと想定した2バイトデータ
+ * の復号を試みる。
+ * 復号に失敗すればU+FFFDを返す。
+ * @param b1 1バイト目
+ * @param b2 2バイト目
+ * @return 復号化された1文字
+ */
+ public static synchronized char getWin31jChar(byte b1, byte b2){
+ char replaced;
+
+ WIN31JDECODER.reset();
+ BYTEBUFFER.clear();
+ BYTEBUFFER.put(b1).put(b2);
+ BYTEBUFFER.flip();
+
+ try{
+ replaced = WIN31JDECODER.decode(BYTEBUFFER).charAt(0);
+ }catch(CharacterCodingException e){
+ replaced = REP_CHAR;
+ }
+
+ return replaced;
+ }
+
+ /**
+ * デコードエラーがwindows-31jに由来する物と仮定して
+ * 復号を試みる。
+ * 1バイトエラーもしくは復号に失敗すればU+FFFDを返す。
+ * @param info デコードエラー
+ * @return 復号化された1文字
+ */
+ public static char getWin31jChar(DecodeErrorInfo info){
+ if( ! info.has2nd() ) return REP_CHAR;
+
+ byte b1 = info.getRawByte1st();
+ byte b2 = info.getRawByte2nd();
+ char replaceChar = getWin31jChar(b1, b2);
+
+ return replaceChar;
+ }
+
+ /**
+ * デコードエラーを含む文字列に対し、
+ * windows-31jによる復号での補完を試みる。
+ * @param content 文字列
+ */
+ public static void supplyWin31jChar(DecodedContent content){
+ if( ! content.hasDecodeError() ) return;
+
+ for(DecodeErrorInfo info : content.getDecodeErrorList()){
+ int pos = info.getCharPosition();
+ char replaceChar = getWin31jChar(info);
+ content.setCharAt(pos, replaceChar);
+ }
+
+ return;
+ }
+
+}
-/*\r
- * XML utils\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.BufferedOutputStream;\r
-import java.io.BufferedWriter;\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.io.Writer;\r
-import java.text.MessageFormat;\r
-import java.util.Calendar;\r
-import java.util.GregorianCalendar;\r
-import java.util.List;\r
-import java.util.TimeZone;\r
-import jp.sourceforge.jindolf.corelib.LandDef;\r
-import jp.sourceforge.jindolf.parser.DecodeErrorInfo;\r
-import jp.sourceforge.jindolf.parser.DecodedContent;\r
-\r
-/**\r
- * XML用各種ユーティリティ。\r
- */\r
-public final class XmlUtils{\r
-\r
- private static final String ORIG_DTD =\r
- "http://jindolf.sourceforge.jp/xml/dtd/bbsArchive-110421.dtd";\r
- private static final String ORIG_NS =\r
- "http://jindolf.sourceforge.jp/xml/ns/501";\r
- private static final String ORIG_SCHEME =\r
- "http://jindolf.sourceforge.jp/xml/xsd/bbsArchive-110421.xsd";\r
- private static final String SCHEMA_NS =\r
- "http://www.w3.org/2001/XMLSchema-instance";\r
-\r
- private static final String OUTPATH = "D:\\TEMP\\zxzx\\";\r
-\r
- private static final char BS_CHAR = (char) 0x005c; // Backslash\r
- private static final String INDENT_UNIT = "\u0020\u0020";\r
-\r
- private static final TimeZone TZ_TOKYO =\r
- TimeZone.getTimeZone("Asia/Tokyo");\r
-\r
-\r
- /**\r
- * 隠れコンストラクタ。\r
- */\r
- private XmlUtils(){\r
- throw new Error();\r
- }\r
-\r
-\r
- /**\r
- * DOCTYPE宣言を出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public static void dumpDocType(Writer writer) throws IOException{\r
- writer.append("<!DOCTYPE village SYSTEM ");\r
- writer.append('"');\r
- writer.append(ORIG_DTD);\r
- writer.append('"');\r
- writer.append(" >");\r
- return;\r
- }\r
-\r
- /**\r
- * オリジナルNameSpace宣言を出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public static void dumpNameSpaceDecl(Writer writer)\r
- throws IOException{\r
- attrOut(writer, "xmlns", ORIG_NS);\r
- return;\r
- }\r
-\r
- /**\r
- * スキーマNameSpace宣言を出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public static void dumpSiNameSpaceDecl(Writer writer)\r
- throws IOException{\r
- attrOut(writer, "xmlns:xsi", SCHEMA_NS);\r
- return;\r
- }\r
-\r
- /**\r
- * スキーマ位置指定を出力する。\r
- * @param writer 出力先\r
- * @throws IOException 出力エラー\r
- */\r
- public static void dumpSchemeLocation(Writer writer)\r
- throws IOException{\r
- attrOut(writer,\r
- "xsi:schemaLocation",\r
- ORIG_NS + " " + ORIG_SCHEME);\r
- return;\r
- }\r
-\r
- /**\r
- * インデント用空白を出力する。\r
- * ネスト単位は空白2文字\r
- * @param writer 出力先\r
- * @param level ネストレベル\r
- * @throws IOException 出力エラー\r
- */\r
- public static void indent(Writer writer, int level) throws IOException{\r
- for(int ct = 1; ct <= level; ct++){\r
- writer.append(INDENT_UNIT);\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * XML数値文字参照を出力する。\r
- * @param writer 出力先\r
- * @param chVal 出力文字\r
- * @throws IOException 出力エラー\r
- */\r
- public static void charRefOut(Writer writer, char chVal)\r
- throws IOException{\r
- if(chVal == '\u0020'){\r
- writer.append(" ");\r
- return;\r
- }\r
-\r
- if(chVal == '\u0009'){\r
- writer.append("	");\r
- return;\r
- }\r
-\r
- int ival = 0xffff & ((int) chVal);\r
- String hex = Integer.toHexString(ival);\r
- if(hex.length() % 2 != 0) hex = "0" + hex;\r
-\r
- writer.append("&#x");\r
- writer.append(hex);\r
- writer.append(";");\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 不正文字をXML出力する。\r
- * @param writer 出力先\r
- * @param chVal 不正文字\r
- * @throws IOException 出力エラー\r
- */\r
- public static void dumpInvalidChar(Writer writer, char chVal)\r
- throws IOException{\r
- int hexVal;\r
- hexVal = chVal & 0xff;\r
- String hexBin = Integer.toHexString(hexVal);\r
- if(hexBin.length() % 2 != 0) hexBin = "0" + hexBin;\r
-\r
- char replaceChar = '\ufffd';\r
- if('\u0000' <= chVal && chVal <= '\u001f'){\r
- replaceChar = (char)( chVal + '\u2400' );\r
- }\r
-\r
- writer.append("<rawdata");\r
-\r
- writer.append(' ');\r
- attrOut(writer, "encoding", "Shift_JIS");\r
-\r
- writer.append(' ');\r
- attrOut(writer, "hexBin", hexBin);\r
-\r
- writer.append(" >");\r
- writer.append(replaceChar);\r
- writer.append("</rawdata>");\r
- }\r
-\r
- /**\r
- * 任意の文字がXML規格上のホワイトスペースに属するか判定する。\r
- * @param chVal 文字\r
- * @return ホワイトスペースならtrue\r
- */\r
- public static boolean isWhiteSpace(char chVal){\r
- switch(chVal){\r
- case '\u0020':\r
- case '\t':\r
- case '\n':\r
- case '\r':\r
- return true;\r
- default:\r
- break;\r
- }\r
-\r
- return false;\r
- }\r
-\r
- /**\r
- * 文字列を出力する。\r
- * <ul>\r
- * <li>先頭および末尾のホワイトスペースは強制的に文字参照化される。\r
- * <li>連続したホワイトスペースの2文字目以降は文字参照化される。\r
- * <li>スペースでないホワイトスペースは無条件に文字参照化される。\r
- * <li>{@literal &, <, >, "}は無条件に文字参照化される。\r
- * </ul>\r
- * 参考:XML 1.0 規格 3.3.3節\r
- * @param writer 出力先\r
- * @param seq CDATA文字列\r
- * @throws IOException 出力エラー\r
- */\r
- public static void textOut(Writer writer, CharSequence seq)\r
- throws IOException{\r
- int len = seq.length();\r
-\r
- boolean leadSpace = false;\r
-\r
- for(int pos = 0; pos < len; pos++){\r
- char chVal = seq.charAt(pos);\r
-\r
- if(isWhiteSpace(chVal)){\r
- if(pos == 0 || pos >= len - 1 || leadSpace){\r
- charRefOut(writer, chVal);\r
- }else if(chVal != '\u0020'){\r
- charRefOut(writer, chVal);\r
- }else{\r
- writer.append(chVal);\r
- }\r
- leadSpace = true;\r
- }else{\r
- if(chVal == '&'){\r
- writer.append("&");\r
- }else if(chVal == '<'){\r
- writer.append("<");\r
- }else if(chVal == '>'){\r
- writer.append(">");\r
- }else if(chVal == '"'){\r
- writer.append(""");\r
- }else if(chVal == '\''){\r
- writer.append("'");\r
- }else if(chVal == BS_CHAR){\r
- writer.append('\u00a5');\r
- }else if(chVal == '\u007e'){\r
- writer.append('\u203e');\r
- }else if(Character.isISOControl(chVal)){\r
- dumpInvalidChar(writer, chVal);\r
- }else{\r
- writer.append(chVal);\r
- }\r
- leadSpace = false;\r
- }\r
- }\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 属性を出力する。\r
- * @param writer 出力先\r
- * @param name 属性名\r
- * @param value 属性値\r
- * @throws IOException 出力エラー\r
- */\r
- public static void attrOut(Writer writer,\r
- CharSequence name,\r
- CharSequence value)\r
- throws IOException{\r
- StringBuilder newValue = new StringBuilder(value);\r
- for(int pt = 0; pt < newValue.length(); pt++){\r
- char chVal = newValue.charAt(pt);\r
- if(chVal == '\n' || chVal == '\r' || chVal == '\t') continue;\r
- if(Character.isISOControl(chVal)){\r
- newValue.setCharAt(pt, (char)('\u2400' + chVal));\r
- }\r
- }\r
-\r
- writer.append(name);\r
- writer.append('=');\r
- writer.append('"');\r
- textOut(writer, newValue);\r
- writer.append('"');\r
- return;\r
- }\r
-\r
- /**\r
- * xsd:time形式の時刻属性を出力する。\r
- * タイムゾーンは「+09:00」固定\r
- * @param writer 出力先\r
- * @param name 属性名\r
- * @param hour 時間\r
- * @param minute 分\r
- * @throws IOException 出力エラー\r
- */\r
- public static void timeAttrOut(Writer writer,\r
- CharSequence name,\r
- int hour, int minute)\r
- throws IOException{\r
- String cmtTime =\r
- MessageFormat\r
- .format("{0,number,#00}:{1,number,#00}:00+09:00",\r
- hour, minute);\r
- attrOut(writer, name, cmtTime);\r
- return;\r
- }\r
-\r
- /**\r
- * xsd:gMonthDay形式の日付属性を出力する。\r
- * タイムゾーンは「+09:00」固定\r
- * @param writer 出力先\r
- * @param name 属性名\r
- * @param month 月\r
- * @param day 日\r
- * @throws IOException 出力エラー\r
- */\r
- public static void dateAttrOut(Writer writer,\r
- CharSequence name,\r
- int month, int day)\r
- throws IOException{\r
- String dateAttr =\r
- MessageFormat.format("--{0,number,#00}-{1,number,#00}+09:00",\r
- month, day);\r
- attrOut(writer, name, dateAttr);\r
- return;\r
- }\r
-\r
- /**\r
- * xsd:dateTime形式の日付時刻属性を出力する。\r
- * タイムゾーンは「+09:00」固定\r
- * @param writer 出力先\r
- * @param name 属性名\r
- * @param epochMs エポック時刻\r
- * @throws IOException 出力エラー\r
- */\r
- public static void dateTimeAttr(Writer writer,\r
- CharSequence name,\r
- long epochMs)\r
- throws IOException{\r
- Calendar calendar = new GregorianCalendar(TZ_TOKYO);\r
-\r
- calendar.setTimeInMillis(epochMs);\r
- int year = calendar.get(Calendar.YEAR);\r
- int month = calendar.get(Calendar.MONTH) + 1;\r
- int day = calendar.get(Calendar.DATE);\r
- int hour = calendar.get(Calendar.HOUR_OF_DAY);\r
- int minute = calendar.get(Calendar.MINUTE);\r
- int sec = calendar.get(Calendar.SECOND);\r
- int msec = calendar.get(Calendar.MILLISECOND);\r
-\r
- String attrVal = MessageFormat.format(\r
- "{0,number,#0000}-{1,number,#00}-{2,number,#00}"\r
- +"T{3,number,#00}:{4,number,#00}:{5,number,#00}"\r
- +".{6,number,#000}+09:00",\r
- year, month, day, hour, minute, sec, msec);\r
-\r
- attrOut(writer, name, attrVal);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * デコードエラー情報をrawdataタグで出力する。\r
- * 文字列集合に関するエラーの場合、windows31jでのデコード出力を試みる。\r
- * @param writer 出力先\r
- * @param errorInfo デコードエラー\r
- * @throws IOException 出力エラー\r
- */\r
- public static void dumpErrorInfo(Writer writer,\r
- DecodeErrorInfo errorInfo)\r
- throws IOException{\r
- int hexVal;\r
- hexVal = errorInfo.getRawByte1st() & 0xff;\r
- if(errorInfo.has2nd()){\r
- hexVal <<= 8;\r
- hexVal |= errorInfo.getRawByte2nd() & 0xff;\r
- }\r
-\r
- String hexBin = Integer.toHexString(hexVal);\r
- if(hexBin.length() % 2 != 0) hexBin = "0" + hexBin;\r
-\r
- char replaceChar = Win31j.getWin31jChar(errorInfo);\r
-\r
- writer.append("<rawdata");\r
-\r
- writer.append(' ');\r
- attrOut(writer, "encoding", "Shift_JIS");\r
-\r
- writer.append(' ');\r
- attrOut(writer, "hexBin", hexBin);\r
-\r
- writer.append(" >");\r
- writer.append(replaceChar);\r
- writer.append("</rawdata>");\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * デコードエラー込みのテキストを出力する。\r
- * @param writer 出力先\r
- * @param content テキスト\r
- * @throws IOException 出力エラー\r
- */\r
- public static void dumpDecodedContent(Writer writer,\r
- DecodedContent content)\r
- throws IOException{\r
- if( ! content.hasDecodeError() ){\r
- textOut(writer, content);\r
- return;\r
- }\r
-\r
- int last = 0;\r
-\r
- List<DecodeErrorInfo> errList = content.getDecodeErrorList();\r
- for(DecodeErrorInfo err : errList){\r
- int charPos = err.getCharPosition();\r
- CharSequence line = content.subSequence(last, charPos);\r
- textOut(writer, line);\r
- dumpErrorInfo(writer, err);\r
- last = charPos + 1;\r
- }\r
-\r
- CharSequence line = content.subSequence(last, content.length());\r
- textOut(writer, line);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 村情報をXML形式で出力する。\r
- * @param writer 出力先\r
- * @param villageData 村情報\r
- * @throws IOException 出力エラー\r
- */\r
- public static void dumpVillageData(Writer writer,\r
- VillageData villageData)\r
- throws IOException{\r
- writer.append("<?xml");\r
- writer.append(' ');\r
- attrOut(writer, "version", "1.0");\r
- writer.append(' ');\r
- attrOut(writer, "encoding", "UTF-8");\r
- writer.append(" ?>\n\n");\r
-\r
- writer.append("<!--\n");\r
- writer.append(" 人狼BBSアーカイブ\n");\r
- writer.append(" http://jindolf.sourceforge.jp/\n");\r
- writer.append("-->\n\n");\r
-\r
- dumpDocType(writer);\r
- writer.append("\n\n");\r
-\r
- villageData.dumpXml(writer);\r
-\r
- writer.append("\n<!-- EOF -->\n");\r
-\r
- writer.flush();\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 村情報を反映した出力ファイル名を生成する。\r
- * @param village 村情報\r
- * @return XML出力ファイル名\r
- */\r
- public static String createOutFileName(VillageData village){\r
- LandDef landDef = village.getLandDef();\r
- String landId = landDef.getLandId();\r
- int vid = village.getVillageId();\r
-\r
- String fname =\r
- MessageFormat.format(\r
- "{0}jin_{1}_{2,number,#00000}.xml", OUTPATH, landId, vid);\r
- return fname;\r
- }\r
-\r
- /**\r
- * 村情報を反映した出力ファイルへの文字ストリームを生成する。\r
- * @param village 村情報\r
- * @return 出力先文字ストリーム\r
- * @throws IOException 出力エラー\r
- */\r
- public static Writer createFileWriter(VillageData village)\r
- throws IOException{\r
- String fname = createOutFileName(village);\r
- File file = new File(fname);\r
-\r
- OutputStream ostream;\r
- ostream = new FileOutputStream(file);\r
- ostream = new BufferedOutputStream(ostream, 10000);\r
- Writer writer;\r
- writer = new OutputStreamWriter(ostream, "UTF-8");\r
- writer = new BufferedWriter(writer, 10000);\r
- return writer;\r
- }\r
-\r
-}\r
+/*
+ * XML utils
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.text.MessageFormat;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.TimeZone;
+import jp.sourceforge.jindolf.corelib.LandDef;
+import jp.sourceforge.jindolf.parser.DecodeErrorInfo;
+import jp.sourceforge.jindolf.parser.DecodedContent;
+
+/**
+ * XML用各種ユーティリティ。
+ */
+public final class XmlUtils{
+
+ private static final String ORIG_DTD =
+ "http://jindolf.sourceforge.jp/xml/dtd/bbsArchive-110421.dtd";
+ private static final String ORIG_NS =
+ "http://jindolf.sourceforge.jp/xml/ns/501";
+ private static final String ORIG_SCHEME =
+ "http://jindolf.sourceforge.jp/xml/xsd/bbsArchive-110421.xsd";
+ private static final String SCHEMA_NS =
+ "http://www.w3.org/2001/XMLSchema-instance";
+
+ private static final String OUTPATH = "D:\\TEMP\\zxzx\\";
+
+ private static final char BS_CHAR = (char) 0x005c; // Backslash
+ private static final String INDENT_UNIT = "\u0020\u0020";
+
+ private static final TimeZone TZ_TOKYO =
+ TimeZone.getTimeZone("Asia/Tokyo");
+
+
+ /**
+ * 隠れコンストラクタ。
+ */
+ private XmlUtils(){
+ throw new Error();
+ }
+
+
+ /**
+ * DOCTYPE宣言を出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public static void dumpDocType(Writer writer) throws IOException{
+ writer.append("<!DOCTYPE village SYSTEM ");
+ writer.append('"');
+ writer.append(ORIG_DTD);
+ writer.append('"');
+ writer.append(" >");
+ return;
+ }
+
+ /**
+ * オリジナルNameSpace宣言を出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public static void dumpNameSpaceDecl(Writer writer)
+ throws IOException{
+ attrOut(writer, "xmlns", ORIG_NS);
+ return;
+ }
+
+ /**
+ * スキーマNameSpace宣言を出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public static void dumpSiNameSpaceDecl(Writer writer)
+ throws IOException{
+ attrOut(writer, "xmlns:xsi", SCHEMA_NS);
+ return;
+ }
+
+ /**
+ * スキーマ位置指定を出力する。
+ * @param writer 出力先
+ * @throws IOException 出力エラー
+ */
+ public static void dumpSchemeLocation(Writer writer)
+ throws IOException{
+ attrOut(writer,
+ "xsi:schemaLocation",
+ ORIG_NS + " " + ORIG_SCHEME);
+ return;
+ }
+
+ /**
+ * インデント用空白を出力する。
+ * ネスト単位は空白2文字
+ * @param writer 出力先
+ * @param level ネストレベル
+ * @throws IOException 出力エラー
+ */
+ public static void indent(Writer writer, int level) throws IOException{
+ for(int ct = 1; ct <= level; ct++){
+ writer.append(INDENT_UNIT);
+ }
+ return;
+ }
+
+ /**
+ * XML数値文字参照を出力する。
+ * @param writer 出力先
+ * @param chVal 出力文字
+ * @throws IOException 出力エラー
+ */
+ public static void charRefOut(Writer writer, char chVal)
+ throws IOException{
+ if(chVal == '\u0020'){
+ writer.append(" ");
+ return;
+ }
+
+ if(chVal == '\u0009'){
+ writer.append("	");
+ return;
+ }
+
+ int ival = 0xffff & ((int) chVal);
+ String hex = Integer.toHexString(ival);
+ if(hex.length() % 2 != 0) hex = "0" + hex;
+
+ writer.append("&#x");
+ writer.append(hex);
+ writer.append(";");
+
+ return;
+ }
+
+ /**
+ * 不正文字をXML出力する。
+ * @param writer 出力先
+ * @param chVal 不正文字
+ * @throws IOException 出力エラー
+ */
+ public static void dumpInvalidChar(Writer writer, char chVal)
+ throws IOException{
+ int hexVal;
+ hexVal = chVal & 0xff;
+ String hexBin = Integer.toHexString(hexVal);
+ if(hexBin.length() % 2 != 0) hexBin = "0" + hexBin;
+
+ char replaceChar = '\ufffd';
+ if('\u0000' <= chVal && chVal <= '\u001f'){
+ replaceChar = (char)( chVal + '\u2400' );
+ }
+
+ writer.append("<rawdata");
+
+ writer.append(' ');
+ attrOut(writer, "encoding", "Shift_JIS");
+
+ writer.append(' ');
+ attrOut(writer, "hexBin", hexBin);
+
+ writer.append(" >");
+ writer.append(replaceChar);
+ writer.append("</rawdata>");
+ }
+
+ /**
+ * 任意の文字がXML規格上のホワイトスペースに属するか判定する。
+ * @param chVal 文字
+ * @return ホワイトスペースならtrue
+ */
+ public static boolean isWhiteSpace(char chVal){
+ switch(chVal){
+ case '\u0020':
+ case '\t':
+ case '\n':
+ case '\r':
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+ }
+
+ /**
+ * 文字列を出力する。
+ * <ul>
+ * <li>先頭および末尾のホワイトスペースは強制的に文字参照化される。
+ * <li>連続したホワイトスペースの2文字目以降は文字参照化される。
+ * <li>スペースでないホワイトスペースは無条件に文字参照化される。
+ * <li>{@literal &, <, >, "}は無条件に文字参照化される。
+ * </ul>
+ * 参考:XML 1.0 規格 3.3.3節
+ * @param writer 出力先
+ * @param seq CDATA文字列
+ * @throws IOException 出力エラー
+ */
+ public static void textOut(Writer writer, CharSequence seq)
+ throws IOException{
+ int len = seq.length();
+
+ boolean leadSpace = false;
+
+ for(int pos = 0; pos < len; pos++){
+ char chVal = seq.charAt(pos);
+
+ if(isWhiteSpace(chVal)){
+ if(pos == 0 || pos >= len - 1 || leadSpace){
+ charRefOut(writer, chVal);
+ }else if(chVal != '\u0020'){
+ charRefOut(writer, chVal);
+ }else{
+ writer.append(chVal);
+ }
+ leadSpace = true;
+ }else{
+ if(chVal == '&'){
+ writer.append("&");
+ }else if(chVal == '<'){
+ writer.append("<");
+ }else if(chVal == '>'){
+ writer.append(">");
+ }else if(chVal == '"'){
+ writer.append(""");
+ }else if(chVal == '\''){
+ writer.append("'");
+ }else if(chVal == BS_CHAR){
+ writer.append('\u00a5');
+ }else if(chVal == '\u007e'){
+ writer.append('\u203e');
+ }else if(Character.isISOControl(chVal)){
+ dumpInvalidChar(writer, chVal);
+ }else{
+ writer.append(chVal);
+ }
+ leadSpace = false;
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * 属性を出力する。
+ * @param writer 出力先
+ * @param name 属性名
+ * @param value 属性値
+ * @throws IOException 出力エラー
+ */
+ public static void attrOut(Writer writer,
+ CharSequence name,
+ CharSequence value)
+ throws IOException{
+ StringBuilder newValue = new StringBuilder(value);
+ for(int pt = 0; pt < newValue.length(); pt++){
+ char chVal = newValue.charAt(pt);
+ if(chVal == '\n' || chVal == '\r' || chVal == '\t') continue;
+ if(Character.isISOControl(chVal)){
+ newValue.setCharAt(pt, (char)('\u2400' + chVal));
+ }
+ }
+
+ writer.append(name);
+ writer.append('=');
+ writer.append('"');
+ textOut(writer, newValue);
+ writer.append('"');
+ return;
+ }
+
+ /**
+ * xsd:time形式の時刻属性を出力する。
+ * タイムゾーンは「+09:00」固定
+ * @param writer 出力先
+ * @param name 属性名
+ * @param hour 時間
+ * @param minute 分
+ * @throws IOException 出力エラー
+ */
+ public static void timeAttrOut(Writer writer,
+ CharSequence name,
+ int hour, int minute)
+ throws IOException{
+ String cmtTime =
+ MessageFormat
+ .format("{0,number,#00}:{1,number,#00}:00+09:00",
+ hour, minute);
+ attrOut(writer, name, cmtTime);
+ return;
+ }
+
+ /**
+ * xsd:gMonthDay形式の日付属性を出力する。
+ * タイムゾーンは「+09:00」固定
+ * @param writer 出力先
+ * @param name 属性名
+ * @param month 月
+ * @param day 日
+ * @throws IOException 出力エラー
+ */
+ public static void dateAttrOut(Writer writer,
+ CharSequence name,
+ int month, int day)
+ throws IOException{
+ String dateAttr =
+ MessageFormat.format("--{0,number,#00}-{1,number,#00}+09:00",
+ month, day);
+ attrOut(writer, name, dateAttr);
+ return;
+ }
+
+ /**
+ * xsd:dateTime形式の日付時刻属性を出力する。
+ * タイムゾーンは「+09:00」固定
+ * @param writer 出力先
+ * @param name 属性名
+ * @param epochMs エポック時刻
+ * @throws IOException 出力エラー
+ */
+ public static void dateTimeAttr(Writer writer,
+ CharSequence name,
+ long epochMs)
+ throws IOException{
+ Calendar calendar = new GregorianCalendar(TZ_TOKYO);
+
+ calendar.setTimeInMillis(epochMs);
+ int year = calendar.get(Calendar.YEAR);
+ int month = calendar.get(Calendar.MONTH) + 1;
+ int day = calendar.get(Calendar.DATE);
+ int hour = calendar.get(Calendar.HOUR_OF_DAY);
+ int minute = calendar.get(Calendar.MINUTE);
+ int sec = calendar.get(Calendar.SECOND);
+ int msec = calendar.get(Calendar.MILLISECOND);
+
+ String attrVal = MessageFormat.format(
+ "{0,number,#0000}-{1,number,#00}-{2,number,#00}"
+ +"T{3,number,#00}:{4,number,#00}:{5,number,#00}"
+ +".{6,number,#000}+09:00",
+ year, month, day, hour, minute, sec, msec);
+
+ attrOut(writer, name, attrVal);
+
+ return;
+ }
+
+ /**
+ * デコードエラー情報をrawdataタグで出力する。
+ * 文字列集合に関するエラーの場合、windows31jでのデコード出力を試みる。
+ * @param writer 出力先
+ * @param errorInfo デコードエラー
+ * @throws IOException 出力エラー
+ */
+ public static void dumpErrorInfo(Writer writer,
+ DecodeErrorInfo errorInfo)
+ throws IOException{
+ int hexVal;
+ hexVal = errorInfo.getRawByte1st() & 0xff;
+ if(errorInfo.has2nd()){
+ hexVal <<= 8;
+ hexVal |= errorInfo.getRawByte2nd() & 0xff;
+ }
+
+ String hexBin = Integer.toHexString(hexVal);
+ if(hexBin.length() % 2 != 0) hexBin = "0" + hexBin;
+
+ char replaceChar = Win31j.getWin31jChar(errorInfo);
+
+ writer.append("<rawdata");
+
+ writer.append(' ');
+ attrOut(writer, "encoding", "Shift_JIS");
+
+ writer.append(' ');
+ attrOut(writer, "hexBin", hexBin);
+
+ writer.append(" >");
+ writer.append(replaceChar);
+ writer.append("</rawdata>");
+
+ return;
+ }
+
+ /**
+ * デコードエラー込みのテキストを出力する。
+ * @param writer 出力先
+ * @param content テキスト
+ * @throws IOException 出力エラー
+ */
+ public static void dumpDecodedContent(Writer writer,
+ DecodedContent content)
+ throws IOException{
+ if( ! content.hasDecodeError() ){
+ textOut(writer, content);
+ return;
+ }
+
+ int last = 0;
+
+ List<DecodeErrorInfo> errList = content.getDecodeErrorList();
+ for(DecodeErrorInfo err : errList){
+ int charPos = err.getCharPosition();
+ CharSequence line = content.subSequence(last, charPos);
+ textOut(writer, line);
+ dumpErrorInfo(writer, err);
+ last = charPos + 1;
+ }
+
+ CharSequence line = content.subSequence(last, content.length());
+ textOut(writer, line);
+
+ return;
+ }
+
+ /**
+ * 村情報をXML形式で出力する。
+ * @param writer 出力先
+ * @param villageData 村情報
+ * @throws IOException 出力エラー
+ */
+ public static void dumpVillageData(Writer writer,
+ VillageData villageData)
+ throws IOException{
+ writer.append("<?xml");
+ writer.append(' ');
+ attrOut(writer, "version", "1.0");
+ writer.append(' ');
+ attrOut(writer, "encoding", "UTF-8");
+ writer.append(" ?>\n\n");
+
+ writer.append("<!--\n");
+ writer.append(" 人狼BBSアーカイブ\n");
+ writer.append(" http://jindolf.sourceforge.jp/\n");
+ writer.append("-->\n\n");
+
+ dumpDocType(writer);
+ writer.append("\n\n");
+
+ villageData.dumpXml(writer);
+
+ writer.append("\n<!-- EOF -->\n");
+
+ writer.flush();
+
+ return;
+ }
+
+ /**
+ * 村情報を反映した出力ファイル名を生成する。
+ * @param village 村情報
+ * @return XML出力ファイル名
+ */
+ public static String createOutFileName(VillageData village){
+ LandDef landDef = village.getLandDef();
+ String landId = landDef.getLandId();
+ int vid = village.getVillageId();
+
+ String fname =
+ MessageFormat.format(
+ "{0}jin_{1}_{2,number,#00000}.xml", OUTPATH, landId, vid);
+ return fname;
+ }
+
+ /**
+ * 村情報を反映した出力ファイルへの文字ストリームを生成する。
+ * @param village 村情報
+ * @return 出力先文字ストリーム
+ * @throws IOException 出力エラー
+ */
+ public static Writer createFileWriter(VillageData village)
+ throws IOException{
+ String fname = createOutFileName(village);
+ File file = new File(fname);
+
+ OutputStream ostream;
+ ostream = new FileOutputStream(file);
+ ostream = new BufferedOutputStream(ostream, 10000);
+ Writer writer;
+ writer = new OutputStreamWriter(ostream, "UTF-8");
+ writer = new BufferedWriter(writer, 10000);
+ return writer;
+ }
+
+}
-/*\r
- * ZIP utils\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
-\r
-import java.io.File;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.io.Writer;\r
-import java.net.MalformedURLException;\r
-import java.net.URI;\r
-import java.net.URISyntaxException;\r
-import java.net.URL;\r
-import java.util.Enumeration;\r
-import java.util.Iterator;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.regex.Matcher;\r
-import java.util.regex.Pattern;\r
-import java.util.zip.ZipEntry;\r
-import java.util.zip.ZipFile;\r
-import jp.sourceforge.jindolf.parser.DecodeException;\r
-import jp.sourceforge.jindolf.parser.HtmlParseException;\r
-\r
-/**\r
- * ZIPアーカイブされた生XHTML情報へのアクセス諸々。\r
- */\r
-public final class ZipUtils{\r
-\r
- /**\r
- * 隠れコンストラクタ。\r
- */\r
- private ZipUtils(){\r
- super();\r
- return;\r
- }\r
-\r
-\r
- /**\r
- * ZIPファイルに格納された村一覧を抽出する。\r
- * 各日のロードはまだ行われない。\r
- * @param zipFile ZIPファイル\r
- * @return 村一覧\r
- * @throws IOException 入力エラー\r
- */\r
- public static List<VillageData> getVillageDataList(ZipFile zipFile)\r
- throws IOException{\r
- List<VillageData> result = new LinkedList<VillageData>();\r
-\r
- List<ZipEntry> logList = getDownloadLogList(zipFile);\r
- for(ZipEntry entry : logList){\r
- VillageData villageData =\r
- getVillageDataFromLogEntry(zipFile, entry);\r
- result.add(villageData);\r
- }\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * ZIPファイルからダウンロードログファイルの一覧を取得する。\r
- * ダウンロードログファイルは必ず「download.log」の名前を持つ。\r
- * @param file ZIPファイル\r
- * @return ログファイル一覧\r
- */\r
- public static List<ZipEntry> getDownloadLogList(ZipFile file){\r
- List<ZipEntry> result = new LinkedList<ZipEntry>();\r
-\r
- Enumeration<? extends ZipEntry> list = file.entries();\r
- while(list.hasMoreElements()){\r
- ZipEntry entry = list.nextElement();\r
- String name = entry.getName();\r
- if(name.endsWith("/download.log" )){\r
- result.add(entry);\r
- }\r
- }\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * ログファイルを表すZIPエントリから村情報を抽出する。\r
- * @param zipFile ZIPファイル\r
- * @param logEntry ログファイルのZIPエントリ\r
- * @return 村情報\r
- * @throws IOException 入力エラー\r
- */\r
- public static VillageData getVillageDataFromLogEntry(\r
- ZipFile zipFile, ZipEntry logEntry)\r
- throws IOException{\r
- InputStream istream = zipFile.getInputStream(logEntry);\r
- List<PeriodResource> list =\r
- FileArchive.parseDownloadLog(istream);\r
- istream.close();\r
-\r
- String baseName = logEntry.getName().replaceAll("/[^/]+$", "/");\r
- for(PeriodResource resource : list){\r
- modifyResourceUrl(zipFile, baseName, resource);\r
- }\r
-\r
- VillageData villageData = new VillageData(list);\r
- return villageData;\r
- }\r
-\r
- /**\r
- * ログ記録に書かれたXHTMLファイル名を実際にアクセス可能なURLに修正する。\r
- * @param zipFile ZIPファイル\r
- * @param entryBase ファイル名のベース\r
- * @param resource リソース情報\r
- * @return 引数と同じ物\r
- */\r
- public static PeriodResource modifyResourceUrl(ZipFile zipFile,\r
- String entryBase,\r
- PeriodResource resource ){\r
- String fileName;\r
- try{\r
- URL resUrl = resource.getResourceUrl();\r
- URI resUri = resUrl.toURI();\r
- File file = new File(resUri);\r
- fileName = file.getName();\r
- }catch(URISyntaxException e){\r
- throw new IllegalArgumentException(e);\r
- }\r
-\r
- String zipUri = new File(zipFile.getName()).toURI().toString();\r
-\r
- String urlText = "jar:" + zipUri + "!/" + entryBase + fileName;\r
-\r
- URL zipResource;\r
- try{\r
- zipResource = new URL(urlText);\r
- }catch(MalformedURLException e){\r
- throw new IllegalArgumentException(e);\r
- }\r
-\r
- resource.setResourceUrl(zipResource);\r
-\r
- return resource;\r
- }\r
-\r
- /**\r
- * 村番号から村情報を得る。\r
- * @param zipFile ZIPファイル\r
- * @param vid 村番号\r
- * @return 村情報\r
- * @throws IOException 入力エラー\r
- */\r
- public static VillageData getVillageData(ZipFile zipFile, int vid)\r
- throws IOException{\r
- ZipEntry entry = getDownloadLogEntry(zipFile, vid);\r
- VillageData result = getVillageDataFromLogEntry(zipFile, entry);\r
- return result;\r
- }\r
-\r
- /**\r
- * 村番号から該当するログファイルエントリを取得する。\r
- * @param file ZIPファイル\r
- * @param vid 村番号\r
- * @return ログファイルのZIPエントリ。見つからなければnull。\r
- */\r
- public static ZipEntry getDownloadLogEntry(ZipFile file, int vid){\r
- Pattern entryPattern =\r
- Pattern.compile("jin_[^_]+_([0-9]+)/download.log$");\r
-\r
- Enumeration<? extends ZipEntry> list = file.entries();\r
- while(list.hasMoreElements()){\r
- ZipEntry entry = list.nextElement();\r
- String name = entry.getName();\r
- Matcher matcher = entryPattern.matcher(name);\r
- if(matcher.find()){\r
- String vnum = matcher.group(1);\r
- if(vid == Integer.parseInt(vnum)) return entry;\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- /**\r
- * ZIPファイル中の指定した村番号の村をXML出力する。\r
- * @param zipFile ZIPファイル\r
- * @param vid 村番号\r
- * @param writer 出力先\r
- * @throws IOException 入出力エラー\r
- * @throws DecodeException デコードエラー\r
- * @throws HtmlParseException パースエラー\r
- */\r
- public static void dumpZipVid(ZipFile zipFile, int vid, Writer writer)\r
- throws IOException, DecodeException, HtmlParseException{\r
- VillageData data = getVillageData(zipFile, vid);\r
- Builder.fillVillageData(data);\r
- XmlUtils.dumpVillageData(writer, data);\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * ZIPファイル中の全村をXML出力する。\r
- * @param zipFile ZIPファイル\r
- * @throws IOException 入出力エラー\r
- * @throws DecodeException デコードエラー\r
- * @throws HtmlParseException パースエラー\r
- */\r
- public static void dumpZipAll(ZipFile zipFile)\r
- throws IOException, DecodeException, HtmlParseException{\r
- List<VillageData> villageDataList;\r
- villageDataList = ZipUtils.getVillageDataList(zipFile);\r
- Iterator<VillageData> it = villageDataList.iterator();\r
- while(it.hasNext()){\r
- VillageData villageData = it.next();\r
- Builder.fillVillageData(villageData);\r
- Writer writer = XmlUtils.createFileWriter(villageData);\r
- XmlUtils.dumpVillageData(writer, villageData);\r
- writer.close();\r
- it.remove();\r
- }\r
-\r
- return;\r
- }\r
-\r
-}\r
+/*
+ * ZIP utils
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf.archiver;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import jp.sourceforge.jindolf.parser.DecodeException;
+import jp.sourceforge.jindolf.parser.HtmlParseException;
+
+/**
+ * ZIPアーカイブされた生XHTML情報へのアクセス諸々。
+ */
+public final class ZipUtils{
+
+ /**
+ * 隠れコンストラクタ。
+ */
+ private ZipUtils(){
+ super();
+ return;
+ }
+
+
+ /**
+ * ZIPファイルに格納された村一覧を抽出する。
+ * 各日のロードはまだ行われない。
+ * @param zipFile ZIPファイル
+ * @return 村一覧
+ * @throws IOException 入力エラー
+ */
+ public static List<VillageData> getVillageDataList(ZipFile zipFile)
+ throws IOException{
+ List<VillageData> result = new LinkedList<VillageData>();
+
+ List<ZipEntry> logList = getDownloadLogList(zipFile);
+ for(ZipEntry entry : logList){
+ VillageData villageData =
+ getVillageDataFromLogEntry(zipFile, entry);
+ result.add(villageData);
+ }
+
+ return result;
+ }
+
+ /**
+ * ZIPファイルからダウンロードログファイルの一覧を取得する。
+ * ダウンロードログファイルは必ず「download.log」の名前を持つ。
+ * @param file ZIPファイル
+ * @return ログファイル一覧
+ */
+ public static List<ZipEntry> getDownloadLogList(ZipFile file){
+ List<ZipEntry> result = new LinkedList<ZipEntry>();
+
+ Enumeration<? extends ZipEntry> list = file.entries();
+ while(list.hasMoreElements()){
+ ZipEntry entry = list.nextElement();
+ String name = entry.getName();
+ if(name.endsWith("/download.log" )){
+ result.add(entry);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * ログファイルを表すZIPエントリから村情報を抽出する。
+ * @param zipFile ZIPファイル
+ * @param logEntry ログファイルのZIPエントリ
+ * @return 村情報
+ * @throws IOException 入力エラー
+ */
+ public static VillageData getVillageDataFromLogEntry(
+ ZipFile zipFile, ZipEntry logEntry)
+ throws IOException{
+ InputStream istream = zipFile.getInputStream(logEntry);
+ List<PeriodResource> list =
+ FileArchive.parseDownloadLog(istream);
+ istream.close();
+
+ String baseName = logEntry.getName().replaceAll("/[^/]+$", "/");
+ for(PeriodResource resource : list){
+ modifyResourceUrl(zipFile, baseName, resource);
+ }
+
+ VillageData villageData = new VillageData(list);
+ return villageData;
+ }
+
+ /**
+ * ログ記録に書かれたXHTMLファイル名を実際にアクセス可能なURLに修正する。
+ * @param zipFile ZIPファイル
+ * @param entryBase ファイル名のベース
+ * @param resource リソース情報
+ * @return 引数と同じ物
+ */
+ public static PeriodResource modifyResourceUrl(ZipFile zipFile,
+ String entryBase,
+ PeriodResource resource ){
+ String fileName;
+ try{
+ URL resUrl = resource.getResourceUrl();
+ URI resUri = resUrl.toURI();
+ File file = new File(resUri);
+ fileName = file.getName();
+ }catch(URISyntaxException e){
+ throw new IllegalArgumentException(e);
+ }
+
+ String zipUri = new File(zipFile.getName()).toURI().toString();
+
+ String urlText = "jar:" + zipUri + "!/" + entryBase + fileName;
+
+ URL zipResource;
+ try{
+ zipResource = new URL(urlText);
+ }catch(MalformedURLException e){
+ throw new IllegalArgumentException(e);
+ }
+
+ resource.setResourceUrl(zipResource);
+
+ return resource;
+ }
+
+ /**
+ * 村番号から村情報を得る。
+ * @param zipFile ZIPファイル
+ * @param vid 村番号
+ * @return 村情報
+ * @throws IOException 入力エラー
+ */
+ public static VillageData getVillageData(ZipFile zipFile, int vid)
+ throws IOException{
+ ZipEntry entry = getDownloadLogEntry(zipFile, vid);
+ VillageData result = getVillageDataFromLogEntry(zipFile, entry);
+ return result;
+ }
+
+ /**
+ * 村番号から該当するログファイルエントリを取得する。
+ * @param file ZIPファイル
+ * @param vid 村番号
+ * @return ログファイルのZIPエントリ。見つからなければnull。
+ */
+ public static ZipEntry getDownloadLogEntry(ZipFile file, int vid){
+ Pattern entryPattern =
+ Pattern.compile("jin_[^_]+_([0-9]+)/download.log$");
+
+ Enumeration<? extends ZipEntry> list = file.entries();
+ while(list.hasMoreElements()){
+ ZipEntry entry = list.nextElement();
+ String name = entry.getName();
+ Matcher matcher = entryPattern.matcher(name);
+ if(matcher.find()){
+ String vnum = matcher.group(1);
+ if(vid == Integer.parseInt(vnum)) return entry;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * ZIPファイル中の指定した村番号の村をXML出力する。
+ * @param zipFile ZIPファイル
+ * @param vid 村番号
+ * @param writer 出力先
+ * @throws IOException 入出力エラー
+ * @throws DecodeException デコードエラー
+ * @throws HtmlParseException パースエラー
+ */
+ public static void dumpZipVid(ZipFile zipFile, int vid, Writer writer)
+ throws IOException, DecodeException, HtmlParseException{
+ VillageData data = getVillageData(zipFile, vid);
+ Builder.fillVillageData(data);
+ XmlUtils.dumpVillageData(writer, data);
+
+ return;
+ }
+
+ /**
+ * ZIPファイル中の全村をXML出力する。
+ * @param zipFile ZIPファイル
+ * @throws IOException 入出力エラー
+ * @throws DecodeException デコードエラー
+ * @throws HtmlParseException パースエラー
+ */
+ public static void dumpZipAll(ZipFile zipFile)
+ throws IOException, DecodeException, HtmlParseException{
+ List<VillageData> villageDataList;
+ villageDataList = ZipUtils.getVillageDataList(zipFile);
+ Iterator<VillageData> it = villageDataList.iterator();
+ while(it.hasNext()){
+ VillageData villageData = it.next();
+ Builder.fillVillageData(villageData);
+ Writer writer = XmlUtils.createFileWriter(villageData);
+ XmlUtils.dumpVillageData(writer, villageData);
+ writer.close();
+ it.remove();
+ }
+
+ return;
+ }
+
+}
-/*\r
- * JinArchive パッケージコメント\r
- *\r
- * このファイルは、SunJDK5.0以降に含まれるJavadoc用に用意された、\r
- * 特別な名前を持つソースファイルです。\r
- * このファイルはソースコードを含まず、\r
- * パッケージコメントとパッケージ宣言のみが含まれます。\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-/**\r
- * このプログラム「JinArchive」は、\r
- * 人狼BBSサーバへアクセスし任意の村のプレイデータを独自のXML形式で\r
- * 保存するためのプログラムです。\r
- *\r
- * <hr>\r
- *\r
- * <p>\r
- * The MIT License\r
- * </p>\r
- * <p>\r
- * Copyright(c) 2009 olyutorskii\r
- * </p>\r
- * <p>\r
- * Permission is hereby granted, free of charge, to any person obtaining a\r
- * copy of this software and associated documentation files (the "Software"),\r
- * to deal in the Software without restriction, including without limitation\r
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
- * and/or sell copies of the Software, and to permit persons to whom the\r
- * Software is furnished to do so, subject to the following conditions:\r
- * </p>\r
- * <p>\r
- * The above copyright notice and this permission notice shall be included in\r
- * all copies or substantial portions of the Software.\r
- * </p>\r
- * <p>\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\r
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\r
- * OTHER DEALINGS IN THE SOFTWARE.\r
- * </p>\r
- *\r
- * <hr>\r
- *\r
- * @see <a href="http://jindolf.sourceforge.jp/">\r
- * Jindolfポータルサイト</a>\r
- * @see <a href="http://sourceforge.jp/projects/jindolf/">\r
- * Jindolf開発プロジェクト</a>\r
- */\r
-\r
-package jp.sourceforge.jindolf.archiver;\r
+/*
+ * JinArchive パッケージコメント
+ *
+ * このファイルは、SunJDK5.0以降に含まれるJavadoc用に用意された、
+ * 特別な名前を持つソースファイルです。
+ * このファイルはソースコードを含まず、
+ * パッケージコメントとパッケージ宣言のみが含まれます。
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+/**
+ * このプログラム「JinArchive」は、
+ * 人狼BBSサーバへアクセスし任意の村のプレイデータを独自のXML形式で
+ * 保存するためのプログラムです。
+ *
+ * <hr>
+ *
+ * <p>
+ * The MIT License
+ * </p>
+ * <p>
+ * Copyright(c) 2009 olyutorskii
+ * </p>
+ * <p>
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * </p>
+ * <p>
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * </p>
+ * <p>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * </p>
+ *
+ * <hr>
+ *
+ * @see <a href="http://jindolf.sourceforge.jp/">
+ * Jindolfポータルサイト</a>
+ * @see <a href="http://sourceforge.jp/projects/jindolf/">
+ * Jindolf開発プロジェクト</a>
+ */
+
+package jp.sourceforge.jindolf.archiver;