From: Olyutorskii Date: Sun, 27 Jan 2013 22:01:21 +0000 (+0900) Subject: 実数表記の揺れを吸収 X-Git-Tag: fromMercurial~32 X-Git-Url: http://git.osdn.net/view?p=mikutoga%2FTogaGem.git;a=commitdiff_plain;h=3f41ff0b41eb0be52398d5e56a5bb00b673da194 実数表記の揺れを吸収 --- diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5cb8762..fc50b2f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -6,6 +6,7 @@ TogaGem 変更履歴 X.XXX.X (20XX-XX-XX) ・Maven3対応。 + ・JRE版数によって"0.001"や"0.0010"になるXML上の実数表記揺れを吸収。 2.101.2 (2011-08-24) ・VMDファイルの読み込みに対応。 diff --git a/src/main/java/jp/sourceforge/mikutoga/parser/CommonParser.java b/src/main/java/jp/sourceforge/mikutoga/parser/CommonParser.java index 8ee1a7c..bbbc473 100644 --- a/src/main/java/jp/sourceforge/mikutoga/parser/CommonParser.java +++ b/src/main/java/jp/sourceforge/mikutoga/parser/CommonParser.java @@ -183,7 +183,6 @@ public class CommonParser { * @return 読み込んだbyte値 * @throws IOException IOエラー * @throws MmdEofException 読み込む途中でストリーム終端に達した。 - * @see MmdInputStream#parseByte() */ protected byte parseByte() throws IOException, MmdEofException{ @@ -204,7 +203,6 @@ public class CommonParser { * @return 読み込まれた値のint値 * @throws IOException IOエラー * @throws MmdEofException 読み込む途中でストリーム終端に達した。 - * @see MmdInputStream#parseUByteAsInt() */ protected int parseUByteAsInt() throws IOException, MmdEofException{ @@ -217,7 +215,6 @@ public class CommonParser { * @return 読み込まれた値のboolean値 * @throws IOException IOエラー * @throws MmdEofException 読み込む途中でストリーム終端に達した。 - * @see MmdInputStream#parseBoolean() */ protected boolean parseBoolean() throws IOException, MmdEofException{ @@ -232,7 +229,6 @@ public class CommonParser { * @return 読み込んだshort値 * @throws IOException IOエラー * @throws MmdEofException 読み込む途中でストリーム終端に達した。 - * @see MmdInputStream#parseShort() */ protected short parseLeShort() throws IOException, MmdEofException{ @@ -248,7 +244,6 @@ public class CommonParser { * @return 読み込まれた値のint値 * @throws IOException IOエラー * @throws MmdEofException 読み込む途中でストリーム終端に達した。 - * @see MmdInputStream#parseUShortAsInteger() */ protected int parseLeUShortAsInt() throws IOException, MmdEofException{ @@ -261,7 +256,6 @@ public class CommonParser { * @return 読み込んだint値 * @throws IOException IOエラー * @throws MmdEofException 読み込む途中でストリーム終端に達した。 - * @see MmdInputStream#parseInteger() */ protected int parseLeInt() throws IOException, MmdEofException{ @@ -276,7 +270,6 @@ public class CommonParser { * @return 読み込んだfloat値 * @throws IOException IOエラー * @throws MmdEofException 読み込む途中でストリーム終端に達した。 - * @see MmdInputStream#parseFloat() */ protected float parseLeFloat() throws IOException, MmdEofException{ diff --git a/src/main/java/jp/sourceforge/mikutoga/parser/ParseStage.java b/src/main/java/jp/sourceforge/mikutoga/parser/ParseStage.java index ffa1e14..f43b094 100644 --- a/src/main/java/jp/sourceforge/mikutoga/parser/ParseStage.java +++ b/src/main/java/jp/sourceforge/mikutoga/parser/ParseStage.java @@ -31,7 +31,7 @@ public class ParseStage { /** * 各インスタンスに割り当てられたユニークな通し番号を返す。 - * @return + * @return 通し番号 */ public int getNo(){ return this.no; diff --git a/src/main/java/jp/sourceforge/mikutoga/pmd/ModelFileType.java b/src/main/java/jp/sourceforge/mikutoga/pmd/ModelFileType.java new file mode 100644 index 0000000..06cf18c --- /dev/null +++ b/src/main/java/jp/sourceforge/mikutoga/pmd/ModelFileType.java @@ -0,0 +1,30 @@ +/* + * MMD model file types. + * + * License : The MIT License + * Copyright(c) 2012 MikuToga Partners + */ + +package jp.sourceforge.mikutoga.pmd; + +/** + * モデルファイル種別。 + */ +public enum ModelFileType { + + /** 不明。 */ + NONE, + + /** MikuMikuDance ver7 前後で読み書きが可能なPMDファイル。 */ + PMD, + + /** + * スキーマ + * http://mikutoga.sourceforge.jp/xml/xsd/pmdxml-101009.xsd + * で定義されたXMLファイル。 + */ + XML_101009, + + ; + +} diff --git a/src/main/java/jp/sourceforge/mikutoga/typical/TypicalObject.java b/src/main/java/jp/sourceforge/mikutoga/typical/I18nAlias.java similarity index 62% rename from src/main/java/jp/sourceforge/mikutoga/typical/TypicalObject.java rename to src/main/java/jp/sourceforge/mikutoga/typical/I18nAlias.java index ff5e2d5..69fdb8d 100644 --- a/src/main/java/jp/sourceforge/mikutoga/typical/TypicalObject.java +++ b/src/main/java/jp/sourceforge/mikutoga/typical/I18nAlias.java @@ -1,5 +1,5 @@ /* - * typical object information + * internationalization name alias * * License : The MIT License * Copyright(c) 2011 MikuToga Partners @@ -9,6 +9,7 @@ package jp.sourceforge.mikutoga.typical; import java.io.IOException; import java.io.InputStream; +import java.text.Normalizer; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -22,34 +23,36 @@ import org.w3c.dom.Element; import org.xml.sax.SAXException; /** - * 各種標準オブジェクトの実装基板。 + * 国際化&別名管理オブジェクトの実装基板。 *

国産モデルではプライマリ名に日本語名が収められることが多い。 * プライマリ名は必ず一つ以上なければならない。 *

