OSDN Git Service

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