TogaGem 変更履歴
+X.XXX.X (XXXX-XX-XX)
+ * Prevent XXE vulnerabilities.
+ * Split entity resolver from resource resolver to prevent XXE vulnerability.
+ * Make Schema-factory safe to prevent XXE vulnerability.
+ * Move out xml-xsd info from resolver.
+
3.121.2 (2019-06-06)
・DatatypeIo is public now, for replacing JAXB.
<!--
Checkstyle suppressions
- for Checkstyle 8.20 or later
+ for Checkstyle 8.22 or later
[ https://checkstyle.org/ ]
<suppress files="" checks="ImportControl" />
<!-- Javadoc Comments -->
- <suppress files="" checks="JavadocParagraph" />
- <suppress files="" checks="JavadocTagContinuationIndentation" />
<suppress files="" checks="SummaryJavadocCheck" />
<!-- Miscellaneous -->
<suppress files="" checks="FinalParameters" />
+ <suppress files="" checks="OrderedProperties" />
<suppress files="" checks="TrailingComment" />
<!-- Modifier -->
- <suppress files="" checks="InterfaceMemberImpliedModifier" />
+ <suppress files="" checks="RedundantModifier" />
<!-- Whitespace -->
+ <suppress files="" checks="ParenPad" />
<suppress files="" checks="SingleSpaceSeparator" />
</suppressions>
<!--
Checkstyle modules
- for Checkstyle 8.21 or later
+ for Checkstyle 8.22 or later
[ https://checkstyle.org/ ]
<property name="fileExtensions" value="xml" />
</module>
<module name="RegexpHeader">
+ <!-- /* ... */ -->
<property name="header" value="^/\*$\n^ \*( .*)?$\n^ \*/$\n" />
<property name="multiLines" value="2" />
<property name="fileExtensions" value="java" />
<module name="NewlineAtEndOfFile">
<property name="fileExtensions" value="java, properties, xml, xsd, md, txt" />
</module>
+ <module name="OrderedProperties" />
<module name="Translation" />
<module name="UniqueProperties" />
<module name="RequireThis">
<property name="checkMethods" value="false" />
</module>
- <module name="ReturnCount" />
+ <module name="ReturnCount">
+ <property name="max" value="5" />
+ <property name="maxForVoid" value="5" />
+ </module>
<module name="SimplifyBooleanExpression" />
<module name="SimplifyBooleanReturn" />
<module name="StringLiteralEquality" />
<module name="SuperClone" />
<module name="SuperFinalize" />
<module name="UnnecessaryParentheses" />
+ <module name="UnnecessarySemicolonInEnumeration" />
+ <module name="UnnecessarySemicolonInTryWithResources" />
<module name="VariableDeclarationUsageDistance">
<property name="allowedDistance" value="5"/>
</module>
<property name="scope" value="protected" />
</module>
<module name="MissingJavadocMethod" />
+ <module name="MissingJavadocPackage" />
<module name="MissingJavadocType" />
<module name="NonEmptyAtclauseDescription" />
<module name="SingleLineJavadoc" />
<module name="GenericWhitespace" />
<module name="MethodParamPad" />
<module name="NoLineWrap" />
- <module name="NoWhitespaceAfter" />
- <module name="NoWhitespaceBefore" />
- <module name="OperatorWrap" />
- <module name="ParenPad">
- <property name="option" value="nospace" />
+ <module name="NoWhitespaceAfter">
<property
name="tokens"
- value="CTOR_CALL, METHOD_CALL, SUPER_CTOR_CALL"
+ value="AT, INC, DEC, UNARY_MINUS, UNARY_PLUS, DOT"
/>
</module>
+ <module name="NoWhitespaceBefore">
+ <property name="allowLineBreaks" value="true" />
+ </module>
+ <module name="OperatorWrap" />
+ <module name="ParenPad" />
<module name="SeparatorWrap">
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
- </module>
+</module>
<!-- EOF -->
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0
- http://pmd.sourceforge.net/ruleset_2_0_0.xsd"
+ https://pmd.sourceforge.io/ruleset_2_0_0.xsd"
name="Custom ruleset"
>
<exclude name="OnlyOneReturn" />
<exclude name="ShortVariable" />
<exclude name="UnnecessaryLocalBeforeReturn" />
+ <exclude name="UnnecessaryModifier" />
<exclude name="UnnecessaryReturn" />
</rule>
+ <rule ref="category/java/codestyle.xml/ClassNamingConventions" >
+ <properties>
+ <property name="utilityClassPattern" value="[A-Z][a-zA-Z0-9]*"/>
+ </properties>
+ </rule>
<rule ref="category/java/codestyle.xml/ControlStatementBraces" >
<properties>
<property name="checkIfElseStmt" value="false"/>
<property name="checkSingleIfStmt" value="false"/>
</properties>
</rule>
+ <rule ref="category/java/codestyle.xml/LongVariable" >
+ <properties>
+ <property name="minimum" value="25"/>
+ </properties>
+ </rule>
<rule ref="category/java/design.xml" >
<exclude name="AvoidThrowingNullPointerException" />
<exclude name="AvoidUncheckedExceptionsInSignatures" />
<exclude name="LawOfDemeter" />
<exclude name="LoosePackageCoupling" />
+ <exclude name="SimplifyBooleanReturns" />
</rule>
<rule ref="category/java/documentation.xml" />
<rule ref="category/java/multithreading.xml" />
<rule ref="category/java/performance.xml" >
+ <exclude name="AvoidUsingShortType" />
<exclude name="ConsecutiveAppendsShouldReuse" />
<exclude name="RedundantFieldInitializer" />
</rule>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <locale>en</locale>
- <site.locales>${locale}</site.locales>
- <javadoc.locale>${locale}</javadoc.locale>
- <spotbugs.jvmArgs>-Duser.language=${locale}</spotbugs.jvmArgs>
-
- <!-- Walk around: JDK 11 javadoc + Maven -->
- <detectJavaApiLink>false</detectJavaApiLink>
+ <!-- DO NOT USE ${locale} with site-plugin -->
+ <site.locales>en</site.locales>
+ <javadoc.locale>en</javadoc.locale>
+ <spotbugs.jvmArgs>-Duser.language=en</spotbugs.jvmArgs>
<surefire-plugin.version>3.0.0-M3</surefire-plugin.version>
<jacoco-plugin.version>0.8.4</jacoco-plugin.version>
<checkstyle-plugin.version>3.1.0</checkstyle-plugin.version>
- <checkstyleruntime.version>8.21</checkstyleruntime.version>
- <checkstyle.config.location>${project.basedir}/config/checkstyle/checkstyle.xml</checkstyle.config.location>
- <checkstyle.suppressions.location>${project.basedir}/config/checkstyle/checkstyle-suppressions.xml</checkstyle.suppressions.location>
+ <checkstyleruntime.version>8.22</checkstyleruntime.version>
+ <checkstyle.config.location>config/checkstyle/checkstyle.xml</checkstyle.config.location>
+ <checkstyle.suppressions.location>config/checkstyle/checkstyle-suppressions.xml</checkstyle.suppressions.location>
<checkstyle.enable.rss>false</checkstyle.enable.rss>
<pmd-plugin.version>3.12.0</pmd-plugin.version>
- <spotbugs-plugin.version>3.1.11</spotbugs-plugin.version>
+ <spotbugs-plugin.version>3.1.12</spotbugs-plugin.version>
<spotbugs.effort>Max</spotbugs.effort>
<spotbugs.threshold>Low</spotbugs.threshold>
<!-- for Jenkins -->
<id>attach-sources</id>
<phase>verify</phase>
<goals>
- <goal>jar-no-fork</goal>
+ <goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.1.0</version>
<configuration>
+ <locale>${javadoc.locale}</locale>
+ <source>${maven.compiler.source}</source>
<author>false</author>
<notimestamp>true</notimestamp>
<quiet>true</quiet>
<show>protected</show>
<header>${project.name} ${project.version} API</header>
<version>true</version>
- <locale>${javadoc.locale}</locale>
<!-- for JDK11 javadoc -->
<additionalJOption>-J-Duser.language=${javadoc.locale}</additionalJOption>
</configuration>
<version>${pmd-plugin.version}</version>
<configuration>
<rulesets>
- <ruleset>${project.basedir}/config/pmd/pmdrules.xml</ruleset>
+ <ruleset>config/pmd/pmdrules.xml</ruleset>
</rulesets>
</configuration>
<reportSets>
/**
* バイナリデータの出力を行う汎用エクスポーター。
+ *
* <p>基本的にリトルエンディアン形式で出力される。
*/
public class BinaryExporter implements Closeable, Flushable{
private final byte[] barray;
- private final TextExporter texporter_w31j;
- private final TextExporter texporter_u16le;
+ private final TextExporter texporterW31j;
+ private final TextExporter texporterU16le;
private final ByteArrayOutputStream xos;
this.barray = new byte[BUFSZ_PRIM];
- this.texporter_w31j = new TextExporter(CS_WIN31J);
- this.texporter_u16le = new TextExporter(CS_UTF16LE);
+ this.texporterW31j = new TextExporter(CS_WIN31J);
+ this.texporterU16le = new TextExporter(CS_UTF16LE);
this.xos = new ByteArrayOutputStream();
return;
/**
* 詰め物パディングを出力する。
+ *
* @param filler byte型配列によるパディングデータの並び。
- * <p>指定パディング長より長い部分は出力されない。
- * 指定パディング長に満たない場合は最後の要素が繰り返し出力される。
- * <p>配列長が0の場合は何も出力されない。
+ *
+ * <p>指定パディング長より長い部分は出力されない。
+ * 指定パディング長に満たない場合は
+ * 最後の要素が繰り返し出力される。</p>
+ *
+ * <p>配列長が0の場合は何も出力されない。</p>
+ *
* @param fillerLength パディング長。
- * <p>パディング長が0以下の場合は何も出力されない。
+ *
+ * <p>パディング長が0以下の場合は何も出力されない。</p>
+ *
* @return this
* @throws IOException 出力エラー
*/
* @return this
* @throws IOException 出力エラー
* @throws IllegalTextExportException テキスト出力エラー。
- * 出力が固定長を超えようとした、
- * もしくは不正なエンコードが行われたかのいずれか。
+ * 出力が固定長を超えようとした、
+ * もしくは不正なエンコードが行われたかのいずれか。
*/
public BinaryExporter dumpFixedW31j(CharSequence text,
int fixedLength,
int encodedSize;
try{
encodedSize =
- this.texporter_w31j.encodeToByteStream(text, this.xos);
+ this.texporterW31j.encodeToByteStream(text, this.xos);
}catch(CharacterCodingException e){
throw new IllegalTextExportException(ERRMSG_ILLENC, e);
}
* @return エンコードバイト列長
* @throws IOException 出力エラー
* @throws IllegalTextExportException テキスト出力エラー。
- * 出力が固定長を超えようとした、
- * もしくは不正なエンコードが行われたかのいずれか。
+ * 出力が固定長を超えようとした、
+ * もしくは不正なエンコードが行われたかのいずれか。
*/
public int dumpHollerithUtf16LE(CharSequence text)
throws IOException, IllegalTextExportException{
int encodedSize;
try{
encodedSize =
- this.texporter_u16le.encodeToByteStream(text, this.xos);
+ this.texporterU16le.encodeToByteStream(text, this.xos);
}catch(CharacterCodingException e){
assert false; // これはない
throw new IllegalTextExportException(ERRMSG_ILLENC, e);
/**
* バイナリファイルへの不正なテキスト情報の出力が検出された場合の例外。
- * <p>
- * {@link java.nio.charset.CharacterCodingException}に由来する異常系を
+ *
+ * <p>{@link java.nio.charset.CharacterCodingException}に由来する異常系を
* {@link java.io.IOException}から分離するために設計された。
- * <p>
- * 異常系の発生した理由としては
+ *
+ * <p>異常系の発生した理由としては
* <ul>
* <li>所定のフォーマットに対し文字列が長すぎる。
* <li>文字エンコーディングできない文字が含まれている
/** デフォルトの出力バッファサイズ(単位:byte)。 */
public static final int DEFBUFSZ_BYTE = 128;
+ private static final String DUMMYTXT = "";
+
private final CharsetEncoder encoder;
private CharBuffer cbuf = CharBuffer.allocate(DEFBUFSZ_CHAR);
private byte[] barray = new byte[DEFBUFSZ_BYTE];
private ByteBuffer bbuf = ByteBuffer.wrap(this.barray);
- private CharSequence textData;
+ private CharSequence textData = DUMMYTXT;
private int textLength;
private int inPos;
try{
total = dumpTextImpl(os);
}finally{
- this.textData = null;
+ this.textData = DUMMYTXT;
}
return total;
/**
* 入力バッファに文字を埋める。
+ *
* <p>入力バッファが一杯になるか
* 入力文字列がなくなるまでバッファが埋められる。
*/
/**
* 与えられた文字列のエンコード結果を格納先バイトストリームへ格納する。
+ *
* <p>エンコード結果は格納先ストリームに追記される。
+ *
* @param text 文字列
* @param bos 格納先ストリーム
* @return エンコードしたバイト数。
/**
* バイナリパーサの共通インタフェース。
+ *
* <p>バイト列、各種プリミティブ型値およびエンコードされた文字列を読み込む。
+ *
* <p>long,double、およびビッグエンディアン形式のデータは未サポート。
*/
public interface BinParser {
/**
* 入力ソースの読み込み位置を返す。
+ *
* @return 入力ソースの読み込み位置。単位はbyte。
*/
- long getPosition();
+ public abstract long getPosition();
/**
* 入力ソースにまだデータが残っているか判定する。
+ *
* @return まだ読み込んでいないデータが残っていればtrue
* @throws IOException IOエラー
*/
- boolean hasMore() throws IOException;
+ public abstract boolean hasMore() throws IOException;
/**
* 入力ソースを読み飛ばす。
+ *
* @param skipLength 読み飛ばすバイト数。
* @throws IOException IOエラー
* @throws MmdEofException 読み飛ばす途中でストリーム終端に達した。
* @see java.io.InputStream#skip(long)
*/
- void skip(long skipLength) throws IOException, MmdEofException;
+ public abstract void skip(long skipLength)
+ throws IOException, MmdEofException;
/**
* byte配列を読み込む。
+ *
* @param dst 格納先配列
* @param off 読み込み開始オフセット
* @param length 読み込みバイト数
* @throws MmdEofException 読み込む途中でストリーム終端に達した。
* @see java.io.InputStream#read(byte[], int, int)
*/
- void parseByteArray(byte[] dst, int off, int length)
+ public abstract void parseByteArray(byte[] dst, int off, int length)
throws NullPointerException,
IndexOutOfBoundsException,
IOException,
/**
* byte配列を読み込む。
+ *
* <p>配列要素全ての読み込みが試みられる。
+ *
* @param dst 格納先配列
* @throws NullPointerException 配列がnull
* @throws IOException IOエラー
* @throws MmdEofException 読み込む途中でストリーム終端に達した。
* @see java.io.InputStream#read(byte[])
*/
- void parseByteArray(byte[] dst)
+ public abstract void parseByteArray(byte[] dst)
throws NullPointerException, IOException, MmdEofException;
/**
* byte値を読み込む。
+ *
* @return 読み込んだbyte値
* @throws IOException IOエラー
* @throws MmdEofException 読み込む途中でストリーム終端に達した。
*/
- byte parseByte() throws IOException, MmdEofException;
+ public abstract byte parseByte() throws IOException, MmdEofException;
/**
* 符号無し値としてbyte値を読み込み、int型に変換して返す。
+ *
* <p>符号は拡張されない。(0xffは0x000000ffとなる)
+ *
* @return 読み込まれた値のint値
* @throws IOException IOエラー
* @throws MmdEofException 読み込む途中でストリーム終端に達した。
*/
- int parseUByteAsInt() throws IOException, MmdEofException;
+ public abstract int parseUByteAsInt() throws IOException, MmdEofException;
/**
* byte値を読み込み、boolean型に変換して返す。
+ *
* <p>0x00は偽、それ以外は真と解釈される。
+ *
* @return 読み込まれた値のboolean値
* @throws IOException IOエラー
* @throws MmdEofException 読み込む途中でストリーム終端に達した。
*/
- boolean parseBoolean() throws IOException, MmdEofException;
+ public abstract boolean parseBoolean()
+ throws IOException, MmdEofException;
/**
* short値を読み込む。
+ *
* <p>short値はリトルエンディアンで格納されていると仮定される。
+ *
* @return 読み込んだshort値
* @throws IOException IOエラー
* @throws MmdEofException 読み込む途中でストリーム終端に達した。
*/
- short parseLeShort() throws IOException, MmdEofException;
+ public abstract short parseLeShort() throws IOException, MmdEofException;
/**
* 符号無し値としてshort値を読み込み、int型に変換して返す。
+ *
* <p>符号は拡張されない。(0xffffは0x0000ffffとなる)
+ *
* <p>short値はリトルエンディアンで格納されていると仮定される。
+ *
* @return 読み込まれた値のint値
* @throws IOException IOエラー
* @throws MmdEofException 読み込む途中でストリーム終端に達した。
*/
- int parseLeUShortAsInt() throws IOException, MmdEofException;
+ public abstract int parseLeUShortAsInt()
+ throws IOException, MmdEofException;
/**
* int値を読み込む。
+ *
* <p>int値はリトルエンディアンで格納されていると仮定される。
+ *
* @return 読み込んだint値
* @throws IOException IOエラー
* @throws MmdEofException 読み込む途中でストリーム終端に達した。
*/
- int parseLeInt() throws IOException, MmdEofException;
+ public abstract int parseLeInt() throws IOException, MmdEofException;
/**
* float値を読み込む。
+ *
* <p>float値はリトルエンディアンで格納されていると仮定される。
+ *
* @return 読み込んだfloat値
* @throws IOException IOエラー
* @throws MmdEofException 読み込む途中でストリーム終端に達した。
*/
- float parseLeFloat() throws IOException, MmdEofException;
+ public abstract float parseLeFloat() throws IOException, MmdEofException;
/**
* 固定バイト長の文字列を読み込む。
* @throws MmdEofException 固定長バイト列を読む前に末端に達した。
* @throws MmdFormatException 文字エンコーディングに関するエラー
*/
- String parseString(TextDecoder decoder, int byteLen)
+ public abstract String parseString(TextDecoder decoder, int byteLen)
throws IOException, MmdEofException, MmdFormatException;
}
private final PushbackInputStream is;
private final byte[] readBuffer;
-// private final ByteBuffer beBuf;
+ // private final ByteBuffer beBuf;
private final ByteBuffer leBuf;
private long position = 0L;
this.readBuffer = new byte[BYTES_PRIM];
-// this.beBuf = ByteBuffer.wrap(this.readBuffer);
+ // this.beBuf = ByteBuffer.wrap(this.readBuffer);
this.leBuf = ByteBuffer.wrap(this.readBuffer);
-// this.beBuf.order(ByteOrder.BIG_ENDIAN);
+ // this.beBuf.order(ByteOrder.BIG_ENDIAN);
this.leBuf.order(ByteOrder.LITTLE_ENDIAN);
return;
/**
* バイナリファイル中ループ構造の通知用ハンドラ。
+ *
* <p>ステージ指定により、多重ネストループをもサポートする。
*/
public interface LoopHandler {
/**
* ループ構造開始の通知を受け取る。
+ *
* <p>0回ループの場合も含め一度呼ばれる。
+ *
* @param stage ループ種別
* @param loops ループ予定回数。未知の場合は負の値。
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void loopStart(ParseStage stage, int loops) throws MmdFormatException;
+ public abstract void loopStart(ParseStage stage, int loops)
+ throws MmdFormatException;
/**
* ループ構造の1イテレーション終了の通知を受け取る。
+ *
* <p>1度しか回らないループでも呼ばれる。
* 0回ループでは決して呼ばれない。
+ *
* @param stage ループ種別
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void loopNext(ParseStage stage) throws MmdFormatException;
+ public abstract void loopNext(ParseStage stage)
+ throws MmdFormatException;
/**
* ループ構造終了の通知を受け取る。
+ *
* <p>0回ループの場合も含め一度呼ばれる。
+ *
* @param stage ループ種別
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void loopEnd(ParseStage stage) throws MmdFormatException;
+ public abstract void loopEnd(ParseStage stage)
+ throws MmdFormatException;
}
/**
* コンストラクタ。
* @param position 入力ソース先頭からのエラー位置。(バイト単位)
- * 負の値を与えると、エラー位置は無効と解釈される。
+ * 負の値を与えると、エラー位置は無効と解釈される。
*/
public MmdEofException(long position){
this(null, position);
* コンストラクタ。
* @param message エラーメッセージ
* @param position 入力ソース先頭からのエラー位置。(バイト単位)
- * 負の値を与えると、エラー位置は無効と解釈される。
+ * 負の値を与えると、エラー位置は無効と解釈される。
*/
public MmdEofException(String message, long position){
super(message, position);
/**
* MMD関連ファイルのパース異常系。
+ *
* <p>必要に応じて、パースに失敗した位置を保持する。
*/
@SuppressWarnings("serial")
/**
* コンストラクタ。
* @param position 入力ソース先頭から数えたエラー位置。(バイト単位)
- * 負の値を与えると、エラー位置は無効と解釈される。
+ * 負の値を与えると、エラー位置は無効と解釈される。
*/
public MmdFormatException(long position){
this(null, position);
* コンストラクタ。
* @param message エラーメッセージ
* @param position 入力ソース先頭から数えたエラー位置。(バイト単位)
- * 負の値を与えると、エラー位置は無効と解釈される。
+ * 負の値を与えると、エラー位置は無効と解釈される。
*/
public MmdFormatException(String message, long position){
super(message);
/**
* エラー位置を取得する。
* @return 入力ソース先頭からのバイト数で表されるエラー位置。
- * 負なら無効なエラー位置。
+ * 負なら無効なエラー位置。
*/
public long getPosition(){
return this.position;
/**
* パース処理の進行ステージ種別を表す。
+ *
* <p>ループ構造の識別に用いられる。
+ *
* <p>enum型と異なり、実行時での要素の追加が可能。
*/
public class ParseStage {
/**
* 委譲パーサ。
+ *
* <p>別のパーサにパース処理を委譲する。
*/
public class ProxyParser implements BinParser{
/**
* 文字デコーダー。
+ *
* <p>あらかじめバイト長が既知であるバイトバッファを読み取り、
* 文字列へのデコード結果を返す。
+ *
* <p>デコード対象のバイト列が全てメモリ上に展開される必要があるので、
* 巨大なテキストのデコードには不適当。
+ *
* <p>入力バイト値0x00以降をデコード処理の対象から外す
* 「ゼロチョップモード」を備える。
* デフォルトではゼロチョップモードはオフ。
this.decoder = decoder;
this.decoder.reset();
- this.decoder.onMalformedInput (CodingErrorAction.REPORT);
+ this.decoder.onMalformedInput( CodingErrorAction.REPORT);
this.decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
return;
/**
* 指定されたバイト長のデコードに必要な出力バッファを用意する。
+ *
* <p>既存バッファで足りなければ新たに確保し直す。
+ *
* @param byteLength 入力バイト長
* @return 出力バッファ長。(キャラクタ単位)
*/
/**
* MMD用各種バイナリファイルパーサ共通ライブラリ。
- * <p>
- * PMDモデルファイルやVMDモーションファイルなどの個別のパーサは
+ *
+ * <p>PMDモデルファイルやVMDモーションファイルなどの個別のパーサは
* 別パッケージにより提供される。
*/
/**
* 何もしないインタフェース実装のインスタンスを生成する。
+ *
* <p>インタフェースの各メソッド戻り値はvoidでなければならない。
+ *
* @param types インタフェース群
* @return インタフェースを実装したインスタンス。
*/
public static Object buildEmptyProxy(Class<?>... types){
- ClassLoader loader = types[0].getClassLoader();
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ Object proxy = buildEmptyProxy(loader, types);
+ return proxy;
+ }
+ /**
+ * 何もしないインタフェース実装のインスタンスを生成する。
+ *
+ * <p>インタフェースの各メソッド戻り値はvoidでなければならない。
+ *
+ * @param loader class-loader
+ * @param types インタフェース群
+ * @return インタフェースを実装したインスタンス。
+ */
+ public static Object buildEmptyProxy(
+ ClassLoader loader, Class<?>... types){
Object proxy =
Proxy.newProxyInstance(loader, types, NOTHING_INVOKER);
-
return proxy;
}
/**
* キーはISO639、値は多言語テキスト。
*/
- private final Map<String, String> nameMap =
- new HashMap<String, String>();
+ private final Map<String, String> nameMap = new HashMap<>();
/**
/**
* プライマリ文字列を返す。
+ *
* <p>見つからなければグローバル文字列を返す。
* それでも見つからなければ長さ0の空文字列を返す。
+ *
* <p>※決してnullは返さない。
+ *
* @return 文字列
*/
public String getText(){
/**
* 実行環境のデフォルトロケールに応じた文字列を返す。
+ *
* <p>見つからなければグローバル文字列、プライマリ文字列の順に返す。
* それでも見つからなければ適当な言語コードの文字列を返す。
* それでも見つからなければ長さ0の空文字列を返す。
+ *
* <p>デフォルトロケールの確認はその都度行われる。
+ *
* <p>※決してnullは返さない。
+ *
* @return 文字列
*/
public String getLocalizedText(){
*/
public List<String> lang639CodeList(){
Set<String> set = this.nameMap.keySet();
- List<String> result = new ArrayList<String>(set.size());
+ List<String> result = new ArrayList<>(set.size());
for(String lang : set){
if(lang.equals(CODE639_PRIMARY)) result.add(lang);
/**
* YXZオイラー角。
* 三次元空間での方向及び姿勢を定義する。
+ *
* <p>回転量はラジアンで表される。
+ *
* <p>※XYZオイラー角ではない。
*/
public strictfp class EulerYXZ {
/**
* コンストラクタ。
+ *
* <p>三軸とも回転量0の状態になる。
*/
public EulerYXZ(){
/**
* コンストラクタ。
+ *
* @param xRot X軸回転量。(ラジアン)
* @param yRot Y軸回転量。(ラジアン)
* @param zRot Z軸回転量。(ラジアン)
/**
* X軸回転量を返す。
+ *
* @return X軸回転量を返す。(ラジアン)
*/
public double getXRot(){
/**
* Y軸回転量を返す。
+ *
* @return Y軸回転量を返す。(ラジアン)
*/
public double getYRot(){
/**
* Z軸回転量を返す。
+ *
* @return Z軸回転量を返す。(ラジアン)
*/
public double getZRot(){
/**
* X軸回転量を設定する。
+ *
* @param xRotArg X軸回転量。(ラジアン)
*/
public void setXRot(double xRotArg){
/**
* Y軸回転量を設定する。
+ *
* @param yRotArg Y軸回転量。(ラジアン)
*/
public void setYRot(double yRotArg){
/**
* Z軸回転量を設定する。
+ *
* @param zRotArg Z軸回転量。(ラジアン)
*/
public void setZRot(double zRotArg){
/**
* 三軸の回転量を設定する。
+ *
* @param xRotArg X軸回転量。(ラジアン)
* @param yRotArg Y軸回転量。(ラジアン)
* @param zRotArg Z軸回転量。(ラジアン)
/**
* パラメータ情報の文字列化。
+ *
* @param x x値
* @param y y値
* @param z z値
/**
* 二次元空間座標及び変量を表す。
+ *
* <p>直交座標を二つの倍精度値で表す。
+ *
* <p>主な用途はUVマッピングなど。
*/
public strictfp class MkPos2D {
/**
* コンストラクタ。
+ *
* @param xPosArg X座標
* @param yPosArg Y座標
*/
/**
* X座標を設定する。
+ *
* @param xPosArg X座標
*/
public void setXpos(double xPosArg){
/**
* X座標を返す。
+ *
* @return X座標
*/
public double getXpos(){
/**
* Y座標を設定する。
+ *
* @param yPosArg Y座標
*/
public void setYpos(double yPosArg){
/**
* Y座標を返す。
+ *
* @return Y座標
*/
public double getYpos(){
/**
* 座標を設定する。
+ *
* @param xPosArg X軸座標
* @param yPosArg Y軸座標
*/
/**
* この点が原点(0,0)か否か判定する。
+ *
* @return 原点ならtrue
*/
public boolean isOriginPoint(){
- if(this.xPos != 0.0) return false;
- if(this.yPos != 0.0) return false;
- return true;
+ boolean result =
+ this.xPos == 0.0 && this.yPos == 0.0;
+ return result;
}
/**
/**
* 三次元位置情報。
+ *
* <p>直交座標を三つの倍精度値で表す。
+ *
* <p>具体的にはボーン位置やカメラターゲット位置など。
*/
public strictfp class MkPos3D {
/**
* コンストラクタ。
+ *
* @param xPosArg X軸座標
* @param yPosArg Y軸座標
* @param zPosArg Z軸座標
/**
* X軸座標を返す。
+ *
* @return X軸座標
*/
public double getXpos() {
/**
* Y軸座標を返す。
+ *
* @return Y軸座標
*/
public double getYpos() {
/**
* Z軸座標を返す。
+ *
* @return Z軸座標
*/
public double getZpos() {
/**
* X軸座標を設定する。
+ *
* @param xPosArg X軸座標
*/
public void setXpos(double xPosArg){
/**
* Y軸座標を設定する。
+ *
* @param yPosArg Y軸座標
*/
public void setYpos(double yPosArg){
/**
* Z軸座標を設定する。
+ *
* @param zPosArg Z軸座標
*/
public void setZpos(double zPosArg){
/**
* 座標を設定する。
+ *
* @param xPosArg X軸座標
* @param yPosArg Y軸座標
* @param zPosArg Z軸座標
/**
* この点が原点(0,0,0)か否か判定する。
+ *
* @return 原点ならtrue
*/
public boolean isOriginPoint(){
- if(this.xPos != 0.0) return false;
- if(this.yPos != 0.0) return false;
- if(this.zPos != 0.0) return false;
- return true;
+ boolean result =
+ this.xPos == 0.0 && this.yPos == 0.0 && this.zPos == 0.0;
+ return result;
}
/**
/**
* クォータニオンによる回転表現。
+ *
* <p>虚部q1,q2,q3と実部qwから構成される。
*/
public strictfp class MkQuat {
/**
* コンストラクタ。
+ *
* <p>虚部が全て0.0、実部が1.0となる。
*/
public MkQuat(){
/**
* コンストラクタ。
+ *
* @param q コピー元クォータニオン
*/
public MkQuat(MkQuat q){
/**
* コンストラクタ。
+ *
* @param q1 虚部1
* @param q2 虚部2
* @param q3 虚部3
/**
* クォータニオン積を求め格納する。
+ *
* <p>クォータニオン積では交換則が成り立たない。
+ *
* <p>引数は同一インスタンスを含んでもよい。
+ *
* @param qA 積前項
* @param qB 積後項
* @param result 積の格納先
/**
* 共役(共軛)クォータニオンを求め格納する。
+ *
* <p>引数は同一インスタンスでもよい。
+ *
* @param q クォータニオン
* @param result 格納先
*/
/**
* 単位クォータニオンを求め格納する。
+ *
* <p>引数は同一インスタンスでもよい。
+ *
* @param q クォータニオン
* @param result 格納先
*/
/**
* 逆元クォータニオンを求め格納する。
+ *
* <p>対象クォータニオンの絶対値が小さい場合、
* 無限大が虚部実部に入る可能性がある。
+ *
* <p>引数は同一インスタンスでもよい。
+ *
* @param q クォータニオン
* @param result 格納先
*/
/**
* 位置情報を読み込む。
+ *
* <p>虚部q1,q2,q3にX,Y,Z軸の変量が入る。
+ *
* <p>実部には0が入る。
+ *
* @param xPos X位置
* @param yPos Y位置
* @param zPos Z位置
/**
* 位置情報を読み込む。
+ *
* <p>虚部q1,q2,q3にX,Y,Z軸の変量が入る。
+ *
* <p>実部には0が入る。
+ *
* @param pos 位置情報
*/
public void setPos3D(MkPos3D pos){
/**
* YXZオイラー角を読み込む。
+ *
* <p>Y軸回転、X軸回転、Z軸回転の順に
* 個別回転クォータニオンの積をとったものと等しい。
+ *
* @param xRot X軸回転量(ラジアン)。第2軸
* @param yRot Y軸回転量(ラジアン)。第1軸
* @param zRot Z軸回転量(ラジアン)。第3軸
/**
* YXZオイラー角を読み込む。
+ *
* <p>Y軸回転、X軸回転、Z軸回転の順に
* 個別回転クォータニオンの積をとったものと等しい。
+ *
* @param rot YXZオイラー角
*/
public void setEulerYXZ(EulerYXZ rot){
/**
* クォータニオンをYXZオイラー角へと変換する。
+ *
* <p>ジンバルロック時のYZ配分が指定可能。
+ *
* @param result YXZオイラー角
* @param oldY ジンバルロック時(オイラー角Xが直角etc.)
- * に使われるY軸回転量
+ * に使われるY軸回転量
*/
public void toEulerYXZ(EulerYXZ result, double oldY){
double qx = this.q1;
double m11 = 1.0 - 2.0 * (qx2 + qz2);
double m12 = 2.0 * (qyz - qwx);
-// double m20 = 2.0 * (qxz - qwy);
-// double m21 = 2.0 * (qwx + qyz);
+ // double m20 = 2.0 * (qxz - qwy);
+ // double m21 = 2.0 * (qwx + qyz);
double m22 = 1.0 - 2.0 * (qx2 + qy2);
double resultX;
double rprrQ1;
double rprrQ2;
double rprrQ3;
-// double rprrQW;
rprrQ1 = rpQ2 * rrQ3 - rpQ3 * rrQ2 + rpQW * rrQ1 + rpQ1 * rrQW;
rprrQ2 = rpQ3 * rrQ1 - rpQ1 * rrQ3 + rpQW * rrQ2 + rpQ2 * rrQW;
rprrQ3 = rpQ1 * rrQ2 - rpQ2 * rrQ1 + rpQW * rrQ3 + rpQ3 * rrQW;
-// rprrQW = rpQW * rrQW - rpQ1 * rrQ1 - rpQ2 * rrQ2 - rpQ3 * rrQ3;
-// assert rprrQW == 0.0;
+ // double rprrQW;
+ // rprrQW = rpQW * rrQW - rpQ1 * rrQ1 - rpQ2 * rrQ2 - rpQ3 * rrQ3;
+ // assert rprrQW == 0.0;
result.setXpos(rprrQ1);
result.setYpos(rprrQ2);
/**
* MMDにおける数学的な各種概念。
+ *
* <p>基本的には左手系直交座標のユークリッド三次元空間を基盤とする。
+ *
* <p>javax.vecmathの代替品。
*/
* コンストラクタ。
* @param code 符号化int値
*/
- private BoneType(int code){
+ BoneType(int code){
this((byte)code);
return;
}
* コンストラクタ。
* @param code 符号化byte値
*/
- private BoneType(byte code){
+ BoneType(byte code){
this.encoded = code;
return;
}
* コンストラクタ。
* @param code 符号化int値
*/
- private MorphType(int code){
+ MorphType(int code){
this((byte)code);
return;
}
* コンストラクタ。
* @param code 符号化byte値
*/
- private MorphType(byte code){
+ MorphType(byte code){
this.encoded = code;
return;
}
/**
* ボーン最大数。
* (Id : 0 - 0xfffe)
+ *
* <p>MMDがいくつまで受け入れるかはまた別の話だよ。
*/
public static final int MAX_BONE = 65535;
* コンストラクタ。
* @param code 符号化int値
*/
- private RigidBehaviorType(int code){
+ RigidBehaviorType(int code){
this((byte)code);
return;
}
* コンストラクタ。
* @param code 符号化byte値
*/
- private RigidBehaviorType(byte code){
+ RigidBehaviorType(byte code){
this.encoded = code;
return;
}
* コンストラクタ。
* @param code 符号化int値
*/
- private RigidShapeType(int code){
+ RigidShapeType(int code){
this((byte)code);
return;
}
* コンストラクタ。
* @param code 符号化byte値
*/
- private RigidShapeType(byte code){
+ RigidShapeType(byte code){
this.encoded = code;
return;
}
/**
* シェーディング情報の各種ユーティリティ。
+ *
* <p>※ スフィアマップファイルの中身はBMP(DIB)形式。
+ *
* <p><a href="http://en.wikipedia.org/wiki/BMP_file_format">
* BMP file format </a>
*/
/**
* スフィアマップファイル名か否か判定する。
+ *
* <p>拡張子が「.sph」(乗算)もしくは「.spa」(加算)なら
* スフィアマップファイル名と判定する。
+ *
* @param fname ファイル名
* @return スフィアマップファイルならtrue
*/
/**
* シェーディング用ファイル情報文字列から
* テクスチャファイル名とスフィアマップファイル名を分離する。
+ *
* <p>2つのファイル名は単一の「*」で区切られ、
* 前部がテクスチャファイル名、後部がスフィアマップファイル名となる。
* 「*」がなく末尾が「.sph」か「.spa」なら
* スフィアマップファイル名のみ、
* 末尾がどちらでもなければテクスチャファイル名のみとなる。
+ *
* @param shadingFile シェーディング用ファイル情報
* @return [0]:テクスチャファイル名 [1]:スフィアマップファイル名。
- * 該当ファイル名が無い場合は空文字列。
+ * 該当ファイル名が無い場合は空文字列。
*/
public static String[] splitShadingFileInfo(String shadingFile) {
String[] result;
/**
* PMDファイルのパース処理開始の通知を受け取る。
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdParseStart()
+ public abstract void pmdParseStart()
throws MmdFormatException;
/**
* PMDファイルのパース処理終了の通知を受け取る。
- * @param hasMoreData 入力ソースに
- * まだ読み込まれていないデータがあればtrue
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @param hasMoreData
+ * 入力ソースにまだ読み込まれていないデータがあればtrue
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdParseEnd(boolean hasMoreData)
+ public abstract void pmdParseEnd(boolean hasMoreData)
throws MmdFormatException;
/**
* PMDファイルのヘッダ情報の通知を受け取る。
* @param header ヘッダ情報バイト列。
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdHeaderInfo(byte[] header)
+ public abstract void pmdHeaderInfo(byte[] header)
throws MmdFormatException;
/**
* PMDファイルのモデル基本情報の通知を受け取る。
* @param modelName モデル名
* @param description モデルの説明文。改行CRLFは"\n"に変換される。
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdModelInfo(String modelName, String description)
+ public abstract void pmdModelInfo(String modelName, String description)
throws MmdFormatException;
}
public interface PmdBoneHandler extends LoopHandler {
/** ボーン定義抽出ループ。 */
- ParseStage BONE_LIST = new ParseStage();
+ public static final ParseStage BONE_LIST = new ParseStage();
/** IKリスト抽出ループ。 */
- ParseStage IK_LIST = new ParseStage();
+ public static final ParseStage IK_LIST = new ParseStage();
/** IKチェーンリスト抽出ループ。 */
- ParseStage IKCHAIN_LIST = new ParseStage();
+ public static final ParseStage IKCHAIN_LIST = new ParseStage();
/** ボーングループ名抽出ループ。 */
- ParseStage BONEGROUP_LIST = new ParseStage();
+ public static final ParseStage BONEGROUP_LIST = new ParseStage();
/** ボーングループ内訳抽出ループ。 */
- ParseStage GROUPEDBONE_LIST = new ParseStage();
+ public static final ParseStage GROUPEDBONE_LIST = new ParseStage();
/**
* ボーン定義情報の通知を受け取る。
+ *
* <p>{@link #BONE_LIST}ループの構成要素。
+ *
* @param boneName ボーン名
* @param boneKind ボーン種別。
* <ul>
* <li>8:捩り
* <li>9:回転連動
* </ul>
- * ※8,9はMMD4.0から?
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * ※8,9はMMD4.0から?
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdBoneInfo(String boneName, byte boneKind)
+ public abstract void pmdBoneInfo(String boneName, byte boneKind)
throws MmdFormatException;
/**
* ボーン間接続情報の通知を受け取る。
+ *
* <p>{@link #BONE_LIST}ループの構成要素。
+ *
* @param parentId 親(前)ボーンID。無い場合は0xffff。
* @param tailId 子(次)ボーンID。末端の場合は0。
- * 捩りボーンの場合は軸方向のボーンID、
- * 回転連動ボーンの場合は影響元ボーンID
+ * 捩りボーンの場合は軸方向のボーンID、
+ * 回転連動ボーンの場合は影響元ボーンID
* @param ikId 影響IKボーンID。未指定の場合は0。
- * ※回転連動では影響度(0-100)、負や100以上もOK!
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * ※回転連動では影響度(0-100)、負や100以上もOK!
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdBoneLink(int parentId, int tailId, int ikId)
+ public abstract void pmdBoneLink(int parentId, int tailId, int ikId)
throws MmdFormatException;
/**
* ボーン位置情報の通知を受け取る。
+ *
* <p>{@link #BONE_LIST}ループの構成要素。
+ *
* @param xPos X座標
* @param yPos Y座標
* @param zPos Z座標
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdBonePosition(float xPos, float yPos, float zPos)
+ public abstract void pmdBonePosition(float xPos, float yPos, float zPos)
throws MmdFormatException;
/**
* IKボーン情報の通知を受け取る。
+ *
* <p>{@link #IK_LIST}ループの構成要素。
+ *
* @param boneId IKボーンID
* @param targetId IKボーンが最初に接続するIK接続先ボーンID
* @param depth 再帰演算の深さ
* @param weight 制限角度強度
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdIKInfo(int boneId, int targetId, int depth, float weight)
+ public abstract void pmdIKInfo(
+ int boneId, int targetId,
+ int depth, float weight)
throws MmdFormatException;
/**
* IKチェイン要素の通知を受け取る。
+ *
* <p>{@link #IK_LIST}ループの下位{@link #IKCHAIN_LIST}ループの構成要素。
+ *
* @param childId IK影響下ボーンID
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdIKChainInfo(int childId)
+ public abstract void pmdIKChainInfo(int childId)
throws MmdFormatException;
/**
* ボーングループ名定義の通知を受け取る。
+ *
* <p>{@link #BONEGROUP_LIST}ループの構成要素。
+ *
* @param groupName ボーングループ名。末尾のLF(0x0a)は削除される。
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdBoneGroupInfo(String groupName) throws MmdFormatException;
+ public abstract void pmdBoneGroupInfo(String groupName)
+ throws MmdFormatException;
/**
* ボーングループ内訳の通知を受け取る。
+ *
* <p>{@link #GROUPEDBONE_LIST}ループの構成要素。
+ *
* @param boneId グループに所属するボーンのID
* @param groupId ボーンが所属するボーングループIDに1を足した数
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdGroupedBoneInfo(int boneId, int groupId)
+ public abstract void pmdGroupedBoneInfo(int boneId, int groupId)
throws MmdFormatException;
}
public interface PmdEngHandler extends LoopHandler {
/** ボーン英語名抽出ループ。 */
- ParseStage ENGBONE_LIST = new ParseStage();
+ public static final ParseStage ENGBONE_LIST = new ParseStage();
/** モーフ英語名抽出ループ。 */
- ParseStage ENGMORPH_LIST = new ParseStage();
+ public static final ParseStage ENGMORPH_LIST = new ParseStage();
/** ボーングループ英語名抽出ループ。 */
- ParseStage ENGBONEGROUP_LIST = new ParseStage();
+ public static final ParseStage ENGBONEGROUP_LIST = new ParseStage();
/**
* PMD英語情報の有無の通知を受け取る。
* @param hasEnglishInfo 英語情報が含まれればtrue
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdEngEnabled(boolean hasEnglishInfo) throws MmdFormatException;
+ public abstract void pmdEngEnabled(boolean hasEnglishInfo)
+ throws MmdFormatException;
/**
* PMD英語基本情報の通知を受け取る。
* @param modelName モデル名
* @param description モデルの説明文。改行CRLFは"\n"に変換される。
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdEngModelInfo(String modelName, String description)
+ public abstract void pmdEngModelInfo(String modelName, String description)
throws MmdFormatException;
/**
* 英語ボーン名の通知を受け取る。
+ *
* <p>{@link #ENGBONE_LIST}ループの構成要素
+ *
* @param boneName 英語ボーン名
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdEngBoneInfo(String boneName) throws MmdFormatException;
+ public abstract void pmdEngBoneInfo(String boneName)
+ throws MmdFormatException;
/**
* 英語モーフ名の通知を受け取る。
* 特殊モーフ名「base」に対応する英語名は通知されない。
+ *
* <p>{@link #ENGMORPH_LIST}ループの構成要素
+ *
* @param morphName 英語モーフ名
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdEngMorphInfo(String morphName) throws MmdFormatException;
+ public abstract void pmdEngMorphInfo(String morphName)
+ throws MmdFormatException;
/**
* 英語ボーングループ名の通知を受け取る。
+ *
* <p>{@link #ENGBONEGROUP_LIST}ループの構成要素
+ *
* @param groupName 英語ボーングループ名
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdEngBoneGroupInfo(String groupName) throws MmdFormatException;
+ public abstract void pmdEngBoneGroupInfo(String groupName)
+ throws MmdFormatException;
}
public interface PmdJointHandler extends LoopHandler {
/** ジョイント情報抽出ループ。 */
- ParseStage JOINT_LIST = new ParseStage();
+ public static final ParseStage JOINT_LIST = new ParseStage();
/**
* ジョイント名の通知を受け取る。
+ *
* <p>{@link #JOINT_LIST}ループの構成要素。
+ *
* @param jointName ジョイント名
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示。
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示。
*/
- void pmdJointName(String jointName)
+ public abstract void pmdJointName(String jointName)
throws MmdFormatException;
/**
* ジョイントが繋ぐ接続剛体IDの通知を受け取る。
+ *
* <p>{@link #JOINT_LIST}ループの構成要素。
+ *
* @param rigidIdA 接続剛体AのID
* @param rigidIdB 接続剛体BのID
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示。
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示。
*/
- void pmdJointLink(int rigidIdA, int rigidIdB)
+ public abstract void pmdJointLink(int rigidIdA, int rigidIdB)
throws MmdFormatException;
/**
* ジョイント位置の通知を受け取る。
+ *
* <p>{@link #JOINT_LIST}ループの構成要素。
+ *
* @param posX X座標
* @param posY Y座標
* @param posZ Z座標
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示。
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示。
*/
- void pmdJointPosition(float posX, float posY, float posZ)
+ public abstract void pmdJointPosition(float posX, float posY, float posZ)
throws MmdFormatException;
/**
* ジョイント回転姿勢の通知を受け取る。
+ *
* <p>{@link #JOINT_LIST}ループの構成要素。
+ *
* @param radX X軸回転量(radian)
* @param radY Y軸回転量(radian)
* @param radZ Z軸回転量(radian)
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示。
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示。
*/
- void pmdJointRotation(float radX, float radY, float radZ)
+ public abstract void pmdJointRotation(float radX, float radY, float radZ)
throws MmdFormatException;
/**
* ジョイント移動制限の通知を受け取る。
+ *
* <p>{@link #JOINT_LIST}ループの構成要素。
+ *
* <p>※ [制限端 その1 <= その2] 条件を満たす必要はあるか?
+ *
* @param posXlim1 X座標制限端その1
* @param posXlim2 X座標制限端その2
* @param posYlim1 Y座標制限端その1
* @param posYlim2 Y座標制限端その2
* @param posZlim1 Z座標制限端その1
* @param posZlim2 Z座標制限端その2
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示。
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示。
*/
- void pmdPositionLimit(float posXlim1, float posXlim2,
+ public abstract void pmdPositionLimit(float posXlim1, float posXlim2,
float posYlim1, float posYlim2,
float posZlim1, float posZlim2 )
throws MmdFormatException;
/**
* ジョイント回転制限の通知を受け取る。
+ *
* <p>{@link #JOINT_LIST}ループの構成要素。
+ *
* <p>※ [制限端 その1 <= その2] 条件を満たす必要はあるか?
+ *
* @param radXlim1 X軸制限端その1(radian)
* @param radXlim2 X軸制限端その2(radian)
* @param radYlim1 Y軸制限端その1(radian)
* @param radYlim2 Y軸制限端その2(radian)
* @param radZlim1 Z軸制限端その1(radian)
* @param radZlim2 Z軸制限端その2(radian)
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示。
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示。
*/
- void pmdRotationLimit(float radXlim1, float radXlim2,
+ public abstract void pmdRotationLimit(float radXlim1, float radXlim2,
float radYlim1, float radYlim2,
float radZlim1, float radZlim2 )
throws MmdFormatException;
/**
* ジョイントのばね移動情報の通知を受け取る。
+ *
* <p>{@link #JOINT_LIST}ループの構成要素。
+ *
* @param elasticPosX X座標
* @param elasticPosY Y座標
* @param elasticPosZ Z座標
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示。
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示。
*/
- void pmdElasticPosition(float elasticPosX,
+ public abstract void pmdElasticPosition(float elasticPosX,
float elasticPosY,
float elasticPosZ )
throws MmdFormatException;
/**
* ジョイントのばね回転情報の通知を受け取る。
+ *
* <p>{@link #JOINT_LIST}ループの構成要素。
+ *
* @param elasticDegX X軸変量(degree)
* @param elasticDegY Y軸変量(degree)
* @param elasticDegZ Z軸変量(degree)
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示。
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示。
*/
- void pmdElasticRotation(float elasticDegX,
+ public abstract void pmdElasticRotation(float elasticDegX,
float elasticDegY,
float elasticDegZ )
throws MmdFormatException;
public interface PmdMaterialHandler extends LoopHandler {
/** 材質抽出ループ。 */
- ParseStage MATERIAL_LIST = new ParseStage();
+ public static final ParseStage MATERIAL_LIST = new ParseStage();
/**
* 材質の拡散光成分の通知を受け取る。
+ *
* <p>{@link #MATERIAL_LIST}ループの構成要素。
+ *
* @param red 0.0~1.0の範囲の赤成分
* @param green 0.0~1.0の範囲の緑成分
* @param blue 0.0~1.0の範囲の青成分
* @param alpha 0.0(透明)~1.0(不透明)のアルファ値。
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void pmdMaterialDiffuse(float red, float green, float blue,
- float alpha )
+ public abstract void pmdMaterialDiffuse(
+ float red, float green, float blue, float alpha)
throws MmdFormatException;
/**
* 材質の反射光成分の通知を受け取る。
+ *
* <p>{@link #MATERIAL_LIST}ループの構成要素。
+ *
* @param red 0.0~1.0の範囲の赤成分
* @param green 0.0~1.0の範囲の緑成分
* @param blue 0.0~1.0の範囲の青成分
* @param shininess 光沢強度(1~15ぐらい)
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void pmdMaterialSpecular(float red, float green, float blue,
- float shininess)
+ public abstract void pmdMaterialSpecular(
+ float red, float green, float blue, float shininess)
throws MmdFormatException;
/**
* 材質の環境色成分の通知を受け取る。
+ *
* <p>{@link #MATERIAL_LIST}ループの構成要素。
+ *
* @param red 0.0~1.0の範囲の赤成分
* @param green 0.0~1.0の範囲の緑成分
* @param blue 0.0~1.0の範囲の青成分
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void pmdMaterialAmbient(float red, float green, float blue)
+ public abstract void pmdMaterialAmbient(
+ float red, float green, float blue)
throws MmdFormatException;
/**
* シェーディング情報の通知を受け取る。
+ *
* <p>{@link #MATERIAL_LIST}ループの構成要素。
+ *
* @param toonIdx トゥーンファイル番号。
- * 0ならtoon01.bmp。9ならtoon10.bmp。0xffならtoon0.bmp。
+ * 0ならtoon01.bmp。9ならtoon10.bmp。0xffならtoon0.bmp。
* @param textureFile テクスチャファイル名。
- * 無ければ空文字。
+ * 無ければ空文字。
* @param sphereFile スフィアマップファイル名。
- * 無ければ空文字。
+ * 無ければ空文字。
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void pmdMaterialShading(int toonIdx,
+ public abstract void pmdMaterialShading(int toonIdx,
String textureFile, String sphereFile )
throws MmdFormatException;
/**
* 材質情報の通知を受け取る。
+ *
* <p>{@link #MATERIAL_LIST}ループの構成要素。
+ *
* @param hasEdge エッジを表示するならtrue
* @param vertexNum 面頂点数。
- * 3の倍数のはず。
- * 3で割ると、材質に属する面の数を表す。
- * <p>通算した面数を面情報通知順と突き合わせることにより、
- * 材質に属する面の集合を得ることが可能。
+ * 3の倍数のはず。
+ * 3で割ると、材質に属する面の数を表す。
+ *
+ * <p>通算した面数を面情報通知順と突き合わせることにより、
+ * 材質に属する面の集合を得ることが可能。</p>
+ *
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
* @see PmdShapeHandler#pmdSurfaceTriangle(int, int, int)
*/
- void pmdMaterialInfo(boolean hasEdge, int vertexNum)
+ public abstract void pmdMaterialInfo(boolean hasEdge, int vertexNum)
throws MmdFormatException;
}
public interface PmdMorphHandler extends LoopHandler {
/** モーフ抽出ループ。 */
- ParseStage MORPH_LIST = new ParseStage();
+ public static final ParseStage MORPH_LIST = new ParseStage();
/** モーフ頂点抽出ループ。 */
- ParseStage MORPHVERTEX_LIST = new ParseStage();
+ public static final ParseStage MORPHVERTEX_LIST = new ParseStage();
/** モーフ出現順抽出ループ。 */
- ParseStage MORPHORDER_LIST = new ParseStage();
+ public static final ParseStage MORPHORDER_LIST = new ParseStage();
/**
* モーフ情報の通知を受け取る。
+ *
* <p>{@link #MORPH_LIST}ループの構成要素
+ *
* @param morphName モーフ名
* @param morphType モーフ種別。
* <ul>
* <li>3:リップ
* <li>4:その他
* </ul>
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdMorphInfo(String morphName, byte morphType)
+ public abstract void pmdMorphInfo(String morphName, byte morphType)
throws MmdFormatException;
/**
* モーフ形状の通知を受け取る。
+ *
* <p>{@link #MORPH_LIST}ループの下位{@link #MORPHVERTEX_LIST}の構成要素。
+ *
* <p>※ base型頂点IDの出現順がモーフ頂点IDとなる。
+ *
* @param serialId base型の場合は頂点ID、それ以外はモーフ頂点ID
* @param xPos base型の場合はX座標、それ以外はX軸変位
* @param yPos base型の場合はY座標、それ以外はY軸変位
* @param zPos base型の場合はZ座標、それ以外はZ軸変位
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdMorphVertexInfo(int serialId,
+ public abstract void pmdMorphVertexInfo(int serialId,
float xPos, float yPos, float zPos)
throws MmdFormatException;
/**
* 各モーフ種別内のGUI表示順の通知を受け取る。
+ *
* <p>{@link #MORPHORDER_LIST}ループの構成要素
+ *
* @param morphId モーフ通し番号。同一モーフ種別内の大小関係のみ意味がある。
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdMorphOrderInfo(int morphId) throws MmdFormatException;
+ public abstract void pmdMorphOrderInfo(int morphId)
+ throws MmdFormatException;
}
/**
* PMDモデルファイルのパーサ最新版。
+ *
* <p>将来のリリースにおいて、
* 常に最新のPMDモデルファイルフォーマットに対応したパーサの
* 別名であることが保証される。つもり。
/**
* 文字列の最後がLF(0x0a)の場合削除する。
+ *
* <p>ボーングループ名対策。
+ *
* @param name 文字列
* @return 末尾LFが削除された文字列
*/
/**
* 指定されたバイト長に収まるゼロ終端(0x00)文字列を読み込む。
+ *
* <p>入力バイト列はwindows-31jエンコーディングとして解釈される。
+ *
* <p>ゼロ終端以降のデータは無視されるが、
* IO入力は指定バイト数だけ読み進められる。
* ゼロ終端が見つからないまま指定バイト数が読み込み終わった場合、
* そこまでのデータから文字列を構成する。
+ *
* @param byteLen 読み込みバイト数
* @return デコードされた文字列
* @throws IOException IOエラー
/**
* PMDモデルファイルのパーサ拡張その1。
+ *
* <p>※ 英名対応
*/
public class PmdParserExt1 extends PmdParserBase {
/**
* PMDモデルファイルのパーサ拡張その2。
+ *
* <p>※ 独自トゥーンテクスチャファイル名対応
*/
public class PmdParserExt2 extends PmdParserExt1 {
/**
* PMDモデルファイルのパーサ拡張その3。
+ *
* <p>※ 剛体情報対応
*/
public class PmdParserExt3 extends PmdParserExt2 {
*/
private void parseRigidDynamics()
throws IOException, MmdFormatException{
- float mass = parseLeFloat();
- float dampingPos = parseLeFloat();
- float dampingRot = parseLeFloat();
- float restitution = parseLeFloat();
- float friction = parseLeFloat();
+ float mass = parseLeFloat();
+ float dampingPos = parseLeFloat();
+ float dampingRot = parseLeFloat();
+ float restitution = parseLeFloat();
+ float friction = parseLeFloat();
- this.rigidHandler.pmdRigidPhysics(
- mass, dampingPos, dampingRot, restitution, friction
- );
+ this.rigidHandler.pmdRigidPhysics(
+ mass, dampingPos, dampingRot, restitution, friction
+ );
return;
}
posXlim1, posXlim2,
posYlim1, posYlim2,
posZlim1, posZlim2
- );
+ );
float rotXlim1 = parseLeFloat();
float rotYlim1 = parseLeFloat();
rotXlim1, rotXlim2,
rotYlim1, rotYlim2,
rotZlim1, rotZlim2
- );
+ );
return;
}
elasticPosX,
elasticPosY,
elasticPosZ
- );
+ );
float elasticRotX = parseLeFloat();
float elasticRotY = parseLeFloat();
elasticRotX,
elasticRotY,
elasticRotZ
- );
+ );
return;
}
/**
* PMDモデルの各種剛体情報の通知用ハンドラ。
+ *
* <p>MMDでの剛体力学では「Bullet Physics Library」が用いられる。
+ *
* @see <a href="http://www.bulletphysics.org/">Bullet Physics Library</a>
*/
public interface PmdRigidHandler extends LoopHandler {
/** 剛体情報抽出ループ。 */
- ParseStage RIGID_LIST = new ParseStage();
+ public static final ParseStage RIGID_LIST = new ParseStage();
/**
* 剛体名の通知を受け取る。
+ *
* <p>{@link #RIGID_LIST}ループの構成要素。
+ *
* @param rigidName 剛体名
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void pmdRigidName(String rigidName)
+ public abstract void pmdRigidName(String rigidName)
throws MmdFormatException;
/**
* 剛体基本情報の通知を受け取る。
+ *
* <p>{@link #RIGID_LIST}ループの構成要素。
+ *
* @param rigidGroupId 剛体グループ番号から1引いた数。(0-15)
* @param linkedBoneId 接続先ボーンID。
- * [ 0x0000 - 0xfffe ] に収まらない場合は接続先ボーン無し。
+ * [ 0x0000 - 0xfffe ] に収まらない場合は接続先ボーン無し。
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void pmdRigidInfo(int rigidGroupId,
+ public abstract void pmdRigidInfo(int rigidGroupId,
int linkedBoneId)
throws MmdFormatException;
/**
* 剛体形状の通知を受け取る。
+ *
* <p>{@link #RIGID_LIST}ループの構成要素。
+ *
* @param shapeType 形状種別。
* <ul>
* <li>0x00:球
* @param height 箱orカプセルの高さ
* @param depth 箱の奥行き
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void pmdRigidShape(byte shapeType,
+ public abstract void pmdRigidShape(byte shapeType,
float width, float height, float depth)
throws MmdFormatException;
/**
* 剛体位置の通知を受け取る。
+ *
* <p>{@link #RIGID_LIST}ループの構成要素。
+ *
* @param posX X座標
* @param posY Y座標
* @param posZ Z座標
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void pmdRigidPosition(float posX, float posY, float posZ)
+ public abstract void pmdRigidPosition(float posX, float posY, float posZ)
throws MmdFormatException;
/**
* 剛体姿勢の通知を受け取る。
+ *
* <p>{@link #RIGID_LIST}ループの構成要素。
+ *
* @param radX X軸回転量(radian)
* @param radY Y軸回転量(radian)
* @param radZ Z軸回転量(radian)
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void pmdRigidRotation(float radX, float radY, float radZ)
+ public abstract void pmdRigidRotation(float radX, float radY, float radZ)
throws MmdFormatException;
/**
* 剛体物理系数の通知を受け取る。
+ *
* <p>{@link #RIGID_LIST}ループの構成要素。
+ *
* @param mass 質量
* @param dampingPos 移動減衰率
* @param dampingRot 回転減衰率
* @param restitution 反発力
* @param friction 摩擦力
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void pmdRigidPhysics(float mass,
+ public abstract void pmdRigidPhysics(float mass,
float dampingPos, float dampingRot,
float restitution, float friction )
throws MmdFormatException;
/**
* 剛体の振る舞い情報の通知を受け取る。
+ *
* <p>{@link #RIGID_LIST}ループの構成要素。
+ *
* @param behaveType 剛体タイプ。
* <ul>
* <li>0:ボーン追従
* <li>2:物理演算+ボーン位置合わせ
* </ul>
* @param collisionMap 非衝突剛体グループビットマップ。
- * <p>
- * (衝突グループ番号-1)位置のビット位置は1に、
- * (非衝突グループ番号-1)位置のビット位置は0になる。
- * 例)グループ1と8のみが非衝突指定の場合、0xff7eになる。
+ * <p>(衝突グループ番号-1)位置のビット位置は1に、
+ * (非衝突グループ番号-1)位置のビット位置は0になる。
+ * 例)グループ1と8のみが非衝突指定の場合、0xff7eになる。</p>
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void pmdRigidBehavior(byte behaveType, short collisionMap)
+ public abstract void pmdRigidBehavior(byte behaveType, short collisionMap)
throws MmdFormatException;
}
/**
* PMDモデルの各種形状(頂点、面)の通知用ハンドラ。
+ *
* <p>0から始まる頂点ID順に頂点は出現する。
+ *
* <p>0から始まる面ID順に面は出現する。
*/
public interface PmdShapeHandler extends LoopHandler {
/** 頂点抽出ループ。 */
- ParseStage VERTEX_LIST = new ParseStage();
+ public static final ParseStage VERTEX_LIST = new ParseStage();
/** 面抽出ループ。 */
- ParseStage SURFACE_LIST = new ParseStage();
+ public static final ParseStage SURFACE_LIST = new ParseStage();
/**
* 頂点の座標の通知を受け取る。
+ *
* <p>{@link #VERTEX_LIST}ループの構成要素
+ *
* @param xPos X座標
* @param yPos Y座標
* @param zPos Z座標
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdVertexPosition(float xPos, float yPos, float zPos)
+ public abstract void pmdVertexPosition(float xPos, float yPos, float zPos)
throws MmdFormatException;
/**
* 頂点の法線情報の通知を受け取る。
+ *
* <p>{@link #VERTEX_LIST}ループの構成要素
+ *
* <p>※単位ベクトル化必須?
+ *
* @param xVec 法線ベクトルX成分
* @param yVec 法線ベクトルY成分
* @param zVec 法線ベクトルZ成分
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdVertexNormal(float xVec, float yVec, float zVec)
+ public abstract void pmdVertexNormal(float xVec, float yVec, float zVec)
throws MmdFormatException;
/**
* 頂点のUVマッピング情報の通知を受け取る。
* (頂点UV)
+ *
* <p>{@link #VERTEX_LIST}ループの構成要素
+ *
* @param uVal テクスチャのU座標
* @param vVal テクスチャのV座標
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdVertexUV(float uVal, float vVal )
+ public abstract void pmdVertexUV(float uVal, float vVal )
throws MmdFormatException;
/**
* 頂点のボーン間ウェイトバランス情報の通知を受け取る。
+ *
* <p>{@link #VERTEX_LIST}ループの構成要素
+ *
* @param boneId1 ボーンその1識別ID
* @param boneId2 ボーンその2識別ID
* @param weightForB1 ボーンその1への影響度。0(min)~100(max)
- * ボーンその2への影響度は100からの引き算で求める。
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * ボーンその2への影響度は100からの引き算で求める。
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdVertexWeight(int boneId1, int boneId2, int weightForB1)
+ public abstract void pmdVertexWeight(
+ int boneId1, int boneId2, int weightForB1)
throws MmdFormatException;
/**
* 頂点のエッジ表現情報の通知を受け取る。
* 材質単位でのエッジ表現指定に優先される。
+ *
* <p>{@link #VERTEX_LIST}ループの構成要素
+ *
* @param hideEdge エッジ無効ならtrue
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdVertexEdge(boolean hideEdge)
+ public abstract void pmdVertexEdge(boolean hideEdge)
throws MmdFormatException;
/**
* 3つの頂点から構成される面情報の通知を受け取る。
+ *
* <p>{@link #SURFACE_LIST}ループの構成要素。
+ *
* <p>3頂点の指定順は、面カリングにおいて意味を持つ。
+ *
* @param vertexId1 頂点IDその1
* @param vertexId2 頂点IDその1
* @param vertexId3 頂点IDその1
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdSurfaceTriangle(int vertexId1, int vertexId2, int vertexId3)
+ public abstract void pmdSurfaceTriangle(
+ int vertexId1, int vertexId2, int vertexId3)
throws MmdFormatException;
}
public interface PmdToonHandler extends LoopHandler {
/** トゥーンテクスチャファイル名抽出ループ。 */
- ParseStage TOON_LIST = new ParseStage();
+ public static final ParseStage TOON_LIST = new ParseStage();
/**
* 独自トゥーンテクスチャファイル名の通知を受け取る。
+ *
* <p>{@link #TOON_LIST}ループの構成要素
+ *
* @param toonName 独自トゥーンテクスチャファイル名
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void pmdToonFileInfo(String toonName) throws MmdFormatException;
+ public abstract void pmdToonFileInfo(String toonName)
+ throws MmdFormatException;
}
PmdJointHandler {
/** 何もしない統合ハンドラ。 */
- PmdUnifiedHandler EMPTY =
+ public static final PmdUnifiedHandler EMPTY =
(PmdUnifiedHandler)
( EmptyProxyFactory.buildEmptyProxy(PmdUnifiedHandler.class) );
/**
* PMDモデルファイル(*.pmd)用パーサライブラリ。
+ *
* <p>コールバックインタフェースを実装したオブジェクトをパーサに渡し、
* PMDモデルファイルのパースを開始すると、
* 各種データの出現に応じてコールバックメソッドを次々と呼び出してくれる。
AliasMap(){
super();
- this.primaryAliasMap = new HashMap<String, T>();
- this.globalAliasMap = new HashMap<String, T>();
+ this.primaryAliasMap = new HashMap<>();
+ this.globalAliasMap = new HashMap<>();
return;
}
/**
* NFKC正規化されたUnicode文字列を返す。
+ *
* <p>等価な全半角、濁点、丸付き数字などの表現の正規化を目的とする。
* <ul>
* <li>「ボーン」は「ボーン」になる
* <li>「ホ゛ーン9」は「ボーン9」になる
* </ul>
+ *
* @param name 正規化対象文字列
* @return 正規化済み文字列
*/
/**
* 別名管理オブジェクトを登録。
+ *
* <p>キーとなる名前は、事前にNFKC正規化で
* 揺らぎ表記が吸収されたプライマリ名およびグローバル名。
+ *
* <p>登録キーが衝突した時は後の方が有効となる。
+ *
* @param alias 別名管理オブジェクト
*/
void addAlias(T alias){
/**
* 別名管理オブジェクトと正規化プライマリ名を対応づける。
+ *
* <p>事前にNFKC正規化されたプライマリ名が登録キーとなる。
+ *
* <p>登録キーが衝突した時は後の方が有効となる。
+ *
* @param alias 別名管理オブジェクト
*/
private void addPrimary(T alias){
/**
* 別名管理オブジェクトと正規化グローバル名を対応づける。
+ *
* <p>事前にNFKC正規化されたグローバル名が登録キーとなる。
+ *
* <p>登録キーが衝突した時は後の方が有効となる。
+ *
* @param alias 別名管理オブジェクト
*/
private void addGlobal(T alias){
/**
* 名前から別名管理オブジェクトを得る。
+ *
* <p>プライマリ名、グローバル名の順で検索される。
+ *
* <p>名前は事前にNFKC正規化された後、検索キーとなる。
+ *
* @param name 名前
* @return 別名管理オブジェクト。見つからなければnull
*/
/**
* プライマリ名から別名管理オブジェクトを得る。
+ *
* <p>プライマリ名は事前にNFKC正規化された後、検索キーとなる。
+ *
* @param primaryName プライマリ名
* @return 別名管理オブジェクト。見つからなければnull
*/
/**
* グローバル名から別名管理オブジェクトを得る。
+ *
* <p>グローバル名は事前にNFKC正規化された後、検索キーとなる。
+ *
* @param globalName グローバル名
* @return 別名管理オブジェクト。見つからなければnull
*/
/**
* プライマリ名から代表グローバル名を得る。
+ *
* <p>プライマリ名は事前にNFKC正規化された後、検索キーとなる。
+ *
* @param primaryName プライマリ名
* @return 代表グローバル名。見つからなければnull
*/
/**
* グローバル名から代表プライマリ名を得る。
+ *
* <p>グローバル名は事前にNFKC正規化された後、検索キーとなる。
+ *
* @param globalName グローバル名
* @return 代表プライマリ名。見つからなければnull
*/
- String global2primary(String globalName){
+ String global2primary(String globalName){
T alias = getAliasByGlobal(globalName);
if(alias == null) return null;
String primary = alias.getTopPrimaryName();
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
+import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
/**
* 国際化&別名管理オブジェクトの実装基板。
+ *
* <p>別名管理オブジェクトは、
* 各々のリストの先頭が代表名となる、
* プライマリ名の不変リストとグローバル名の不変リストを持つ。
+ *
* <p>国産モデルではプライマリ名に日本語名が収められることが多い。
* プライマリ名は必ず一つ以上なければならない。
+ *
* <p>国産モデルではグローバル名に英語名が収められることが多いが、
* プライマリ名と同一の日本語名が収められている場合も多い。
+ *
* <p>別名管理オブジェクトは、
* インスタンス間での順序を定義するためのオーダー番号を持つ。
*/
public static final Comparator<I18nAlias> ORDER_COMPARATOR =
new OrderComparator();
+ private static final String F_DISALLOW_DOCTYPE_DECL =
+ "http://apache.org/xml/features/disallow-doctype-decl";
+ private static final String F_EXTERNAL_GENERAL_ENTITIES =
+ "http://xml.org/sax/features/external-general-entities";
+ private static final String F_EXTERNAL_PARAMETER_ENTITIES =
+ "http://xml.org/sax/features/external-parameter-entities";
+ private static final String F_LOAD_EXTERNAL_DTD =
+ "http://apache.org/xml/features/nonvalidating/load-external-dtd";
+
private int orderNo;
/**
* コンストラクタ。
+ *
* <p>各初期数が0以下の場合は、
* 状況に応じて伸長する連結リストが用意される。
+ *
* @param primaryNum プライマリ名初期数。
* @param globalNum グローバル名初期数。
*/
super();
if(primaryNum <= 0){
- this.primaryNameList = new LinkedList<String>();
+ this.primaryNameList = new LinkedList<>();
}else{
- this.primaryNameList = new ArrayList<String>(primaryNum);
+ this.primaryNameList = new ArrayList<>(primaryNum);
}
if(globalNum <= 0){
- this.globalNameList = new LinkedList<String>();
+ this.globalNameList = new LinkedList<>();
}else{
- this.globalNameList = new ArrayList<String>(globalNum);
+ this.globalNameList = new ArrayList<>(globalNum);
}
this.umodPrimaryNameList =
/**
* コンストラクタ。
+ *
* <p>プライマリ名、グローバル名共、
* 状況に応じて伸長する連結リストが用意される。
*/
DocumentBuilderFactory factory;
factory = DocumentBuilderFactory.newInstance();
+ factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ factory.setFeature(F_EXTERNAL_GENERAL_ENTITIES, false);
+ factory.setFeature(F_EXTERNAL_PARAMETER_ENTITIES, false);
+ factory.setFeature(F_LOAD_EXTERNAL_DTD, false);
+
+ // unsafe but we use DOCTYPE
+ factory.setFeature(F_DISALLOW_DOCTYPE_DECL, false);
+
+ factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+ factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+
+ factory.setXIncludeAware(false);
+ factory.setExpandEntityReferences(false);
+
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(is);
/**
* プライマリ名の代表をひとつ返す。
+ *
* <p>必ず存在しなければならない。
+ *
* @return 最初のプライマリ名
*/
public String getTopPrimaryName(){
/**
* 一般的な標準ボーン構成に関する情報。
+ *
* <p>各ボーン情報はひとつ以上のプライマリ名(≒日本語名)と
* ゼロ個以上のグローバル名(≒英語名)を持つ。
+ *
* <p>選択基準は独断。
+ *
* <p>和英対訳はMMD Ver7.39の同梱モデルにほぼ準拠。
*/
public final class TypicalBone extends I18nAlias {
private static final String ATTR_NAME = "name";
private static final List<TypicalBone> BONE_LIST =
- new LinkedList<TypicalBone>();
+ new LinkedList<>();
private static final AliasMap<TypicalBone> BONE_ALIAS_MAP =
- new AliasMap<TypicalBone>();
+ new AliasMap<>();
private static final List<TypicalBone> BONE_UNMODLIST =
Collections.unmodifiableList(BONE_LIST);
Element top;
try{
top = I18nAlias.loadXml(is);
- }catch(ParserConfigurationException e){
- throw new ExceptionInInitializerError(e);
- }catch(SAXException e){
- throw new ExceptionInInitializerError(e);
- }catch(IOException e){
+ }catch(ParserConfigurationException | SAXException | IOException e){
throw new ExceptionInInitializerError(e);
}
/**
* コンストラクタ。
+ *
* <p>各初期数が0以下の場合は、
* 状況に応じて伸長する連結リストが用意される。
+ *
* @param primaryNum プライマリ名初期数。
* @param globalNum グローバル名初期数。
*/
/**
* 全ボーン情報に通し番号を付ける。
+ *
* <p>XMLでの定義順が反映される。
*/
private static void numbering(){
/**
* このボーンが親を持たないルートボーンとして扱われる慣習なのか
* 判定する。
+ *
* <p>※「全親」ボーンに関する慣習は無視される。
+ *
* @return 親を持たなければtrue
*/
public boolean isRoot(){
/**
* 一般的な標準モーフに関する情報。
+ *
* <p>各モーフ情報はひとつ以上のプライマリ名(≒日本語名)と
* ゼロ個以上のグローバル名(≒英語名)を持つ。
+ *
* <p>選択基準は独断。
+ *
* <p>和英対訳はMMD Ver7.39の同梱モデルにほぼ準拠。
*/
public final class TypicalMorph extends I18nAlias {
private static final List<TypicalMorph> EMPTY = Collections.emptyList();
private static final Map<MorphType, List<TypicalMorph>> TYPED_MAP =
- new EnumMap<MorphType, List<TypicalMorph>>(MorphType.class);
+ new EnumMap<>(MorphType.class);
private static final AliasMap<TypicalMorph> MORPH_ALIAS_MAP =
- new AliasMap<TypicalMorph>();
+ new AliasMap<>();
static{
Element top;
try{
top = I18nAlias.loadXml(is);
- }catch(ParserConfigurationException e){
- throw new ExceptionInInitializerError(e);
- }catch(SAXException e){
- throw new ExceptionInInitializerError(e);
- }catch(IOException e){
+ }catch(ParserConfigurationException | SAXException | IOException e){
throw new ExceptionInInitializerError(e);
}
/**
* コンストラクタ。
+ *
* <p>各初期数が0以下の場合は、
* 状況に応じて伸長する連結リストが用意される。
+ *
* @param type モーフ種別
* @param primaryNum プライマリ名初期数。
* @param globalNum グローバル名初期数。
NodeList morphList = groupElem.getElementsByTagName(ELEM_MORPH);
int morphNo = morphList.getLength();
List<TypicalMorph> groupedList =
- new ArrayList<TypicalMorph>(morphNo);
+ new ArrayList<>(morphNo);
for(int idx = 0; idx < morphNo; idx++){
Element morphElem = (Element) morphList.item(idx);
/**
* 全モーフ情報に通し番号を付ける。
+ *
* <p>同一グループ内ではXMLでの定義順が反映される。
*/
private static void numbering(){
/**
* IK演算時の回転方向に制限を受ける「ひざボーン」か否か、
* ボーン名で判定する。
+ *
* <p>ボーンのプライマリ名が「左ひざ」もしくは「右ひざ」で始まれば
* ひざボーンとする。
+ *
* <p>ひざボーン名の例
* <ul>
* <li>「左ひざ」
* <li>「左ひざげり」
* </ul>
+ *
* <p>ひざボーン名ではない例
* <ul>
* <li>「左ひ」
* <li>「左膝」
* <li>「Knee_L」
* </ul>
+ *
* @param boneNameJp プライマリボーン名
* @return ひざボーンならtrue
*/
/**
* MMDコミュニティにおける一般的な慣例に関する情報を提供する。
+ *
* <p>例)ボーン名やモーフ名の一般的な名前、対訳など
+ *
* <p>MikuMikuDance Ver.7.39同梱のモデルなどが主な情報源。
*/
public interface FrameNumbered {
/** 昇順での比較子。 */
- Comparator<FrameNumbered> COMPARATOR = new FrameComparator();
+ public static final Comparator<FrameNumbered> COMPARATOR =
+ new FrameComparator();
/**
* フレーム番号を設定する。
* @param num フレーム番号
*/
- void setFrameNumber(int num);
+ public abstract void setFrameNumber(int num);
/**
* フレーム番号を返す。
* @return フレーム番号
*/
- int getFrameNumber();
+ public abstract int getFrameNumber();
/**
* フレーム番号の昇順を定義づける。
*/
@SuppressWarnings("serial")
- class FrameComparator
+ public static class FrameComparator
implements Comparator<FrameNumbered> {
/**
/**
* IK ON/OFFスイッチ用ボーン名最大長。バイト単位。
+ *
* <p>※MikuMikuDance Ver7.40からの機能。
+ *
* <p>モーション指定用ボーン名と長さが違うので注意。
*/
public static final int IKSWBONENAME_MAX = 20;
/**
* カメラやライティングなどのステージ演出データの可能性があるか、
* モデル名から推測する。
+ *
* <p>モデル名が「カメラ・照明」である場合、
* そのモーションファイルはほぼ
* カメラ・ライティング用ステージ演出データであると推測される。
+ *
* @param modelName モデル名
* @return モデル名にカメラもしくはライティングの可能性があるならtrue
*/
/**
* VMDモーションファイルの基本情報(ボーンモーション/モーフモーション)
* の通知用ハンドラ。
+ *
* <p>フレーム番号は相対的なものとなる。
* 一番若いモーションのフレーム番号が0となる模様。
+ *
* <p>位置情報の座標基準は左手系ワールド座標で表される。
+ *
* <p>モーション補間情報は三次ベジェ曲線により記述される。
* 三次ベジェ曲線は4つの制御点P0,P1,P2,P3により定義される。
* P0は(0,0)、P3は(127,127)で固定。
* P1,P2はP0,P3を対角線とする正方形の内部になければならない。
* 直線補間の場合、P1には(20,20)、P2には(107,107)が使われることが多い。
+ *
* <p>補間情報は直後のボーンモーション情報との差分に関するもの。
*/
public interface VmdBasicHandler extends LoopHandler {
/** ボーンモーション抽出ループ識別子。 */
- ParseStage BONEMOTION_LIST = new ParseStage();
+ public static final ParseStage BONEMOTION_LIST = new ParseStage();
/** モーフ抽出ループ識別子。 */
- ParseStage MORPH_LIST = new ParseStage();
+ public static final ParseStage MORPH_LIST = new ParseStage();
/**
* VMDファイルのパース処理開始の通知を受け取る。
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdParseStart()
+ public abstract void vmdParseStart()
throws MmdFormatException;
/**
* VMDファイルのパース処理終了の通知を受け取る。
- * @param hasMoreData 入力ソースに
- * まだ読み込まれていないデータがあればtrue
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @param hasMoreData
+ * 入力ソースにまだ読み込まれていないデータがあればtrue
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdParseEnd(boolean hasMoreData)
+ public abstract void vmdParseEnd(boolean hasMoreData)
throws MmdFormatException;
/**
* VMDファイルの固定長ヘッダを通知する。
* @param header ヘッダ情報
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdHeaderInfo(byte[] header)
+ public abstract void vmdHeaderInfo(byte[] header)
throws MmdFormatException;
/**
* モーションの適用先モデル名に関する情報を通知する。
+ *
* <p>カメラやライティングなどの演出データには
* 特殊なモデル名が使われる。
+ *
* @param modelName モデル名
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdModelName(String modelName)
+ public abstract void vmdModelName(String modelName)
throws MmdFormatException;
/**
* ボーンモーションのボーン名及びキーフレーム番号に関する情報を通知する。
+ *
* <p>{@link #BONEMOTION_LIST}ループの構成要素。
+ *
* @param boneName ボーン名
* @param keyFrameNo キーフレーム番号
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdBoneMotion(String boneName, int keyFrameNo)
+ public abstract void vmdBoneMotion(String boneName, int keyFrameNo)
throws MmdFormatException;
/**
* ボーン移動モーション情報の通知を受け取る。
+ *
* <p>座標基準は親ボーンもしくはワールド座標。
+ *
* <p>{@link #BONEMOTION_LIST}ループの構成要素。
+ *
* @param xPos X座標
* @param yPos Y座標
* @param zPos Z座標
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdBonePosition(float xPos, float yPos, float zPos)
+ public abstract void vmdBonePosition(float xPos, float yPos, float zPos)
throws MmdFormatException;
/**
* ボーン回転モーション情報の通知を受け取る。
+ *
* <p>回転及び姿勢はクォータニオンによって記述される。
* MMDUI上のボーン数値入力YXZオイラー角と等価な回転。
+ *
* <p>座標基準は親ボーンもしくはワールド座標。
+ *
* <p>※ボーン種別によっては、無意味な情報。
+ *
* <p>{@link #BONEMOTION_LIST}ループの構成要素。
+ *
* @param qx クォータニオン虚部 X
* @param qy クォータニオン虚部 Y
* @param qz クォータニオン虚部 Z
* @param qw クォータニオン実部 W
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdBoneRotationQt(float qx, float qy, float qz, float qw)
+ public abstract void vmdBoneRotationQt(
+ float qx, float qy, float qz, float qw)
throws MmdFormatException;
/**
* ボーンモーションX軸移動補間情報の通知を受け取る。
+ *
* <p>三次ベジェ曲線のP1,P2点に関する情報を受け取る。
+ *
* <p>{@link #BONEMOTION_LIST}ループの構成要素。
+ *
* @param xP1x P1点のX座標
* @param xP1y P1点のY座標
* @param xP2x P2点のX座標
* @param xP2y P2点のY座標
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdBoneIntpltXpos(byte xP1x, byte xP1y, byte xP2x, byte xP2y)
+ public abstract void vmdBoneIntpltXpos(
+ byte xP1x, byte xP1y, byte xP2x, byte xP2y)
throws MmdFormatException;
/**
* ボーンモーションY軸移動補間情報の通知を受け取る。
+ *
* <p>三次ベジェ曲線のP1,P2点に関する情報を受け取る。
+ *
* <p>{@link #BONEMOTION_LIST}ループの構成要素。
+ *
* @param yP1x P1点のX座標
* @param yP1y P1点のY座標
* @param yP2x P2点のX座標
* @param yP2y P2点のY座標
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdBoneIntpltYpos(byte yP1x, byte yP1y, byte yP2x, byte yP2y)
+ public abstract void vmdBoneIntpltYpos(
+ byte yP1x, byte yP1y, byte yP2x, byte yP2y)
throws MmdFormatException;
/**
* ボーンモーションZ軸移動補間情報の通知を受け取る。
+ *
* <p>三次ベジェ曲線のP1,P2点に関する情報を受け取る。
+ *
* <p>{@link #BONEMOTION_LIST}ループの構成要素。
+ *
* @param zP1x P1点のX座標
* @param zP1y P1点のY座標
* @param zP2x P2点のX座標
* @param zP2y P2点のY座標
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdBoneIntpltZpos(byte zP1x, byte zP1y, byte zP2x, byte zP2y)
+ public abstract void vmdBoneIntpltZpos(
+ byte zP1x, byte zP1y, byte zP2x, byte zP2y)
throws MmdFormatException;
/**
* ボーンモーション回転量補間情報の通知を受け取る。
+ *
* <p>三次ベジェ曲線のP1,P2点に関する情報を受け取る。
+ *
* <p>{@link #BONEMOTION_LIST}ループの構成要素。
+ *
* <p>クォータニオン間のslerp処理に利用される。
+ *
* @param rP1x P1点のX座標
* @param rP1y P1点のY座標
* @param rP2x P2点のX座標
* @param rP2y P2点のY座標
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdBoneIntpltRot(byte rP1x, byte rP1y, byte rP2x, byte rP2y)
+ public abstract void vmdBoneIntpltRot(
+ byte rP1x, byte rP1y, byte rP2x, byte rP2y)
throws MmdFormatException;
/**
* モーフモーション情報の通知を受け取る。
+ *
* <p>{@link #MORPH_LIST}ループの構成要素。
+ *
* @param morphName モーフ名。特殊モーフ名「base」は無視してもよい?
* @param keyFrameNo フレーム番号
* @param flex モーフ変量。通常は0.0以上1.0以下。
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdMorphMotion(String morphName, int keyFrameNo, float flex)
+ public abstract void vmdMorphMotion(
+ String morphName, int keyFrameNo, float flex)
throws MmdFormatException;
}
/**
* VMDモーションファイルの基本部パーサ。
+ *
* <p>ボーンのモーション情報およびモーフモーション情報のパース処理を含む。
*/
class VmdBasicParser extends ProxyParser{
this.handler.vmdBoneIntpltXpos(xP1x, xP1y, xP2x, xP2y);
this.handler.vmdBoneIntpltYpos(yP1x, yP1y, yP2x, yP2y);
this.handler.vmdBoneIntpltZpos(zP1x, zP1y, zP2x, zP2y);
- this.handler.vmdBoneIntpltRot (rP1x, rP1y, rP2x, rP2y);
+ this.handler.vmdBoneIntpltRot( rP1x, rP1y, rP2x, rP2y);
return;
}
/**
* 補間情報の冗長箇所の整合性チェックを行う。
+ *
* <p>※ MMDの版数によって微妙に詳細が異なる場合がある。
+ *
* @throws MmdFormatException 冗長箇所の不整合を検出した。
*/
private void checkIntpltStrict() throws MmdFormatException{
/**
* VMDモーションファイルの各種ON/OFF情報(モデル表示・IK有効無効)
* の通知用ハンドラ。
+ *
* <p>MikuMikuDance Ver7.40よりVMDファイルに導入された新仕様。
*/
public interface VmdBoolHandler extends LoopHandler {
/** モデル表示スイッチ抽出ループ識別子。 */
- ParseStage MODELSIGHT_LIST = new ParseStage();
+ public static final ParseStage MODELSIGHT_LIST = new ParseStage();
/** IK有効スイッチ抽出ループ識別子。 */
- ParseStage IKSW_LIST = new ParseStage();
+ public static final ParseStage IKSW_LIST = new ParseStage();
/**
* モデルの表示フラグを通知する。
+ *
* <p>{@link #MODELSIGHT_LIST}ループの構成要素。
+ *
* @param show モデルの表示が行われる場合true
* @param keyFrameNo キーフレーム番号
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdModelSight(boolean show, int keyFrameNo)
+ public abstract void vmdModelSight(boolean show, int keyFrameNo)
throws MmdFormatException;
/**
* IKボーン別のIK処理のON/OFFを通知する。
+ *
* <p>{@link #MODELSIGHT_LIST}ループの下位
* {@link #IKSW_LIST}ループの構成要素。
+ *
* @param boneName IKボーン名
* @param validIk IK処理が無効になる場合false
* @param keyFrameNo キーフレーム番号
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdIkSwitch(String boneName, boolean validIk, int keyFrameNo)
+ public abstract void vmdIkSwitch(
+ String boneName, boolean validIk, int keyFrameNo)
throws MmdFormatException;
}
/**
* VMDモーションファイルの各種ON/OFF情報(モデル表示・IK有効無効)
* パーサ。
+ *
* <p>MikuMikuDance Ver7.40以降でサポート
*/
class VmdBoolParser extends ProxyParser {
/**
* VMDモーションファイルのカメラワーク情報の通知用ハンドラ。
+ *
* <p>フレーム番号は相対的なものとなる。
* カメラ・照明・シャドウのうち
* 一番若いモーションのフレーム番号が0となる模様。
+ *
* <p>ターゲット位置、カメラ回転量とも、座標基準はワールド座標。
+ *
* <p>カメラターゲットの座標は左手系で表される。
+ *
* <p>ターゲットに対するカメラ位置は極座標で表される。
+ *
* <p>補間情報は直前カメラ情報との差分に関するもの。
*/
public interface VmdCameraHandler extends LoopHandler {
/** カメラデータ抽出ループ識別子。 */
- ParseStage CAMERA_LIST = new ParseStage();
+ public static final ParseStage CAMERA_LIST = new ParseStage();
/**
* カメラモーションのキーフレーム番号に関する情報を通知する。
+ *
* <p>{@link #CAMERA_LIST}ループの構成要素。
+ *
* @param keyFrameNo キーフレーム番号
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdCameraMotion(int keyFrameNo)
+ public abstract void vmdCameraMotion(int keyFrameNo)
throws MmdFormatException;
/**
* ターゲットとカメラ間の距離情報を通知する。
+ *
* <p>球座標(極座標)の動径に相当する。
* 通常はターゲットより手前に位置するカメラまでの距離が負の値で渡される。
+ *
* <p>カメラ位置がターゲットを突き抜けた場合は正の値もとりうる。
* ※MMDのUIと符号が逆なので注意。
+ *
* <p>{@link #CAMERA_LIST}ループの構成要素。
+ *
* @param range 距離
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void vmdCameraRange(float range)
+ public abstract void vmdCameraRange(float range)
throws MmdFormatException;
/**
* カメラのターゲット位置情報を通知する。
+ *
* <p>{@link #CAMERA_LIST}ループの構成要素。
+ *
* @param xPos ターゲットのX座標
* @param yPos ターゲットのY座標
* @param zPos ターゲットのZ座標
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void vmdCameraPosition(float xPos, float yPos, float zPos)
+ public abstract void vmdCameraPosition(float xPos, float yPos, float zPos)
throws MmdFormatException;
/**
* カメラの回転および回転量情報を通知する。
+ *
* <p>極座標(球座標)が用いられる。
+ *
* <p>180度を超える値も回転量として意味を持つ。
+ *
* <p>{@link #CAMERA_LIST}ループの構成要素。
+ *
* @param latitude ターゲットから見たカメラの仰俯角(≒緯度)。
- * 単位はラジアン。
- * <p>Y軸回転量が0の時のZ正軸がY正軸へ倒れる方向が正回転。
- * (MMDのUIとは符号が逆になるので注意)
- * <p>仰俯角が0の場合、
- * カメラはターゲットに対しXZ平面(水平)と平行な箇所に位置する。
+ * 単位はラジアン。
+ *
+ * <p>Y軸回転量が0の時のZ正軸がY正軸へ倒れる方向が正回転。
+ * (MMDのUIとは符号が逆になるので注意)</p>
+ *
+ * <p>仰俯角が0の場合、
+ * カメラはターゲットに対しXZ平面(水平)と平行な箇所に位置する。</p>
+ *
* @param longitude Y軸周りの回転量(≒経度)。単位はラジアン。
- * <p>X正軸がZ正軸へ倒れる方向が正回転。(ボーン回転と逆)
- * <p>仰俯角およびY軸回転量が0の場合、
- * カメラレンズはZ軸-∞方向からZ軸+∞方向を向く。
+ *
+ * <p>X正軸がZ正軸へ倒れる方向が正回転。(ボーン回転と逆)</p>
+ *
+ * <p>仰俯角およびY軸回転量が0の場合、
+ * カメラレンズはZ軸-∞方向からZ軸+∞方向を向く。</p>
+ *
* @param roll レンズをターゲットを向けたカメラのロール回転量。
- * <p>仰俯角とY軸回転量が0の時にY正軸がX正軸に倒れる方向が正回転。
- * <p>仰俯角およびロール回転量が0の場合、カメラ上部はY軸+∞の方を向く。
+ *
+ * <p>仰俯角とY軸回転量が0の時に
+ * Y正軸がX正軸に倒れる方向が正回転。</p>
+ *
+ * <p>仰俯角およびロール回転量が0の場合、
+ * カメラ上部はY軸+∞の方を向く。</p>
+ *
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void vmdCameraRotation(float latitude, float longitude, float roll)
+ public abstract void vmdCameraRotation(
+ float latitude, float longitude, float roll)
throws MmdFormatException;
/**
* カメラを通じたスクリーン座標への投影に関する情報を通知する。
+ *
* <p>{@link #CAMERA_LIST}ループの構成要素。
+ *
* @param angle 縦画角。単位は度数法。MMDのUIでは1から125が指定可能。
* @param hasPerspective パースペクティブスイッチがONならtrue。
- * スイッチがOFFの場合、画角は無視され遠近感処理が行われなくなる。
- * (平行投影?)
+ * スイッチがOFFの場合、画角は無視され遠近感処理が行われなくなる。
+ * (平行投影?)
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void vmdCameraProjection(int angle, boolean hasPerspective)
+ public abstract void vmdCameraProjection(
+ int angle, boolean hasPerspective)
throws MmdFormatException;
/**
* カメラターゲットX軸移動補間情報の通知を受け取る。
* 三次ベジェ曲線のP1,P2点に関する情報を受け取る。
+ *
* <p>{@link #CAMERA_LIST}ループの構成要素。
+ *
* @param p1x P1点のX座標
* @param p1y P1点のY座標
* @param p2x P2点のX座標
* @param p2y P2点のY座標
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void vmdCameraIntpltXpos(byte p1x, byte p1y, byte p2x, byte p2y)
+ public abstract void vmdCameraIntpltXpos(
+ byte p1x, byte p1y, byte p2x, byte p2y)
throws MmdFormatException;
/**
* カメラターゲットY軸移動補間情報の通知を受け取る。
* 三次ベジェ曲線のP1,P2点に関する情報を受け取る。
+ *
* <p>{@link #CAMERA_LIST}ループの構成要素。
+ *
* @param p1x P1点のX座標
* @param p1y P1点のY座標
* @param p2x P2点のX座標
* @param p2y P2点のY座標
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void vmdCameraIntpltYpos(byte p1x, byte p1y, byte p2x, byte p2y)
+ public abstract void vmdCameraIntpltYpos(
+ byte p1x, byte p1y, byte p2x, byte p2y)
throws MmdFormatException;
/**
* カメラターゲットZ軸移動補間情報の通知を受け取る。
* 三次ベジェ曲線のP1,P2点に関する情報を受け取る。
+ *
* <p>{@link #CAMERA_LIST}ループの構成要素。
+ *
* @param p1x P1点のX座標
* @param p1y P1点のY座標
* @param p2x P2点のX座標
* @param p2y P2点のY座標
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void vmdCameraIntpltZpos(byte p1x, byte p1y, byte p2x, byte p2y)
+ public abstract void vmdCameraIntpltZpos(
+ byte p1x, byte p1y, byte p2x, byte p2y)
throws MmdFormatException;
/**
* カメラ回転量補間情報の通知を受け取る。
* 三次ベジェ曲線のP1,P2点に関する情報を受け取る。
+ *
* <p>{@link #CAMERA_LIST}ループの構成要素。
+ *
* <p>カメラ回転でクォータニオン補間は使われない。
+ *
* @param p1x P1点のX座標
* @param p1y P1点のY座標
* @param p2x P2点のX座標
* @param p2y P2点のY座標
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void vmdCameraIntpltRotation(byte p1x, byte p1y, byte p2x, byte p2y)
+ public abstract void vmdCameraIntpltRotation(
+ byte p1x, byte p1y, byte p2x, byte p2y)
throws MmdFormatException;
/**
* カメラ-ターゲット間距離補間情報の通知を受け取る。
* 三次ベジェ曲線のP1,P2点に関する情報を受け取る。
+ *
* <p>{@link #CAMERA_LIST}ループの構成要素。
+ *
* @param p1x P1点のX座標
* @param p1y P1点のY座標
* @param p2x P2点のX座標
* @param p2y P2点のY座標
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void vmdCameraIntpltRange(byte p1x, byte p1y, byte p2x, byte p2y)
+ public abstract void vmdCameraIntpltRange(
+ byte p1x, byte p1y, byte p2x, byte p2y)
throws MmdFormatException;
/**
* スクリーン投影補間情報の通知を受け取る。
* 三次ベジェ曲線のP1,P2点に関する情報を受け取る。
+ *
* <p>{@link #CAMERA_LIST}ループの構成要素。
+ *
* @param p1x P1点のX座標
* @param p1y P1点のY座標
* @param p2x P2点のX座標
* @param p2y P2点のY座標
* @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * パース処理の中断をパーサに指示
*/
- void vmdCameraIntpltProjection(byte p1x, byte p1y, byte p2x, byte p2y)
+ public abstract void vmdCameraIntpltProjection(
+ byte p1x, byte p1y, byte p2x, byte p2y)
throws MmdFormatException;
}
assert idx == this.etcIntplt.length;
- this.handler.vmdCameraIntpltRotation (rP1x, rP1y, rP2x, rP2y);
- this.handler.vmdCameraIntpltRange (dP1x, dP1y, dP2x, dP2y);
+ this.handler.vmdCameraIntpltRotation( rP1x, rP1y, rP2x, rP2y);
+ this.handler.vmdCameraIntpltRange( dP1x, dP1y, dP2x, dP2y);
this.handler.vmdCameraIntpltProjection(pP1x, pP1y, pP2x, pP2y);
return;
/**
* VMDモーションファイルのライティング情報(照明光源・セルフシャドウ)
* の通知用ハンドラ。
+ *
* <p>フレーム番号は相対的なものとなる。
* カメラ・照明・シャドウのうち
* 一番若いモーションのフレーム番号が0となる模様。
public interface VmdLightingHandler extends LoopHandler {
/** 照明光源データ抽出ループ識別子。 */
- ParseStage LUMINOUS_LIST = new ParseStage();
+ public static final ParseStage LUMINOUS_LIST = new ParseStage();
/** セルフシャドウデータ抽出ループ識別子。 */
- ParseStage SHADOW_LIST = new ParseStage();
+ public static final ParseStage SHADOW_LIST = new ParseStage();
/**
* 照明情報のキーフレーム番号に関する情報を通知する。
+ *
* <p>{@link #LUMINOUS_LIST}ループの構成要素。
+ *
* @param keyFrameNo キーフレーム番号
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdLuminousMotion(int keyFrameNo)
+ public abstract void vmdLuminousMotion(int keyFrameNo)
throws MmdFormatException;
/**
* 光源の色情報を通知する。
+ *
* <p>色情報はRGB色空間で記述される。
+ *
* <p>MMDのUI上の各色成分指定0~255定義域に便宜上256を追加したものが、
* 0.0以上1.0以下にマップされる。
* <ul>
* <li>128は正しく0.5にマップされる。
* <li>255は1.0より少しだけ小さい数にマップされる。
* </ul>
+ *
* <p>{@link #LUMINOUS_LIST}ループの構成要素。
+ *
* @param rVal 赤成分(0.0以上1.0以下)
* @param gVal 緑成分(0.0以上1.0以下)
* @param bVal 青成分(0.0以上1.0以下)
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdLuminousColor(float rVal, float gVal, float bVal)
+ public abstract void vmdLuminousColor(float rVal, float gVal, float bVal)
throws MmdFormatException;
/**
* 光源の方向情報を通知する。
+ *
* <p>照明方向は、
* ワールド座標原点から伸びる方向ベクトルとして記述される。
* この方向ベクトルに向けて、無限遠の光源から照明が当たる。
+ *
* <p>MMDのスライダUI上では各軸成分の定義域は-1.0以上+1.0以下だが、
* さらに絶対値の大きな値を指定することも可能。
+ *
* <p>方向ベクトルの長さは演出上の意味を持たないが、
* キーフレーム間の照明方向の補間に影響を及ぼすかもしれない。
+ *
* <p>方向ベクトルが零ベクトル(0,0,0)の場合、全ポリゴンに影が落ちる。
+ *
* <p>{@link #LUMINOUS_LIST}ループの構成要素。
+ *
* @param xVec 方向ベクトルX軸成分
* @param yVec 方向ベクトルY軸成分
* @param zVec 方向ベクトルZ軸成分
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdLuminousDirection(float xVec, float yVec, float zVec)
+ public abstract void vmdLuminousDirection(
+ float xVec, float yVec, float zVec)
throws MmdFormatException;
/**
* シャドウ演出情報のキーフレーム番号に関する情報を通知する。
+ *
* <p>{@link #SHADOW_LIST}ループの構成要素。
+ *
* @param keyFrameNo キーフレーム番号
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdShadowMotion(int keyFrameNo)
+ public abstract void vmdShadowMotion(int keyFrameNo)
throws MmdFormatException;
/**
* セルフシャドウモードを通知する。
+ *
* <p>{@link #SHADOW_LIST}ループの構成要素。
+ *
* @param shadowMode シャドウモード指定。
* <ul>
* <li>0 : シャドウOFF
* <li>2 : mode2 影描画の質をカメラからの距離に応じて劣化させる
* ことにより、カメラに近いオブジェクトの影描画の質を向上させる。
* </ul>
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdShadowMode(byte shadowMode)
+ public abstract void vmdShadowMode(byte shadowMode)
throws MmdFormatException;
/**
* セルフシャドウの描画対象となるオブジェクトの範囲(カメラからの距離)
* を通知する。
+ *
* <p>通知されるのは幾何的な距離ではない。
* MMDのUI値(カメラからの距離の100倍?)を
* 10万で割った商を0.1から引いた値が通知される。
+ *
* <p>{@link #SHADOW_LIST}ループの構成要素。
+ *
* @param shadowScope 距離情報。
- * @throws MmdFormatException 不正フォーマットによる
- * パース処理の中断をパーサに指示
+ * @throws MmdFormatException
+ * 不正フォーマットによるパース処理の中断をパーサに指示
*/
- void vmdShadowScopeRaw(float shadowScope)
+ public abstract void vmdShadowScopeRaw(float shadowScope)
throws MmdFormatException;
}
/**
* VMDモーションファイルのライティング情報パーサ。
* 照明光源演出データと影演出データを含む。
+ *
* <p>古い版のVMDファイルには影演出データが記述されていない場合がある。
*/
class VmdLightingParser extends ProxyParser {
/**
* ライティングデータのパースと通知。
+ *
* <p>影演出データが無ければ読みに行かない。
+ *
* @throws IOException IOエラー
* @throws MmdFormatException フォーマットエラー
*/
/**
* ボーンモーション補間情報冗長部のチェックを行うか否か設定する。
* デフォルトではチェックを行わない。
+ *
* <p>※MMDVer7.30前後のVMD出力不具合を回避したい場合は、
* オフにするとパースに成功する場合がある。
+ *
* <p>※MMD Ver7.39x64以降はチェック回避必須。
+ *
* @param mode チェックさせたければtrue
*/
public void setRedundantCheck(boolean mode){
VmdBoolHandler {
/** 何もしない統合ハンドラ。 */
- VmdUnifiedHandler EMPTY =
+ public static final VmdUnifiedHandler EMPTY =
(VmdUnifiedHandler)
( EmptyProxyFactory.buildEmptyProxy(VmdUnifiedHandler.class) );
/**
* VMDモーションファイル(*.vmd)用パーサライブラリ。
+ *
* <p>コールバックインタフェースを実装したオブジェクトをパーサに渡し、
* VMDモーションファイルのパースを開始すると、
* 各種データの出現に応じてコールバックメソッドを次々と呼び出してくれる。
/**
* ASCIIコード相当(UCS:Basic-Latin)の文字か否か判定する。
+ *
* <p>※ Basic-Latinには各種制御文字も含まれる。
+ *
* @param ch 判定対象文字
* @return Basic-Latin文字ならtrue
* <a href="http://www.unicode.org/charts/PDF/U0000.pdf">
case CH_GT: escTxt = ">"; break;
case CH_DQ: escTxt = """; break;
case CH_SQ: escTxt = "'"; break;
- default: escTxt = null; break;
+ default: return putRawCh(ch);
}
- if(escTxt != null){
- putRawText(escTxt);
- }else{
- putRawCh(ch);
- }
+ putRawText(escTxt);
return this;
}
*/
public final class DatatypeIo {
+ private static final String XSD_POS_INF = "INF";
+ private static final String XSD_NEG_INF = "-INF";
+ private static final String JAVA_INF = "Infinity";
+
+
/**
* Hidden constructor.
*/
String result;
if(fVal == Float.POSITIVE_INFINITY){
- result = "INF";
+ result = XSD_POS_INF;
}else if(fVal == Float.NEGATIVE_INFINITY){
- result = "-INF";
+ result = XSD_NEG_INF;
}else{
result = String.valueOf(fVal);
}
String trimmed = xsdTrim(xsdVal).toString();
float result;
- if("INF".equals(trimmed)){
+ if(XSD_POS_INF.equals(trimmed)){
result = Float.POSITIVE_INFINITY;
- }else if("-INF".equals(trimmed)){
+ }else if(XSD_NEG_INF.equals(trimmed)){
result = Float.NEGATIVE_INFINITY;
- }else if(trimmed.endsWith("Infinity")){
+ }else if(trimmed.endsWith(JAVA_INF)){
throw new NumberFormatException(trimmed);
}else if(trimmed.contains("x") || trimmed.contains("X")){
// HexFloatingPointLiteral
+++ /dev/null
-/*
- * XML DOM utilities with namespace
- *
- * License : The MIT License
- * Copyright(c) 2011 MikuToga Partners
- */
-
-package jp.sfjp.mikutoga.xml;
-
-import java.text.MessageFormat;
-import java.util.Iterator;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-/**
- * DOMユーティリティ(名前空間対応)。
- * <p>各種名前空間引数にnullが渡された場合、全ての名前空間にマッチする。
- * <p>各種ローカル名引数にnullが渡された場合、全てのローカル名にマッチする。
- * <p>ノードの持つ名前空間がnullの場合、全ての名前空間引数にマッチする。
- */
-public final class DomNsUtils {
-
- private static final String ERRMSG_NOELEM =
- "Elem:[{0}] was not found in Elem:[{1}]";
- private static final String ERRMSG_NOATTR =
- "Attr:[{0}] was not found in Elem:[{1}]";
- private static final String ERRMSG_INVATTR =
- "Invalid attribute form Attr[{0}] Value[{1}]";
-
-
- /**
- * 隠しコンストラクタ。
- */
- private DomNsUtils(){
- assert false;
- throw new AssertionError();
- }
-
-
- /**
- * 名前空間とローカル名が一致するノードか判定する。
- * @param node ノード
- * @param nsuri 名前空間URI
- * @param localName ローカル名。
- * @return ノードの名前空間およびローカル名が一致したらtrue
- */
- public static boolean hasNsLocalNameNode(Node node,
- String nsuri,
- String localName ){
- String nodeLocalName = node.getLocalName();
- String nodeNsUri = node.getNamespaceURI();
-
- if(localName != null){
- if( ! localName.equals(nodeLocalName) ) return false;
- }
-
- if(nsuri != null && nodeNsUri != null){
- if( ! nsuri.equals(nodeNsUri) ) return false;
- }
-
- return true;
- }
-
- /**
- * 名前空間とローカル名が一致する要素か判定する。
- * @param node ノード
- * @param nsuri 名前空間URI
- * @param localName ローカル名。
- * @return 名前空間およびローカル名が一致する要素であればtrue
- */
- public static boolean hasNsLocalNameElem(Node node,
- String nsuri,
- String localName ){
- if(node.getNodeType() != Node.ELEMENT_NODE) return false;
- if( ! hasNsLocalNameNode(node, nsuri, localName) ) return false;
- return true;
- }
-
- /**
- * 親要素が指定された名前の子要素を持つか判定する。
- * @param parent 親要素
- * @param nsuri 名前空間URI
- * @param localName ローカル名
- * @return 指定名の子要素が存在すればtrue
- */
- public static boolean hasChild(Element parent,
- String nsuri,
- String localName ){
- for(Node node = parent.getFirstChild();
- node != null;
- node = node.getNextSibling() ){
-
- if(hasNsLocalNameElem(node, nsuri, localName)){
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * 指定された名前空間とローカル名に合致する最初の直下子要素を返す。
- * @param parent 親要素
- * @param nsuri 名前空間URI
- * @param localName ローカル名
- * @return 最初の直下子要素。見つからなければnull。
- */
- public static Element pickFirstChild(Node parent,
- String nsuri,
- String localName ){
- Node node = parent.getFirstChild();
- while(node != null){
- if(hasNsLocalNameElem(node, nsuri, localName)){
- break;
- }
- node = node.getNextSibling();
- }
- return (Element) node;
- }
-
- /**
- * 指定された名前空間とローカル名に合致する最初の直下子要素を返す。
- * <p>見つからなければ例外を投げる。
- * @param parent 親要素
- * @param nsuri 名前空間URI
- * @param localName ローカル名
- * @return 最初の直下子要素。
- * @throws TogaXmlException 1つも見つからなかった
- */
- public static Element getFirstChild(Element parent,
- String nsuri,
- String localName )
- throws TogaXmlException{
- Element elem = pickFirstChild(parent, nsuri, localName);
-
- if(elem == null){
- String message = MessageFormat.format(ERRMSG_NOELEM,
- localName,
- parent.getLocalName() );
- throw new TogaXmlException(message);
- }
-
- return elem;
- }
-
- /**
- * 指定された名前の子要素のforeachを返す。
- * @param parent 親要素
- * @param nsuri 名前空間URI
- * @param localName 子要素名
- * @return 子要素のforeach
- */
- public static Iterable<Element> getEachChild(final Element parent,
- final String nsuri,
- final String localName ){
- Iterable<Element> result = new Iterable<Element>(){
- @Override
- public Iterator<Element> iterator(){
- return new SiblingElemIterator(parent, nsuri, localName);
- }
- };
- return result;
- }
-
- /**
- * 要素に属性が存在するか判定する。
- * @param elem 要素
- * @param nsuri 名前空間URI
- * @param localName ローカル名
- * @return 存在するならtrue
- */
- public static boolean hasAttrNS(Element elem,
- String nsuri,
- String localName ){
- return elem.hasAttributeNS(nsuri, localName);
- }
-
- /**
- * 要素からxsd:string型属性値を読み取る。
- * @param elem 要素
- * @param nsuri 名前空間URI
- * @param localName 属性名
- * @return 文字列
- * @throws TogaXmlException 属性値が見つからなかった。
- */
- public static String getStringAttrNS(Element elem,
- String nsuri,
- String localName )
- throws TogaXmlException{
- if( ! hasAttrNS(elem, nsuri, localName) ){
- String message = MessageFormat.format(ERRMSG_NOATTR,
- localName,
- elem.getLocalName() );
- throw new TogaXmlException(message);
- }
-
- String result;
- try{
- result = elem.getAttributeNS(nsuri, localName);
- }catch(DOMException e){
- assert false;
- throw new AssertionError(e);
- }
-
- return result;
- }
-
- /**
- * 要素からxsd:boolean型属性値を読み取る。
- * @param elem 要素
- * @param nsuri 名前空間URI
- * @param localName 属性名
- * @return 真ならtrue
- * @throws TogaXmlException 属性値が見つからなかった。
- */
- public static boolean getBooleanAttrNS(Element elem,
- String nsuri,
- String localName )
- throws TogaXmlException{
- String value = getStringAttrNS(elem, nsuri, localName);
-
- boolean result;
- try{
- result = DatatypeIo.parseBoolean(value);
- }catch(IllegalArgumentException e){
- String message = MessageFormat.format(ERRMSG_INVATTR,
- localName,
- value );
- throw new TogaXmlException(message, e);
- }
-
- return result;
- }
-
- /**
- * 要素からxsd:integer型属性値を読み取る。
- * @param elem 要素
- * @param nsuri 名前空間URI
- * @param localName 属性名
- * @return int値
- * @throws TogaXmlException 属性値が見つからなかった。
- */
- public static int getIntegerAttrNS(Element elem,
- String nsuri,
- String localName )
- throws TogaXmlException{
- String value = getStringAttrNS(elem, nsuri, localName);
-
- int result;
- try{
- result = DatatypeIo.parseInt(value);
- }catch(NumberFormatException e){
- String message = MessageFormat.format(ERRMSG_INVATTR,
- localName,
- value );
- throw new TogaXmlException(message, e);
- }
-
- return result;
- }
-
- /**
- * 要素からxsd:float型属性値を読み取る。
- * @param elem 要素
- * @param nsuri 名前空間URI
- * @param localName 属性名
- * @return float値
- * @throws TogaXmlException 属性値が見つからなかった。
- */
- public static float getFloatAttrNS(Element elem,
- String nsuri,
- String localName )
- throws TogaXmlException{
- String value = getStringAttrNS(elem, nsuri, localName);
-
- float result;
- try{
- result = DatatypeIo.parseFloat(value);
- }catch(NumberFormatException e){
- String message = MessageFormat.format(ERRMSG_INVATTR,
- localName,
- value );
- throw new TogaXmlException(message, e);
- }
-
- return result;
- }
-
-}
+++ /dev/null
-/*
- * XML DOM utilities
- *
- * License : The MIT License
- * Copyright(c) 2010 MikuToga Partners
- */
-
-package jp.sfjp.mikutoga.xml;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.NoSuchElementException;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-/**
- * DOMユーティリティ。
- */
-public final class DomUtils {
-
- // 構文解析バグ回避。
- private static final char BS_CHAR = (char) 0x005c;
-
- /**
- * 隠しコンストラクタ。
- */
- private DomUtils(){
- super();
- assert false;
- throw new AssertionError();
- }
-
- /**
- * 要素からxsd:string型属性値を読み取る。
- * @param elem 要素
- * @param attrName 属性名
- * @return 文字列
- * @throws TogaXmlException 属性値が見つからなかった。
- */
- public static String getStringAttr(Element elem, String attrName)
- throws TogaXmlException{
- if( ! elem.hasAttribute(attrName) ){
- String message = "Attr:[" + attrName + "] "
- + "was not found in "
- + "Elem:[" + elem.getTagName()+"]";
- throw new TogaXmlException(message);
- }
-
- String result;
- try{
- result = elem.getAttribute(attrName);
- }catch(IllegalArgumentException e){
- String message = "Invalid attribute form [" + attrName + "]";
- throw new TogaXmlException(message, e);
- }
-
- return result;
- }
-
- /**
- * 要素からxsd:boolean型属性値を読み取る。
- * @param elem 要素
- * @param attrName 属性名
- * @return 真ならtrue
- * @throws TogaXmlException 属性値が見つからなかった。
- */
- public static boolean getBooleanAttr(Element elem, String attrName)
- throws TogaXmlException{
- String value = getStringAttr(elem, attrName);
-
- boolean result;
- try{
- result = DatatypeIo.parseBoolean(value);
- }catch(IllegalArgumentException e){
- String message =
- "Invalid boolean attribute form "
- + "[" + attrName + "][" + value + "]";
- throw new TogaXmlException(message, e);
- }
-
- return result;
- }
-
- /**
- * 要素からxsd:integer型属性値を読み取る。
- * @param elem 要素
- * @param attrName 属性名
- * @return int値
- * @throws TogaXmlException 属性値が見つからなかった。
- */
- public static int getIntegerAttr(Element elem, String attrName)
- throws TogaXmlException{
- String value = getStringAttr(elem, attrName);
-
- int result;
- try{
- result = DatatypeIo.parseInt(value);
- }catch(IllegalArgumentException e){
- String message =
- "Invalid integer attribute form "
- + "[" + attrName + "][" + value + "]";
- throw new TogaXmlException(message, e);
- }
-
- return result;
- }
-
- /**
- * 要素からxsd:float型属性値を読み取る。
- * @param elem 要素
- * @param attrName 属性名
- * @return float値
- * @throws TogaXmlException 属性値が見つからなかった。
- */
- public static float getFloatAttr(Element elem, String attrName)
- throws TogaXmlException{
- String value = getStringAttr(elem, attrName);
-
- float result;
- try{
- result = DatatypeIo.parseFloat(value);
- }catch(IllegalArgumentException e){
- String message =
- "Invalid float attribute form "
- + "[" + attrName + "][" + value + "]";
- throw new TogaXmlException(message, e);
- }
-
- return result;
- }
-
- /**
- * 要素から日本語Windows用ファイル名を属性値として読み取る。
- * 念のため文字U+00A5は文字U-005Cに変換される。
- * @param elem 要素
- * @param attrName 属性名
- * @return ファイル名
- * @throws TogaXmlException 属性値が見つからなかった。
- */
- public static String getSjisFileNameAttr(Element elem, String attrName)
- throws TogaXmlException{
- String result;
- try{
- result = getStringAttr(elem, attrName);
- }catch(IllegalArgumentException e){
- String message =
- "Invalid winfile attribute form "
- + "[" + attrName + "]";
- throw new TogaXmlException(message, e);
- }
-
- result = result.replace("" + '\u00a5', "" + BS_CHAR);
-
- return result;
- }
-
- /**
- * 指定された名前の子要素を1つだけ返す。
- * @param parent 親要素
- * @param tagName 子要素名
- * @return 子要素
- * @throws TogaXmlException 1つも見つからなかった
- */
- public static Element getChild(Element parent, String tagName)
- throws TogaXmlException{
- Element result = null;
-
- for(Node node = parent.getFirstChild();
- node != null;
- node = node.getNextSibling() ){
-
- if(node.getNodeType() != Node.ELEMENT_NODE) continue;
- Element elem = (Element) node;
-
- String elemTagName = elem.getTagName();
- if( tagName.equals(elemTagName) ){
- result = elem;
- break;
- }
- }
-
- if(result == null){
- String message =
- "Elem:[" + tagName + "] was not found in "
- +"Elem:[" + parent.getTagName() + "]";
- throw new TogaXmlException(message);
- }
-
- return result;
- }
-
- /**
- * 親要素が指定された名前の子要素を持つか判定する。
- * @param parent 親要素
- * @param tagName 子要素名
- * @return 指定名の子要素が存在すればtrue
- */
- public static boolean hasChild(Element parent, String tagName){
- for(Node node = parent.getFirstChild();
- node != null;
- node = node.getNextSibling() ){
-
- if(node.getNodeType() != Node.ELEMENT_NODE) continue;
- Element elem = (Element) node;
-
- String elemTagName = elem.getTagName();
- if( tagName.equals(elemTagName) ) return true;
- }
-
- return false;
- }
-
- /**
- * 指定された名前の子要素のリストを返す。
- * @param parent 親要素
- * @param childTag 子要素名
- * @return 子要素のリスト
- */
- public static List<Element> getChildList(Element parent,
- String childTag){
- List<Element> result = new LinkedList<Element>();
-
- for(Node node = parent.getFirstChild();
- node != null;
- node = node.getNextSibling() ){
-
- if(node.getNodeType() != Node.ELEMENT_NODE) continue;
- Element elem = (Element) node;
-
- String tagName = elem.getTagName();
- if( ! childTag.equals(tagName) ) continue;
-
- result.add(elem);
- }
-
- return result;
- }
-
- /**
- * 指定された名前の子要素の列挙子を返す。
- * @param parent 親要素
- * @param childTag 子要素名
- * @return 子要素の列挙子
- */
- public static Iterator<Element> getChildIterator(Element parent,
- String childTag){
- Element firstElem;
- try{
- firstElem = getChild(parent, childTag);
- }catch(TogaXmlException e){
- firstElem = null;
- }
-
- Iterator<Element> result = new ElemIterator(firstElem);
-
- return result;
- }
-
- /**
- * 指定された名前の子要素のforeachを返す。
- * @param parent 親要素
- * @param childTag 子要素名
- * @return 子要素のforeach
- */
- public static Iterable<Element> getEachChild(Element parent,
- String childTag){
- final Iterator<Element> iterator = getChildIterator(parent, childTag);
- Iterable<Element> result = new Iterable<Element>(){
- @Override
- public Iterator<Element> iterator(){
- return iterator;
- }
- };
- return result;
- }
-
- /**
- * 要素の次の要素を返す。
- * @param elem 要素
- * @return 次の要素。なければnull
- */
- public static Element nextElement(Element elem){
- Node nextNode = elem;
- for(;;){
- nextNode = nextNode.getNextSibling();
- if(nextNode == null) break;
- if(nextNode.getNodeType() == Node.ELEMENT_NODE){
- break;
- }
- }
-
- return (Element) nextNode;
- }
-
- /**
- * 同じ要素名を持つ次の要素を返す。
- * @param elem 要素
- * @return 次の要素。なければnull
- */
- public static Element nextNamedElement(Element elem){
- String tagName = elem.getTagName();
- Element nextElem = elem;
- for(;;){
- nextElem = nextElement(nextElem);
- if(nextElem == null) break;
- if(tagName.equals(nextElem.getTagName())) break;
- }
-
- return nextElem;
- }
-
- /**
- * 同じ親要素と同じ要素名を持つ兄弟要素を列挙する列挙子。
- */
- private static final class ElemIterator implements Iterator<Element> {
- private Element next;
-
- /**
- * コンストラクタ。
- * @param elem 最初の要素。nullを指定すれば空列挙子となる。
- */
- ElemIterator(Element elem){
- super();
- this.next = elem;
- }
-
- /**
- * {@inheritDoc}
- * @return {@inheritDoc}
- */
- @Override
- public boolean hasNext(){
- if(this.next == null) return false;
- return true;
- }
-
- /**
- * {@inheritDoc}
- * @return {@inheritDoc}
- * @throws NoSuchElementException {@inheritDoc}
- */
- @Override
- public Element next() throws NoSuchElementException{
- if(this.next == null) throw new NoSuchElementException();
- Element result = this.next;
- this.next = nextNamedElement(this.next);
- return result;
- }
-
- /**
- * {@inheritDoc}
- * ※ 未サポート。
- */
- @Override
- public void remove(){
- throw new UnsupportedOperationException();
- }
-
- }
-
-}
+++ /dev/null
-/*
- * xml local resource map
- *
- * License : The MIT License
- * Copyright(c) 2013 olyutorskii
- */
-
-package jp.sfjp.mikutoga.xml;
-
-import java.net.URI;
-
-/**
- * 代用ローカルリソースの管理を行う。
- * <p>ネットワークを介したグローバルなリソースと、
- * アプリ上のローカルな代用リソースとを対応付ける。
- */
-public interface LocalXmlResource {
-
- /**
- * オリジナル版XMLリソースのURIを返す。
- * @return オリジナル版リソースのURL。
- */
- URI getOriginalResource();
-
- /**
- * ローカル版XMLリソースのURIを返す。
- * @return ローカル版リソースのURL。
- */
- URI getLocalResource();
-
-}
--- /dev/null
+/*
+ * No-operation Entity Resolver for XML.
+ *
+ * License : The MIT License
+ * Copyright(c) 2019 olyutorskii
+ */
+
+package jp.sfjp.mikutoga.xml;
+
+import java.io.Reader;
+import java.io.StringReader;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+
+/**
+ * No-operation Entity Resolver implementation for preventing XXE.
+ *
+ * @see <a href="https://en.wikipedia.org/wiki/XML_external_entity_attack">
+ * XML external entity attack (Wikipedia)
+ * </a>
+ */
+public final class NoopEntityResolver implements EntityResolver{
+
+ /** Singleton resolver. */
+ public static final EntityResolver NOOP_RESOLVER =
+ new NoopEntityResolver();
+
+
+ /**
+ * Constructor.
+ */
+ private NoopEntityResolver(){
+ super();
+ return;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Prevent any external entity reference XXE.
+ *
+ * @param publicId {@inheritDoc}
+ * @param systemId {@inheritDoc}
+ * @return empty input source
+ */
+ @Override
+ public InputSource resolveEntity(String publicId, String systemId){
+ Reader emptyReader = new StringReader("");
+ InputSource source = new InputSource(emptyReader);
+
+ source.setPublicId(publicId);
+ source.setSystemId(systemId);
+
+ return source;
+ }
+
+}
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.MalformedURLException;
import java.net.URI;
+import java.net.URISyntaxException;
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.SchemaFactory;
import org.w3c.dom.ls.LSResourceResolver;
import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
/**
- * XMLスキーマの各種ビルダ。
+ * XML schema (XSD) utilities.
+ *
+ * <p>RELAX NG is not supported.
*/
public final class SchemaUtil {
+
+ /** XML Schema. */
+ public static final String SCHEMA_XML =
+ "http://www.w3.org/2001/xml.xsd";
+
+ /** XSD namespace. */
+ public static final String NS_XSD =
+ "http://www.w3.org/2001/XMLSchema-instance";
+
+ private static final String LOCAL_SCHEMA_XML =
+ "resources/xmlspace.xsd";
+
+ private static final URI URI_XSD_ORIG;
+ private static final URI URI_XSD_LOCAL;
+
+ private static final String ALLOWED_USCHEMA = "http";
+
+ private static final Class<?> THISCLASS = SchemaUtil.class;
+
+
+ static{
+ URL localXsdUrl = THISCLASS.getResource(LOCAL_SCHEMA_XML);
+ URI localXsdUri;
+ try{
+ localXsdUri = localXsdUrl.toURI();
+ }catch(URISyntaxException e){
+ throw new ExceptionInInitializerError(e);
+ }
+
+ URI_XSD_ORIG = URI.create(SCHEMA_XML);
+ URI_XSD_LOCAL = localXsdUri;
+
+ assert ALLOWED_USCHEMA.equalsIgnoreCase(URI_XSD_ORIG.getScheme());
+ }
+
+
/**
- * 隠しコンストラクタ。
+ * Hidden constructor.
*/
private SchemaUtil(){
assert false;
/**
- * XML Schema 用のスキーマファクトリを返す。
- * @return スキーマファクトリ
+ * build xml.xsd redirection info.
+ *
+ * @return resolver
*/
- public static SchemaFactory newSchemaFactory(){
- SchemaFactory result = newSchemaFactory(null);
+ public static XmlResourceResolver buildXmlXsdResolver(){
+ XmlResourceResolver result = new XmlResourceResolver();
+ result.putRedirected(URI_XSD_ORIG, URI_XSD_LOCAL);
return result;
}
/**
- * XML Schema 用のスキーマファクトリを返す。
- * @param resolver カスタムリゾルバ。nullも可。
- * @return スキーマファクトリ
+ * Build SchemaFactory for XML Schema but safety.
+ *
+ * <p>Includes some considerations for XXE vulnerabilities.
+ *
+ * <p>Restrict access to
+ * External Entity Reference & external DTDs
+ * in xml schema file.
+ *
+ * <p>Restrict access to External schema file access in xml schema file,
+ * but HTTP access is allowed.
+ * This special limit considers access to
+ * importing http://www.w3.org/2001/xml.xsd
+ * in top of common xml schema file.
+ *
+ * @return schema factory
*/
- public static SchemaFactory newSchemaFactory(
- LSResourceResolver resolver ){
- SchemaFactory schemaFactory =
- SchemaFactory.newInstance(
- XMLConstants.W3C_XML_SCHEMA_NS_URI
- );
-
-// schemaFactory.setFeature(name, value);
-// schemaFactory.setProperty(name, object);
+ public static SchemaFactory newSchemaFactory(){
+ SchemaFactory schemaFactory;
+ schemaFactory = SchemaFactory.newInstance(
+ XMLConstants.W3C_XML_SCHEMA_NS_URI);
- schemaFactory.setErrorHandler(BotherHandler.HANDLER);
- schemaFactory.setResourceResolver(resolver);
+ try{
+ // Prevent denial-of-service attack.
+ schemaFactory.setFeature(
+ XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ }catch(SAXNotRecognizedException | SAXNotSupportedException e){
+ // THIS FEATURE MUST BE SUPPORTED
+ assert false;
+ }
- return schemaFactory;
- }
+ try{
+ // Disallow external entity reference & external DTD access.
+ schemaFactory.setProperty(
+ XMLConstants.ACCESS_EXTERNAL_DTD, "");
+ // Allow only HTTP external schema file.
+ schemaFactory.setProperty(
+ XMLConstants.ACCESS_EXTERNAL_SCHEMA, ALLOWED_USCHEMA);
+ }catch(SAXNotRecognizedException | SAXNotSupportedException e){
+ // THIS PROPERTY MUST BE SUPPORTED JAXP1.5 or later
+ assert false;
+ }
- /**
- * ローカルリソースを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();
+ LSResourceResolver resolver = buildXmlXsdResolver();
+ schemaFactory.setResourceResolver(resolver);
- InputStream is = localUrl.openStream();
- is = new BufferedInputStream(is);
+ schemaFactory.setErrorHandler(BotherHandler.HANDLER);
- Source result = new StreamSource(is);
- return result;
+ return schemaFactory;
}
/**
- * ローカルリソース群をSource群に変換する。
- * @param resArray ローカルリソースURI並び
- * @return XML Source並び
- * @throws MalformedURLException 不正なURI
- * @throws IOException オープンエラー
+ * pre-load & pre-compile local schema files.
+ *
+ * @param localSchemaUris local schema resources.
+ * @return schema
+ * @throws SAXException invalid schema definition
+ * @throws IOException local resource i/o error
*/
- 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);
+ public static Schema newSchema(URI... localSchemaUris)
+ throws SAXException, IOException{
+ SchemaFactory schemaFactory = newSchemaFactory();
+
+ int uris = localSchemaUris.length;
+ if(uris <= 0){
+ // on-demand xml-schema with schemaLocation attribute.
+ return schemaFactory.newSchema();
}
- 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);
+ InputStream[] iss = new InputStream[uris];
+ for(int idx = 0; idx < uris; idx++){
+ URI localUri = localSchemaUris[idx];
+ URL localUrl = localUri.toURL();
+ InputStream is;
+ is = localUrl.openStream();
+ is = new BufferedInputStream(is);
+ iss[idx] = is;
}
- Source[] sources;
- try{
- sources = toLocalSourceArray(resArray);
- }catch(IOException e){ // ビルド障害
- assert false;
- throw new AssertionError(e);
+ Source[] sources = new Source[uris];
+ for(int idx = 0; idx < uris; idx++){
+ InputStream is = iss[idx];
+ sources[idx] = new StreamSource(is);
}
- SchemaFactory schemaFactory = newSchemaFactory(resolver);
-
Schema result;
try{
- if(sources.length <= 0){
- // ドキュメント埋め込みスキーマURLにリゾルバ経由でアクセス
- result = schemaFactory.newSchema();
- }else{
- result = schemaFactory.newSchema(sources);
+ result = schemaFactory.newSchema(sources);
+ }finally{
+ for(InputStream is : iss){
+ is.close();
}
- }catch(SAXException e){ // Build error
- assert false;
- throw new AssertionError(e);
}
- // TODO: Sourceを閉めるのは誰の責務?
-
return result;
}
+++ /dev/null
-/*
- * sibling element iterator on DOM tree
- *
- * License : The MIT License
- * Copyright(c) 2011 MikuToga Partners
- */
-
-package jp.sfjp.mikutoga.xml;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-/**
- * 兄弟要素間用Iterator。
- * <p>同じ親と名前空間とローカル名を持つ要素同士を「兄弟要素」とする。
- * <p>ノードの持つ名前空間がnullの場合、全ての名前空間引数にマッチする。
- * <p>削除操作は未サポート。
- */
-public class SiblingElemIterator implements Iterator<Element> {
-
- private Element next;
- private final String nsuri;
- private final String localName;
-
-
- /**
- * コンストラクタ。
- * @param first 最初の兄弟要素。nullだと一度もiterateしない。
- */
- public SiblingElemIterator(Element first){
- super();
-
- this.next = first;
-
- if(this.next == null){
- this.nsuri = null;
- this.localName = null;
- }else{
- this.nsuri = this.next.getNamespaceURI();
- this.localName = this.next.getLocalName();
- }
-
- return;
- }
-
- /**
- * コンストラクタ。
- * <p>名前空間引数にnullが渡された場合、全ての名前空間にマッチする。
- * <p>ローカル名引数にnullが渡された場合、全てのローカル名にマッチする。
- * @param parent 親要素
- * @param nsuri 子要素の名前空間URI
- * @param localName 子要素のローカル名
- */
- public SiblingElemIterator(Element parent,
- String nsuri,
- String localName ){
- super();
-
- this.next = DomNsUtils.pickFirstChild(parent, nsuri, localName);
-
- if(this.next == null){
- this.nsuri = null;
- this.localName = null;
- }else{
- this.nsuri = nsuri;
- this.localName = localName;
- }
-
- return;
- }
-
-
- /**
- * {@inheritDoc}
- * @return {@inheritDoc}
- */
- @Override
- public boolean hasNext(){
- if(this.next != null) return true;
- return false;
- }
-
- /**
- * {@inheritDoc}
- * @return {@inheritDoc}
- * @throws NoSuchElementException {@inheritDoc}
- */
- @Override
- public Element next() throws NoSuchElementException {
- if(this.next == null) throw new NoSuchElementException();
-
- Element result = this.next;
-
- Node sibNode = result;
- do{
- sibNode = sibNode.getNextSibling();
- if(sibNode == null) break;
- }while( ! matchElemName(sibNode) );
- this.next = (Element) sibNode;
-
- return result;
- }
-
- /**
- * 兄弟要素にふさわしい名前を持つか判定する。
- * @param node 判定対象
- * @return 兄弟にふさわしい名前を持つならtrue
- */
- private boolean matchElemName(Node node){
- return DomNsUtils.hasNsLocalNameElem(node,
- this.nsuri, this.localName );
- }
-
- /**
- * {@inheritDoc}
- * ※削除不可。
- * @throws UnsupportedOperationException 削除を試みたので失敗した
- */
- @Override
- public void remove() throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
-}
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putRawCh(char ch) throws IOException;
+ public abstract XmlExporter putRawCh(char ch) throws IOException;
/**
* 文字列を生出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putRawText(CharSequence seq) throws IOException;
+ public abstract XmlExporter putRawText(CharSequence seq)
+ throws IOException;
/**
* 空白を出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter sp() throws IOException;
+ public abstract XmlExporter sp() throws IOException;
/**
* 空白を指定回数出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter sp(int count) throws IOException;
+ public abstract XmlExporter sp(int count) throws IOException;
/**
* 改行文字列を返す。
* @return 改行文字列
*/
- String getNewLine();
+ public abstract String getNewLine();
/**
* 改行文字列を設定する。
* @param newLine 改行文字列
* @throws NullPointerException 引数がnull
*/
- void setNewLine(String newLine) throws NullPointerException;
+ public abstract void setNewLine(String newLine)
+ throws NullPointerException;
/**
* 改行を出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter ln() throws IOException;
+ public abstract XmlExporter ln() throws IOException;
/**
* 改行を指定回数出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter ln(int count) throws IOException;
+ public abstract XmlExporter ln(int count) throws IOException;
/**
* インデント単位文字列を返す。
* @return インデント単位文字列
*/
- String getIndentUnit();
+ public abstract String getIndentUnit();
/**
* インデント単位文字列を設定する。
+ *
* <p>デフォルトでは空白2個。
+ *
* @param indUnit インデント単位文字列。
* @throws NullPointerException 引数がnull
*/
- void setIndentUnit(String indUnit) throws NullPointerException;
+ public abstract void setIndentUnit(String indUnit)
+ throws NullPointerException;
/**
* インデントレベルを一段下げる。
*/
- void pushNest();
+ public abstract void pushNest();
/**
* インデントレベルを一段上げる。
* インデントレベル0の状態をさらに上げようとした場合、何も起こらない。
*/
- void popNest();
+ public abstract void popNest();
/**
* インデントレベルを返す。
+ *
* <p>深さ1の場合1を返す。
+ *
* @return インデントレベル
*/
- int getIndentLevel();
+ public abstract int getIndentLevel();
/**
* インデントを出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter ind() throws IOException;
+ public abstract XmlExporter ind() throws IOException;
/**
* BasicLatin文字だけを出力する状態か判定する。
+ *
* <p>コメント部中身は対象外。
+ *
* @return BasicLatin文字だけで出力するならtrue
*/
- boolean isBasicLatinOnlyOut();
+ public abstract boolean isBasicLatinOnlyOut();
/**
* BasicLatin文字だけで出力するか設定する。
+ *
* <p>BasicLatin以外の文字(≒日本語)を、そのまま出力するか、
* 文字参照で出力するか、の設定が可能。
+ *
* <p>コメント部中身は対象外。
+ *
* @param bool BasicLatin文字だけで出力するならtrue
*/
- void setBasicLatinOnlyOut(boolean bool);
+ public abstract void setBasicLatinOnlyOut(boolean bool);
/**
* 指定された文字を16進2桁の文字参照形式で出力する。
+ *
* <p>「A」は「&#x41;」になる。
+ *
* <p>2桁で出力できない場合(>0x00ff)は4桁で出力する。
+ *
* @param ch 文字
* @return this本体
* @throws IOException 出力エラー
* W3C XML1.1 Character Reference
* </a>
*/
- XmlExporter putCharRef2Hex(char ch) throws IOException;
+ public abstract XmlExporter putCharRef2Hex(char ch) throws IOException;
/**
* 指定された文字を16進4桁の文字参照形式で出力する。
+ *
* <p>「亜」は「&#x4E9C;」になる。
+ *
* <p>UCS4に伴うサロゲートペアは未サポート
+ *
* @param ch 文字
* @return this本体
* @throws IOException 出力エラー
* W3C XML1.1 Character Reference
* </a>
*/
- XmlExporter putCharRef4Hex(char ch) throws IOException;
+ public abstract XmlExporter putCharRef4Hex(char ch) throws IOException;
/**
* 要素の中身および属性値中身を出力する。
+ *
* <p>XMLの構文規則を守る上で必要な各種エスケープ処理が行われる。
+ *
* @param ch 文字
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putCh(char ch) throws IOException;
+ public abstract 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;
+ public abstract XmlExporter putContent(CharSequence content)
+ throws IOException;
/**
* コメントの内容を出力する。
+ *
* <p>コメント中の'\n'記号出現に伴い、
* あらかじめ指定された改行文字が出力される。
+ *
* <p>コメント中の'\n'以外のコントロールコードは
* Control Pictures(U+2400〜)で代替される。
+ *
* <p>それ以外の非BasicLatin文字はそのまま出力される。
+ *
* <p>連続するハイフン(-)記号間には強制的にスペースが挿入される。
+ *
* @param comment コメント内容
* @return this本体
* @throws IOException 出力エラー
* Unicode 6.2 Controll Pictures
* </a>
*/
- XmlExporter putCommentContent(CharSequence comment) throws IOException;
+ public abstract XmlExporter putCommentContent(CharSequence comment)
+ throws IOException;
/**
* 1行コメントを出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putLineComment(CharSequence comment) throws IOException;
+ public abstract XmlExporter putLineComment(CharSequence comment)
+ throws IOException;
/**
* ブロックコメントを出力する。
+ *
* <p>コメント内部の頭の前に改行が出力される。
+ *
* <p>コメント内部の末尾が改行でない場合、改行が挿入される。
+ *
* <p>ブロックコメント末尾は改行で終わる。
+ *
* <p>インデント設定は無視される。
+ *
* @param comment コメント内容
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putBlockComment(CharSequence comment) throws IOException;
+ public abstract XmlExporter putBlockComment(CharSequence comment)
+ throws IOException;
/**
* 開始タグ開き表記を出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putOpenSTag(CharSequence tagName) throws IOException;
+ public abstract XmlExporter putOpenSTag(CharSequence tagName)
+ throws IOException;
/**
* 開始タグ閉じ表記を出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putCloseSTag() throws IOException;
+ public abstract XmlExporter putCloseSTag() throws IOException;
/**
* 属性の無いシンプルな開始タグ表記を出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putSimpleSTag(CharSequence tagName) throws IOException;
+ public abstract XmlExporter putSimpleSTag(CharSequence tagName)
+ throws IOException;
/**
* 終了タグ表記を出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putETag(CharSequence tagName) throws IOException;
+ public abstract XmlExporter putETag(CharSequence tagName)
+ throws IOException;
/**
* 属性の無い単出タグ表記を出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putSimpleEmpty(CharSequence tagName) throws IOException;
+ public abstract XmlExporter putSimpleEmpty(CharSequence tagName)
+ throws IOException;
/**
* 単出タグ閉じ表記を出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putCloseEmpty() throws IOException;
+ public abstract XmlExporter putCloseEmpty() throws IOException;
/**
* xsd:int値をXMLスキーマ準拠の形式で出力する。
* XML Schema 1.1 Datatypes int
* </a>
*/
- XmlExporter putXsdInt(int iVal) throws IOException;
+ public abstract XmlExporter putXsdInt(int iVal) throws IOException;
/**
* xsd:float値をXMLスキーマ準拠の形式で出力する。
* XML Schema 1.1 Datatypes float Lexical Mapping
* </a>
*/
- XmlExporter putXsdFloat(float fVal) throws IOException;
+ public abstract XmlExporter putXsdFloat(float fVal) throws IOException;
/**
* int型属性値を出力する。
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putIntAttr(CharSequence attrName, int iVal)
+ public abstract XmlExporter putIntAttr(CharSequence attrName, int iVal)
throws IOException;
/**
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putFloatAttr(CharSequence attrName, float fVal)
+ public abstract XmlExporter putFloatAttr(
+ CharSequence attrName, float fVal)
throws IOException;
/**
* @return this本体
* @throws IOException 出力エラー
*/
- XmlExporter putAttr(CharSequence attrName, CharSequence content)
+ public abstract XmlExporter putAttr(
+ CharSequence attrName, CharSequence content)
throws IOException;
}
package jp.sfjp.mikutoga.xml;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.Reader;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
/**
- * URL変換マップに従い、XML文書からの外部参照をリダイレクトする。
- * 相対URIはこのクラスをベースに解決される。
- * 主な用途は外部スキーマのリソース化など。
+ * register & redirect original URI to local resource contents.
*/
public class XmlResourceResolver
- implements LSResourceResolver, EntityResolver {
-
- /** XML Schema. */
- public static final String SCHEMA_XML =
- "http://www.w3.org/2001/xml.xsd";
-
- /** XSD名前空間。 */
- public static final String NS_XSD =
- "http://www.w3.org/2001/XMLSchema-instance";
-
- private static final String LOCAL_SCHEMA_XML =
- "resources/xmlspace.xsd";
+ implements LSResourceResolver{
private static final URI EMPTY_URI = URI.create("");
- private static final Class<?> THISCLASS = XmlResourceResolver.class;
+ private static final DOMImplementationLS DOM_LS;
private final Map<URI, URI> uriMap;
+ static{
+ try{
+ DOM_LS = buildDomImplLS();
+ }catch( ClassNotFoundException
+ | IllegalAccessException
+ | InstantiationException e){
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+
/**
- * コンストラクタ。
+ * Constructor.
*/
public XmlResourceResolver(){
super();
- assert this.getClass().equals(THISCLASS);
-
Map<URI, URI> map;
- map = new HashMap<URI, URI>();
+ map = new HashMap<>();
map = Collections.synchronizedMap(map);
this.uriMap = map;
- URL redirectRes = THISCLASS.getResource(LOCAL_SCHEMA_XML);
- String redirectResName = redirectRes.toString();
-
- URI originalURI = URI.create(SCHEMA_XML);
- URI redirectURI = URI.create(redirectResName);
+ return;
+ }
- putRedirectedImpl(originalURI, redirectURI);
- return;
+ /**
+ * return DOMImplementationLS implement.
+ *
+ * @return DOMImplementationLS implement
+ * @throws ClassNotFoundException no class
+ * @throws InstantiationException no object
+ * @throws IllegalAccessException no grant
+ */
+ private static DOMImplementationLS buildDomImplLS() throws
+ ClassNotFoundException,
+ InstantiationException,
+ IllegalAccessException {
+ DOMImplementationRegistry domReg;
+ DOMImplementation domImp;
+ DOMImplementationLS domImpLs;
+
+ domReg = DOMImplementationRegistry.newInstance();
+ domImp = domReg.getDOMImplementation("LS 3.0");
+
+ Object feature = domImp.getFeature("LS", "3.0");
+ assert feature instanceof DOMImplementationLS;
+ domImpLs = (DOMImplementationLS) feature;
+
+ return domImpLs;
}
+ /**
+ * return LSInput implement.
+ *
+ * @return LSInput implement
+ */
+ public static LSInput createLSInput(){
+ LSInput input = DOM_LS.createLSInput();
+ return input;
+ }
/**
- * 絶対URIと相対URIを合成したURIを返す。
- * 正規化も行われる。
- * @param base 絶対URIでなければならない。nullでもよい。
- * @param relative 絶対URIでもよいがその場合baseは無視される。null可。
- * @return 合成結果のURLオブジェクト。必ず絶対URIになる。
- * @throws java.net.URISyntaxException URIとして変。
- * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。
+ * merge base-uri text & relative URI text.
+ *
+ * @param base base URI text must be absolute or null.
+ * @param relative relative URI text.
+ * If absolute, base is ignored.
+ * Ignored if null.
+ * @return merged absolute URI.
+ * @throws java.net.URISyntaxException illegal URI
+ * @throws java.lang.IllegalArgumentException result is not Absolute.
*/
protected static URI buildBaseRelativeURI(String base, String relative)
throws URISyntaxException,
relativeURI = EMPTY_URI;
}
+ URI result = buildBaseRelativeURI(baseURI, relativeURI);
+ return result;
+ }
+
+ /**
+ * merge base-uri & relative URI.
+ *
+ * @param baseURI base URI must be absolute or null.
+ * @param relativeURI relative URI. If absolute, baseURI is ignored.
+ * @return merged absolute URI.
+ * @throws java.lang.IllegalArgumentException result is not Absolute.
+ */
+ private static URI buildBaseRelativeURI(URI baseURI, URI relativeURI)
+ throws IllegalArgumentException {
URI resultURI;
+
if(baseURI == null || relativeURI.isAbsolute()){
resultURI = relativeURI;
}else{
return resultURI;
}
- /**
- * LSInput実装を生成する。
- * @return LSInput実装
- */
- public static LSInput createLSInput(){
- LSInput input = new LSInputImpl();
- return input;
- }
-
/**
- * オリジナルURIとリダイレクト先のURIを登録する。
- * オリジナルURIへのアクセスはリダイレクトされる。
- * @param original オリジナルURI
- * @param redirect リダイレクトURI
+ * map original URI & local resource URI.
+ *
+ * @param original original URI
+ * @param redirect local resource URI
*/
- private void putRedirectedImpl(URI original, URI redirect){
+ public void putRedirected(URI original, URI redirect){
URI oridinalNorm = original.normalize();
URI redirectNorm = redirect.normalize();
}
/**
- * オリジナルURIとリダイレクト先のURIを登録する。
- * オリジナルURIへのアクセスはリダイレクトされる。
- * @param original オリジナルURI
- * @param redirect リダイレクトURI
- */
- public void putRedirected(URI original, URI redirect){
- putRedirectedImpl(original, redirect);
- return;
- }
-
- /**
- * ローカル版リソース参照解決を登録する。
- * @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 別リゾルバ
+ * add other resolver mapping.
+ *
+ * @param other resolver
*/
public void putRedirected(XmlResourceResolver other){
this.uriMap.putAll(other.uriMap);
}
/**
- * 登録済みリダイレクト先URIを返す。
- * @param original オリジナルURI
- * @return リダイレクト先URI。未登録の場合はnull
+ * get redirected local resource URI.
+ *
+ * @param original original URI
+ * @return mapped local resource URI. null if unmapped.
*/
public URI getRedirected(URI original){
URI keyURI = original.normalize();
}
/**
- * 登録済みリダイレクト先URIを返す。
- * @param original オリジナルURI
- * @return リダイレクト先URI。未登録の場合はオリジナルを返す
- */
- public URI resolveRedirected(URI original){
- URI result = getRedirected(original);
- if(result == null) result = original;
- return result;
- }
-
- /**
- * 登録済みリダイレクト先リソースの入力ストリームを得る。
- * @param originalURI オリジナルURI
- * @return 入力ストリーム。リダイレクト先が未登録の場合はnull
- * @throws java.io.IOException 入出力エラー。
- * もしくはリソースが見つからない。
+ * get redirected local input stream.
+ *
+ * @param originalURI original URI
+ * @return mapped local resource input stream.
+ * If no mapping, return zero-length data stream.
+ * @throws java.io.IOException local resource i/o error
*/
private InputStream getXMLResourceAsStream(URI originalURI)
throws IOException{
+ InputStream result;
+
URI resourceURI = getRedirected(originalURI);
- if(resourceURI == null) return null;
+ if(resourceURI == null){
+ result = new ByteArrayInputStream(new byte[0]);
+ }else{
+ URL resourceURL = resourceURI.toURL();
+ result = resourceURL.openStream();
+ }
- URL resourceURL = resourceURI.toURL();
- InputStream is = resourceURL.openStream();
+ result = new BufferedInputStream(result);
- return is;
+ return result;
}
/**
* {@inheritDoc}
- * URL変換したあとの入力ソースを返す。
+ *
+ * <p>Return redirected local resource data.
+ *
* @param type {@inheritDoc}
* @param namespaceURI {@inheritDoc}
* @param publicId {@inheritDoc}
* @param systemId {@inheritDoc}
* @param baseURI {@inheritDoc}
- * @return {@inheritDoc}
+ * @return {@inheritDoc} LSInput of local resource.
+ * If no mapping, return zero-length data.
*/
@Override
- public LSInput resolveResource(String type,
- String namespaceURI,
- String publicId,
- String systemId,
- String baseURI ){
+ public LSInput resolveResource(
+ String type,
+ String namespaceURI,
+ String publicId,
+ String systemId,
+ String baseURI ){
if(systemId == null) return null;
URI originalURI;
try{
originalURI = buildBaseRelativeURI(baseURI, systemId);
}catch(URISyntaxException e){
- return null;
+ assert false;
+ throw new AssertionError(e);
}
InputStream is;
try{
is = getXMLResourceAsStream(originalURI);
}catch(IOException e){
- return null;
+ assert false;
+ throw new AssertionError(e);
}
- if(is == null) return null;
LSInput input = createLSInput();
input.setBaseURI(baseURI);
return input;
}
- /**
- * {@inheritDoc}
- * URL変換したあとの入力ソースを返す。
- * @param publicId {@inheritDoc}
- * @param systemId {@inheritDoc}
- * @return {@inheritDoc}
- * @throws org.xml.sax.SAXException {@inheritDoc}
- * @throws java.io.IOException {@inheritDoc}
- */
- @Override
- public InputSource resolveEntity(String publicId, String systemId)
- throws SAXException, IOException{
- if(systemId == null) return null;
-
- URI originalUri;
- try{
- originalUri = new URI(systemId);
- }catch(URISyntaxException e){
- return null;
- }
-
- InputStream is = getXMLResourceAsStream(originalUri);
- if(is == null) return null;
-
- InputSource source = new InputSource(is);
- source.setPublicId(publicId);
- source.setSystemId(systemId);
-
- return source;
- }
-
- /**
- * JRE1.5用LSInput実装。
- * JRE1.6なら
- * org.w3c.dom.ls.DOMImplementationLS#createLSInput()
- * で生成可能かも。
- */
- private static final class LSInputImpl implements LSInput {
-
- private String baseURI = null;
- private InputStream byteStream = null;
- private boolean certifiedText = false;
- private Reader characterStream = null;
- private String encoding = null;
- private String publicId = null;
- private String stringData = null;
- private String systemId = null;
-
- /**
- * コンストラクタ。
- */
- LSInputImpl(){
- super();
- return;
- }
-
- /**
- * {@inheritDoc}
- * @return {@inheritDoc}
- */
- @Override
- public String getBaseURI(){
- return this.baseURI;
- }
-
- /**
- * {@inheritDoc}
- * @param baseURI {@inheritDoc}
- */
- @Override
- public void setBaseURI(String baseURI){
- this.baseURI = baseURI;
- return;
- }
-
- /**
- * {@inheritDoc}
- * @return {@inheritDoc}
- */
- @Override
- public InputStream getByteStream(){
- return this.byteStream;
- }
-
- /**
- * {@inheritDoc}
- * @param byteStream {@inheritDoc}
- */
- @Override
- public void setByteStream(InputStream byteStream){
- this.byteStream = byteStream;
- }
-
- /**
- * {@inheritDoc}
- * @return {@inheritDoc}
- */
- @Override
- public boolean getCertifiedText(){
- return this.certifiedText;
- }
-
- /**
- * {@inheritDoc}
- * @param certifiedText {@inheritDoc}
- */
- @Override
- public void setCertifiedText(boolean certifiedText){
- this.certifiedText = certifiedText;
- return;
- }
-
- /**
- * {@inheritDoc}
- * @return {@inheritDoc}
- */
- @Override
- public Reader getCharacterStream(){
- return this.characterStream;
- }
-
- /**
- * {@inheritDoc}
- * @param characterStream {@inheritDoc}
- */
- @Override
- public void setCharacterStream(Reader characterStream){
- this.characterStream = characterStream;
- }
-
- /**
- * {@inheritDoc}
- * @return {@inheritDoc}
- */
- @Override
- public String getEncoding(){
- return this.encoding;
- }
-
- /**
- * {@inheritDoc}
- * @param encoding {@inheritDoc}
- */
- @Override
- public void setEncoding(String encoding){
- this.encoding = encoding;
- return;
- }
-
- /**
- * {@inheritDoc}
- * @return {@inheritDoc}
- */
- @Override
- public String getPublicId(){
- return this.publicId;
- }
-
- /**
- * {@inheritDoc}
- * @param publicId {@inheritDoc}
- */
- @Override
- public void setPublicId(String publicId){
- this.publicId = publicId;
- return;
- }
-
- /**
- * {@inheritDoc}
- * @return {@inheritDoc}
- */
- @Override
- public String getStringData(){
- return this.stringData;
- }
-
- /**
- * {@inheritDoc}
- * @param stringData {@inheritDoc}
- */
- @Override
- public void setStringData(String stringData){
- this.stringData = stringData;
- return;
- }
-
- /**
- * {@inheritDoc}
- * @return {@inheritDoc}
- */
- @Override
- public String getSystemId(){
- return this.systemId;
- }
-
- /**
- * {@inheritDoc}
- * @param systemId {@inheritDoc}
- */
- @Override
- public void setSystemId(String systemId){
- this.systemId = systemId;
- return;
- }
-
- }
-
}
assertEquals(3.0, pos.getXpos(), 0.0);
assertEquals(4.0, pos.getYpos(), 0.0);
+ pos.setPosition(1.0, 0.0);
+ assertFalse(pos.isOriginPoint());
+
+ pos.setPosition(0.0, 1.0);
+ assertFalse(pos.isOriginPoint());
+
+ pos.setPosition(0.0, 0.0);
+ assertTrue(pos.isOriginPoint());
+
+ pos.setPosition(-0.0, -0.0);
+ assertTrue(pos.isOriginPoint());
+
pos = new MkPos2D(5.0, 6.0);
assertEquals(5.0, pos.getXpos(), 0.0);
assertEquals(6.0, pos.getYpos(), 0.0);
assertEquals(5.0, pos.getYpos(), 0.0);
assertEquals(6.0, pos.getZpos(), 0.0);
+ pos.setPosition(0.0, 0.0, 0.0);
+ assertTrue(pos.isOriginPoint());
+
+ pos.setPosition(1.0, 0.0, 0.0);
+ assertFalse(pos.isOriginPoint());
+
+ pos.setPosition(0.0, 1.0, 0.0);
+ assertFalse(pos.isOriginPoint());
+
+ pos.setPosition(0.0, 0.0, 1.0);
+ assertFalse(pos.isOriginPoint());
+
+ pos.setPosition(-0.0, -0.0, -0.0);
+ assertTrue(pos.isOriginPoint());
+
pos = new MkPos3D(7.0, 8.0, 9.0);
assertEquals(7.0, pos.getXpos(), 0.0);
assertEquals(8.0, pos.getYpos(), 0.0);
assert0UlpEquals(yRad, eu.getYRot());
assertUlpEquals(zRad, eu.getZRot(), 1);
+ xRad = toRadians(90);
+ yRad = toRadians(-120);
+ zRad = toRadians(120);
+ qq.setEulerYXZ(xRad, yRad, zRad);
+ qq.toEulerYXZ(eu, yRad);
+ assert0UlpEquals(xRad, eu.getXRot());
+ assert0UlpEquals(yRad, eu.getYRot());
+ assertUlpEquals(zRad, eu.getZRot(), 1);
+
xRad = toRadians(89.999);
yRad = toRadians(89.999);
zRad = toRadians(89.999);
}
/**
+ * Test of putCharRef2Hex method, of class BasicXmlExporter.
+ * @throws IOException
+ */
+ @Test
+ public void testPutCharRef2Hex() throws IOException{
+ System.out.println("putCharRef2Hex");
+
+ BasicXmlExporter instance;
+ StringBuffer buf;
+
+ instance = new BasicXmlExporter();
+
+ buf = new StringBuffer();
+ instance.setAppendable(buf);
+ instance.putCharRef2Hex('\u0000');
+ assertEquals("�", buf.toString());
+
+ buf = new StringBuffer();
+ instance.setAppendable(buf);
+ instance.putCharRef2Hex('A');
+ assertEquals("A", buf.toString());
+
+ buf = new StringBuffer();
+ instance.setAppendable(buf);
+ instance.putCharRef2Hex('\u00ff');
+ assertEquals("ÿ", buf.toString());
+
+ buf = new StringBuffer();
+ instance.setAppendable(buf);
+ instance.putCharRef2Hex('\u0100');
+ assertEquals("Ā", buf.toString());
+
+ return;
+ }
+
+ /**
+ * Test of putCh method, of class BasicXmlExporter.
+ * @throws IOException
+ */
+ @Test
+ public void testPutCh() throws IOException{
+ System.out.println("putCh");
+
+ BasicXmlExporter instance;
+ StringBuffer buf;
+
+ instance = new BasicXmlExporter();
+
+ buf = new StringBuffer();
+ instance.setAppendable(buf);
+ instance.putCh('A');
+ assertEquals("A", buf.toString());
+
+ buf = new StringBuffer();
+ instance.setAppendable(buf);
+ instance.putCh('B').putCh('7').putCh('あ');
+ assertEquals("B7あ", buf.toString());
+
+ buf = new StringBuffer();
+ instance.setAppendable(buf);
+ instance.putCh('&').putCh('<').putCh('>').putCh('"').putCh('\'');
+ assertEquals("&<>"'", buf.toString());
+
+ buf = new StringBuffer();
+ instance.setAppendable(buf);
+ instance.putCh('\b');
+ assertEquals("", buf.toString());
+
+ return;
+ }
+
+ /**
* Test of append method, of class BasicXmlExporter.
*/
@Test
+++ /dev/null
-/*
-@see https://www.w3.org/TR/xmlschema-2/
- */
-
-package jp.sfjp.mikutoga.xml;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import static org.junit.Assert.*;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-/**
- *
- */
-public class DomUtilsTest {
-
- private static final DocumentBuilderFactory FACTORY =
- DocumentBuilderFactory.newInstance();
- private static final DocumentBuilder BUILDER;
-
- private static final String TESTELEM = "testelem";
- private static final String TESTATTR = "testattr";
-
- private static Element getTestAttredElem(String attrVal){
- Document doc = BUILDER.newDocument();
- Element elem = doc.createElement(TESTELEM);
- elem.setAttribute(TESTATTR, attrVal);
- return elem;
- }
-
- static{
- try{
- BUILDER = FACTORY.newDocumentBuilder();
- }catch(ParserConfigurationException e){
- throw new ExceptionInInitializerError(e);
- }
- }
-
- public DomUtilsTest() {
- }
-
- @BeforeClass
- public static void setUpClass() throws ParserConfigurationException{
- }
-
- @AfterClass
- public static void tearDownClass() {
- }
-
- @Before
- public void setUp() {
- }
-
- @After
- public void tearDown() {
- }
-
- /**
- * Test of getBooleanAttr method, of class DomUtils.
- */
- @Test
- public void testGetBooleanAttr() throws Exception {
- System.out.println("getBooleanAttr");
-
- boolean result;
- Element elem;
-
- elem = getTestAttredElem("true");
- result = DomUtils.getBooleanAttr(elem, TESTATTR);
- assertTrue(result);
-
- elem = getTestAttredElem("false");
- result = DomUtils.getBooleanAttr(elem, TESTATTR);
- assertFalse(result);
-
- elem = getTestAttredElem("0");
- result = DomUtils.getBooleanAttr(elem, TESTATTR);
- assertFalse(result);
-
- elem = getTestAttredElem("1");
- result = DomUtils.getBooleanAttr(elem, TESTATTR);
- assertTrue(result);
-
- elem = getTestAttredElem("\n\rtrue\u0020\t");
- result = DomUtils.getBooleanAttr(elem, TESTATTR);
- assertTrue(result);
-
- elem = getTestAttredElem("?");
- try{
- DomUtils.getBooleanAttr(elem, TESTATTR);
- fail();
- }catch(TogaXmlException e){
- assert true;
- }
-
- return;
- }
-
- /**
- * Test of getIntegerAttr method, of class DomUtils.
- */
- @Test
- public void testGetIntegerAttr() throws TogaXmlException {
- System.out.println("getIntegerAttr");
-
- int result;
- Element elem;
-
- elem = getTestAttredElem("0");
- result = DomUtils.getIntegerAttr(elem, TESTATTR);
- assertEquals(0, result);
-
- elem = getTestAttredElem("1");
- result = DomUtils.getIntegerAttr(elem, TESTATTR);
- assertEquals(1, result);
-
- elem = getTestAttredElem("-1");
- result = DomUtils.getIntegerAttr(elem, TESTATTR);
- assertEquals(-1, result);
-
- elem = getTestAttredElem("999");
- result = DomUtils.getIntegerAttr(elem, TESTATTR);
- assertEquals(999, result);
-
- elem = getTestAttredElem("-9999");
- result = DomUtils.getIntegerAttr(elem, TESTATTR);
- assertEquals(-9999, result);
-
- elem = getTestAttredElem("\n\r999\u0020\t");
- result = DomUtils.getIntegerAttr(elem, TESTATTR);
- assertEquals(999, result);
-
- elem = getTestAttredElem("?");
- try{
- result = DomUtils.getIntegerAttr(elem, TESTATTR);
- fail();
- }catch(TogaXmlException e){
- assert true;
- }
-
- return;
- }
-
- /**
- * Test of getFloatAttr method, of class DomUtils.
- */
- @Test
- public void testGetFloatAttr() throws TogaXmlException {
- System.out.println("getFloatAttr");
-
- float result;
- Element elem;
-
- elem = getTestAttredElem("0.0");
- result = DomUtils.getFloatAttr(elem, TESTATTR);
- assertEquals(0.0f, result, 0.0f);
-
- elem = getTestAttredElem("-0.0");
- result = DomUtils.getFloatAttr(elem, TESTATTR);
- assertEquals(0.0f, result, 0.0f);
- assertEquals("-0.0", Float.toString(result));
-
- elem = getTestAttredElem("-123.456");
- result = DomUtils.getFloatAttr(elem, TESTATTR);
- assertEquals(-123.456f, result, 0.0f);
-
- elem = getTestAttredElem("654.321");
- result = DomUtils.getFloatAttr(elem, TESTATTR);
- assertEquals(654.321f, result, 0.0f);
-
- elem = getTestAttredElem("2.3E4");
- result = DomUtils.getFloatAttr(elem, TESTATTR);
- assertEquals(23000.0f, result, 0.0f);
-
- elem = getTestAttredElem("INF");
- result = DomUtils.getFloatAttr(elem, TESTATTR);
- assertEquals(Float.POSITIVE_INFINITY, result, 0.0f);
-
- elem = getTestAttredElem("+INF");
- try{
- DomUtils.getFloatAttr(elem, TESTATTR);
- fail();
- }catch(TogaXmlException e){
- assert true;
- }
-
- elem = getTestAttredElem("NaN");
- result = DomUtils.getFloatAttr(elem, TESTATTR);
- assertTrue(Float.isNaN(result));
-
- elem = getTestAttredElem("\n\r123.456\u0020\t");
- result = DomUtils.getFloatAttr(elem, TESTATTR);
- assertEquals(123.456f, result, 0.0f);
-
- elem = getTestAttredElem("?");
- try{
- DomUtils.getFloatAttr(elem, TESTATTR);
- fail();
- }catch(TogaXmlException e){
- assert true;
- }
-
- return;
- }
-
-}
--- /dev/null
+/*
+ */
+
+package jp.sfjp.mikutoga.xml;
+
+import java.net.URI;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ */
+public class XmlResourceResolverTest {
+
+ public XmlResourceResolverTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ /**
+ * Test of buildBaseRelativeURI method, of class XmlResourceResolver.
+ */
+ @Test
+ public void testBuildBaseRelativeURI() throws Exception {
+ System.out.println("buildBaseRelativeURI");
+
+ URI result;
+
+ result = XmlResourceResolver.buildBaseRelativeURI("http://example.com", "/a");
+ assertEquals("http://example.com/a", result.toASCIIString());
+
+ result = XmlResourceResolver.buildBaseRelativeURI("http://example.com/", "a");
+ assertEquals("http://example.com/a", result.toASCIIString());
+
+ result = XmlResourceResolver.buildBaseRelativeURI("http://example.com/", "/a");
+ assertEquals("http://example.com/a", result.toASCIIString());
+
+ result = XmlResourceResolver.buildBaseRelativeURI("http://example.com/a", "/b");
+ assertEquals("http://example.com/b", result.toASCIIString());
+
+ result = XmlResourceResolver.buildBaseRelativeURI("http://example.com/a/", "b");
+ assertEquals("http://example.com/a/b", result.toASCIIString());
+
+ result = XmlResourceResolver.buildBaseRelativeURI("http://example.com/a/", "/b");
+ assertEquals("http://example.com/b", result.toASCIIString());
+
+ result = XmlResourceResolver.buildBaseRelativeURI("http://example.com/a", "http://example.org/b");
+ assertEquals("http://example.org/b", result.toASCIIString());
+
+ result = XmlResourceResolver.buildBaseRelativeURI(null, "http://example.org/b");
+ assertEquals("http://example.org/b", result.toASCIIString());
+
+ result = XmlResourceResolver.buildBaseRelativeURI("http://example.com/a", null);
+ assertEquals("http://example.com/", result.toASCIIString());
+
+ result = XmlResourceResolver.buildBaseRelativeURI("http://example.com/a/b/", "../c");
+ assertEquals("http://example.com/a/c", result.toASCIIString());
+
+ try{
+ XmlResourceResolver.buildBaseRelativeURI("a/b/", "c/d");
+ fail();
+ }catch(IllegalArgumentException e){
+ assert true;
+ }
+
+ try{
+ XmlResourceResolver.buildBaseRelativeURI(null, "c/d");
+ fail();
+ }catch(IllegalArgumentException e){
+ assert true;
+ }
+
+ return;
+ }
+
+}