OSDN Git Service

12c37d818480c115e57a41e1e09997a8fba96ec9
[mikutoga/TogaGem.git] / src / main / java / jp / sourceforge / mikutoga / typical / TypicalMorph.java
1 /*
2  * typical morph information
3  *
4  * License : The MIT License
5  * Copyright(c) 2011 MikuToga Partners
6  */
7
8 package jp.sourceforge.mikutoga.typical;
9
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.HashMap;
16 import java.util.List;
17 import java.util.Map;
18 import javax.xml.parsers.ParserConfigurationException;
19 import jp.sourceforge.mikutoga.pmd.MorphType;
20 import org.w3c.dom.Element;
21 import org.w3c.dom.NodeList;
22 import org.xml.sax.SAXException;
23
24
25 /**
26  * 一般的な標準モーフに関する情報。
27  * <p>各モーフ情報はひとつ以上のプライマリ名(≒日本語名)と
28  * ゼロ個以上のグローバル名(≒英語名)を持つ。
29  * <p>選択基準は独断。
30  * <p>和英対訳はMMD Ver7.39の同梱モデルにほぼ準拠。
31  */
32 public final class TypicalMorph extends TypicalObject {
33
34     private static final Class<?> THISCLASS = TypicalMorph.class;
35     private static final String MORPH_XML = "resources/typicalMorph.xml";
36
37     private static final List<TypicalMorph> EMPTY = Collections.emptyList();
38
39     private static final Map<MorphType, List<TypicalMorph>> TYPED_MAP =
40             new EnumMap<MorphType, List<TypicalMorph>>(MorphType.class);
41
42     private static final Map<String, TypicalMorph> PRIMARY_MAP =
43             new HashMap<String, TypicalMorph>();
44     private static final Map<String, TypicalMorph> GLOBAL_MAP =
45             new HashMap<String, TypicalMorph>();
46
47
48     static{
49         InputStream is = THISCLASS.getResourceAsStream(MORPH_XML);
50         Element top;
51         try{
52             top = TypicalObject.loadXml(is);
53         }catch(ParserConfigurationException e){
54             throw new ExceptionInInitializerError(e);
55         }catch(SAXException e){
56             throw new ExceptionInInitializerError(e);
57         }catch(IOException e){
58             throw new ExceptionInInitializerError(e);
59         }
60
61         parse(top);
62
63         numbering();
64     }
65
66
67     private final MorphType type;
68
69
70     /**
71      * コンストラクタ。
72      * <p>各初期数が0以下の場合は、状況に応じて伸長する連結リストが用意される。
73      * @param type モーフ種別
74      * @param primaryNo プライマリ名初期数。
75      * @param globalNo グローバル名初期数。
76      */
77     private TypicalMorph(MorphType type, int primaryNo, int globalNo){
78         super(primaryNo, globalNo);
79         this.type = type;
80         return;
81     }
82
83
84     /**
85      * XML文書の最上位構造を解読する。
86      * @param top 最上位要素
87      */
88     private static void parse(Element top) {
89         NodeList groupList = top.getElementsByTagName("morphGroup");
90         int groupNo = groupList.getLength();
91         for(int idx = 0; idx < groupNo; idx++){
92             Element group = (Element) groupList.item(idx);
93             parseGroup(group);
94         }
95
96         // 空リスト登録
97         for(MorphType morphType : MorphType.values()){
98             if( ! TYPED_MAP.containsKey(morphType) ){
99                 TYPED_MAP.put(morphType, EMPTY);
100             }
101         }
102
103         return;
104     }
105
106     /**
107      * モーフグループ構造を解読する。
108      * @param group morphGroup要素
109      */
110     private static void parseGroup(Element group){
111         String typeAttr = group.getAttribute("type");
112         MorphType morphType = MorphType.valueOf(typeAttr);
113
114         NodeList morphList = group.getElementsByTagName("morph");
115         int morphNo = morphList.getLength();
116         List<TypicalMorph> groupedList = new ArrayList<TypicalMorph>(morphNo);
117
118         for(int idx = 0; idx < morphNo; idx++){
119             Element morph = (Element) morphList.item(idx);
120             TypicalMorph common = parseMorph(morph, morphType);
121             groupedList.add(common);
122         }
123
124         TYPED_MAP.put(morphType, Collections.unmodifiableList(groupedList));
125
126         return;
127     }
128
129     /**
130      * morph要素を解読する。
131      * @param morph morph要素
132      * @param mtype モーフ種別
133      * @return モーフ情報
134      */
135     private static TypicalMorph parseMorph(Element morph, MorphType mtype){
136         NodeList primaryNodes = morph.getElementsByTagName("primary");
137         NodeList globalNodes  = morph.getElementsByTagName("global");
138         int primaryNo = primaryNodes.getLength();
139         int globalNo  = globalNodes.getLength();
140
141         TypicalMorph typMorph = new TypicalMorph(mtype, primaryNo, globalNo);
142
143         for(int idx = 0; idx < primaryNo; idx++){
144             Element primary = (Element) primaryNodes.item(idx);
145             String name = primary.getAttribute("name");
146             typMorph.primaryList.add(name);
147         }
148
149         for(int idx = 0; idx < globalNo; idx++){
150             Element global = (Element) globalNodes.item(idx);
151             String name = global.getAttribute("name");
152             typMorph.globalList.add(name);
153         }
154
155         for(String primaryName : typMorph.primaryList){
156             PRIMARY_MAP.put(primaryName, typMorph);
157         }
158
159         for(String globalName : typMorph.globalList){
160             GLOBAL_MAP.put(globalName, typMorph);
161         }
162
163         return typMorph;
164     }
165
166     /**
167      * 全モーフ情報を一意に順序付ける設定を行う。
168      * <p>同一グループ内ではXMLでの定義順が反映される。
169      */
170     private static void numbering(){
171         int order = 0;
172         for(MorphType morphType : MorphType.values()){
173             for(TypicalMorph common : TYPED_MAP.get(morphType)){
174                 common.orderNo = order++;
175             }
176         }
177
178         return;
179     }
180
181
182     /**
183      * 種別ごとのモーフ情報リストを取得する。
184      * @param morphType モーフ種別
185      * @return モーフ情報リスト
186      */
187     public static List<TypicalMorph> getTypedMorphList(MorphType morphType){
188         List<TypicalMorph> result = TYPED_MAP.get(morphType);
189         return result;
190     }
191
192     /**
193      * プライマリ名の合致するモーフ情報を返す。
194      * @param primaryName プライマリ名
195      * @return モーフ情報。見つからなければnull
196      */
197     public static TypicalMorph findWithPrimary(String primaryName){
198         TypicalMorph result = PRIMARY_MAP.get(primaryName);
199         return result;
200     }
201
202     /**
203      * グローバル名の合致するモーフ情報を返す。
204      * @param globalName グローバル名
205      * @return モーフ情報。見つからなければnull
206      */
207     public static TypicalMorph findWithGlobal(String globalName){
208         TypicalMorph result = GLOBAL_MAP.get(globalName);
209         return result;
210     }
211
212     /**
213      * プライマリ名をグローバル名に変換する。
214      * @param primaryName プライマリ名
215      * @return グローバル名。見つからなければnull
216      */
217     public static String primary2global(String primaryName){
218         TypicalMorph morph = findWithPrimary(primaryName);
219         if(morph == null) return null;
220         String global = morph.getTopGlobalName();
221         return global;
222     }
223
224     /**
225      * グローバル名をプライマリ名へ変換する。
226      * @param globalName グローバル名
227      * @return プライマリ名。見つからなければnull
228      */
229     public static String global2primary(String globalName){
230         TypicalMorph morph = findWithGlobal(globalName);
231         if(morph == null) return null;
232         String primary = morph.getTopPrimaryName();
233         return primary;
234     }
235
236     /**
237      * モーフ種別を返す。
238      * @return モーフ種別
239      */
240     public MorphType getMorphType(){
241         return this.type;
242     }
243
244 }