2 * typical morph information
4 * License : The MIT License
5 * Copyright(c) 2011 MikuToga Partners
8 package jp.sfjp.mikutoga.typical;
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.EnumMap;
15 import java.util.List;
17 import javax.xml.parsers.ParserConfigurationException;
18 import jp.sfjp.mikutoga.pmd.MorphType;
19 import org.w3c.dom.Element;
20 import org.w3c.dom.NodeList;
21 import org.xml.sax.SAXException;
27 * <p>各モーフ情報はひとつ以上のプライマリ名(≒日本語名)と
28 * ゼロ個以上のグローバル名(≒英語名)を持つ。
32 * <p>和英対訳はMMD Ver7.39の同梱モデルにほぼ準拠。
34 public final class TypicalMorph extends I18nAlias {
36 private static final Class<?> THISCLASS = TypicalMorph.class;
37 private static final String MORPH_XML = "resources/typicalMorph.xml";
39 private static final String ELEM_MORPHGROUP = "morphGroup";
40 private static final String ELEM_MORPH = "morph";
41 private static final String ATTR_TYPE = "type";
42 private static final String ELEM_PRIMARY = "primary";
43 private static final String ELEM_GLOBAL = "global";
44 private static final String ATTR_NAME = "name";
46 private static final List<TypicalMorph> EMPTY = Collections.emptyList();
48 private static final Map<MorphType, List<TypicalMorph>> TYPED_MAP =
49 new EnumMap<MorphType, List<TypicalMorph>>(MorphType.class);
51 private static final AliasMap<TypicalMorph> MORPH_ALIAS_MAP =
52 new AliasMap<TypicalMorph>();
56 InputStream is = THISCLASS.getResourceAsStream(MORPH_XML);
60 top = I18nAlias.loadXml(is);
61 }catch(ParserConfigurationException e){
62 throw new ExceptionInInitializerError(e);
63 }catch(SAXException e){
64 throw new ExceptionInInitializerError(e);
65 }catch(IOException e){
66 throw new ExceptionInInitializerError(e);
75 private final MorphType type;
82 * 状況に応じて伸長する連結リストが用意される。
85 * @param primaryNum プライマリ名初期数。
86 * @param globalNum グローバル名初期数。
88 private TypicalMorph(MorphType type, int primaryNum, int globalNum){
89 super(primaryNum, globalNum);
93 assert this.getClass() == THISCLASS;
103 private static void parse(Element top) {
104 NodeList groupList = top.getElementsByTagName(ELEM_MORPHGROUP);
105 int groupNo = groupList.getLength();
106 for(int idx = 0; idx < groupNo; idx++){
107 Element groupElem = (Element) groupList.item(idx);
108 parseGroup(groupElem);
111 // 必要に応じモーフ枠に不変空リスト登録
112 for(MorphType morphType : MorphType.values()){
113 if( ! TYPED_MAP.containsKey(morphType) ){
114 TYPED_MAP.put(morphType, EMPTY);
123 * @param groupElem morphGroup要素
125 private static void parseGroup(Element groupElem){
126 String typeAttr = groupElem.getAttribute(ATTR_TYPE);
127 MorphType morphType = MorphType.valueOf(typeAttr);
129 NodeList morphList = groupElem.getElementsByTagName(ELEM_MORPH);
130 int morphNo = morphList.getLength();
131 List<TypicalMorph> groupedList =
132 new ArrayList<TypicalMorph>(morphNo);
134 for(int idx = 0; idx < morphNo; idx++){
135 Element morphElem = (Element) morphList.item(idx);
136 TypicalMorph morph = parseMorph(morphElem, morphType);
137 groupedList.add(morph);
138 MORPH_ALIAS_MAP.addAlias(morph);
141 groupedList = Collections.unmodifiableList(groupedList);
142 TYPED_MAP.put(morphType, groupedList);
149 * @param morphElem morph要素
153 private static TypicalMorph parseMorph(Element morphElem,
155 NodeList primaryNodes = morphElem.getElementsByTagName(ELEM_PRIMARY);
156 NodeList globalNodes = morphElem.getElementsByTagName(ELEM_GLOBAL);
157 int primaryNo = primaryNodes.getLength();
158 int globalNo = globalNodes.getLength();
160 assert primaryNo > 0;
162 TypicalMorph morph = new TypicalMorph(mtype, primaryNo, globalNo);
164 for(int idx = 0; idx < primaryNo; idx++){
165 Element primaryElem = (Element) primaryNodes.item(idx);
166 String primaryName = primaryElem.getAttribute(ATTR_NAME);
167 morph.addPrimaryName(primaryName);
170 for(int idx = 0; idx < globalNo; idx++){
171 Element globalElem = (Element) globalNodes.item(idx);
172 String globalName = globalElem.getAttribute(ATTR_NAME);
173 morph.addGlobalName(globalName);
182 * <p>同一グループ内ではXMLでの定義順が反映される。
184 private static void numbering(){
186 for(MorphType morphType : MorphType.values()){
187 for(TypicalMorph morph : TYPED_MAP.get(morphType)){
188 morph.setOrderNo(order++);
196 * 種別ごとのモーフ情報不変リストを取得する。
197 * @param morphType モーフ種別
200 public static List<TypicalMorph> getTypicalMorphList(
201 MorphType morphType ){
202 List<TypicalMorph> result = TYPED_MAP.get(morphType);
207 * プライマリ名の合致するモーフ情報を返す。
208 * NFKCで正規化されたプライマリ名で検索される。
209 * @param primaryName プライマリ名
210 * @return モーフ情報。見つからなければnull
212 public static TypicalMorph findWithPrimary(String primaryName){
213 TypicalMorph result = MORPH_ALIAS_MAP.getAliasByPrimary(primaryName);
218 * グローバル名の合致するモーフ情報を返す。
219 * NFKCで正規化されたグローバル名で検索される。
220 * @param globalName グローバル名
221 * @return モーフ情報。見つからなければnull
223 public static TypicalMorph findWithGlobal(String globalName){
224 TypicalMorph result = MORPH_ALIAS_MAP.getAliasByGlobal(globalName);
229 * プライマリ名をグローバル名に変換する。
230 * @param primaryName プライマリ名
231 * @return グローバル名。見つからなければnull
233 public static String primary2global(String primaryName){
234 String globalName = MORPH_ALIAS_MAP.primary2global(primaryName);
239 * グローバル名をプライマリ名へ変換する。
240 * @param globalName グローバル名
241 * @return プライマリ名。見つからなければnull
243 public static String global2primary(String globalName){
244 String primaryName = MORPH_ALIAS_MAP.global2primary(globalName);
253 public MorphType getMorphType(){