OSDN Git Service

パッケージ移動
authorOlyutorskii <olyutorskii@users.osdn.me>
Sun, 19 May 2013 14:00:55 +0000 (23:00 +0900)
committerOlyutorskii <olyutorskii@users.osdn.me>
Sun, 19 May 2013 14:00:55 +0000 (23:00 +0900)
37 files changed:
pom.xml
src/main/java/jp/sfjp/mikutoga/bin/parser/BinParser.java [new file with mode: 0644]
src/main/java/jp/sfjp/mikutoga/bin/parser/CommonParser.java
src/main/java/jp/sfjp/mikutoga/bin/parser/ParseStage.java
src/main/java/jp/sfjp/mikutoga/bin/parser/ProxyParser.java [new file with mode: 0644]
src/main/java/jp/sfjp/mikutoga/corelib/EmptyProxyFactory.java
src/main/java/jp/sfjp/mikutoga/pmd/PmdConst.java [moved from src/main/java/jp/sfjp/mikutoga/pmd/PmdLimits.java with 97% similarity]
src/main/java/jp/sfjp/mikutoga/pmd/parser/PmdParserBase.java
src/main/java/jp/sfjp/mikutoga/pmd/parser/PmdParserExt1.java
src/main/java/jp/sfjp/mikutoga/pmd/parser/PmdParserExt2.java
src/main/java/jp/sfjp/mikutoga/pmd/parser/PmdParserExt3.java
src/main/java/jp/sfjp/mikutoga/vmd/AbstractNumbered.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/AbstractNumbered.java with 95% similarity]
src/main/java/jp/sfjp/mikutoga/vmd/FrameNumbered.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/FrameNumbered.java with 97% similarity]
src/main/java/jp/sfjp/mikutoga/vmd/IllegalVmdDataException.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/IllegalVmdDataException.java with 96% similarity]
src/main/java/jp/sfjp/mikutoga/vmd/VmdConst.java [new file with mode: 0644]
src/main/java/jp/sfjp/mikutoga/vmd/VmdUniq.java [new file with mode: 0644]
src/main/java/jp/sfjp/mikutoga/vmd/package-info.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/package-info.java with 87% similarity]
src/main/java/jp/sfjp/mikutoga/vmd/parser/VmdBasicHandler.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/parser/VmdBasicHandler.java with 99% similarity]
src/main/java/jp/sfjp/mikutoga/vmd/parser/VmdBasicParser.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/parser/VmdBasicParser.java with 87% similarity]
src/main/java/jp/sfjp/mikutoga/vmd/parser/VmdCameraHandler.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/parser/VmdCameraHandler.java with 99% similarity]
src/main/java/jp/sfjp/mikutoga/vmd/parser/VmdCameraParser.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/parser/VmdCameraParser.java with 94% similarity]
src/main/java/jp/sfjp/mikutoga/vmd/parser/VmdLightingHandler.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/parser/VmdLightingHandler.java with 99% similarity]
src/main/java/jp/sfjp/mikutoga/vmd/parser/VmdLightingParser.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/parser/VmdLightingParser.java with 92% similarity]
src/main/java/jp/sfjp/mikutoga/vmd/parser/VmdParser.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/parser/VmdParser.java with 67% similarity]
src/main/java/jp/sfjp/mikutoga/vmd/parser/VmdUnifiedHandler.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/parser/VmdUnifiedHandler.java with 92% similarity]
src/main/java/jp/sfjp/mikutoga/vmd/parser/package-info.java [moved from src/main/java/jp/sourceforge/mikutoga/vmd/parser/package-info.java with 91% similarity]
src/main/java/jp/sourceforge/mikutoga/vmd/VmdConst.java [deleted file]
src/main/java/jp/sourceforge/mikutoga/xml/AbstractXmlExporter.java [new file with mode: 0644]
src/main/java/jp/sourceforge/mikutoga/xml/BasicXmlExporter.java
src/main/java/jp/sourceforge/mikutoga/xml/LocalSchema.java [deleted file]
src/main/java/jp/sourceforge/mikutoga/xml/LocalXmlResource.java [new file with mode: 0644]
src/main/java/jp/sourceforge/mikutoga/xml/ProxyXmlExporter.java [new file with mode: 0644]
src/main/java/jp/sourceforge/mikutoga/xml/SchemaUtil.java [new file with mode: 0644]
src/main/java/jp/sourceforge/mikutoga/xml/XmlExporter.java [new file with mode: 0644]
src/main/java/jp/sourceforge/mikutoga/xml/XmlResourceResolver.java
src/test/java/sample/vmd/DummyHandler.java
src/test/java/sample/vmd/DummyMain.java

diff --git a/pom.xml b/pom.xml
index 73470b5..732123b 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,7 @@
     <groupId>jp.sourceforge.mikutoga</groupId>
     <artifactId>togagem</artifactId>
 
-    <version>2.102.3-SNAPSHOT</version>
+    <version>2.102.5-SNAPSHOT</version>
 
     <packaging>jar</packaging>
     <name>TogaGem</name>
diff --git a/src/main/java/jp/sfjp/mikutoga/bin/parser/BinParser.java b/src/main/java/jp/sfjp/mikutoga/bin/parser/BinParser.java
new file mode 100644 (file)
index 0000000..3ce9f21
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * binary parser interface
+ *
+ * License : The MIT License
+ * Copyright(c) 2013 MikuToga Partners
+ */
+
+package jp.sfjp.mikutoga.bin.parser;
+
+import java.io.IOException;
+
+/**
+ * バイナリパーサの共通インタフェース。
+ * <p>バイト列、各種プリミティブ型値およびエンコードされた文字列を読み込む。
+ * <p>long,double、およびビッグエンディアン形式のデータは未サポート。
+ */
+public interface BinParser {
+
+    /**
+     * 入力ソースの読み込み位置を返す。
+     * @return 入力ソースの読み込み位置。単位はbyte。
+     */
+    long getPosition();
+
+    /**
+     * 入力ソースにまだデータが残っているか判定する。
+     * @return まだ読み込んでいないデータが残っていればtrue
+     * @throws IOException IOエラー
+     */
+    boolean hasMore() throws IOException;
+
+    /**
+     * 入力ソースを読み飛ばす。
+     * @param skipLength 読み飛ばすバイト数。
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み飛ばす途中でストリーム終端に達した。
+     * @see java.io.InputStream#skip(long)
+     */
+    void skip(long skipLength) throws IOException, MmdEofException;
+
+    /**
+     * byte配列を読み込む。
+     * @param dst 格納先配列
+     * @param off 読み込み開始オフセット
+     * @param length 読み込みバイト数
+     * @throws NullPointerException 配列がnull
+     * @throws IndexOutOfBoundsException 引数が配列属性と矛盾
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see java.io.InputStream#read(byte[], int, int)
+     */
+    void parseByteArray(byte[] dst, int off, int length)
+            throws NullPointerException,
+                   IndexOutOfBoundsException,
+                   IOException,
+                   MmdEofException;
+
+    /**
+     * byte配列を読み込む。
+     * <p>配列要素全ての読み込みが試みられる。
+     * @param dst 格納先配列
+     * @throws NullPointerException 配列がnull
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * @see java.io.InputStream#read(byte[])
+     */
+    void parseByteArray(byte[] dst)
+            throws NullPointerException, IOException, MmdEofException;
+
+    /**
+     * byte値を読み込む。
+     * @return 読み込んだbyte値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    byte parseByte() throws IOException, MmdEofException;
+
+    /**
+     * 符号無し値としてbyte値を読み込み、int型に変換して返す。
+     * <p>符号は拡張されない。(0xffは0x000000ffとなる)
+     * @return 読み込まれた値のint値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    int parseUByteAsInt() throws IOException, MmdEofException;
+
+    /**
+     * byte値を読み込み、boolean型に変換して返す。
+     * <p>0x00は偽、それ以外は真と解釈される。
+     * @return 読み込まれた値のboolean値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    boolean parseBoolean() throws IOException, MmdEofException;
+
+    /**
+     * short値を読み込む。
+     * <p>short値はリトルエンディアンで格納されていると仮定される。
+     * @return 読み込んだshort値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    short parseLeShort() throws IOException, MmdEofException;
+
+    /**
+     * 符号無し値としてshort値を読み込み、int型に変換して返す。
+     * <p>符号は拡張されない。(0xffffは0x0000ffffとなる)
+     * <p>short値はリトルエンディアンで格納されていると仮定される。
+     * @return 読み込まれた値のint値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    int parseLeUShortAsInt() throws IOException, MmdEofException;
+
+    /**
+     * int値を読み込む。
+     * <p>int値はリトルエンディアンで格納されていると仮定される。
+     * @return 読み込んだint値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    int parseLeInt() throws IOException, MmdEofException;
+
+    /**
+     * float値を読み込む。
+     * <p>float値はリトルエンディアンで格納されていると仮定される。
+     * @return 読み込んだfloat値
+     * @throws IOException IOエラー
+     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     */
+    float parseLeFloat() throws IOException, MmdEofException;
+
+    /**
+     * 固定バイト長の文字列を読み込む。
+     * @param decoder 文字デコーダ
+     * @param byteLen 読み込む固定バイト長
+     * @return 文字列
+     * @throws IOException 入力エラー
+     * @throws MmdEofException 固定長バイト列を読む前に末端に達した。
+     * @throws MmdFormatException 文字エンコーディングに関するエラー
+     */
+    String parseString(TextDecoder decoder, int byteLen)
+            throws IOException, MmdEofException, MmdFormatException;
+
+}
index e1cd3fe..ceedad5 100644 (file)
@@ -18,11 +18,9 @@ import java.nio.charset.MalformedInputException;
 import java.nio.charset.UnmappableCharacterException;
 
 /**
- * 各種バイナリファイルパーサの共通実装。
- * <p>バイト列、各種プリミティブ型値およびエンコードされた文字列を読み込む。
- * <p>long,double、およびビッグエンディアン形式のデータは未サポート。
+ * 入力ストリームをソースとするバイナリパーサ実装。
  */
