OSDN Git Service

4f907e8ac5ee09ff0a1379fd427c99b524375f54
[mikutoga/TogaGem.git] / src / main / java / jp / sourceforge / mikutoga / typical / TypicalBone.java
1 /*
2  * typical bone 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.Collections;
13 import java.util.HashMap;
14 import java.util.LinkedList;
15 import java.util.List;
16 import java.util.Map;
17 import javax.xml.parsers.ParserConfigurationException;
18 import org.w3c.dom.Element;
19 import org.w3c.dom.NodeList;
20 import org.xml.sax.SAXException;
21
22 /**
23  * 一般的な標準ボーン構成に関する情報。
24  * <p>各ボーン情報はひとつ以上のプライマリ名(≒日本語名)と
25  * ゼロ個以上のグローバル名(≒英語名)を持つ。
26  * <p>選択基準は独断。
27  * <p>和英対訳はMMD Ver7.39の同梱モデルにほぼ準拠。
28  */
29 public final class TypicalBone extends I18nAlias {
30
31     private static final Class<?> THISCLASS = TypicalBone.class;
32     private static final String BONE_XML = "resources/typicalBone.xml";
33
34     private static final List<TypicalBone> TYP_BONE_LIST =
35             new LinkedList<TypicalBone>();
36     private static final Map<String, TypicalBone> PRIMARY_MAP =
37             new HashMap<String, TypicalBone>();
38     private static final Map<String, TypicalBone> GLOBAL_MAP =
39             new HashMap<String, TypicalBone>();
40
41     private static final List<TypicalBone> TYP_BONE_UNMODLIST =
42             Collections.unmodifiableList(TYP_BONE_LIST);
43
44     static{
45         InputStream is = THISCLASS.getResourceAsStream(BONE_XML);
46         Element top;
47         try{
48             top = I18nAlias.loadXml(is);
49         }catch(ParserConfigurationException e){
50             throw new ExceptionInInitializerError(e);
51         }catch(SAXException e){
52             throw new ExceptionInInitializerError(e);
53         }catch(IOException e){
54             throw new ExceptionInInitializerError(e);
55         }
56
57         parse(top);
58
59         numbering();
60     }
61
62
63     /**
64      * コンストラクタ。
65      * <p>各初期数が0以下の場合は、
66      * 状況に応じて伸長する連結リストが用意される。
67      * @param primaryNo プライマリ名初期数。
68      * @param globalNo グローバル名初期数。
69      */
70     private TypicalBone(int primaryNo, int globalNo){
71         super(primaryNo, globalNo);
72         return;
73     }
74
75
76     /**
77      * XML文書の最上位構造を解読する。
78      * @param top 最上位要素
79      */
80     private static void parse(Element top) {
81         NodeList boneList = top.getElementsByTagName("bone");
82         int boneNo = boneList.getLength();
83         for(int idx = 0; idx < boneNo; idx++){
84             Element bone = (Element) boneList.item(idx);
85             TypicalBone typBone = parseBone(bone);
86             TYP_BONE_LIST.add(typBone);
87         }
88
89         return;
90     }
91
92     /**
93      * bone要素を解読する。
94      * @param bone bone要素
95      * @return ボーン情報
96      */
97     private static TypicalBone parseBone(Element bone){
98         NodeList primaryNodes = bone.getElementsByTagName("primary");
99         NodeList globalNodes  = bone.getElementsByTagName("global");
100         int primaryNo = primaryNodes.getLength();
101         int globalNo  = globalNodes.getLength();
102
103         TypicalBone typBone = new TypicalBone(primaryNo, globalNo);
104
105         for(int idx = 0; idx < primaryNo; idx++){
106             Element primary = (Element) primaryNodes.item(idx);
107             String name = primary.getAttribute("name");
108             typBone.addPrimaryName(name);
109         }
110
111         for(int idx = 0; idx < globalNo; idx++){
112             Element global = (Element) globalNodes.item(idx);
113             String name = global.getAttribute("name");
114             typBone.addGlobalName(name);
115         }
116
117         for(String primaryName : typBone.getPrimaryList()){
118             String key = normalize(primaryName).intern();
119             PRIMARY_MAP.put(key, typBone);
120         }
121
122         for(String globalName : typBone.getGlobalList()){
123             String key = normalize(globalName).intern();
124             GLOBAL_MAP.put(key, typBone);
125         }
126
127         return typBone;
128     }
129
130     /**
131      * 全ボーン情報を一意に順序付ける設定を行う。
132      * <p>XMLでの定義順が反映される。
133      */
134     private static void numbering(){
135         int order = 0;
136         for(TypicalBone bone : TYP_BONE_LIST){
137             bone.setOrderNo(order++);
138         }
139
140         return;
141     }
142
143     /**
144      * 全ボーンの不変リストを返す。
145      * @return 全ボーンのリスト
146      */
147     public static List<TypicalBone> getBoneList(){
148         return TYP_BONE_UNMODLIST;
149     }
150
151     /**
152      * プライマリ名の合致するボーン情報を返す。
153      * NFKCで正規化されたプライマリ名で検索される。
154      * @param primaryName プライマリ名
155      * @return モーフ情報。見つからなければnull
156      */
157     public static TypicalBone findWithPrimary(String primaryName){
158         String key = normalize(primaryName);
159         TypicalBone result = PRIMARY_MAP.get(key);
160         return result;
161     }
162
163     /**
164      * グローバル名の合致するボーン情報を返す。
165      * NFKCで正規化されたグローバル名で検索される。
166      * @param globalName グローバル名
167      * @return モーフ情報。見つからなければnull
168      */
169     public static TypicalBone findWithGlobal(String globalName){
170         String key = normalize(globalName);
171         TypicalBone result = GLOBAL_MAP.get(key);
172         return result;
173     }
174
175     /**
176      * プライマリ名をグローバル名に変換する。
177      * @param primaryName プライマリ名
178      * @return グローバル名。見つからなければnull
179      */
180     public static String primary2global(String primaryName){
181         TypicalBone bone = findWithPrimary(primaryName);
182         if(bone == null) return null;
183         String global = bone.getTopGlobalName();
184         return global;
185     }
186
187     /**
188      * グローバル名をプライマリ名へ変換する。
189      * @param globalName グローバル名
190      * @return プライマリ名。見つからなければnull
191      */
192     public static String global2primary(String globalName){
193         TypicalBone bone = findWithGlobal(globalName);
194         if(bone == null) return null;
195         String primary = bone.getTopPrimaryName();
196         return primary;
197     }
198
199 }