OSDN Git Service

PmdLimitsパッケージ移動
[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.sfjp.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 I18nAlias {
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 = I18nAlias.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      * 状況に応じて伸長する連結リストが用意される。
74      * @param type モーフ種別
75      * @param primaryNo プライマリ名初期数。
76      * @param globalNo グローバル名初期数。
77      */
78     private TypicalMorph(MorphType type, int primaryNo, int globalNo){
79         super(primaryNo, globalNo);
80         this.type = type;
81         return;
82     }
83
84
85     /**
86      * XML文書の最上位構造を解読する。
87      * @param top 最上位要素
88      */
89     private static void parse(Element top) {
90         NodeList groupList = top.getElementsByTagName("morphGroup");
91         int groupNo = groupList.getLength();
92         for(int idx = 0; idx < groupNo; idx++){
93             Element group = (Element) groupList.item(idx);
94             parseGroup(group);
95         }
96
97         // 必要に応じモーフ枠に不変空リスト登録
98         for(MorphType morphType : MorphType.values()){
99             if( ! TYPED_MAP.containsKey(morphType) ){
100                 TYPED_MAP.put(morphType, EMPTY);
101             }
102         }
103
104         return;
105     }
106
107     /**
108      * モーフグループ構造を解読する。
109      * @param group morphGroup要素
110      */
111     private static void parseGroup(Element group){
112         String typeAttr = group.getAttribute("type");
113         MorphType morphType = MorphType.valueOf(typeAttr);
114
115         NodeList morphList = group.getElementsByTagName("morph");
116         int morphNo = morphList.getLength();
117         List<TypicalMorph> groupedList =
118                 new ArrayList<TypicalMorph>(morphNo);
119
120         for(int idx = 0; idx < morphNo; idx++){
121             Element morph = (Element) morphList.item(idx);
122             TypicalMorph common = parseMorph(morph, morphType);
123             groupedList.add(common);
124         }
125
126         groupedList = Collections.unmodifiableList(groupedList);
127         TYPED_MAP.put(morphType, groupedList);
128
129         return;
130     }
131
132     /**
133      * morph要素を解読する。
134      * @param morph morph要素
135      * @param mtype モーフ種別
136      * @return モーフ情報
137      */
138     private static TypicalMorph parseMorph(Element morph, MorphType mtype){
139         NodeList primaryNodes = morph.getElementsByTagName("primary");
140         NodeList globalNodes  = morph.getElementsByTagName("global");
141         int primaryNo = primaryNodes.getLength();
142         int globalNo  = globalNodes.getLength();
143
144         TypicalMorph typMorph = new TypicalMorph(mtype, primaryNo, globalNo);
145
146         for(int idx = 0; idx < primaryNo; idx++){
147             Element primary = (Element) primaryNodes.item(idx);
148             String name = primary.getAttribute("name");
149             typMorph.addPrimaryName(name);
150         }
151
152         for(int idx = 0; idx < globalNo; idx++){
153             Element global = (Element) globalNodes.item(idx);
154             String name = global.getAttribute("name");
155             typMorph.addGlobalName(name);
156         }
157
158         for(String primaryName : typMorph.getPrimaryList()){
159             String key = normalize(primaryName).intern();
160             PRIMARY_MAP.put(key, typMorph);
161         }
162
163         for(String globalName : typMorph.getGlobalList()){
164             String key = normalize(globalName).intern();
165             GLOBAL_MAP.put(key, typMorph);
166         }
167
168         return typMorph;
169     }
170
171     /**
172      * 全モーフ情報を一意に順序付ける設定を行う。
173      * <p>同一グループ内ではXMLでの定義順が反映される。
174      */
175     private static void numbering(){
176         int order = 0;
177         for(MorphType morphType : MorphType.values()){
178             for(TypicalMorph common : TYPED_MAP.get(morphType)){
179                 common.setOrderNo(order++);
180             }
181         }
182
183         return;
184     }
185
186
187     /**
188      * 種別ごとのモーフ情報リストを取得する。
189      * @param morphType モーフ種別
190      * @return モーフ情報リスト
191      */
192     public static List<TypicalMorph> getTypedMorphList(MorphType morphType){
193         List<TypicalMorph> result = TYPED_MAP.get(morphType);
194         return result;
195     }
196
197     /**
198      * プライマリ名の合致するモーフ情報を返す。
199      * NFKCで正規化されたプライマリ名で検索される。
200      * @param primaryName プライマリ名
201      * @return モーフ情報。見つからなければnull
202      */
203     public static TypicalMorph findWithPrimary(String primaryName){
204         String key = normalize(primaryName);
205         TypicalMorph result = PRIMARY_MAP.get(key);
206         return result;
207     }
208
209     /**
210      * グローバル名の合致するモーフ情報を返す。
211      * NFKCで正規化されたグローバル名で検索される。
212      * @param globalName グローバル名
213      * @return モーフ情報。見つからなければnull
214      */
215     public static TypicalMorph findWithGlobal(String globalName){
216         String key = normalize(globalName);
217         TypicalMorph result = GLOBAL_MAP.get(key);
218         return result;
219     }
220
221     /**
222      * プライマリ名をグローバル名に変換する。
223      * @param primaryName プライマリ名
224      * @return グローバル名。見つからなければnull
225      */
226     public static String primary2global(String primaryName){
227         TypicalMorph morph = findWithPrimary(primaryName);
228         if(morph == null) return null;
229         String global = morph.getTopGlobalName();
230         return global;
231     }
232
233     /**
234      * グローバル名をプライマリ名へ変換する。
235      * @param globalName グローバル名
236      * @return プライマリ名。見つからなければnull
237      */
238     public static String global2primary(String globalName){
239         TypicalMorph morph = findWithGlobal(globalName);
240         if(morph == null) return null;
241         String primary = morph.getTopPrimaryName();
242         return primary;
243     }
244
245
246     /**
247      * モーフ種別を返す。
248      * @return モーフ種別
249      */
250     public MorphType getMorphType(){
251         return this.type;
252     }
253
254 }