国産モデルではグローバル名に英語名が収められることが多いが、 * プライマリ名と同一の日本語名が収められている場合も多い。 */ -class TypicalObject { +class I18nAlias { /** オーダ番号によるコンパレータ。 */ - public static final Comparator ORDER_COMPARATOR = + public static final Comparator ORDER_COMPARATOR = new OrderComparator(); - protected final List primaryList; - protected final List globalList; - protected final List umodPrimaryList; - protected final List umodGlobalList; + private int orderNo; - protected int orderNo; + private final List primaryList; + private final List globalList; + + private final List umodPrimaryList; + private final List umodGlobalList; /** * コンストラクタ。 - *

各初期数が0以下の場合は、状況に応じて伸長する連結リストが用意される。 + *

各初期数が0以下の場合は、 + * 状況に応じて伸長する連結リストが用意される。 * @param primaryNo プライマリ名初期数。 * @param globalNo グローバル名初期数。 */ - protected TypicalObject(int primaryNo, int globalNo){ + protected I18nAlias(int primaryNo, int globalNo){ super(); if(primaryNo <= 0){ @@ -74,9 +77,10 @@ class TypicalObject { /** * コンストラクタ。 - *

プライマリ名、グローバル名共、状況に応じて伸長する連結リストが用意される。 + *

プライマリ名、グローバル名共、 + * 状況に応じて伸長する連結リストが用意される。 */ - protected TypicalObject(){ + protected I18nAlias(){ this(0, 0); return; } @@ -104,9 +108,41 @@ class TypicalObject { return top; } + /** + * NFKC正規化された文字列を返す。 + *

+ * @param name + * @return + */ + protected static String normalize(CharSequence name){ + String result; + result = Normalizer.normalize(name, Normalizer.Form.NFKC); + return result; + } + + + /** + * オーダー番号を返す。 + * @return + */ + protected int getOrderNo(){ + return this.orderNo; + } + + /** + * オーダー番号を設定する。 + * @param orderNo + */ + protected void setOrderNo(int orderNo){ + this.orderNo = orderNo; + return; + } /** - * プライマリ名をひとつ返す。 + * プライマリ名の代表をひとつ返す。 * @return 最初のプライマリ名 */ public String getTopPrimaryName(){ @@ -115,7 +151,7 @@ class TypicalObject { } /** - * グローバル名をひとつ返す。 + * グローバル名の代表をひとつ返す。 * @return 最初のグローバル名。ひとつもなければnull */ public String getTopGlobalName(){ @@ -126,7 +162,7 @@ class TypicalObject { } /** - * 全プライマリ名を返す。 + * プライマリ名の全エイリアス文字列リストを返す。 * @return 全プライマリ名リスト。(不可変) */ public List getPrimaryList(){ @@ -134,7 +170,16 @@ class TypicalObject { } /** - * 全グローバル名を返す。 + * プライマリ名を追加。 + * @param name プライマリ名 + */ + protected void addPrimaryName(String name){ + this.primaryList.add(name); + return; + } + + /** + * グローバル名の全エイリアス文字列リストを返す。 * @return 全グローバル名リスト。(不可変) */ public List getGlobalList(){ @@ -142,10 +187,20 @@ class TypicalObject { } /** + * グローバル名を追加。 + * @param name グローバル名 + */ + protected void addGlobalName(String name){ + this.globalList.add(name); + return; + } + + /** * オーダ番号によるコンパレータ。 */ + @SuppressWarnings("serial") private static class OrderComparator - implements Comparator { + implements Comparator { /** * コンストラクタ。 @@ -162,8 +217,8 @@ class TypicalObject { * @return {@inheritDoc} */ @Override - public int compare(TypicalObject o1, TypicalObject o2){ - int result = o1.orderNo - o2.orderNo; + public int compare(I18nAlias o1, I18nAlias o2){ + int result = o1.getOrderNo() - o2.getOrderNo(); return result; } diff --git a/src/main/java/jp/sourceforge/mikutoga/typical/TypicalBone.java b/src/main/java/jp/sourceforge/mikutoga/typical/TypicalBone.java index 1be886a..4f907e8 100644 --- a/src/main/java/jp/sourceforge/mikutoga/typical/TypicalBone.java +++ b/src/main/java/jp/sourceforge/mikutoga/typical/TypicalBone.java @@ -9,6 +9,7 @@ package jp.sourceforge.mikutoga.typical; import java.io.IOException; import java.io.InputStream; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -25,7 +26,7 @@ import org.xml.sax.SAXException; *

選択基準は独断。 *

和英対訳はMMD Ver7.39の同梱モデルにほぼ準拠。 */ -public final class TypicalBone extends TypicalObject { +public final class TypicalBone extends I18nAlias { private static final Class THISCLASS = TypicalBone.class; private static final String BONE_XML = "resources/typicalBone.xml"; @@ -37,12 +38,14 @@ public final class TypicalBone extends TypicalObject { private static final Map GLOBAL_MAP = new HashMap(); + private static final List TYP_BONE_UNMODLIST = + Collections.unmodifiableList(TYP_BONE_LIST); static{ InputStream is = THISCLASS.getResourceAsStream(BONE_XML); Element top; try{ - top = TypicalObject.loadXml(is); + top = I18nAlias.loadXml(is); }catch(ParserConfigurationException e){ throw new ExceptionInInitializerError(e); }catch(SAXException e){ @@ -59,7 +62,8 @@ public final class TypicalBone extends TypicalObject { /** * コンストラクタ。 - *

各初期数が0以下の場合は、状況に応じて伸長する連結リストが用意される。 + *

各初期数が0以下の場合は、 + * 状況に応じて伸長する連結リストが用意される。 * @param primaryNo プライマリ名初期数。 * @param globalNo グローバル名初期数。 */ @@ -101,21 +105,23 @@ public final class TypicalBone extends TypicalObject { for(int idx = 0; idx < primaryNo; idx++){ Element primary = (Element) primaryNodes.item(idx); String name = primary.getAttribute("name"); - typBone.primaryList.add(name); + typBone.addPrimaryName(name); } for(int idx = 0; idx < globalNo; idx++){ Element global = (Element) globalNodes.item(idx); String name = global.getAttribute("name"); - typBone.globalList.add(name); + typBone.addGlobalName(name); } - for(String primaryName : typBone.primaryList){ - PRIMARY_MAP.put(primaryName, typBone); + for(String primaryName : typBone.getPrimaryList()){ + String key = normalize(primaryName).intern(); + PRIMARY_MAP.put(key, typBone); } - for(String globalName : typBone.globalList){ - GLOBAL_MAP.put(globalName, typBone); + for(String globalName : typBone.getGlobalList()){ + String key = normalize(globalName).intern(); + GLOBAL_MAP.put(key, typBone); } return typBone; @@ -128,29 +134,41 @@ public final class TypicalBone extends TypicalObject { private static void numbering(){ int order = 0; for(TypicalBone bone : TYP_BONE_LIST){ - bone.orderNo = order++; + bone.setOrderNo(order++); } return; } /** + * 全ボーンの不変リストを返す。 + * @return 全ボーンのリスト + */ + public static List getBoneList(){ + return TYP_BONE_UNMODLIST; + } + + /** * プライマリ名の合致するボーン情報を返す。 + * NFKCで正規化されたプライマリ名で検索される。 * @param primaryName プライマリ名 * @return モーフ情報。見つからなければnull */ public static TypicalBone findWithPrimary(String primaryName){ - TypicalBone result = PRIMARY_MAP.get(primaryName); + String key = normalize(primaryName); + TypicalBone result = PRIMARY_MAP.get(key); return result; } /** * グローバル名の合致するボーン情報を返す。 + * NFKCで正規化されたグローバル名で検索される。 * @param globalName グローバル名 * @return モーフ情報。見つからなければnull */ public static TypicalBone findWithGlobal(String globalName){ - TypicalBone result = GLOBAL_MAP.get(globalName); + String key = normalize(globalName); + TypicalBone result = GLOBAL_MAP.get(key); return result; } diff --git a/src/main/java/jp/sourceforge/mikutoga/typical/TypicalMorph.java b/src/main/java/jp/sourceforge/mikutoga/typical/TypicalMorph.java index 12c37d8..0c552fe 100644 --- a/src/main/java/jp/sourceforge/mikutoga/typical/TypicalMorph.java +++ b/src/main/java/jp/sourceforge/mikutoga/typical/TypicalMorph.java @@ -29,7 +29,7 @@ import org.xml.sax.SAXException; *

選択基準は独断。 *

和英対訳はMMD Ver7.39の同梱モデルにほぼ準拠。 */ -public final class TypicalMorph extends TypicalObject { +public final class TypicalMorph extends I18nAlias { private static final Class THISCLASS = TypicalMorph.class; private static final String MORPH_XML = "resources/typicalMorph.xml"; @@ -49,7 +49,7 @@ public final class TypicalMorph extends TypicalObject { InputStream is = THISCLASS.getResourceAsStream(MORPH_XML); Element top; try{ - top = TypicalObject.loadXml(is); + top = I18nAlias.loadXml(is); }catch(ParserConfigurationException e){ throw new ExceptionInInitializerError(e); }catch(SAXException e){ @@ -69,7 +69,8 @@ public final class TypicalMorph extends TypicalObject { /** * コンストラクタ。 - *

各初期数が0以下の場合は、状況に応じて伸長する連結リストが用意される。 + *

各初期数が0以下の場合は、 + * 状況に応じて伸長する連結リストが用意される。 * @param type モーフ種別 * @param primaryNo プライマリ名初期数。 * @param globalNo グローバル名初期数。 @@ -93,7 +94,7 @@ public final class TypicalMorph extends TypicalObject { parseGroup(group); } - // 空リスト登録 + // 必要に応じモーフ枠に不変空リスト登録 for(MorphType morphType : MorphType.values()){ if( ! TYPED_MAP.containsKey(morphType) ){ TYPED_MAP.put(morphType, EMPTY); @@ -113,7 +114,8 @@ public final class TypicalMorph extends TypicalObject { NodeList morphList = group.getElementsByTagName("morph"); int morphNo = morphList.getLength(); - List groupedList = new ArrayList(morphNo); + List groupedList = + new ArrayList(morphNo); for(int idx = 0; idx < morphNo; idx++){ Element morph = (Element) morphList.item(idx); @@ -121,7 +123,8 @@ public final class TypicalMorph extends TypicalObject { groupedList.add(common); } - TYPED_MAP.put(morphType, Collections.unmodifiableList(groupedList)); + groupedList = Collections.unmodifiableList(groupedList); + TYPED_MAP.put(morphType, groupedList); return; } @@ -143,21 +146,23 @@ public final class TypicalMorph extends TypicalObject { for(int idx = 0; idx < primaryNo; idx++){ Element primary = (Element) primaryNodes.item(idx); String name = primary.getAttribute("name"); - typMorph.primaryList.add(name); + typMorph.addPrimaryName(name); } for(int idx = 0; idx < globalNo; idx++){ Element global = (Element) globalNodes.item(idx); String name = global.getAttribute("name"); - typMorph.globalList.add(name); + typMorph.addGlobalName(name); } - for(String primaryName : typMorph.primaryList){ - PRIMARY_MAP.put(primaryName, typMorph); + for(String primaryName : typMorph.getPrimaryList()){ + String key = normalize(primaryName).intern(); + PRIMARY_MAP.put(key, typMorph); } - for(String globalName : typMorph.globalList){ - GLOBAL_MAP.put(globalName, typMorph); + for(String globalName : typMorph.getGlobalList()){ + String key = normalize(globalName).intern(); + GLOBAL_MAP.put(key, typMorph); } return typMorph; @@ -171,7 +176,7 @@ public final class TypicalMorph extends TypicalObject { int order = 0; for(MorphType morphType : MorphType.values()){ for(TypicalMorph common : TYPED_MAP.get(morphType)){ - common.orderNo = order++; + common.setOrderNo(order++); } } @@ -191,21 +196,25 @@ public final class TypicalMorph extends TypicalObject { /** * プライマリ名の合致するモーフ情報を返す。 + * NFKCで正規化されたプライマリ名で検索される。 * @param primaryName プライマリ名 * @return モーフ情報。見つからなければnull */ public static TypicalMorph findWithPrimary(String primaryName){ - TypicalMorph result = PRIMARY_MAP.get(primaryName); + String key = normalize(primaryName); + TypicalMorph result = PRIMARY_MAP.get(key); return result; } /** * グローバル名の合致するモーフ情報を返す。 + * NFKCで正規化されたグローバル名で検索される。 * @param globalName グローバル名 * @return モーフ情報。見つからなければnull */ public static TypicalMorph findWithGlobal(String globalName){ - TypicalMorph result = GLOBAL_MAP.get(globalName); + String key = normalize(globalName); + TypicalMorph result = GLOBAL_MAP.get(key); return result; } @@ -233,6 +242,7 @@ public final class TypicalMorph extends TypicalObject { return primary; } + /** * モーフ種別を返す。 * @return モーフ種別 diff --git a/src/main/java/jp/sourceforge/mikutoga/xml/BasicXmlExporter.java b/src/main/java/jp/sourceforge/mikutoga/xml/BasicXmlExporter.java index 92cab4c..b429c55 100644 --- a/src/main/java/jp/sourceforge/mikutoga/xml/BasicXmlExporter.java +++ b/src/main/java/jp/sourceforge/mikutoga/xml/BasicXmlExporter.java @@ -14,6 +14,8 @@ import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.nio.charset.Charset; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.xml.bind.DatatypeConverter; /** @@ -26,34 +28,42 @@ public class BasicXmlExporter { private static final Charset CS_UTF8 = Charset.forName("UTF-8"); /** デフォルトの改行文字列。 */ - private static final String LF = "\n"; // 0x0a + private static final String DEF_NL = "\n"; // 0x0a(LF) /** デフォルトのインデント単位。 */ - private static final String DEFAULT_INDENT_UNIT = "\u0020\u0020"; + private static final String DEF_INDENT_UNIT = "\u0020\u0020"; // ␣␣ - private static final char CH_SP = '\u0020'; // - private static final char CH_YEN = '\u00a5'; // ¥ - private static final char CH_BSLASH = '\u005c\u005c'; // \ + private static final char CH_SP = '\u0020'; // ␣ + private static final char CH_YEN = '\u00a5'; // ¥ + private static final char CH_BSLASH = (char)0x005c; // \ + private static final char CH_DQ = '\u0022'; // " + private static final char CH_SQ = (char)0x0027; // ' + private static final String COMM_START = ""; + private static final String REF_HEX = "&#x"; + + private static final Pattern NUM_FUZZY = + Pattern.compile("([^.]*\\.[0-9][0-9]*?)0+"); + + private static final int HEX_EXP = 4; // 2 ** 4 == 16 + private static final int MASK_1HEX = (1 << HEX_EXP) - 1; // 0b00001111 + private static final int MAX_OCTET = (1 << Byte.SIZE) - 1; // 0xff private static final char[] HEXCHAR_TABLE = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', }; - private static final String COMM_START = ""; - - private static final int MASK_BIT8 = 0x000f; - private static final int MASK_BIT16 = 0x00ff; static{ - assert HEXCHAR_TABLE.length == 16; + assert HEX_EXP * 2 == Byte.SIZE; + assert HEXCHAR_TABLE.length == (1 << HEX_EXP); } private final Appendable appendable; - private String newline = LF; - private String indentUnit = DEFAULT_INDENT_UNIT; + private String newline = DEF_NL; + private String indentUnit = DEF_INDENT_UNIT; private int indentNest = 0; private boolean basicLatinOnlyOut = true; @@ -93,33 +103,47 @@ public class BasicXmlExporter { return; } + /** * ASCIIコード相当(UCS:Basic-Latin)の文字か否か判定する。 + *

※ Basic-Latinには各種制御文字も含まれる。 * @param ch 判定対象文字 * @return Basic-Latin文字ならtrue */ public static boolean isBasicLatin(char ch){ - Character.UnicodeBlock block = Character.UnicodeBlock.of(ch); - if(block == Character.UnicodeBlock.BASIC_LATIN) return true; + if('\u0000' <= ch && ch <= '\u007f'){ + return true; + } return false; } /** - * 改行文字列を設定する。 - * @param newLine 改行文字列 - * @throws NullPointerException 引数がnull + * 冗長な実数出力を抑止する。 + *

DatatypeConverterにおけるJDK1.6系と1.7系の仕様変更を吸収する。 + *

0.001fは"0.0010"ではなく"0.001"と出力される。 + *

指数表記での冗長桁は無視する。 + * @param numTxt 実数表記 + * @return 冗長桁が抑止された実数表記 */ - public void setNewLine(String newLine) throws NullPointerException{ - if(newLine == null) throw new NullPointerException(); - this.newline = newLine; - return; + public static String chopFuzzyZero(String numTxt){ + String result; + + Matcher matcher = NUM_FUZZY.matcher(numTxt); + if(matcher.matches()){ + result = matcher.group(1); + }else{ + result = numTxt; + } + + return result; } + /** * BasicLatin文字だけで出力するか設定する。 - * BasicLatin以外の文字(≒日本語)をそのまま出力するか - * 文字参照で出力するかの設定が可能。 - * コメント部中身は対象外。 + *

BasicLatin以外の文字(≒日本語)を、そのまま出力するか、 + * 文字参照で出力するか、の設定が可能。 + *

コメント部中身は対象外。 * @param bool BasicLatin文字だけで出力するならtrue */ public void setBasicLatinOnlyOut(boolean bool){ @@ -129,7 +153,7 @@ public class BasicXmlExporter { /** * BasicLatin文字だけを出力する状態か判定する。 - * コメント部中身は対象外。 + *

コメント部中身は対象外。 * @return BasicLatin文字だけで出力するならtrue */ public boolean isBasicLatinOnlyOut(){ @@ -138,23 +162,41 @@ public class BasicXmlExporter { /** * 改行文字列を設定する。 - * デフォルトではLF(0x0a)\nが用いられる。 - * @param seq 改行文字列。nullは空文字列""と解釈される。 + * @param newLine 改行文字列 + * @throws NullPointerException 引数がnull */ - public void setNewLine(CharSequence seq){ - if(seq == null) this.newline = ""; - else this.newline = seq.toString(); + public void setNewLine(String newLine) throws NullPointerException{ + if(newLine == null) throw new NullPointerException(); + this.newline = newLine; return; } /** + * 改行文字列を返す。 + * @return 改行文字列 + */ + public String getNewLine(){ + return this.newline; + } + + /** * インデント単位文字列を設定する。 - * デフォルトでは空白2個。 - * @param seq インデント単位文字列。nullは空文字列""と解釈される。 + *

デフォルトでは空白2個。 + * @param indUnit インデント単位文字列。 + * @throws NullPointerException 引数がnull + */ + public void setIndentUnit(String indUnit) throws NullPointerException{ + if(indUnit == null) throw new NullPointerException(); + this.indentUnit = indUnit; + return; + } + + /** + * インデント単位文字列を返す。 + * @return インデント単位文字列 */ - public void setIndentUnit(CharSequence seq){ - if(seq == null) this.indentUnit = ""; - else this.indentUnit = seq.toString(); + public String getIndentUnit(){ + return this.indentUnit; } /** @@ -185,7 +227,7 @@ public class BasicXmlExporter { * @return this本体 * @throws IOException 出力エラー */ - public BasicXmlExporter put(char ch) throws IOException{ + public BasicXmlExporter putRawCh(char ch) throws IOException{ this.appendable.append(ch); return this; } @@ -196,34 +238,134 @@ public class BasicXmlExporter { * @return this本体 * @throws IOException 出力エラー */ - public BasicXmlExporter put(CharSequence seq) throws IOException{ + public BasicXmlExporter putRawText(CharSequence seq) throws IOException{ this.appendable.append(seq); return this; } /** - * int値を出力する。 - * @param iVal int値 + * 指定された文字を16進2桁の文字参照形式で出力する。 + * 2桁で出力できない場合(>0x00ff)は4桁で出力する。 + * @param ch 文字 * @return this本体 * @throws IOException 出力エラー - * @see java.lang.Integer#toString(int) */ - public BasicXmlExporter put(int iVal) throws IOException{ - String value = DatatypeConverter.printInt(iVal); - this.appendable.append(value); + public BasicXmlExporter putCharRef2Hex(char ch) throws IOException{ + if(ch > MAX_OCTET) return putCharRef4Hex(ch); + + int ibits = ch; // 常に正なので符号拡張なし + + int idx4 = ibits & MASK_1HEX; + ibits >>= HEX_EXP; + int idx3 = ibits & MASK_1HEX; + + char hex3 = HEXCHAR_TABLE[idx3]; + char hex4 = HEXCHAR_TABLE[idx4]; + + putRawText(REF_HEX).putRawCh(hex3).putRawCh(hex4) + .putRawCh(';'); + return this; } /** - * float値を出力する。 - * @param fVal float値 + * 指定された文字を16進4桁の文字参照形式で出力する。 + * UCS4に伴うサロゲートペアは未サポート + * @param ch 文字 * @return this本体 * @throws IOException 出力エラー - * @see java.lang.Float#toString(float) */ - public BasicXmlExporter put(float fVal) throws IOException{ - String value = DatatypeConverter.printFloat(fVal); - this.appendable.append(value); + public BasicXmlExporter putCharRef4Hex(char ch) throws IOException{ + int ibits = ch; // 常に正なので符号拡張なし + + int idx4 = ibits & MASK_1HEX; + ibits >>= HEX_EXP; + int idx3 = ibits & MASK_1HEX; + ibits >>= HEX_EXP; + int idx2 = ibits & MASK_1HEX; + ibits >>= HEX_EXP; + int idx1 = ibits & MASK_1HEX; + + char hex1 = HEXCHAR_TABLE[idx1]; + char hex2 = HEXCHAR_TABLE[idx2]; + char hex3 = HEXCHAR_TABLE[idx3]; + char hex4 = HEXCHAR_TABLE[idx4]; + + putRawText(REF_HEX).putRawCh(hex1).putRawCh(hex2) + .putRawCh(hex3).putRawCh(hex4) + .putRawCh(';'); + + return this; + } + + /** + * 要素の中身および属性値中身を出力する。 + *

XMLの構文規則を守る上で必要な各種エスケープ処理が行われる。 + * @param ch 文字 + * @return this本体 + * @throws IOException 出力エラー + */ + public BasicXmlExporter putCh(char ch) throws IOException{ + if(Character.isISOControl(ch)){ + putCharRef2Hex(ch); + return this; + } + + String escTxt; + switch(ch){ + case '&': escTxt = "&"; break; + case '<': escTxt = "<"; break; + case '>': escTxt = ">"; break; + case CH_DQ: escTxt = """; break; + case CH_SQ: escTxt = "'"; break; + default: escTxt = null; break; + } + + if(escTxt != null){ + putRawText(escTxt); + }else{ + putRawCh(ch); + } + + return this; + } + + /** + * 要素の中身および属性値中身を出力する。 + *

必要に応じてXML定義済み実体文字が割り振られた文字、 + * コントロールコード、および非BasicLatin文字がエスケープされる。 + *

半角通貨記号U+00A5はバックスラッシュU+005Cに置換される。 + *

連続するスペースU+0020の2文字目以降は文字参照化される。 + *

全角スペースその他空白文字は無条件に文字参照化される。 + * @param content 内容 + * @return this本体 + * @throws IOException 出力エラー + */ + public BasicXmlExporter putContent(CharSequence content) + throws IOException{ + int length = content.length(); + + char prev = '\0'; + for(int pos = 0; pos < length; pos++){ + char ch = content.charAt(pos); + + if( isBasicLatinOnlyOut() && ! isBasicLatin(ch) ){ + putCharRef4Hex(ch); + }else if(ch == CH_YEN){ + putRawCh(CH_BSLASH); + }else if(Character.isSpaceChar(ch)){ + if(ch == CH_SP && prev != CH_SP){ + putRawCh(ch); + }else{ + putCharRef2Hex(ch); + } + }else{ + putCh(ch); + } + + prev = ch; + } + return this; } @@ -281,7 +423,7 @@ public class BasicXmlExporter { */ public BasicXmlExporter ind() throws IOException{ for(int ct = 1; ct <= this.indentNest; ct++){ - put(this.indentUnit); + putRawText(this.indentUnit); } return this; } @@ -305,87 +447,28 @@ public class BasicXmlExporter { } /** - * 指定された文字を16進2桁の文字参照形式で出力する。 - * 2桁で出力できない場合は4桁で出力する。 - * @param ch 文字 - * @return this本体 - * @throws IOException 出力エラー - */ - public BasicXmlExporter putCharRef2Hex(char ch) throws IOException{ - if(ch > MASK_BIT16) return putCharRef4Hex(ch); - - char hex3 = HEXCHAR_TABLE[(ch >> 4) & MASK_BIT8]; - char hex4 = HEXCHAR_TABLE[(ch >> 0) & MASK_BIT8]; - - put("&#x").put(hex3).put(hex4).put(';'); - - return this; - } - - /** - * 指定された文字を16進4桁の文字参照形式で出力する。 - * UCS4に伴うサロゲートペアは未サポート - * @param ch 文字 + * int値をXMLスキーマ準拠の形式で出力する。 + * @param iVal int値 * @return this本体 * @throws IOException 出力エラー + * @see java.lang.Integer#toString(int) */ - public BasicXmlExporter putCharRef4Hex(char ch) throws IOException{ - char hex1 = HEXCHAR_TABLE[(ch >> 12) & MASK_BIT8]; - char hex2 = HEXCHAR_TABLE[(ch >> 8) & MASK_BIT8]; - char hex3 = HEXCHAR_TABLE[(ch >> 4) & MASK_BIT8]; - char hex4 = HEXCHAR_TABLE[(ch >> 0) & MASK_BIT8]; - - put("&#x").put(hex1).put(hex2).put(hex3).put(hex4).put(';'); - + public BasicXmlExporter putXsdInt(int iVal) throws IOException{ + String value = DatatypeConverter.printInt(iVal); + this.appendable.append(value); return this; } /** - * 要素の中身および属性値中身を出力する。 - *

必要に応じてXML定義済み実体文字が割り振られた文字、 - * コントロールコード、および非BasicLatin文字がエスケープされる。 - *

半角通貨記号U+00A5はバックスラッシュU+005Cに置換される。 - * @param content 内容 + * float値をXMLスキーマ準拠の形式で出力する。 + * @param fVal float値 * @return this本体 * @throws IOException 出力エラー + * @see java.lang.Float#toString(float) */ - public BasicXmlExporter putContent(CharSequence content) - throws IOException{ - int length = content.length(); - - char prev = '\0'; - for(int pos = 0; pos < length; pos++){ - char ch = content.charAt(pos); - - if(Character.isISOControl(ch)){ - putCharRef2Hex(ch); - }else if( ! isBasicLatin(ch) && isBasicLatinOnlyOut()){ - putCharRef4Hex(ch); - }else if(ch == CH_SP){ - if(prev == CH_SP){ - putCharRef2Hex(ch); - }else{ - put(ch); - } - }else if(Character.isSpaceChar(ch)){ - // 全角スペースその他 - putCharRef2Hex(ch); - }else if(ch == CH_YEN){ - put(CH_BSLASH); - }else{ - switch(ch){ - case '&': put("&"); break; - case '<': put("<"); break; - case '>': put(">"); break; - case '"': put("""); break; - case '\'': put("'"); break; - default: put(ch); break; - } - } - - prev = ch; - } - + public BasicXmlExporter putXsdFloat(float fVal) throws IOException{ + String value = DatatypeConverter.printFloat(fVal); + this.appendable.append(value); return this; } @@ -399,7 +482,12 @@ public class BasicXmlExporter { public BasicXmlExporter putAttr(CharSequence attrName, CharSequence content) throws IOException{ - put(attrName).put('=').put('"').putContent(content).put('"'); + putRawText(attrName).putRawCh('='); + + putRawCh('"'); + putContent(content); + putRawCh('"'); + return this; } @@ -411,9 +499,10 @@ public class BasicXmlExporter { * @throws IOException 出力エラー */ public BasicXmlExporter putIntAttr(CharSequence attrName, - int iVal) + int iVal) throws IOException{ - put(attrName).put('=').put('"').put(iVal).put('"'); + String attrValue = DatatypeConverter.printInt(iVal); + putAttr(attrName, attrValue); return this; } @@ -425,9 +514,11 @@ public class BasicXmlExporter { * @throws IOException 出力エラー */ public BasicXmlExporter putFloatAttr(CharSequence attrName, - float fVal) + float fVal) throws IOException{ - put(attrName).put('=').put('"').put(fVal).put('"'); + String attrValue = DatatypeConverter.printFloat(fVal); + attrValue = chopFuzzyZero(attrValue); + putAttr(attrName, attrValue); return this; } @@ -454,13 +545,13 @@ public class BasicXmlExporter { if(ch == '\n'){ ln(); }else if('\u0000' <= ch && ch <= '\u001f'){ - put((char)('\u2400' + ch)); + putRawCh((char)('\u2400' + ch)); }else if(ch == '\u007f'){ - put('\u2421'); + putRawCh('\u2421'); }else if(prev == '-' && ch == '-'){ - sp().put(ch); + sp().putRawCh(ch); }else{ - put(ch); + putRawCh(ch); } prev = ch; @@ -478,9 +569,9 @@ public class BasicXmlExporter { */ public BasicXmlExporter putLineComment(CharSequence comment) throws IOException{ - put(COMM_START).sp(); + putRawText(COMM_START).sp(); putCommentContent(comment); - sp().put(COMM_END); + sp().putRawText(COMM_END); return this; } @@ -496,7 +587,7 @@ public class BasicXmlExporter { */ public BasicXmlExporter putBlockComment(CharSequence comment) throws IOException{ - put(COMM_START).ln(); + putRawText(COMM_START).ln(); putCommentContent(comment); @@ -508,7 +599,7 @@ public class BasicXmlExporter { } } - put(COMM_END).ln(); + putRawText(COMM_END).ln(); return this; } diff --git a/src/main/java/jp/sourceforge/mikutoga/xml/DomUtils.java b/src/main/java/jp/sourceforge/mikutoga/xml/DomUtils.java index 66dea2d..c516563 100644 --- a/src/main/java/jp/sourceforge/mikutoga/xml/DomUtils.java +++ b/src/main/java/jp/sourceforge/mikutoga/xml/DomUtils.java @@ -314,7 +314,7 @@ public final class DomUtils { /** * 同じ親要素と同じ要素名を持つ兄弟要素を列挙する列挙子。 */ - private static final class ElemIterator implements Iterator{ + private static final class ElemIterator implements Iterator { private Element next; /** diff --git a/src/main/java/jp/sourceforge/mikutoga/xml/XmlResourceResolver.java b/src/main/java/jp/sourceforge/mikutoga/xml/XmlResourceResolver.java index dc7ffd0..bed0634 100644 --- a/src/main/java/jp/sourceforge/mikutoga/xml/XmlResourceResolver.java +++ b/src/main/java/jp/sourceforge/mikutoga/xml/XmlResourceResolver.java @@ -13,6 +13,7 @@ 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.ls.LSInput; @@ -39,10 +40,14 @@ public class XmlResourceResolver private static final String LOCAL_SCHEMA_XML = "resources/xml-2009-01.xsd"; + private static final URI EMPTY_URI = URI.create(""); + private static final Class THISCLASS = XmlResourceResolver.class; - private final Map uriMap = new HashMap(); + + private final Map uriMap; + /** * コンストラクタ。 @@ -52,21 +57,23 @@ public class XmlResourceResolver assert this.getClass().equals(THISCLASS); + Map map; + 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); - URL redirectURL = THISCLASS.getResource(LOCAL_SCHEMA_XML); - URI redirectURI; - try{ - redirectURI = redirectURL.toURI(); - }catch(URISyntaxException e){ - assert false; - throw new AssertionError(e); - } + URI redirectURI = URI.create(redirectResName); - this.uriMap.put(originalURI, redirectURI); + putURIMapImpl(originalURI, redirectURI); return; } + /** * 絶対URIと相対URIを合成したURIを返す。 * 正規化も行われる。 @@ -79,15 +86,21 @@ public class XmlResourceResolver protected static URI buildBaseRelativeURI(String base, String relative) throws URISyntaxException, IllegalArgumentException { - URI baseURI = null; + URI baseURI; if(base != null){ baseURI = new URI(base); - if( ! baseURI.isAbsolute() ) throw new IllegalArgumentException(); + if( ! baseURI.isAbsolute() ){ + throw new IllegalArgumentException(); + } + }else{ + baseURI = null; } - URI relativeURI = EMPTY_URI; + URI relativeURI; if(relative != null){ relativeURI = new URI(relative); + }else{ + relativeURI = EMPTY_URI; } URI resultURI; @@ -97,7 +110,9 @@ public class XmlResourceResolver resultURI = baseURI.resolve(relativeURI); } - if( ! resultURI.isAbsolute() ) throw new IllegalArgumentException(); + if( ! resultURI.isAbsolute() ){ + throw new IllegalArgumentException(); + } resultURI = resultURI.normalize(); @@ -113,6 +128,22 @@ public class XmlResourceResolver return input; } + + /** + * オリジナルURIとリダイレクト先のURIを登録する。 + * オリジナルURIへのアクセスはリダイレクトされる。 + * @param original オリジナルURI + * @param redirect リダイレクトURI + */ + private void putURIMapImpl(URI original, URI redirect){ + URI oridinalNorm = original.normalize(); + URI redirectNorm = redirect.normalize(); + + this.uriMap.put(oridinalNorm, redirectNorm); + + return; + } + /** * オリジナルURIとリダイレクト先のURIを登録する。 * オリジナルURIへのアクセスはリダイレクトされる。 @@ -120,19 +151,25 @@ public class XmlResourceResolver * @param redirect リダイレクトURI */ public void putURIMap(URI original, URI redirect){ - this.uriMap.put(original.normalize(), redirect.normalize()); + putURIMapImpl(original, redirect); return; } /** - * 変換後のリソースの入力ストリームを得る。 + * 登録済みリダイレクト先リソースの入力ストリームを得る。 * @param originalURI オリジナルURI - * @return 入力ストリーム - * @throws java.io.IOException 入出力エラー + * @return 入力ストリーム。リダイレクト先が未登録の場合はnull + * @throws java.io.IOException 入出力エラー。 + * もしくはリソースが見つからない。 */ - public InputStream getXMLResourceAsStream(URI originalURI) + private InputStream getXMLResourceAsStream(URI originalURI) throws IOException{ - URI resourceURI = this.uriMap.get(originalURI.normalize()); + URI keyURI = originalURI.normalize(); + URI resourceURI = this.uriMap.get(keyURI); + if(resourceURI == null){ + return null; + } + URL resourceURL = resourceURI.toURL(); InputStream is = resourceURL.openStream(); @@ -170,6 +207,7 @@ public class XmlResourceResolver }catch(IOException e){ return null; } + if(is == null) return null; LSInput input = createLSInput(); input.setBaseURI(baseURI); @@ -202,6 +240,7 @@ public class XmlResourceResolver } InputStream is = getXMLResourceAsStream(originalUri); + if(is == null) return null; InputSource source = new InputSource(is); source.setPublicId(publicId); @@ -387,5 +426,4 @@ public class XmlResourceResolver } - // TODO OASIS XML Catalog などと調和したい。 } diff --git a/src/test/java/jp/sourceforge/mikutoga/typical/TypicalBoneTest.java b/src/test/java/jp/sourceforge/mikutoga/typical/TypicalBoneTest.java new file mode 100644 index 0000000..e27d84f --- /dev/null +++ b/src/test/java/jp/sourceforge/mikutoga/typical/TypicalBoneTest.java @@ -0,0 +1,150 @@ +/* + */ + +package jp.sourceforge.mikutoga.typical; + +import java.util.List; +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 TypicalBoneTest { + + public TypicalBoneTest() { + } + + @BeforeClass + public static void setUpClass() { + } + + @AfterClass + public static void tearDownClass() { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of findWithPrimary method, of class TypicalBone. + */ + @Test + public void testFindWithPrimary() { + System.out.println("findWithPrimary"); + + TypicalBone result; + result = TypicalBone.findWithPrimary("頭"); + + assertEquals("頭", result.getTopPrimaryName()); + assertEquals("head", result.getTopGlobalName()); + assertEquals(1, result.getPrimaryList().size()); + assertEquals("頭", result.getPrimaryList().get(0)); + assertEquals(1, result.getGlobalList().size()); + assertEquals("head", result.getGlobalList().get(0)); + + return; + } + + /** + * Test of findWithGlobal method, of class TypicalBone. + */ + @Test + public void testFindWithGlobal() { + System.out.println("findWithGlobal"); + + TypicalBone result; + + result = TypicalBone.findWithGlobal("head"); + assertNotNull(result); + + TypicalBone result2; + result2 = TypicalBone.findWithPrimary("頭"); + + assertSame(result, result2); + + return; + } + + /** + * Test of primary2global method, of class TypicalBone. + */ + @Test + public void testPrimary2global() { + System.out.println("primary2global"); + + String result; + + result = TypicalBone.primary2global("頭"); + assertEquals("head", result); + + String result1; + String result2; + + result1 = TypicalBone.primary2global("ボーン15"); + result2 = TypicalBone.primary2global("ボーン15"); + assertSame(result1, result2); + + result = TypicalBone.primary2global("XXX"); + assertNull(result); + + return; + } + + /** + * Test of global2primary method, of class TypicalBone. + */ + @Test + public void testGlobal2primary() { + System.out.println("global2primary"); + + String result; + + result = TypicalBone.global2primary("head"); + assertEquals("頭", result); + + result = TypicalBone.global2primary("head"); + assertEquals("頭", result); + + result = TypicalBone.global2primary("XXX"); + assertNull(result); + + return; + } + + /** + * Test of getBoneList method, of class TypicalBone. + */ + @Test + public void testGetBoneList() { + System.out.println("getBoneList"); + + List boneList; + + boneList = TypicalBone.getBoneList(); + + assertNotNull(boneList); + assertEquals(77, boneList.size()); + + TypicalBone bone1st = boneList.get(0); + TypicalBone boneLast = boneList.get(77-1); + + assertEquals("センター", bone1st.getTopPrimaryName()); + assertEquals("ボーン15", boneLast.getTopPrimaryName()); + + assertEquals("center", bone1st.getTopGlobalName()); + assertEquals("bone15", boneLast.getTopGlobalName()); + + return; + } + +} diff --git a/src/test/java/jp/sourceforge/mikutoga/typical/TypicalMorphTest.java b/src/test/java/jp/sourceforge/mikutoga/typical/TypicalMorphTest.java new file mode 100644 index 0000000..8a4bb86 --- /dev/null +++ b/src/test/java/jp/sourceforge/mikutoga/typical/TypicalMorphTest.java @@ -0,0 +1,210 @@ +/* + */ + +package jp.sourceforge.mikutoga.typical; + +import java.util.List; +import jp.sourceforge.mikutoga.pmd.MorphType; +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 TypicalMorphTest { + + public TypicalMorphTest() { + } + + @BeforeClass + public static void setUpClass() { + } + + @AfterClass + public static void tearDownClass() { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of getTypedMorphList method, of class TypicalMorph. + */ + @Test + public void testGetTypedMorphList() { + System.out.println("getTypedMorphList"); + + List morphList; + + morphList = TypicalMorph.getTypedMorphList(MorphType.EYEBROW); + assertEquals(6, morphList.size()); + + morphList = TypicalMorph.getTypedMorphList(MorphType.EYE); + assertEquals(7, morphList.size()); + + morphList = TypicalMorph.getTypedMorphList(MorphType.LIP); + assertEquals(12, morphList.size()); + + morphList = TypicalMorph.getTypedMorphList(MorphType.EXTRA); + assertEquals(2, morphList.size()); + + return; + } + + /** + * Test of findWithPrimary method, of class TypicalMorph. + */ + @Test + public void testFindWithPrimary() { + System.out.println("findWithPrimary"); + + TypicalMorph result; + + result = TypicalMorph.findWithPrimary("あ"); + assertNotNull(result); + assertEquals(MorphType.LIP, result.getMorphType()); + assertEquals("あ", result.getTopPrimaryName()); + assertEquals("a", result.getTopGlobalName()); + assertEquals(1, result.getPrimaryList().size()); + assertEquals("あ", result.getPrimaryList().get(0)); + assertEquals(1, result.getGlobalList().size()); + assertEquals("a", result.getGlobalList().get(0)); + + TypicalMorph result1; + TypicalMorph result2; + + result1 = TypicalMorph.findWithPrimary("べー"); + result2 = TypicalMorph.findWithPrimary("ぺろっ"); + assertSame(result1, result2); + assertEquals(MorphType.EXTRA, result1.getMorphType()); + assertEquals("べー", result1.getTopPrimaryName()); + assertEquals("tongue", result1.getTopGlobalName()); + assertEquals(2, result1.getPrimaryList().size()); + assertEquals("べー", result1.getPrimaryList().get(0)); + assertEquals("ぺろっ", result1.getPrimaryList().get(1)); + assertEquals(1, result1.getGlobalList().size()); + assertEquals("tongue", result1.getGlobalList().get(0)); + + return; + } + + /** + * Test of findWithGlobal method, of class TypicalMorph. + */ + @Test + public void testFindWithGlobal() { + System.out.println("findWithGlobal"); + + TypicalMorph result; + + result = TypicalMorph.findWithGlobal("a"); + assertNotNull(result); + + TypicalMorph result2; + result2 = TypicalMorph.findWithPrimary("あ"); + + assertSame(result, result2); + + return; + } + + /** + * Test of primary2global method, of class TypicalMorph. + */ + @Test + public void testPrimary2global() { + System.out.println("primary2global"); + + String result; + + result = TypicalMorph.primary2global("あ"); + assertEquals("a", result); + + String result1; + String result2; + + result1 = TypicalMorph.primary2global("べー"); + result2 = TypicalMorph.primary2global("ぺろっ"); + assertSame(result1, result2); + + result1 = TypicalMorph.primary2global("ウィンク"); + result2 = TypicalMorph.primary2global("ウィンク"); + assertSame(result1, result2); + + result = TypicalMorph.primary2global("XXX"); + assertNull(result); + + return; + } + + /** + * Test of global2primary method, of class TypicalMorph. + */ + @Test + public void testGlobal2primary() { + System.out.println("global2primary"); + + String result; + + result = TypicalMorph.global2primary("a"); + assertEquals("あ", result); + + result = TypicalMorph.global2primary("tongue"); + assertEquals("べー", result); + + result = TypicalMorph.global2primary("XXX"); + assertNull(result); + + return; + } + + /** + * Test of getMorphType method, of class TypicalMorph. + */ + @Test + public void testGetMorphType() { + System.out.println("getMorphType"); + + List morphList; + + morphList = TypicalMorph.getTypedMorphList(MorphType.EYEBROW); + + for(TypicalMorph morph : morphList){ + MorphType type = morph.getMorphType(); + assertEquals(MorphType.EYEBROW, type); + } + + morphList = TypicalMorph.getTypedMorphList(MorphType.EYE); + + for(TypicalMorph morph : morphList){ + MorphType type = morph.getMorphType(); + assertEquals(MorphType.EYE, type); + } + + morphList = TypicalMorph.getTypedMorphList(MorphType.LIP); + + for(TypicalMorph morph : morphList){ + MorphType type = morph.getMorphType(); + assertEquals(MorphType.LIP, type); + } + + morphList = TypicalMorph.getTypedMorphList(MorphType.EXTRA); + + for(TypicalMorph morph : morphList){ + MorphType type = morph.getMorphType(); + assertEquals(MorphType.EXTRA, type); + } + + return; + } + +}