-public class CommonParser {
+public class CommonParser implements BinParser{
 
     private static final String ERRMSG_ILLENC =
             "illegal character encoding";
@@ -77,19 +75,21 @@ public class CommonParser {
 
 
     /**
-     * 入力ソースの読み込み位置を返す。
-     * @return 入力ソースの読み込み位置。単位はbyte。
+     * {@inheritDoc}
+     * @return {@inheritDoc}
      */
-    protected long getPosition(){
+    @Override
+    public long getPosition(){
         long result = this.position;
         return result;
     }
 
     /**
-     * 入力ソースにまだデータが残っているか判定する。
-     * @return まだ読み込んでいないデータが残っていればtrue
-     * @throws IOException IOエラー
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
      */
+    @Override
     public boolean hasMore() throws IOException{
         int bVal;
 
@@ -109,13 +109,13 @@ public class CommonParser {
     }
 
     /**
-     * 入力ソースを読み飛ばす。
-     * @param skipLength 読み飛ばすバイト数。
-     * @throws IOException IOエラー
-     * @throws MmdEofException 読み飛ばす途中でストリーム終端に達した。
-     * @see InputStream#skip(long)
+     * {@inheritDoc}
+     * @param skipLength {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
      */
-    protected void skip(long skipLength)
+    @Override
+    public void skip(long skipLength)
             throws IOException, MmdEofException {
         long remain = skipLength;
 
@@ -132,20 +132,20 @@ public class CommonParser {
     }
 
     /**
-     * byte配列を読み込む。
-     * @param dst 格納先配列
-     * @param off 読み込み開始オフセット
-     * @param length 読み込みバイト数
-     * @throws IOException IOエラー
-     * @throws NullPointerException 配列がnull
-     * @throws IndexOutOfBoundsException 引数が配列属性と矛盾
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
-     * @see InputStream#read(byte[], int, int)
+     * {@inheritDoc}
+     * @param dst {@inheritDoc}
+     * @param off {@inheritDoc}
+     * @param length {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     * @throws IndexOutOfBoundsException {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
      */
-    protected void parseByteArray(byte[] dst, int off, int length)
-            throws IOException,
-                   NullPointerException,
+    @Override
+    public void parseByteArray(byte[] dst, int off, int length)
+            throws NullPointerException,
                    IndexOutOfBoundsException,
+                   IOException,
                    MmdEofException {
         int remain = length;
         int offset = off;
@@ -164,16 +164,15 @@ public class CommonParser {
     }
 
     /**
-     * byte配列を読み込む。
-     * <p>配列要素全ての読み込みが試みられる。
-     * @param dst 格納先配列
-     * @throws IOException IOエラー
-     * @throws NullPointerException 配列がnull
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
-     * @see InputStream#read(byte[])
+     * {@inheritDoc}
+     * @param dst {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
      */
-    protected void parseByteArray(byte[] dst)
-            throws IOException, NullPointerException, MmdEofException{
+    @Override
+    public void parseByteArray(byte[] dst)
+            throws NullPointerException, IOException, MmdEofException{
         parseByteArray(dst, 0, dst.length);
         return;
     }
@@ -191,12 +190,13 @@ public class CommonParser {
     }
 
     /**
-     * byte値を読み込む。
-     * @return 読み込んだbyte値
-     * @throws IOException IOエラー
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
      */
-    protected byte parseByte()
+    @Override
+    public byte parseByte()
             throws IOException, MmdEofException{
         int bData = this.is.read();
         if(bData < 0){
@@ -210,25 +210,25 @@ public class CommonParser {
     }
 
     /**
-     * 符号無し値としてbyte値を読み込み、int型に変換して返す。
-     * <p>符号は拡張されない。(0xffは0x000000ffとなる)
-     * @return 読み込まれた値のint値
-     * @throws IOException IOエラー
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
      */
-    protected int parseUByteAsInt()
+    @Override
+    public int parseUByteAsInt()
             throws IOException, MmdEofException{
         return parseByte() & MASK_8BIT;
     }
 
     /**
-     * byte値を読み込み、boolean型に変換して返す。
-     * <p>0x00は偽、それ以外は真と解釈される。
-     * @return 読み込まれた値のboolean値
-     * @throws IOException IOエラー
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
      */
-    protected boolean parseBoolean()
+    @Override
+    public boolean parseBoolean()
             throws IOException, MmdEofException{
         byte result = parseByte();
         if(result == 0x00) return false;
@@ -236,13 +236,13 @@ public class CommonParser {
     }
 
     /**
-     * short値を読み込む。
-     * <p>short値はリトルエンディアンで格納されていると仮定される。
-     * @return 読み込んだshort値
-     * @throws IOException IOエラー
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
      */
-    protected short parseLeShort()
+    @Override
+    public short parseLeShort()
             throws IOException, MmdEofException{
         fillBuffer(BYTES_SHORT);
         short result = this.leBuf.getShort(0);
@@ -250,26 +250,25 @@ public class CommonParser {
     }
 
     /**
-     * 符号無し値としてshort値を読み込み、int型に変換して返す。
-     * <p>符号は拡張されない。(0xffffは0x0000ffffとなる)
-     * <p>short値はリトルエンディアンで格納されていると仮定される。
-     * @return 読み込まれた値のint値
-     * @throws IOException IOエラー
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
      */
-    protected int parseLeUShortAsInt()
+    @Override
+    public int parseLeUShortAsInt()
             throws IOException, MmdEofException{
         return parseLeShort() & MASK_16BIT;
     }
 
     /**
-     * int値を読み込む。
-     * <p>int値はリトルエンディアンで格納されていると仮定される。
-     * @return 読み込んだint値
-     * @throws IOException IOエラー
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
      */
-    protected int parseLeInt()
+    @Override
+    public int parseLeInt()
             throws IOException, MmdEofException{
         fillBuffer(BYTES_INT);
         int result = this.leBuf.getInt(0);
@@ -277,13 +276,13 @@ public class CommonParser {
     }
 
     /**
-     * float値を読み込む。
-     * <p>float値はリトルエンディアンで格納されていると仮定される。
-     * @return 読み込んだfloat値
-     * @throws IOException IOエラー
-     * @throws MmdEofException 読み込む途中でストリーム終端に達した。
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
      */
-    protected float parseLeFloat()
+    @Override
+    public float parseLeFloat()
             throws IOException, MmdEofException{
         fillBuffer(BYTES_FLOAT);
         float result = this.leBuf.getFloat(0);
@@ -291,15 +290,16 @@ public class CommonParser {
     }
 
     /**
-     * 固定バイト長の文字列を読み込む。
-     * @param decoder 文字デコーダ
-     * @param byteLen 読み込む固定バイト長
-     * @return 文字列
-     * @throws IOException 入力エラー
-     * @throws MmdEofException 固定長バイト列を読む前に末端に達した。
-     * @throws MmdFormatException 文字エンコーディングに関するエラー
+     * {@inheritDoc}
+     * @param decoder {@inheritDoc}
+     * @param byteLen {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
+     * @throws MmdFormatException {@inheritDoc}
      */
-    protected String parseString(TextDecoder decoder, int byteLen)
+    @Override
+    public String parseString(TextDecoder decoder, int byteLen)
             throws IOException, MmdEofException, MmdFormatException {
         if(this.btextBuf == null || this.btextBuf.capacity() < byteLen){
             this.btextBuf = ByteBuffer.allocate(byteLen);
index 1198b7d..638422a 100644 (file)
@@ -18,8 +18,10 @@ public class ParseStage {
 
     private static final AtomicInteger LAST_NO = new AtomicInteger(0);
 
+
     /** 全インスタンスに割り振られたユニークな番号。変更不可。 */
-    public final int no;
+    private final int no;
+
 
     /**
      * コンストラクタ。
@@ -31,6 +33,7 @@ public class ParseStage {
         return;
     }
 
+
     /**
      * 各インスタンスに割り当てられたユニークな通し番号を返す。
      * @return 通し番号
diff --git a/src/main/java/jp/sfjp/mikutoga/bin/parser/ProxyParser.java b/src/main/java/jp/sfjp/mikutoga/bin/parser/ProxyParser.java
new file mode 100644 (file)
index 0000000..578f768
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * parser proxy
+ *
+ * License : The MIT License
+ * Copyright(c) 2013 MikuToga Partners
+ */
+
+package jp.sfjp.mikutoga.bin.parser;
+
+import java.io.IOException;
+
+/**
+ * 委譲パーサ。
+ * <p>別のパーサにパース処理を委譲する。
+ */
+public class ProxyParser implements BinParser{
+
+    private final BinParser delegate;
+
+
+    /**
+     * コンストラクタ。
+     * @param delegate 委譲先パーサ
+     * @throws NullPointerException 引数がnull
+     */
+    public ProxyParser(BinParser delegate) throws NullPointerException{
+        super();
+
+        if(delegate == null) throw new NullPointerException();
+        this.delegate = delegate;
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public long getPosition() {
+        return this.delegate.getPosition();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public boolean hasMore() throws IOException {
+        return this.delegate.hasMore();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param skipLength {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
+     */
+    @Override
+    public void skip(long skipLength) throws IOException, MmdEofException {
+        this.delegate.skip(skipLength);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param dst {@inheritDoc}
+     * @param off {@inheritDoc}
+     * @param length {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     * @throws IndexOutOfBoundsException {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
+     */
+    @Override
+    public void parseByteArray(byte[] dst, int off, int length)
+            throws NullPointerException,
+                   IndexOutOfBoundsException,
+                   IOException,
+                   MmdEofException {
+        this.delegate.parseByteArray(dst, off, length);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param dst {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
+     */
+    @Override
+    public void parseByteArray(byte[] dst)
+            throws NullPointerException,
+                   IOException,
+                   MmdEofException {
+        this.delegate.parseByteArray(dst);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
+     */
+    @Override
+    public byte parseByte() throws IOException, MmdEofException {
+        return this.delegate.parseByte();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
+     */
+    @Override
+    public int parseUByteAsInt() throws IOException, MmdEofException {
+        return this.delegate.parseUByteAsInt();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
+     */
+    @Override
+    public boolean parseBoolean() throws IOException, MmdEofException {
+        return this.delegate.parseBoolean();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
+     */
+    @Override
+    public short parseLeShort() throws IOException, MmdEofException {
+        return this.delegate.parseLeShort();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
+     */
+    @Override
+    public int parseLeUShortAsInt() throws IOException, MmdEofException {
+        return this.delegate.parseLeUShortAsInt();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
+     */
+    @Override
+    public int parseLeInt() throws IOException, MmdEofException {
+        return this.delegate.parseLeInt();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
+     */
+    @Override
+    public float parseLeFloat() throws IOException, MmdEofException {
+        return this.delegate.parseLeFloat();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param decoder {@inheritDoc}
+     * @param byteLen {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     * @throws MmdEofException {@inheritDoc}
+     * @throws MmdFormatException {@inheritDoc}
+     */
+    @Override
+    public String parseString(TextDecoder decoder, int byteLen)
+            throws IOException, MmdEofException, MmdFormatException {
+        return this.delegate.parseString(decoder, byteLen);
+    }
+
+}
index 360074a..bbfba54 100644 (file)
@@ -17,7 +17,7 @@ import java.lang.reflect.Proxy;
 public final class EmptyProxyFactory {
 
     /** 何もせず何も返さないInvoker。 */
-    public static InvocationHandler NOTHING_INVOKER = new Nothing();
+    public static final InvocationHandler NOTHING_INVOKER = new Nothing();
 
 
     /**
@@ -10,7 +10,7 @@ package jp.sfjp.mikutoga.pmd;
 /**
  * PMDファイルフォーマットの各種リミット値その他定数。
  */
-public final class PmdLimits {
+public final class PmdConst {
 
     /** モデル名最大長。バイト単位。 */
     public static final int MAXBYTES_MODELNAME = 20;
@@ -57,7 +57,7 @@ public final class PmdLimits {
     /**
      * 隠しコンストラクタ。
      */
-    private PmdLimits(){
+    private PmdConst(){
         super();
         assert false;
         throw new AssertionError();
index e991ad0..ca41f78 100644 (file)
@@ -15,7 +15,7 @@ import jp.sfjp.mikutoga.bin.parser.CommonParser;
 import jp.sfjp.mikutoga.bin.parser.MmdEofException;
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
 import jp.sfjp.mikutoga.bin.parser.TextDecoder;
-import jp.sfjp.mikutoga.pmd.PmdLimits;
+import jp.sfjp.mikutoga.pmd.PmdConst;
 import jp.sfjp.mikutoga.pmd.ShadingUtil;
 
 /**
@@ -257,9 +257,9 @@ public class PmdParserBase extends CommonParser {
         }
 
         String modelName =
-                parsePmdText(PmdLimits.MAXBYTES_MODELNAME);
+                parsePmdText(PmdConst.MAXBYTES_MODELNAME);
         String description =
-                parsePmdText(PmdLimits.MAXBYTES_MODELDESC);
+                parsePmdText(PmdConst.MAXBYTES_MODELDESC);
         description = description.replace(CRLF, LF);
 
         this.basicHandler.pmdHeaderInfo(header);
@@ -355,7 +355,7 @@ public class PmdParserBase extends CommonParser {
             int surfaceCount = parseLeInt();
 
             String shadingFile =
-                    parsePmdText(PmdLimits.MAXBYTES_TEXTUREFILENAME);
+                    parsePmdText(PmdConst.MAXBYTES_TEXTUREFILENAME);
             String[] splitted = ShadingUtil.splitShadingFileInfo(shadingFile);
             String textureFile = splitted[0];
             String sphereFile  = splitted[1];
@@ -418,7 +418,7 @@ public class PmdParserBase extends CommonParser {
 
         for(int ct = 0; ct < this.boneCount; ct++){
             String boneName =
-                    parsePmdText(PmdLimits.MAXBYTES_BONENAME);
+                    parsePmdText(PmdConst.MAXBYTES_BONENAME);
             int parentId  = parseLeUShortAsInt();
             int tailId    = parseLeUShortAsInt();
             byte boneKind = parseByte();
@@ -506,7 +506,7 @@ public class PmdParserBase extends CommonParser {
 
         for(int ct = 0; ct < this.morphCount; ct++){
             String morphName =
-                    parsePmdText(PmdLimits.MAXBYTES_MORPHNAME);
+                    parsePmdText(PmdConst.MAXBYTES_MORPHNAME);
             int vertexCount = parseLeInt();
             byte morphType  = parseByte();
 
@@ -586,7 +586,7 @@ public class PmdParserBase extends CommonParser {
 
         for(int ct = 0; ct < this.boneGroupCount; ct++){
             String groupName =
-                    parsePmdText(PmdLimits.MAXBYTES_BONEGROUPNAME);
+                    parsePmdText(PmdConst.MAXBYTES_BONEGROUPNAME);
             groupName = chopLastLF(groupName);
             this.boneHandler.pmdBoneGroupInfo(groupName);
 
index fbab5a8..680c83f 100644 (file)
@@ -10,7 +10,7 @@ package jp.sfjp.mikutoga.pmd.parser;
 import java.io.IOException;
 import java.io.InputStream;
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
-import jp.sfjp.mikutoga.pmd.PmdLimits;
+import jp.sfjp.mikutoga.pmd.PmdConst;
 
 /**
  * PMDモデルファイルのパーサ拡張その1。
@@ -78,9 +78,9 @@ public class PmdParserExt1 extends PmdParserBase {
         if( ! this.hasEnglishInfo ) return;
 
         String modelName =
-                parsePmdText(PmdLimits.MAXBYTES_MODELNAME);
+                parsePmdText(PmdConst.MAXBYTES_MODELNAME);
         String description =
-                parsePmdText(PmdLimits.MAXBYTES_MODELDESC);
+                parsePmdText(PmdConst.MAXBYTES_MODELDESC);
         description = description.replace(CRLF, LF);
 
         this.engHandler.pmdEngModelInfo(modelName, description);
@@ -101,7 +101,7 @@ public class PmdParserExt1 extends PmdParserBase {
 
         for(int ct = 0; ct < boneNum; ct++){
             String boneName =
-                    parsePmdText(PmdLimits.MAXBYTES_BONENAME);
+                    parsePmdText(PmdConst.MAXBYTES_BONENAME);
             this.engHandler.pmdEngBoneInfo(boneName);
 
             this.engHandler.loopNext(PmdEngHandler.ENGBONE_LIST);
@@ -125,7 +125,7 @@ public class PmdParserExt1 extends PmdParserBase {
 
         for(int ct = 0; ct < morphNum; ct++){
             String morphName =
-                    parsePmdText(PmdLimits.MAXBYTES_MORPHNAME);
+                    parsePmdText(PmdConst.MAXBYTES_MORPHNAME);
             this.engHandler.pmdEngMorphInfo(morphName);
 
             this.engHandler.loopNext(PmdEngHandler.ENGMORPH_LIST);
@@ -149,7 +149,7 @@ public class PmdParserExt1 extends PmdParserBase {
 
         for(int ct = 0; ct < groupNum; ct++){
             String boneGroupName =
-                    parsePmdText(PmdLimits.MAXBYTES_BONEGROUPNAME);
+                    parsePmdText(PmdConst.MAXBYTES_BONEGROUPNAME);
             this.engHandler.pmdEngBoneGroupInfo(boneGroupName);
 
             this.engHandler.loopNext(PmdEngHandler.ENGBONEGROUP_LIST);
index 3e6ce5c..3e9dd3c 100644 (file)
@@ -10,7 +10,7 @@ package jp.sfjp.mikutoga.pmd.parser;
 import java.io.IOException;
 import java.io.InputStream;
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
-import jp.sfjp.mikutoga.pmd.PmdLimits;
+import jp.sfjp.mikutoga.pmd.PmdConst;
 
 /**
  * PMDモデルファイルのパーサ拡張その2。
@@ -66,11 +66,11 @@ public class PmdParserExt2 extends PmdParserExt1 {
      */
     private void parseToonName() throws IOException, MmdFormatException{
         this.toonHandler.loopStart(PmdToonHandler.TOON_LIST,
-                                   PmdLimits.TOON_FIXEDNUM );
+                                   PmdConst.TOON_FIXEDNUM );
 
-        for(int ct = 0; ct < PmdLimits.TOON_FIXEDNUM; ct++){
+        for(int ct = 0; ct < PmdConst.TOON_FIXEDNUM; ct++){
             String toonName =
-                    parsePmdText(PmdLimits.MAXBYTES_TOONFILENAME);
+                    parsePmdText(PmdConst.MAXBYTES_TOONFILENAME);
             this.toonHandler.pmdToonFileInfo(toonName);
 
             this.toonHandler.loopNext(PmdToonHandler.TOON_LIST);
index 555f185..eb4f6f4 100644 (file)
@@ -10,7 +10,7 @@ package jp.sfjp.mikutoga.pmd.parser;
 import java.io.IOException;
 import java.io.InputStream;
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
-import jp.sfjp.mikutoga.pmd.PmdLimits;
+import jp.sfjp.mikutoga.pmd.PmdConst;
 
 /**
  * PMDモデルファイルのパーサ拡張その3。
@@ -86,7 +86,7 @@ public class PmdParserExt3 extends PmdParserExt2 {
 
         for(int ct = 0; ct < rigidNum; ct++){
             String rigidName =
-                    parsePmdText(PmdLimits.MAXBYTES_RIGIDNAME);
+                    parsePmdText(PmdConst.MAXBYTES_RIGIDNAME);
             this.rigidHandler.pmdRigidName(rigidName);
 
             int linkedBoneId   = parseLeUShortAsInt();
@@ -168,7 +168,7 @@ public class PmdParserExt3 extends PmdParserExt2 {
 
         for(int ct = 0; ct < jointNum; ct++){
             String jointName =
-                    parsePmdText(PmdLimits.MAXBYTES_JOINTNAME);
+                    parsePmdText(PmdConst.MAXBYTES_JOINTNAME);
             this.jointHandler.pmdJointName(jointName);
 
             int rigidIdA = parseLeInt();
@@ -5,7 +5,7 @@
  * Copyright(c) 2011 MikuToga Partners
  */
 
-package jp.sourceforge.mikutoga.vmd;
+package jp.sfjp.mikutoga.vmd;
 
 /**
  * FrameNumberedの抽象実装クラス。
@@ -5,7 +5,7 @@
  * Copyright(c) 2011 MikuToga Partners
  */
 
-package jp.sourceforge.mikutoga.vmd;
+package jp.sfjp.mikutoga.vmd;
 
 import java.util.Comparator;
 
@@ -5,7 +5,7 @@
  * Copyright(c) 2011 MikuToga Partners
  */
 
-package jp.sourceforge.mikutoga.vmd;
+package jp.sfjp.mikutoga.vmd;
 
 /**
  * VMDモーションデータの不備を発見した場合の例外。
diff --git a/src/main/java/jp/sfjp/mikutoga/vmd/VmdConst.java b/src/main/java/jp/sfjp/mikutoga/vmd/VmdConst.java
new file mode 100644 (file)
index 0000000..f60a7a4
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * VMD constant data
+ *
+ * License : The MIT License
+ * Copyright(c) 2011 MikuToga Partners
+ */
+
+package jp.sfjp.mikutoga.vmd;
+
+/**
+ * VMDファイルフォーマットの各種定数。
+ */
+public final class VmdConst {
+
+    /**
+     * VMDファイルヘッダ長。バイト単位。
+     */
+    public static final int HEADER_LENGTH = 30;
+
+    /**
+     * ファイルヘッダ部先頭のASCIIコード相当部。
+     */
+    public static final String MAGIC_TXT = "Vocaloid Motion Data 0002";
+
+    /**
+     * モデル名最大長。バイト単位。
+     */
+    public static final int MODELNAME_MAX = 20;
+
+    /**
+     * ボーン名最大長。バイト単位。
+     */
+    public static final int BONENAME_MAX = 15;
+
+    /**
+     * モーフ名最大長。バイト単位。
+     */
+    public static final int MORPHNAME_MAX = 15;
+
+
+    /**
+     * 隠しコンストラクタ。
+     */
+    private VmdConst(){
+        super();
+        assert false;
+        throw new AssertionError();
+    }
+
+}
diff --git a/src/main/java/jp/sfjp/mikutoga/vmd/VmdUniq.java b/src/main/java/jp/sfjp/mikutoga/vmd/VmdUniq.java
new file mode 100644 (file)
index 0000000..44faede
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * VMD special unique names
+ *
+ * License : The MIT License
+ * Copyright(c) 2013 MikuToga Partners
+ */
+
+package jp.sfjp.mikutoga.vmd;
+
+/**
+ * 各種特殊名に関する定義。
+ */
+public final class VmdUniq {
+
+    /**
+     * 便宜上割り振られる特殊なモーフ名。
+     */
+    public static final String MORPHNAME_BASE = "base";
+
+    /**
+     * カメラもしくはライティングデータに便宜上割り当てられるモデル名。
+     */
+    public static final String MODELNAME_STAGEACT =
+            "\u30ab\u30e1\u30e9\u30fb\u7167\u660e"; // "カメラ・照明";
+
+    static{
+        assert "カメラ・照明".equals(VmdUniq.MODELNAME_STAGEACT);
+    }
+
+
+    /**
+     * 隠しコンストラクタ。
+     */
+    private VmdUniq(){
+        assert false;
+        throw new AssertionError();
+    }
+
+
+    /**
+     * 特殊なモーフ名「base」か否か判定する。
+     * @param morphName モーフ名
+     * @return モーフ名が「base」ならtrue
+     */
+    public static boolean isBaseMorphName(String morphName) {
+        if(MORPHNAME_BASE.equals(morphName)){
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * カメラやライティングなどのステージ演出データの可能性があるか、
+     * モデル名から推測する。
+     * <p>モデル名が「カメラ・照明」である場合、
+     * そのモーションファイルはほぼ
+     * カメラ・ライティング用ステージ演出データであると推測される。
+     * @param modelName モデル名
+     * @return モデル名にカメラもしくはライティングの可能性があるならtrue
+     */
+    public static boolean isStageActName(String modelName) {
+        if(MODELNAME_STAGEACT.equals(modelName)){
+            return true;
+        }
+        return false;
+    }
+
+}
@@ -10,6 +10,6 @@
  * VMDファイル(*.vmd)操作関連の共通資産。
  */
 
-package jp.sourceforge.mikutoga.vmd;
+package jp.sfjp.mikutoga.vmd;
 
 /* EOF */
@@ -5,7 +5,7 @@
  * Copyright(c) 2011 MikuToga Partners
  */
 
-package jp.sourceforge.mikutoga.vmd.parser;
+package jp.sfjp.mikutoga.vmd.parser;
 
 import jp.sfjp.mikutoga.bin.parser.LoopHandler;
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
@@ -5,22 +5,23 @@
  * Copyright(c) 2011 MikuToga Partners
  */
 
-package jp.sourceforge.mikutoga.vmd.parser;
+package jp.sfjp.mikutoga.vmd.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.Charset;
-import jp.sfjp.mikutoga.bin.parser.CommonParser;
+import jp.sfjp.mikutoga.bin.parser.BinParser;
 import jp.sfjp.mikutoga.bin.parser.MmdEofException;
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
+import jp.sfjp.mikutoga.bin.parser.ProxyParser;
 import jp.sfjp.mikutoga.bin.parser.TextDecoder;
-import jp.sourceforge.mikutoga.vmd.VmdConst;
+import jp.sfjp.mikutoga.vmd.VmdConst;
+import jp.sfjp.mikutoga.vmd.VmdUniq;
 
 /**
  * VMDモーションファイルの基本部パーサ。
  * <p>ボーンのモーション情報およびモーフモーション情報のパース処理を含む。
  */
-class VmdBasicParser extends CommonParser{
+class VmdBasicParser extends ProxyParser{
 
     /**
      * VMDで用いられる文字エンコーディング(windows-31j)。
@@ -28,6 +29,7 @@ class VmdBasicParser extends CommonParser{
      * デコード結果はUCS-2集合に収まるはず。
      */
     public static final Charset CS_WIN31J = Charset.forName("windows-31j");
+    private static final Charset CS_ASCII = Charset.forName("US-ASCII");
 
     private static final int BZ_SIZE = 4;           // 4byte Bezier parameter
     private static final int BZXYZR_SIZE = BZ_SIZE * 4; // XYZR Bezier
@@ -37,6 +39,8 @@ class VmdBasicParser extends CommonParser{
     private static final String ERRMSG_INVINTPLT =
             "there is potential inconsistency in motion interpolation data. "
             +"(Strict-mode)";
+    private static final String ERRMSG_UK_HEADER =
+            "unknown VMD-header type";
 
 
     private final TextDecoder decoderWin31j  = new TextDecoder(CS_WIN31J);
@@ -46,15 +50,15 @@ class VmdBasicParser extends CommonParser{
     private VmdBasicHandler handler = VmdUnifiedHandler.EMPTY;
 
     private boolean hasStageActName = false;
-    private boolean strictMode = true;
+    private boolean redundantCheck = false;
 
 
     /**
      * コンストラクタ。
-     * @param source 入力ソース
+     * @param parser 委譲先パーサ
      */
-    VmdBasicParser(InputStream source){
-        super(source);
+    VmdBasicParser(BinParser parser){
+        super(parser);
         this.decoderWin31j.setZeroChopMode(true);
         return;
     }
@@ -83,14 +87,12 @@ class VmdBasicParser extends CommonParser{
     }
 
     /**
-     * 厳密なパース(Strict-mode)を行うか否か設定する。
-     * デフォルトではStrict-modeはオン。
-     * <p>Strict-mode下では、
-     * ボーンモーションの冗長な補間情報の一貫性チェックが行わる。
-     * @param mode Strict-modeに設定したければtrue
+     * ボーンモーション補間情報冗長部のチェックを行うか否か設定する。
+     * デフォルトではチェックを行わない。
+     * @param mode チェックさせたければtrue
      */
-    void setStrictMode(boolean mode){
-        this.strictMode = mode;
+    void setRedundantCheck(boolean mode){
+        this.redundantCheck = mode;
         return;
     }
 
@@ -107,7 +109,7 @@ class VmdBasicParser extends CommonParser{
      * @throws MmdEofException 読み込む途中でストリーム終端に達した。
      * @throws MmdFormatException 不正な文字エンコーディングが検出された。
      */
-    protected String parseVmdText(int byteLen)
+    private String parseVmdText(int byteLen)
             throws IOException,
                    MmdEofException,
                    MmdFormatException {
@@ -140,8 +142,11 @@ class VmdBasicParser extends CommonParser{
         byte[] header = new byte[VmdConst.HEADER_LENGTH];
         parseByteArray(header);
 
-        if( ! VmdConst.startsWithMagic(header) ){
-            throw new MmdFormatException("unknown VMD-header type");
+        byte[] magic = (VmdConst.MAGIC_TXT + '\0').getBytes(CS_ASCII);
+        for(int idx = 0; idx < magic.length; idx++){
+            if(header.length <= idx || header[idx] != magic[idx]){
+                throw new MmdFormatException(ERRMSG_UK_HEADER);
+            }
         }
 
         this.handler.vmdHeaderInfo(header);
@@ -157,7 +162,7 @@ class VmdBasicParser extends CommonParser{
     private void parseVmdModelName() throws IOException, MmdFormatException{
         String modelName = parseVmdText(VmdConst.MODELNAME_MAX);
 
-        if(VmdConst.isStageActName(modelName)){
+        if(VmdUniq.isStageActName(modelName)){
             this.hasStageActName = true;
         }
 
@@ -213,7 +218,7 @@ class VmdBasicParser extends CommonParser{
             throws IOException, MmdFormatException{
         parseByteArray(this.motionIntplt);
 
-        if(this.strictMode){
+        if(this.redundantCheck){
             checkIntpltStrict();
         }
 
@@ -251,6 +256,7 @@ class VmdBasicParser extends CommonParser{
 
     /**
      * 補間情報の冗長箇所の整合性チェックを行う。
+     * <p>※ MMDの版数によって微妙に詳細が異なる場合がある。
      * @throws MmdFormatException 冗長箇所の不整合を検出した。
      */
     private void checkIntpltStrict() throws MmdFormatException{
@@ -5,7 +5,7 @@
  * Copyright(c) 2011 MikuToga Partners
  */
 
-package jp.sourceforge.mikutoga.vmd.parser;
+package jp.sfjp.mikutoga.vmd.parser;
 
 import jp.sfjp.mikutoga.bin.parser.LoopHandler;
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
@@ -5,17 +5,17 @@
  * Copyright(c) 2011 MikuToga Partners
  */
 
-package jp.sourceforge.mikutoga.vmd.parser;
+package jp.sfjp.mikutoga.vmd.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
-import jp.sfjp.mikutoga.bin.parser.CommonParser;
+import jp.sfjp.mikutoga.bin.parser.BinParser;
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
+import jp.sfjp.mikutoga.bin.parser.ProxyParser;
 
 /**
  * VMDモーションファイルのカメラモーションパーサ。
  */
-class VmdCameraParser extends CommonParser{
+class VmdCameraParser extends ProxyParser{
 
     private static final int BZ_SIZE = 4;           // 4byte Bezier parameter
     private static final int BZXYZ_SIZE = BZ_SIZE * 3; // XYZ Bezier
@@ -30,10 +30,10 @@ class VmdCameraParser extends CommonParser{
 
     /**
      * コンストラクタ。
-     * @param source 入力ソース
+     * @param parser 委譲先パーサ
      */
-    VmdCameraParser(InputStream source){
-        super(source);
+    VmdCameraParser(BinParser parser){
+        super(parser);
         return;
     }
 
@@ -5,7 +5,7 @@
  * Copyright(c) 2011 MikuToga Partners
  */
 
-package jp.sourceforge.mikutoga.vmd.parser;
+package jp.sfjp.mikutoga.vmd.parser;
 
 import jp.sfjp.mikutoga.bin.parser.LoopHandler;
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
@@ -5,29 +5,29 @@
  * Copyright(c) 2011 MikuToga Partners
  */
 
-package jp.sourceforge.mikutoga.vmd.parser;
+package jp.sfjp.mikutoga.vmd.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
-import jp.sfjp.mikutoga.bin.parser.CommonParser;
+import jp.sfjp.mikutoga.bin.parser.BinParser;
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
+import jp.sfjp.mikutoga.bin.parser.ProxyParser;
 
 /**
  * VMDモーションファイルのライティング情報パーサ。
  * 照明光源演出データと影演出データを含む。
  * <p>古い版のVMDファイルには影演出データが記述されていない場合がある。
  */
-class VmdLightingParser extends CommonParser {
+class VmdLightingParser extends ProxyParser {
 
     private VmdLightingHandler handler = VmdUnifiedHandler.EMPTY;
 
 
     /**
      * コンストラクタ。
-     * @param source 入力ソース
+     * @param parser 委譲先パーサ
      */
-    VmdLightingParser(InputStream source){
-        super(source);
+    VmdLightingParser(BinParser parser){
+        super(parser);
         return;
     }
 
@@ -5,10 +5,12 @@
  * Copyright(c) 2011 MikuToga Partners
  */
 
-package jp.sourceforge.mikutoga.vmd.parser;
+package jp.sfjp.mikutoga.vmd.parser;
 
 import java.io.IOException;
 import java.io.InputStream;
+import jp.sfjp.mikutoga.bin.parser.BinParser;
+import jp.sfjp.mikutoga.bin.parser.CommonParser;
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
 
 /**
@@ -23,7 +25,9 @@ public class VmdParser {
     private final VmdLightingParser lightingParser;
 
     private VmdBasicHandler basicHandler  = VmdUnifiedHandler.EMPTY;
-    private boolean strictMode = true;
+
+    private boolean ignoreName = true;
+    private boolean redundantCheck = false;
 
 
     /**
@@ -37,9 +41,11 @@ public class VmdParser {
         if(source == null) throw new NullPointerException();
         this.source = source;
 
-        this.basicParser    = new VmdBasicParser(source);
-        this.cameraParser   = new VmdCameraParser(source);
-        this.lightingParser = new VmdLightingParser(source);
+        BinParser parser = new CommonParser(this.source);
+
+        this.basicParser    = new VmdBasicParser(parser);
+        this.cameraParser   = new VmdCameraParser(parser);
+        this.lightingParser = new VmdLightingParser(parser);
 
         return;
     }
@@ -88,18 +94,28 @@ public class VmdParser {
     }
 
     /**
-     * 厳密なパース(Strict-mode)を行うか否か設定する。
-     * デフォルトではStrict-modeはオン。
-     * <p>Strict-mode下では、
-     * ボーンモーションの冗長な補間情報の一貫性チェックが行われ、
-     * モデル名がなんであろうとカメラ・ライティングデータのパースを試みる。
+     * カメラ・ライティングデータのパースを試みるか否かの判断で、
+     * 特殊モデル名判定を無視するか否か設定する。
+     * デフォルトではモデル名を無視。
      * <p>※MMDVer7.30前後のVMD出力不具合を回避したい場合は、
-     * Strict-modeをオフにするとパースに成功する場合がある。
-     * @param mode Strict-modeに設定したければtrue
+     * オフにするとパースに成功する場合がある。
+     * @param mode モデル名を無視するならtrue
      */
-    public void setStrictMode(boolean mode){
-        this.strictMode = mode;
-        this.basicParser.setStrictMode(this.strictMode);
+    public void setIgnoreName(boolean mode){
+        this.ignoreName = mode;
+        return;
+    }
+
+    /**
+     * ボーンモーション補間情報冗長部のチェックを行うか否か設定する。
+     * デフォルトではチェックを行わない。
+     * <p>※MMDVer7.30前後のVMD出力不具合を回避したい場合は、
+     * オフにするとパースに成功する場合がある。
+     * @param mode チェックさせたければtrue
+     */
+    public void setRedundantCheck(boolean mode){
+        this.redundantCheck = mode;
+        this.basicParser.setRedundantCheck(mode);
         return;
     }
 
@@ -109,6 +125,9 @@ public class VmdParser {
      * @throws MmdFormatException フォーマットエラー
      */
     public void parseVmd() throws IOException, MmdFormatException {
+        setIgnoreName(this.ignoreName);
+        setRedundantCheck(this.redundantCheck);
+
         this.basicHandler.vmdParseStart();
 
         parseBody();
@@ -130,7 +149,7 @@ public class VmdParser {
     private void parseBody() throws IOException, MmdFormatException{
         this.basicParser.parse();
 
-        if(this.basicParser.hasStageActName() || this.strictMode){
+        if(this.basicParser.hasStageActName() || this.ignoreName){
             this.cameraParser.parse();
             this.lightingParser.parse();
         }
@@ -5,7 +5,7 @@
  * Copyright(c) 2013 MikuToga Partners
  */
 
-package jp.sourceforge.mikutoga.vmd.parser;
+package jp.sfjp.mikutoga.vmd.parser;
 
 import jp.sfjp.mikutoga.corelib.EmptyProxyFactory;
 
@@ -12,6 +12,6 @@
  * 各種データの出現に応じてコールバックメソッドを次々と呼び出してくれる。
  */
 
-package jp.sourceforge.mikutoga.vmd.parser;
+package jp.sfjp.mikutoga.vmd.parser;
 
 /* EOF */
diff --git a/src/main/java/jp/sourceforge/mikutoga/vmd/VmdConst.java b/src/main/java/jp/sourceforge/mikutoga/vmd/VmdConst.java
deleted file mode 100644 (file)
index a114f0c..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * VMD constant data
- *
- * License : The MIT License
- * Copyright(c) 2011 MikuToga Partners
- */
-
-package jp.sourceforge.mikutoga.vmd;
-
-import java.nio.charset.Charset;
-
-/**
- * VMDファイルフォーマットの各種定数。
- */
-public final class VmdConst {
-
-    /**
-     * VMDファイルヘッダ長。バイト単位。
-     */
-    public static final int HEADER_LENGTH = 30;
-
-    /**
-     * ファイルヘッダ部先頭のASCIIコード相当部。
-     */
-    public static final String MAGIC_TXT = "Vocaloid Motion Data 0002";
-
-    /**
-     * モデル名最大長。バイト単位。
-     */
-    public static final int MODELNAME_MAX = 20;
-
-    /**
-     * ボーン名最大長。バイト単位。
-     */
-    public static final int BONENAME_MAX = 15;
-
-    /**
-     * モーフ名最大長。バイト単位。
-     */
-    public static final int MORPHNAME_MAX = 15;
-
-    /**
-     * カメラもしくはライティングデータに便宜上割り当てられるモデル名。
-     */
-    public static final String MODELNAME_STAGEACT =
-            "\u30ab\u30e1\u30e9\u30fb\u7167\u660e"; // "カメラ・照明";
-
-    /**
-     * 便宜上割り振られる特殊なモーフ名。
-     */
-    public static final String MORPHNAME_BASE = "base";
-
-
-    private static final Charset CS_ASCII = Charset.forName("US-ASCII");
-    private static final byte[] MAGIC_BYTES;
-
-
-    static{
-        MAGIC_BYTES = createMagicHeader();
-        assert MAGIC_BYTES.length <= HEADER_LENGTH;
-
-        assert "カメラ・照明".equals(MODELNAME_STAGEACT);
-    }
-
-
-    /**
-     * 隠しコンストラクタ。
-     */
-    private VmdConst(){
-        super();
-        assert false;
-        throw new AssertionError();
-    }
-
-    /**
-     * ヘッダ先頭のマジックバイト列を生成する。
-     * @return マジックバイト列
-     */
-    public static byte[] createMagicHeader(){
-        byte[] result = (MAGIC_TXT + '\0').getBytes(CS_ASCII);
-        return result;
-    }
-
-    /**
-     * バイト列先頭がマジックヘッダで始まるか検査する。
-     * @param array 検査対象のバイト列。
-     * @return マジックヘッダが検出されればtrue。
-     */
-    public static boolean startsWithMagic(byte[] array){
-        if(MAGIC_BYTES.length > array.length) return false;
-
-        for(int idx = 0; idx < MAGIC_BYTES.length; idx++){
-            if(array[idx] != MAGIC_BYTES[idx]) return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * カメラやライティングなどのステージ演出データの可能性があるか、
-     * モデル名から推測する。
-     * モデル名が"カメラ・照明"である場合、
-     * そのモーションファイルはほぼ
-     * カメラ・ライティング用ステージ演出データであると推測される。
-     * @param modelName モデル名
-     * @return モデル名にカメラもしくはライティングの可能性があるならtrue
-     */
-    public static boolean isStageActName(String modelName){
-        if(MODELNAME_STAGEACT.equals(modelName)) return true;
-        return false;
-    }
-
-    /**
-     * 特殊なモーフ名「base」か否か判定する。
-     * @param morphName モーフ名
-     * @return モーフ名が「base」ならtrue
-     */
-    public static boolean isBaseMorphName(String morphName){
-        if(MORPHNAME_BASE.equals(morphName)) return true;
-        return false;
-    }
-
-}
diff --git a/src/main/java/jp/sourceforge/mikutoga/xml/AbstractXmlExporter.java b/src/main/java/jp/sourceforge/mikutoga/xml/AbstractXmlExporter.java
new file mode 100644 (file)
index 0000000..8344b4c
--- /dev/null
@@ -0,0 +1,664 @@
+/*
+ * abstract xml exporter
+ *
+ * License : The MIT License
+ * Copyright(c) 2013 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.xml;
+
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.xml.bind.DatatypeConverter;
+
+/**
+ * XMLエクスポータの半実装。
+ * UCS4は未サポート。
+ */
+abstract class AbstractXmlExporter implements XmlExporter{
+
+    /** デフォルトの改行文字列。 */
+    private static final String DEF_NL = "\n";       // 0x0a(LF)
+    /** デフォルトのインデント単位。 */
+    private static final String DEF_INDENT_UNIT = "\u0020\u0020"; // ␣␣
+
+    private static final char CH_SP     = '\u0020';    // ␣
+    private static final char CH_YEN    = '\u00a5';    // ¥
+    private static final char CH_BSLASH = (char)0x005c; // \
+    private static final char CH_DQ     = '\u0022';    // "
+    private static final char CH_SQ     = (char)0x0027; // '
+    private static final char CH_EQ     = '=';          // =
+    private static final char CH_LT     = '<';
+    private static final char CH_GT     = '>';
+
+    private static final String COMM_START = "<!--";
+    private static final String COMM_END   =   "-->";
+
+    private static final Pattern NUM_FUZZY =
+            Pattern.compile("([^.]*\\.[0-9][0-9]*?)0+");
+
+    private static final String REF_HEX = "&#x";
+    private static final int HEX_EXP = 4;    // 2 ** 4 == 16
+    private static final int MASK_1HEX = (1 << HEX_EXP) - 1;  // 0b00001111
+    private static final int MAX_OCTET = (1 << Byte.SIZE) - 1;   // 0xff
+    private static final char[] HEXCHAR_TABLE = {
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        'A', 'B', 'C', 'D', 'E', 'F',
+    };
+
+    static{
+        assert HEX_EXP * 2 == Byte.SIZE;
+        assert HEXCHAR_TABLE.length == (1 << HEX_EXP);
+    }
+
+
+    private boolean basicLatinOnlyOut = true;
+    private String newline = DEF_NL;
+    private String indentUnit = DEF_INDENT_UNIT;
+    private int indentNest = 0;
+
+
+    /**
+     * コンストラクタ。
+     */
+    protected AbstractXmlExporter(){
+        super();
+        return;
+    }
+
+
+    /**
+     * ASCIIコード相当(UCS:Basic-Latin)の文字か否か判定する。
+     * <p>※ Basic-Latinには各種制御文字も含まれる。
+     * @param ch 判定対象文字
+     * @return Basic-Latin文字ならtrue
+     * <a href="http://www.unicode.org/charts/PDF/U0000.pdf">
+     * Unicode 6.2 Controls and Basic Latin
+     * </a>
+     */
+    protected static boolean isBasicLatin(char ch){
+        if('\u0000' <= ch && ch <= '\u007f'){
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 冗長な実数出力を抑止する。
+     * <p>DatatypeConverterにおけるJDK1.6系と1.7系の仕様変更を吸収する。
+     * <p>0.001fは"0.0010"ではなく"0.001"と出力される。
+     * <p>指数表記での冗長桁は無視する。
+     * @param numTxt 実数表記
+     * @return 冗長桁が抑止された実数表記
+     * @see javax.xml.bind.DatatypeConverter
+     */
+    protected static String chopFuzzyZero(String numTxt){
+        String result;
+
+        Matcher matcher = NUM_FUZZY.matcher(numTxt);
+        if(matcher.matches()){
+            result = matcher.group(1);
+        }else{
+            result = numTxt;
+        }
+
+        return result;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public abstract void flush() throws IOException;
+
+    /**
+     * {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public abstract void close() throws IOException;
+
+    /**
+     * {@inheritDoc}
+     * @param ch {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public abstract XmlExporter putRawCh(char ch)
+            throws IOException;
+
+    /**
+     * {@inheritDoc}
+     * @param seq {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public abstract XmlExporter putRawText(CharSequence seq)
+            throws IOException;
+
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter sp() throws IOException{
+        putRawCh(CH_SP);
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param count {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter sp(int count) throws IOException{
+        for(int ct = 1; ct <= count; ct++){
+            sp();
+        }
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String getNewLine(){
+        return this.newline;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param newLine {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     */
+    @Override
+    public void setNewLine(String newLine) throws NullPointerException{
+        if(newLine == null) throw new NullPointerException();
+        this.newline = newLine;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter ln() throws IOException{
+        putRawText(getNewLine());
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param count {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter ln(int count) throws IOException{
+        for(int ct = 1; ct <= count; ct++){
+            ln();
+        }
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String getIndentUnit(){
+        return this.indentUnit;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param indUnit {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     */
+    @Override
+    public void setIndentUnit(String indUnit) throws NullPointerException{
+        if(indUnit == null) throw new NullPointerException();
+        this.indentUnit = indUnit;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void pushNest(){
+        this.indentNest++;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void popNest(){
+        this.indentNest--;
+        if(this.indentNest < 0) this.indentNest = 0;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int getIndentLevel(){
+        return this.indentNest;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter ind() throws IOException{
+        int level = getIndentLevel();
+        for(int ct = 1; ct <= level; ct++){
+            putRawText(getIndentUnit());
+        }
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public boolean isBasicLatinOnlyOut(){
+        return this.basicLatinOnlyOut;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param bool {@inheritDoc}
+     */
+    @Override
+    public void setBasicLatinOnlyOut(boolean bool){
+        this.basicLatinOnlyOut = bool;
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param ch {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putCharRef2Hex(char ch) throws IOException{
+        if(ch > MAX_OCTET) return putCharRef4Hex(ch);
+
+        int ibits = ch;   // 常に正なので符号拡張なし
+
+        int idx4 = ibits & MASK_1HEX;
+        ibits >>= HEX_EXP;
+        int idx3 = ibits & MASK_1HEX;
+
+        char hex3 = HEXCHAR_TABLE[idx3];
+        char hex4 = HEXCHAR_TABLE[idx4];
+
+        putRawText(REF_HEX).putRawCh(hex3).putRawCh(hex4)
+                           .putRawCh(';');
+
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param ch {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putCharRef4Hex(char ch) throws IOException{
+        int ibits = ch;   // 常に正なので符号拡張なし
+
+        int idx4 = ibits & MASK_1HEX;
+        ibits >>= HEX_EXP;
+        int idx3 = ibits & MASK_1HEX;
+        ibits >>= HEX_EXP;
+        int idx2 = ibits & MASK_1HEX;
+        ibits >>= HEX_EXP;
+        int idx1 = ibits & MASK_1HEX;
+
+        char hex1 = HEXCHAR_TABLE[idx1];
+        char hex2 = HEXCHAR_TABLE[idx2];
+        char hex3 = HEXCHAR_TABLE[idx3];
+        char hex4 = HEXCHAR_TABLE[idx4];
+
+        putRawText(REF_HEX).putRawCh(hex1).putRawCh(hex2)
+                           .putRawCh(hex3).putRawCh(hex4)
+                           .putRawCh(';');
+
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param ch {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putCh(char ch) throws IOException{
+        if(Character.isISOControl(ch)){
+            putCharRef2Hex(ch);
+            return this;
+        }
+
+        String escTxt;
+        switch(ch){
+        case '&':   escTxt = "&amp;";  break;
+        case CH_LT: escTxt = "&lt;";   break;
+        case CH_GT: escTxt = "&gt;";   break;
+        case CH_DQ: escTxt = "&quot;"; break;
+        case CH_SQ: escTxt = "&apos;"; break;
+        default:    escTxt = null;     break;
+        }
+
+        if(escTxt != null){
+            putRawText(escTxt);
+        }else{
+            putRawCh(ch);
+        }
+
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param content {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putContent(CharSequence content)
+            throws IOException{
+        int length = content.length();
+
+        char prev = '\0';
+        for(int pos = 0; pos < length; pos++){
+            char ch = content.charAt(pos);
+
+            if( isBasicLatinOnlyOut() && ! isBasicLatin(ch) ){
+                putCharRef4Hex(ch);
+            }else if(ch == CH_YEN){
+                putRawCh(CH_BSLASH);
+            }else if(Character.isSpaceChar(ch)){
+                if(ch == CH_SP && prev != CH_SP){
+                    putRawCh(ch);
+                }else{
+                    putCharRef2Hex(ch);
+                }
+            }else{
+                putCh(ch);
+            }
+
+            prev = ch;
+        }
+
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param comment {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putCommentContent(CharSequence comment)
+            throws IOException{
+        int length = comment.length();
+
+        char prev = '\0';
+        for(int pos = 0; pos < length; pos++){
+            char ch = comment.charAt(pos);
+
+            if(ch == '\n'){
+                ln();
+            }else if('\u0000' <= ch && ch <= '\u001f'){
+                putRawCh((char)('\u2400' + ch));
+            }else if(ch == '\u007f'){
+                putRawCh('\u2421');
+            }else if(prev == '-' && ch == '-'){
+                sp().putRawCh(ch);
+            }else{
+                putRawCh(ch);
+            }
+
+            prev = ch;
+        }
+
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param comment {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putLineComment(CharSequence comment)
+            throws IOException{
+        putRawText(COMM_START).sp();
+        putCommentContent(comment);
+        sp().putRawText(COMM_END);
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param comment {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putBlockComment(CharSequence comment)
+            throws IOException{
+        putRawText(COMM_START).ln();
+
+        putCommentContent(comment);
+
+        int commentLength = comment.length();
+        if(commentLength > 0){
+            char lastCh = comment.charAt(commentLength - 1);
+            if(lastCh != '\n'){
+                ln();
+            }
+        }
+
+        putRawText(COMM_END).ln();
+
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param tagName {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putOpenSTag(CharSequence tagName)
+            throws IOException{
+        putRawCh(CH_LT);
+        putRawText(tagName);
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putCloseSTag()
+            throws IOException{
+        putRawCh(CH_GT);
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param tagName {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putSimpleSTag(CharSequence tagName)
+            throws IOException{
+        putRawCh(CH_LT);
+        putRawText(tagName);
+        putRawCh(CH_GT);
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param tagName {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putETag(CharSequence tagName)
+            throws IOException{
+        putRawText("</");
+        putRawText(tagName);
+        putRawCh(CH_GT);
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param tagName {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putSimpleEmpty(CharSequence tagName)
+            throws IOException{
+        putRawCh(CH_LT);
+        putRawText(tagName).sp();
+        putCloseEmpty();
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putCloseEmpty()
+            throws IOException{
+        putRawText("/>");
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param iVal {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putXsdInt(int iVal) throws IOException{
+        String value = DatatypeConverter.printInt(iVal);
+        putRawText(value);
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param fVal {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putXsdFloat(float fVal) throws IOException{
+        String value = DatatypeConverter.printFloat(fVal);
+        value = chopFuzzyZero(value);
+        putRawText(value);
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param attrName {@inheritDoc}
+     * @param iVal {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putIntAttr(CharSequence attrName,
+                                        int iVal)
+            throws IOException{
+        putRawText(attrName).putRawCh(CH_EQ);
+
+        putRawCh(CH_DQ);
+        putXsdInt(iVal);
+        putRawCh(CH_DQ);
+
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param attrName {@inheritDoc}
+     * @param fVal {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putFloatAttr(CharSequence attrName,
+                                           float fVal)
+            throws IOException{
+        putRawText(attrName).putRawCh(CH_EQ);
+
+        putRawCh(CH_DQ);
+        putXsdFloat(fVal);
+        putRawCh(CH_DQ);
+
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param attrName {@inheritDoc}
+     * @param content {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putAttr(CharSequence attrName,
+                                     CharSequence content)
+            throws IOException{
+        putRawText(attrName).putRawCh(CH_EQ);
+
+        putRawCh(CH_DQ);
+        putContent(content);
+        putRawCh(CH_DQ);
+
+        return this;
+    }
+
+}
index b429c55..5e3c1fa 100644 (file)
@@ -14,60 +14,18 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.nio.charset.Charset;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.xml.bind.DatatypeConverter;
 
 /**
- * 各種XMLエクスポータの基本機能。
- * UCS4は未サポート。
+ * Appendable用XMLエクスポータ実装。
  */
-public class BasicXmlExporter {
+public class BasicXmlExporter extends AbstractXmlExporter{
 
     /** デフォルトエンコーディング。 */
     private static final Charset CS_UTF8 = Charset.forName("UTF-8");
 
-    /** デフォルトの改行文字列。 */
-    private static final String DEF_NL = "\n";       // 0x0a(LF)
-    /** デフォルトのインデント単位。 */
-    private static final String DEF_INDENT_UNIT = "\u0020\u0020"; // ␣␣
-
-    private static final char CH_SP     = '\u0020';    // ␣
-    private static final char CH_YEN    = '\u00a5';    // ¥
-    private static final char CH_BSLASH = (char)0x005c; // \
-    private static final char CH_DQ     = '\u0022';    // "
-    private static final char CH_SQ     = (char)0x0027; // '
-
-    private static final String COMM_START = "<!--";
-    private static final String COMM_END   =   "-->";
-    private static final String REF_HEX = "&#x";
-
-    private static final Pattern NUM_FUZZY =
-            Pattern.compile("([^.]*\\.[0-9][0-9]*?)0+");
-
-    private static final int HEX_EXP = 4;    // 2 ** 4 == 16
-    private static final int MASK_1HEX = (1 << HEX_EXP) - 1;  // 0b00001111
-    private static final int MAX_OCTET = (1 << Byte.SIZE) - 1;   // 0xff
-    private static final char[] HEXCHAR_TABLE = {
-        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-        'A', 'B', 'C', 'D', 'E', 'F',
-    };
-
-
-    static{
-        assert HEX_EXP * 2 == Byte.SIZE;
-        assert HEXCHAR_TABLE.length == (1 << HEX_EXP);
-    }
-
 
     private final Appendable appendable;
 
-    private String newline = DEF_NL;
-    private String indentUnit = DEF_INDENT_UNIT;
-
-    private int indentNest = 0;
-    private boolean basicLatinOnlyOut = true;
-
 
     /**
      * コンストラクタ。
@@ -105,104 +63,35 @@ public class BasicXmlExporter {
 
 
     /**
-     * ASCIIコード相当(UCS:Basic-Latin)の文字か否か判定する。
-     * <p>※ Basic-Latinには各種制御文字も含まれる。
-     * @param ch 判定対象文字
-     * @return Basic-Latin文字ならtrue
-     */
-    public static boolean isBasicLatin(char ch){
-        if('\u0000' <= ch && ch <= '\u007f'){
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * 冗長な実数出力を抑止する。
-     * <p>DatatypeConverterにおけるJDK1.6系と1.7系の仕様変更を吸収する。
-     * <p>0.001fは"0.0010"ではなく"0.001"と出力される。
-     * <p>指数表記での冗長桁は無視する。
-     * @param numTxt 実数表記
-     * @return 冗長桁が抑止された実数表記
-     */
-    public static String chopFuzzyZero(String numTxt){
-        String result;
-
-        Matcher matcher = NUM_FUZZY.matcher(numTxt);
-        if(matcher.matches()){
-            result = matcher.group(1);
-        }else{
-            result = numTxt;
-        }
-
-        return result;
-    }
-
-
-    /**
-     * BasicLatin文字だけで出力するか設定する。
-     * <p>BasicLatin以外の文字(≒日本語)を、そのまま出力するか、
-     * 文字参照で出力するか、の設定が可能。
-     * <p>コメント部中身は対象外。
-     * @param bool BasicLatin文字だけで出力するならtrue
-     */
-    public void setBasicLatinOnlyOut(boolean bool){
-        this.basicLatinOnlyOut = bool;
-        return;
-    }
-
-    /**
-     * BasicLatin文字だけを出力する状態か判定する。
-     * <p>コメント部中身は対象外。
-     * @return BasicLatin文字だけで出力するならtrue
-     */
-    public boolean isBasicLatinOnlyOut(){
-        return this.basicLatinOnlyOut;
-    }
-
-    /**
-     * 改行文字列を設定する。
-     * @param newLine 改行文字列
-     * @throws NullPointerException 引数がnull
-     */
-    public void setNewLine(String newLine) throws NullPointerException{
-        if(newLine == null) throw new NullPointerException();
-        this.newline = newLine;
-        return;
-    }
-
-    /**
-     * 改行文字列を返す。
-     * @return 改行文字列
-     */
-    public String getNewLine(){
-        return this.newline;
-    }
-
-    /**
-     * インデント単位文字列を設定する。
-     * <p>デフォルトでは空白2個。
-     * @param indUnit インデント単位文字列。
-     * @throws NullPointerException 引数がnull
+     * {@inheritDoc}
+     * @param ch {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
      */
-    public void setIndentUnit(String indUnit) throws NullPointerException{
-        if(indUnit == null) throw new NullPointerException();
-        this.indentUnit = indUnit;
-        return;
+    @Override
+    public BasicXmlExporter putRawCh(char ch) throws IOException{
+        this.appendable.append(ch);
+        return this;
     }
 
     /**
-     * インデント単位文字列を返す。
-     * @return インデント単位文字列
+     * {@inheritDoc}
+     * @param seq {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
      */
-    public String getIndentUnit(){
-        return this.indentUnit;
+    @Override
+    public BasicXmlExporter putRawText(CharSequence seq) throws IOException{
+        this.appendable.append(seq);
+        return this;
     }
 
     /**
+     * {@inheritDoc}
      * 可能であれば出力をフラッシュする。
-     * @throws IOException 出力エラー
+     * @throws IOException {@inheritDoc}
      */
+    @Override
     public void flush() throws IOException{
         if(this.appendable instanceof Flushable){
             ((Flushable)this.appendable).flush();
@@ -211,9 +100,11 @@ public class BasicXmlExporter {
     }
 
     /**
+     * {@inheritDoc}
      * 可能であれば出力をクローズする。
-     * @throws IOException 出力エラー
+     * @throws IOException {@inheritDoc}
      */
+    @Override
     public void close() throws IOException{
         if(this.appendable instanceof Closeable){
             ((Closeable)this.appendable).close();
@@ -221,387 +112,4 @@ public class BasicXmlExporter {
         return;
     }
 
-    /**
-     * 1文字出力する。
-     * @param ch 文字
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter putRawCh(char ch) throws IOException{
-        this.appendable.append(ch);
-        return this;
-    }
-
-    /**
-     * 文字列を出力する。
-     * @param seq 文字列
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter putRawText(CharSequence seq) throws IOException{
-        this.appendable.append(seq);
-        return this;
-    }
-
-    /**
-     * 指定された文字を16進2桁の文字参照形式で出力する。
-     * 2桁で出力できない場合(>0x00ff)は4桁で出力する。
-     * @param ch 文字
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter putCharRef2Hex(char ch) throws IOException{
-        if(ch > MAX_OCTET) return putCharRef4Hex(ch);
-
-        int ibits = ch;   // 常に正なので符号拡張なし
-
-        int idx4 = ibits & MASK_1HEX;
-        ibits >>= HEX_EXP;
-        int idx3 = ibits & MASK_1HEX;
-
-        char hex3 = HEXCHAR_TABLE[idx3];
-        char hex4 = HEXCHAR_TABLE[idx4];
-
-        putRawText(REF_HEX).putRawCh(hex3).putRawCh(hex4)
-                           .putRawCh(';');
-
-        return this;
-    }
-
-    /**
-     * 指定された文字を16進4桁の文字参照形式で出力する。
-     * UCS4に伴うサロゲートペアは未サポート
-     * @param ch 文字
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter putCharRef4Hex(char ch) throws IOException{
-        int ibits = ch;   // 常に正なので符号拡張なし
-
-        int idx4 = ibits & MASK_1HEX;
-        ibits >>= HEX_EXP;
-        int idx3 = ibits & MASK_1HEX;
-        ibits >>= HEX_EXP;
-        int idx2 = ibits & MASK_1HEX;
-        ibits >>= HEX_EXP;
-        int idx1 = ibits & MASK_1HEX;
-
-        char hex1 = HEXCHAR_TABLE[idx1];
-        char hex2 = HEXCHAR_TABLE[idx2];
-        char hex3 = HEXCHAR_TABLE[idx3];
-        char hex4 = HEXCHAR_TABLE[idx4];
-
-        putRawText(REF_HEX).putRawCh(hex1).putRawCh(hex2)
-                           .putRawCh(hex3).putRawCh(hex4)
-                           .putRawCh(';');
-
-        return this;
-    }
-
-    /**
-     * 要素の中身および属性値中身を出力する。
-     * <p>XMLの構文規則を守る上で必要な各種エスケープ処理が行われる。
-     * @param ch 文字
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter putCh(char ch) throws IOException{
-        if(Character.isISOControl(ch)){
-            putCharRef2Hex(ch);
-            return this;
-        }
-
-        String escTxt;
-        switch(ch){
-        case '&':   escTxt = "&amp;";  break;
-        case '<':   escTxt = "&lt;";   break;
-        case '>':   escTxt = "&gt;";   break;
-        case CH_DQ: escTxt = "&quot;"; break;
-        case CH_SQ: escTxt = "&apos;"; break;
-        default:    escTxt = null;     break;
-        }
-
-        if(escTxt != null){
-            putRawText(escTxt);
-        }else{
-            putRawCh(ch);
-        }
-
-        return this;
-    }
-
-    /**
-     * 要素の中身および属性値中身を出力する。
-     * <p>必要に応じてXML定義済み実体文字が割り振られた文字、
-     * コントロールコード、および非BasicLatin文字がエスケープされる。
-     * <p>半角通貨記号U+00A5はバックスラッシュU+005Cに置換される。
-     * <p>連続するスペースU+0020の2文字目以降は文字参照化される。
-     * <p>全角スペースその他空白文字は無条件に文字参照化される。
-     * @param content 内容
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter putContent(CharSequence content)
-            throws IOException{
-        int length = content.length();
-
-        char prev = '\0';
-        for(int pos = 0; pos < length; pos++){
-            char ch = content.charAt(pos);
-
-            if( isBasicLatinOnlyOut() && ! isBasicLatin(ch) ){
-                putCharRef4Hex(ch);
-            }else if(ch == CH_YEN){
-                putRawCh(CH_BSLASH);
-            }else if(Character.isSpaceChar(ch)){
-                if(ch == CH_SP && prev != CH_SP){
-                    putRawCh(ch);
-                }else{
-                    putCharRef2Hex(ch);
-                }
-            }else{
-                putCh(ch);
-            }
-
-            prev = ch;
-        }
-
-        return this;
-    }
-
-    /**
-     * 改行を出力する。
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter ln() throws IOException{
-        this.appendable.append(this.newline);
-        return this;
-    }
-
-    /**
-     * 改行を指定回数出力する。
-     * @param count 改行回数。0以下の場合は何も出力しない。
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter ln(int count) throws IOException{
-        for(int ct = 1; ct <= count; ct++){
-            this.appendable.append(this.newline);
-        }
-        return this;
-    }
-
-    /**
-     * 空白を出力する。
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter sp() throws IOException{
-        this.appendable.append(CH_SP);
-        return this;
-    }
-
-    /**
-     * 空白を指定回数出力する。
-     * @param count 空白回数。0以下の場合は何も出力しない。
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter sp(int count) throws IOException{
-        for(int ct = 1; ct <= count; ct++){
-            this.appendable.append(CH_SP);
-        }
-        return this;
-    }
-
-    /**
-     * インデントを出力する。
-     * インデント単位文字列をネストレベル回数分出力する。
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter ind() throws IOException{
-        for(int ct = 1; ct <= this.indentNest; ct++){
-            putRawText(this.indentUnit);
-        }
-        return this;
-    }
-
-    /**
-     * インデントレベルを一段下げる。
-     */
-    public void pushNest(){
-        this.indentNest++;
-        return;
-    }
-
-    /**
-     * インデントレベルを一段上げる。
-     * インデントレベル0の状態をさらに上げようとした場合、何も起こらない。
-     */
-    public void popNest(){
-        this.indentNest--;
-        if(this.indentNest < 0) this.indentNest = 0;
-        return;
-    }
-
-    /**
-     * int値をXMLスキーマ準拠の形式で出力する。
-     * @param iVal int値
-     * @return this本体
-     * @throws IOException 出力エラー
-     * @see java.lang.Integer#toString(int)
-     */
-    public BasicXmlExporter putXsdInt(int iVal) throws IOException{
-        String value = DatatypeConverter.printInt(iVal);
-        this.appendable.append(value);
-        return this;
-    }
-
-    /**
-     * float値をXMLスキーマ準拠の形式で出力する。
-     * @param fVal float値
-     * @return this本体
-     * @throws IOException 出力エラー
-     * @see java.lang.Float#toString(float)
-     */
-    public BasicXmlExporter putXsdFloat(float fVal) throws IOException{
-        String value = DatatypeConverter.printFloat(fVal);
-        this.appendable.append(value);
-        return this;
-    }
-
-    /**
-     * 属性値を出力する。
-     * @param attrName 属性名
-     * @param content 属性内容
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter putAttr(CharSequence attrName,
-                                     CharSequence content)
-            throws IOException{
-        putRawText(attrName).putRawCh('=');
-
-        putRawCh('"');
-        putContent(content);
-        putRawCh('"');
-
-        return this;
-    }
-
-    /**
-     * int型属性値を出力する。
-     * @param attrName 属性名
-     * @param iVal int値
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter putIntAttr(CharSequence attrName,
-                                        int iVal)
-            throws IOException{
-        String attrValue = DatatypeConverter.printInt(iVal);
-        putAttr(attrName, attrValue);
-        return this;
-    }
-
-    /**
-     * float型属性値を出力する。
-     * @param attrName 属性名
-     * @param fVal float値
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter putFloatAttr(CharSequence attrName,
-                                           float fVal)
-            throws IOException{
-        String attrValue = DatatypeConverter.printFloat(fVal);
-        attrValue = chopFuzzyZero(attrValue);
-        putAttr(attrName, attrValue);
-        return this;
-    }
-
-    /**
-     * コメントの内容を出力する。
-     * <p>コメント中の'\n'記号出現に伴い、
-     * あらかじめ指定された改行文字が出力される。
-     * <p>コメント中の'\n'以外のコントロールコードは
-     * Control Pictures(U+2400〜)で代替される。
-     * <p>それ以外の非BasicLatin文字はそのまま出力される。
-     * <p>連続するハイフン(-)記号間には強制的にスペースが挿入される。
-     * @param comment コメント内容
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter putCommentContent(CharSequence comment)
-            throws IOException{
-        int length = comment.length();
-
-        char prev = '\0';
-        for(int pos = 0; pos < length; pos++){
-            char ch = comment.charAt(pos);
-
-            if(ch == '\n'){
-                ln();
-            }else if('\u0000' <= ch && ch <= '\u001f'){
-                putRawCh((char)('\u2400' + ch));
-            }else if(ch == '\u007f'){
-                putRawCh('\u2421');
-            }else if(prev == '-' && ch == '-'){
-                sp().putRawCh(ch);
-            }else{
-                putRawCh(ch);
-            }
-
-            prev = ch;
-        }
-
-        return this;
-    }
-
-    /**
-     * 1行コメントを出力する。
-     * コメント内部の頭及び末尾に空白が1つ挿入される。
-     * @param comment コメント内容
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter putLineComment(CharSequence comment)
-            throws IOException{
-        putRawText(COMM_START).sp();
-        putCommentContent(comment);
-        sp().putRawText(COMM_END);
-        return this;
-    }
-
-    /**
-     * ブロックコメントを出力する。
-     * <p>コメント内部の頭の前に改行が出力される。
-     * <p>コメント内部の末尾が改行でない場合、改行が挿入される。
-     * <p>ブロックコメント末尾は改行で終わる。
-     * <p>インデント設定は無視される。
-     * @param comment コメント内容
-     * @return this本体
-     * @throws IOException 出力エラー
-     */
-    public BasicXmlExporter putBlockComment(CharSequence comment)
-            throws IOException{
-        putRawText(COMM_START).ln();
-
-        putCommentContent(comment);
-
-        int commentLength = comment.length();
-        if(commentLength > 0){
-            char lastCh = comment.charAt(commentLength - 1);
-            if(lastCh != '\n'){
-                ln();
-            }
-        }
-
-        putRawText(COMM_END).ln();
-
-        return this;
-    }
-
 }
diff --git a/src/main/java/jp/sourceforge/mikutoga/xml/LocalSchema.java b/src/main/java/jp/sourceforge/mikutoga/xml/LocalSchema.java
deleted file mode 100644 (file)
index 92da58a..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * local xml schema
- *
- * License : The MIT License
- * Copyright(c) 2013 MikuToga Partners
- */
-
-package jp.sourceforge.mikutoga.xml;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URL;
-import java.util.LinkedList;
-import java.util.List;
-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 org.xml.sax.SAXException;
-
-/**
- * XML用各種スキーマのローカル参照解決基盤。
- */
-public abstract class LocalSchema {
-
-    /**
-     * コンストラクタ。
-     */
-    protected LocalSchema(){
-        super();
-        return;
-    }
-
-
-    /**
-     * XML Schema 用のスキーマファクトリを返す。
-     * @return スキーマファクトリ
-     */
-    private static SchemaFactory newSchemaFactory(){
-        SchemaFactory schemaFactory =
-                SchemaFactory.newInstance(
-                    XMLConstants.W3C_XML_SCHEMA_NS_URI
-                );
-
-//      schemaFactory.setFeature(name, value);
-//      schemaFactory.setProperty(name, object);
-
-        schemaFactory.setErrorHandler(BotherHandler.HANDLER);
-
-        return schemaFactory;
-    }
-
-    /**
-     * ローカルスキーマをロードする。
-     * <p>任意のリゾルバを指定可能
-     * @param resolver リゾルバ
-     * @param lscs ローカルスキーマ情報の配列
-     * @return スキーマ
-     */
-    public static Schema newSchema(XmlResourceResolver resolver,
-                                    LocalSchema... lscs ){
-        List<Source> sourceList = new LinkedList<Source>();
-        for(LocalSchema lsc : lscs){
-            if(lsc == null) continue;
-            lsc.appendToUriMap(resolver);
-
-            Source local = lsc.getLocalSchemaSource();
-            if(local == null) continue;
-            sourceList.add(local);
-        }
-
-        SchemaFactory schemaFactory = newSchemaFactory();
-        schemaFactory.setResourceResolver(resolver);
-
-        Source[] sources = new Source[sourceList.size()];
-        sourceList.toArray(sources);
-
-        Schema result;
-        try{
-            if(sources.length <= 0){
-                result = schemaFactory.newSchema();
-            }else{
-                result = schemaFactory.newSchema(sources);
-            }
-        }catch(SAXException e){   // Build error
-            assert false;
-            throw new AssertionError(e);
-        }
-
-        return result;
-    }
-
-    /**
-     * オリジナル版スキーマ定義のURIを返す。
-     * <p>nullを返す場合は
-     * スキーマの自動判定&ダウンロードが求められていると見なされる。
-     * <p>このクラスの実装では常にnullを返す。
-     * @return オリジナル版スキーマのURL。
-     */
-    public abstract URI getOriginalSchema();
-
-    /**
-     * ローカルリソース版スキーマ定義のURIを返す。
-     * <p>nullを返す場合は
-     * スキーマの自動判定&ダウンロードが求められていると見なされる。
-     * <p>このクラスの実装では常にnullを返す。
-     * @return ローカルリソース版スキーマのURL。
-     */
-    public abstract URI getLocalSchema();
-
-    /**
-     * スキーマのSourceを返す。
-     * <p>ローカルスキーマのSourceを返す。
-     * @return Source 見つからなければnull
-     */
-    public Source getLocalSchemaSource(){
-        URI uri;
-
-        uri = getLocalSchema();
-        if(uri == null) return null;
-
-        URL url;
-        try{
-            url = uri.toURL();
-        }catch(MalformedURLException e){      // Build error
-            assert false;
-            throw new AssertionError(e);
-        }
-
-        InputStream is;
-        try{
-            is = url.openStream();
-        }catch(IOException e){              // Build error
-            assert false;
-            throw new AssertionError(e);
-        }
-        is = new BufferedInputStream(is);
-
-        Source result = new StreamSource(is);
-
-        return result;
-    }
-
-    /**
-     * ローカルで解決可能なリソース参照をリゾルバに追加登録する。
-     * @param resolver リゾルバ
-     */
-    public void appendToUriMap(XmlResourceResolver resolver){
-        URI original = getOriginalSchema();
-        URI local    = getLocalSchema();
-
-        if(original == null) return;
-
-        resolver.putRedirected(original, local);
-
-        return;
-    }
-
-}
diff --git a/src/main/java/jp/sourceforge/mikutoga/xml/LocalXmlResource.java b/src/main/java/jp/sourceforge/mikutoga/xml/LocalXmlResource.java
new file mode 100644 (file)
index 0000000..5d009f2
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * xml local resource map
+ *
+ * License : The MIT License
+ * Copyright(c) 2013 olyutorskii
+ */
+
+package jp.sourceforge.mikutoga.xml;
+
+import java.net.URI;
+
+/**
+ * 代用ローカルリソースの管理を行う。
+ * <p>ネットワークを介したグローバルなリソースと、
+ * アプリ上のローカルな代用リソースとを対応付ける。
+ */
+public interface LocalXmlResource {
+
+    /**
+     * オリジナル版XMLリソースのURIを返す。
+     * @return オリジナル版リソースのURL。
+     */
+    URI getOriginalResource();
+
+    /**
+     * ローカル版XMLリソースのURIを返す。
+     * @return ローカル版リソースのURL。
+     */
+    URI getLocalResource();
+
+}
diff --git a/src/main/java/jp/sourceforge/mikutoga/xml/ProxyXmlExporter.java b/src/main/java/jp/sourceforge/mikutoga/xml/ProxyXmlExporter.java
new file mode 100644 (file)
index 0000000..c1934ea
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * proxy xml exporter
+ *
+ * License : The MIT License
+ * Copyright(c) 2013 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.xml;
+
+import java.io.IOException;
+
+/**
+ * 委譲型XMLエクスポータ。
+ */
+public class ProxyXmlExporter extends AbstractXmlExporter{
+
+    private final XmlExporter delegate;
+
+
+    /**
+     * コンストラクタ。
+     * @param proxy 委譲先
+     */
+    public ProxyXmlExporter(XmlExporter proxy){
+        super();
+        this.delegate = proxy;
+        return;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * @param ch {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putRawCh(char ch) throws IOException{
+        return this.delegate.putRawCh(ch);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param seq {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public XmlExporter putRawText(CharSequence seq) throws IOException{
+        return this.delegate.putRawText(seq);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public void flush() throws IOException{
+        this.delegate.flush();
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws IOException {@inheritDoc}
+     */
+    @Override
+    public void close() throws IOException{
+        this.delegate.close();
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public boolean isBasicLatinOnlyOut(){
+        return this.delegate.isBasicLatinOnlyOut();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param bool {@inheritDoc}
+     */
+    @Override
+    public void setBasicLatinOnlyOut(boolean bool){
+        this.delegate.setBasicLatinOnlyOut(bool);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String getNewLine(){
+        return this.delegate.getNewLine();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param newLine {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     */
+    @Override
+    public void setNewLine(String newLine) throws NullPointerException{
+        this.delegate.setNewLine(newLine);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public String getIndentUnit(){
+        return this.delegate.getIndentUnit();
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param indUnit {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     */
+    @Override
+    public void setIndentUnit(String indUnit) throws NullPointerException{
+        this.delegate.setIndentUnit(indUnit);
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void pushNest(){
+        this.delegate.pushNest();
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void popNest(){
+        this.delegate.popNest();
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @return {@inheritDoc}
+     */
+    @Override
+    public int getIndentLevel(){
+        return this.delegate.getIndentLevel();
+    }
+
+}
diff --git a/src/main/java/jp/sourceforge/mikutoga/xml/SchemaUtil.java b/src/main/java/jp/sourceforge/mikutoga/xml/SchemaUtil.java
new file mode 100644 (file)
index 0000000..d8965aa
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * xml schema utility
+ *
+ * License : The MIT License
+ * Copyright(c) 2013 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.xml;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+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 org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.SAXException;
+
+/**
+ * XMLスキーマの各種ビルダ。
+ */
+public final class SchemaUtil {
+
+    /**
+     * 隠しコンストラクタ。
+     */
+    private SchemaUtil(){
+        assert false;
+        throw new AssertionError();
+    }
+
+
+    /**
+     * XML Schema 用のスキーマファクトリを返す。
+     * @return スキーマファクトリ
+     */
+    public static SchemaFactory newSchemaFactory(){
+        SchemaFactory result = newSchemaFactory(null);
+        return result;
+    }
+
+    /**
+     * XML Schema 用のスキーマファクトリを返す。
+     * @param resolver カスタムリゾルバ。nullも可。
+     * @return スキーマファクトリ
+     */
+    public static SchemaFactory newSchemaFactory(
+            LSResourceResolver resolver ){
+        SchemaFactory schemaFactory =
+                SchemaFactory.newInstance(
+                    XMLConstants.W3C_XML_SCHEMA_NS_URI
+                );
+
+//      schemaFactory.setFeature(name, value);
+//      schemaFactory.setProperty(name, object);
+
+        schemaFactory.setErrorHandler(BotherHandler.HANDLER);
+        schemaFactory.setResourceResolver(resolver);
+
+        return schemaFactory;
+    }
+
+    /**
+     * ローカルリソースをSourceに変換する。
+     * @param resource ローカルリソース
+     * @return XML Source
+     * @throws MalformedURLException 不正なURI
+     * @throws IOException オープンエラー
+     */
+    private static Source toLocalSource(LocalXmlResource resource)
+            throws MalformedURLException, IOException{
+        URI localUri = resource.getLocalResource();
+        URL localUrl = localUri.toURL();
+
+        InputStream is = localUrl.openStream();
+        is = new BufferedInputStream(is);
+
+        Source result = new StreamSource(is);
+        return result;
+    }
+
+    /**
+     * ローカルリソース群をSource群に変換する。
+     * @param resArray ローカルリソースURI並び
+     * @return XML Source並び
+     * @throws MalformedURLException 不正なURI
+     * @throws IOException オープンエラー
+     */
+    private static Source[] toLocalSourceArray(LocalXmlResource[] resArray)
+            throws MalformedURLException, IOException{
+        List<Source> sourceList = new ArrayList<Source>(resArray.length);
+
+        for(LocalXmlResource resource : resArray){
+            Source localSource = toLocalSource(resource);
+            sourceList.add(localSource);
+        }
+
+        Source[] result = new Source[sourceList.size()];
+        result = sourceList.toArray(result);
+        return result;
+    }
+
+    /**
+     * ローカルスキーマをロードする。
+     * <p>任意のリゾルバを指定可能
+     * @param resolver リゾルバ
+     * @param resArray ローカルスキーマ情報並び
+     * @return スキーマ
+     */
+    public static Schema newSchema(XmlResourceResolver resolver,
+                                    LocalXmlResource... resArray ){
+        for(LocalXmlResource resource : resArray){
+            resolver.putRedirected(resource);
+        }
+
+        Source[] sources;
+        try{
+            sources = toLocalSourceArray(resArray);
+        }catch(IOException e){                   // ビルド障害
+            assert false;
+            throw new AssertionError(e);
+        }
+
+        SchemaFactory schemaFactory = newSchemaFactory(resolver);
+
+        Schema result;
+        try{
+            if(sources.length <= 0){
+                // ドキュメント埋め込みスキーマURLにリゾルバ経由でアクセス
+                result = schemaFactory.newSchema();
+            }else{
+                result = schemaFactory.newSchema(sources);
+            }
+        }catch(SAXException e){   // Build error
+            assert false;
+            throw new AssertionError(e);
+        }
+
+        // TODO: Sourceを閉めるのは誰の責務?
+
+        return result;
+    }
+
+}
diff --git a/src/main/java/jp/sourceforge/mikutoga/xml/XmlExporter.java b/src/main/java/jp/sourceforge/mikutoga/xml/XmlExporter.java
new file mode 100644 (file)
index 0000000..9055a5d
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * xml exporter
+ *
+ * License : The MIT License
+ * Copyright(c) 2013 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.xml;
+
+import java.io.Closeable;
+import java.io.Flushable;
+import java.io.IOException;
+
+/**
+ * XMLエクスポータ基本機能のセット。
+ */
+public interface XmlExporter extends Flushable, Closeable{
+
+    /**
+     * 1文字出力する。
+     * @param ch 文字
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putRawCh(char ch) throws IOException;
+
+    /**
+     * 文字列を出力する。
+     * @param seq 文字列
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putRawText(CharSequence seq) throws IOException;
+
+    /**
+     * 空白を出力する。
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter sp() throws IOException;
+
+    /**
+     * 空白を指定回数出力する。
+     * @param count 空白回数。0以下の場合は何も出力しない。
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter sp(int count) throws IOException;
+
+    /**
+     * 改行文字列を返す。
+     * @return 改行文字列
+     */
+    String getNewLine();
+
+    /**
+     * 改行文字列を設定する。
+     * @param newLine 改行文字列
+     * @throws NullPointerException 引数がnull
+     */
+    void setNewLine(String newLine) throws NullPointerException;
+
+    /**
+     * 改行を出力する。
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter ln() throws IOException;
+
+    /**
+     * 改行を指定回数出力する。
+     * @param count 改行回数。0以下の場合は何も出力しない。
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter ln(int count) throws IOException;
+
+    /**
+     * インデント単位文字列を返す。
+     * @return インデント単位文字列
+     */
+    String getIndentUnit();
+
+    /**
+     * インデント単位文字列を設定する。
+     * <p>デフォルトでは空白2個。
+     * @param indUnit インデント単位文字列。
+     * @throws NullPointerException 引数がnull
+     */
+    void setIndentUnit(String indUnit) throws NullPointerException;
+
+    /**
+     * インデントレベルを一段下げる。
+     */
+    void pushNest();
+
+    /**
+     * インデントレベルを一段上げる。
+     * インデントレベル0の状態をさらに上げようとした場合、何も起こらない。
+     */
+    void popNest();
+
+    /**
+     * インデントレベルを返す。
+     * <p>深さ1の場合1を返す。
+     * @return インデントレベル
+     */
+    int getIndentLevel();
+
+    /**
+     * インデントを出力する。
+     * インデント単位文字列をネストレベル回数分出力する。
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter ind() throws IOException;
+
+    /**
+     * BasicLatin文字だけを出力する状態か判定する。
+     * <p>コメント部中身は対象外。
+     * @return BasicLatin文字だけで出力するならtrue
+     */
+    boolean isBasicLatinOnlyOut();
+
+    /**
+     * BasicLatin文字だけで出力するか設定する。
+     * <p>BasicLatin以外の文字(≒日本語)を、そのまま出力するか、
+     * 文字参照で出力するか、の設定が可能。
+     * <p>コメント部中身は対象外。
+     * @param bool BasicLatin文字だけで出力するならtrue
+     */
+    void setBasicLatinOnlyOut(boolean bool);
+
+    /**
+     * 指定された文字を16進2桁の文字参照形式で出力する。
+     * <p>「A」は「&amp;#x41;」になる。
+     * <p>2桁で出力できない場合(>0x00ff)は4桁で出力する。
+     * @param ch 文字
+     * @return this本体
+     * @throws IOException 出力エラー
+     * @see <a href="http://www.w3.org/TR/xml11/#NT-CharRef">
+     * W3C XML1.1 Character Reference
+     * </a>
+     */
+    XmlExporter putCharRef2Hex(char ch) throws IOException;
+
+    /**
+     * 指定された文字を16進4桁の文字参照形式で出力する。
+     * <p>「亜」は「&amp;#x4E9C;」になる。
+     * <p>UCS4に伴うサロゲートペアは未サポート
+     * @param ch 文字
+     * @return this本体
+     * @throws IOException 出力エラー
+     * @see <a href="http://www.w3.org/TR/xml11/#NT-CharRef">
+     * W3C XML1.1 Character Reference
+     * </a>
+     */
+    XmlExporter putCharRef4Hex(char ch) throws IOException;
+
+    /**
+     * 要素の中身および属性値中身を出力する。
+     * <p>XMLの構文規則を守る上で必要な各種エスケープ処理が行われる。
+     * @param ch 文字
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putCh(char ch) throws IOException;
+
+    /**
+     * 要素の中身および属性値中身を出力する。
+     * <p>必要に応じてXML定義済み実体文字が割り振られた文字、
+     * コントロールコード、および非BasicLatin文字がエスケープされる。
+     * <p>半角円通貨記号U+00A5はバックスラッシュU+005Cに置換される。
+     * <p>連続するスペースU+0020の2文字目以降は文字参照化される。
+     * <p>全角スペースその他空白文字は無条件に文字参照化される。
+     * @param content 内容
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putContent(CharSequence content) throws IOException;
+
+    /**
+     * コメントの内容を出力する。
+     * <p>コメント中の'\n'記号出現に伴い、
+     * あらかじめ指定された改行文字が出力される。
+     * <p>コメント中の'\n'以外のコントロールコードは
+     * Control Pictures(U+2400〜)で代替される。
+     * <p>それ以外の非BasicLatin文字はそのまま出力される。
+     * <p>連続するハイフン(-)記号間には強制的にスペースが挿入される。
+     * @param comment コメント内容
+     * @return this本体
+     * @throws IOException 出力エラー
+     * <a href="http://www.unicode.org/charts/PDF/U2400.pdf">
+     * Unicode 6.2 Controll Pictures
+     * </a>
+     */
+    XmlExporter putCommentContent(CharSequence comment) throws IOException;
+
+    /**
+     * 1行コメントを出力する。
+     * コメント内部の頭及び末尾に空白が1つ挿入される。
+     * @param comment コメント内容
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putLineComment(CharSequence comment) throws IOException;
+
+    /**
+     * ブロックコメントを出力する。
+     * <p>コメント内部の頭の前に改行が出力される。
+     * <p>コメント内部の末尾が改行でない場合、改行が挿入される。
+     * <p>ブロックコメント末尾は改行で終わる。
+     * <p>インデント設定は無視される。
+     * @param comment コメント内容
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putBlockComment(CharSequence comment) throws IOException;
+
+    /**
+     * 開始タグ開き表記を出力する。
+     * @param tagName タグ名
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putOpenSTag(CharSequence tagName) throws IOException;
+
+    /**
+     * 開始タグ閉じ表記を出力する。
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putCloseSTag() throws IOException;
+
+    /**
+     * 属性の無いシンプルな開始タグ表記を出力する。
+     * @param tagName タグ名
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putSimpleSTag(CharSequence tagName) throws IOException;
+
+    /**
+     * 終了タグ表記を出力する。
+     * @param tagName タグ名
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putETag(CharSequence tagName) throws IOException;
+
+    /**
+     * 属性の無い単出タグ表記を出力する。
+     * @param tagName タグ名
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putSimpleEmpty(CharSequence tagName) throws IOException;
+
+    /**
+     * 単出タグ閉じ表記を出力する。
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putCloseEmpty() throws IOException;
+
+    /**
+     * int値をXMLスキーマ準拠の形式で出力する。
+     * @param iVal int値
+     * @return this本体
+     * @throws IOException 出力エラー
+     * @see java.lang.Integer#toString(int)
+     * @see <a href="http://www.w3.org/TR/xmlschema11-2/#integer">
+     * XML Schema 1.1 Datatypes integer
+     * </a>
+     */
+    XmlExporter putXsdInt(int iVal) throws IOException;
+
+    /**
+     * float値をXMLスキーマ準拠の形式で出力する。
+     * @param fVal float値
+     * @return this本体
+     * @throws IOException 出力エラー
+     * @see <a href="http://www.w3.org/TR/xmlschema11-2/#sec-lex-float">
+     * XML Schema 1.1 Datatypes float Lexical Mapping
+     * </a>
+     */
+    XmlExporter putXsdFloat(float fVal) throws IOException;
+
+    /**
+     * int型属性値を出力する。
+     * @param attrName 属性名
+     * @param iVal int値
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putIntAttr(CharSequence attrName, int iVal)
+            throws IOException;
+
+    /**
+     * float型属性値を出力する。
+     * @param attrName 属性名
+     * @param fVal float値
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putFloatAttr(CharSequence attrName, float fVal)
+            throws IOException;
+
+    /**
+     * 属性値を出力する。
+     * @param attrName 属性名
+     * @param content 属性内容
+     * @return this本体
+     * @throws IOException 出力エラー
+     */
+    XmlExporter putAttr(CharSequence attrName, CharSequence content)
+            throws IOException;
+
+}
index 4ea9167..660496a 100644 (file)
@@ -156,6 +156,21 @@ public class XmlResourceResolver
     }
 
     /**
+     * ローカル版リソース参照解決を登録する。
+     * @param lsc ローカル版リソース参照解決
+     */
+    public void putRedirected(LocalXmlResource lsc){
+        URI original = lsc.getOriginalResource();
+        if(original == null) return;
+
+        URI local = lsc.getLocalResource();
+
+        putRedirected(original, local);
+
+        return;
+    }
+
+    /**
      * 別リゾルバの登録内容を追加登録する。
      * @param other 別リゾルバ
      */
index 73bf7be..f0ee821 100644 (file)
@@ -9,19 +9,15 @@ package sample.vmd;
 
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
 import jp.sfjp.mikutoga.bin.parser.ParseStage;
-import jp.sourceforge.mikutoga.vmd.VmdConst;
-import jp.sourceforge.mikutoga.vmd.parser.VmdBasicHandler;
-import jp.sourceforge.mikutoga.vmd.parser.VmdCameraHandler;
-import jp.sourceforge.mikutoga.vmd.parser.VmdLightingHandler;
+import jp.sfjp.mikutoga.vmd.VmdUniq;
+import jp.sfjp.mikutoga.vmd.parser.VmdUnifiedHandler;
 
 /**
  * サンプルのハンドラ。
  * これはユニットテストではない。
  * 必要に応じて要所でデバッガのブレークポイントを設定しておくと便利。
  */
-public class DummyHandler implements VmdBasicHandler,
-                                       VmdLightingHandler,
-                                       VmdCameraHandler {
+public class DummyHandler implements VmdUnifiedHandler {
 
     public DummyHandler(){
         super();
@@ -68,7 +64,7 @@ public class DummyHandler implements VmdBasicHandler,
     @Override
     public void vmdModelName(String modelName) throws MmdFormatException{
         println("modelname = " + modelName);
-        println("isStageAct="+VmdConst.isStageActName(modelName));
+        println("isStageAct="+VmdUniq.isStageActName(modelName));
     }
 
     @Override
@@ -115,7 +111,7 @@ public class DummyHandler implements VmdBasicHandler,
 
     @Override
     public void vmdMorphMotion(String morphName, int keyFrameNo, float flex){
-        if(VmdConst.isBaseMorphName(morphName)) return;
+        if(VmdUniq.isBaseMorphName(morphName)) return;
         println(morphName+":"+keyFrameNo+" flex="+flex);
         return;
     }
index 565e18f..f3c7d3b 100644 (file)
@@ -14,7 +14,7 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
-import jp.sourceforge.mikutoga.vmd.parser.VmdParser;
+import jp.sfjp.mikutoga.vmd.parser.VmdParser;
 
 /**
  * パーサ利用のサンプルプログラム。
@@ -66,7 +66,8 @@ public class DummyMain {
         VmdParser parser = new VmdParser(source);
 
         setupHandler(parser);
-        parser.setStrictMode(true);
+        parser.setIgnoreName(true);
+        parser.setRedundantCheck(false);
 
         try{
             parser.parseVmd();