OSDN Git Service

Pmd2XMLとの共通化
[mikutoga/Vmd2XML.git] / src / main / java / jp / sfjp / mikutoga / vmd2xml / Vmd2XmlConv.java
1 /*
2  * vmd 2 xml converter
3  *
4  * License : The MIT License
5  * Copyright(c) 2013 MikuToga Partners
6  */
7
8 package jp.sfjp.mikutoga.vmd2xml;
9
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.io.OutputStream;
13 import javax.xml.parsers.DocumentBuilder;
14 import javax.xml.parsers.DocumentBuilderFactory;
15 import javax.xml.parsers.ParserConfigurationException;
16 import javax.xml.validation.Schema;
17 import jp.sfjp.mikutoga.bin.parser.MmdFormatException;
18 import jp.sfjp.mikutoga.vmd.IllegalVmdDataException;
19 import jp.sfjp.mikutoga.vmd.model.VmdMotion;
20 import jp.sfjp.mikutoga.vmd.model.binio.VmdExporter;
21 import jp.sfjp.mikutoga.vmd.model.binio.VmdLoader;
22 import jp.sourceforge.mikutoga.vmd.model.xml.Schema110820;
23 import jp.sourceforge.mikutoga.vmd.model.xml.VmdXmlExporter;
24 import jp.sourceforge.mikutoga.vmd.model.xml.Xml2VmdLoader;
25 import jp.sourceforge.mikutoga.xml.BotherHandler;
26 import jp.sourceforge.mikutoga.xml.SchemaUtil;
27 import jp.sourceforge.mikutoga.xml.TogaXmlException;
28 import jp.sourceforge.mikutoga.xml.XmlResourceResolver;
29 import org.xml.sax.InputSource;
30 import org.xml.sax.SAXException;
31
32 /**
33  * VMD-XML間コンバータ本体。
34  */
35 public class Vmd2XmlConv {
36
37     private MotionFileType inTypes  = MotionFileType.NONE;
38     private MotionFileType outTypes = MotionFileType.NONE;
39     private String newLine = "\r\n";
40     private String generator = null;
41     private boolean isQuaternionMode = true;
42
43
44     /**
45      * コンストラクタ。
46      */
47     public Vmd2XmlConv(){
48         super();
49         return;
50     }
51
52
53     /**
54      * ドキュメントビルダファクトリを初期化する。
55      * @param builderFactory ドキュメントビルダファクトリ
56      */
57     private static void initBuilderFactory(
58             DocumentBuilderFactory builderFactory ){
59         builderFactory.setCoalescing(true);
60         builderFactory.setExpandEntityReferences(true);
61         builderFactory.setIgnoringComments(true);
62         builderFactory.setIgnoringElementContentWhitespace(false);
63         builderFactory.setNamespaceAware(true);
64         builderFactory.setValidating(false);
65         builderFactory.setXIncludeAware(false);
66
67 //      builderFactory.setFeature(name, value);
68 //      builderFactory.setAttribute(name, value);
69
70         return;
71     }
72
73     /**
74      * DOMビルダ生成。
75      * @return DOMビルダ
76      */
77     private DocumentBuilder buildBuilder(){
78         XmlResourceResolver resolver = new XmlResourceResolver();
79
80         Schema schema;
81         schema = SchemaUtil.newSchema(resolver, Schema110820.SINGLETON);
82
83         DocumentBuilderFactory builderFactory =
84                 DocumentBuilderFactory.newInstance();
85         initBuilderFactory(builderFactory);
86         builderFactory.setSchema(schema);
87
88         DocumentBuilder result;
89         try{
90             result = builderFactory.newDocumentBuilder();
91         }catch(ParserConfigurationException e){
92             assert false;
93             throw new AssertionError(e);
94         }
95         result.setEntityResolver(resolver);
96         result.setErrorHandler(BotherHandler.HANDLER);
97
98         return result;
99     }
100
101     /**
102      * 入力ファイル種別を設定する。
103      * @param type ファイル種別
104      * @throws IllegalArgumentException 具体的な種別を渡さなかった
105      */
106     public void setInType(MotionFileType type)
107             throws IllegalArgumentException {
108         if(type == null) throw new NullPointerException();
109         if(type == MotionFileType.NONE) throw new IllegalArgumentException();
110         this.inTypes = type;
111         return;
112     }
113
114     /**
115      * 入力ファイル種別を返す。
116      * @return ファイル種別
117      */
118     public MotionFileType getInTypes(){
119         return this.inTypes;
120     }
121
122     /**
123      * 出力ファイル種別を設定する。
124      * @param type ファイル種別
125      * @throws IllegalArgumentException 具体的な種別を渡さなかった
126      */
127     public void setOutType(MotionFileType type)
128             throws IllegalArgumentException {
129         if(type == null) throw new NullPointerException();
130         if(type == MotionFileType.NONE) throw new IllegalArgumentException();
131         this.outTypes = type;
132         return;
133     }
134
135     /**
136      * 出力ファイル種別を返す。
137      * @return ファイル種別
138      */
139     public MotionFileType getOutTypes(){
140         return this.outTypes;
141     }
142
143     /**
144      * XML出力用改行文字列を設定する。
145      * @param newline 改行文字
146      */
147     public void setNewline(String newline){
148         this.newLine = newline;
149         return;
150     }
151
152     /**
153      * XML出力用改行文字列を返す。
154      * @return 改行文字
155      */
156     public String getNewline(){
157         return this.newLine;
158     }
159
160     /**
161      * ジェネレータ名を設定する。
162      * @param generator ジェネレータ名。表示したくない場合はnull
163      */
164     public void setGenerator(String generator){
165         this.generator = generator;
166         return;
167     }
168
169     /**
170      * ジェネレータ名を返す。
171      * @return ジェネレータ名。非表示の場合はnullを返す。
172      */
173     public String getGenerator(){
174         return this.generator;
175     }
176
177     /**
178      * 回転情報をクォータニオン形式でXML出力するか設定する。
179      * @param sw クォータニオン形式ならtrue、
180      * YXZオイラー角で出力したければfalse。
181      */
182     public void setQuaterniomMode(boolean sw){
183         this.isQuaternionMode = sw;
184         return;
185     }
186
187     /**
188      * 回転情報のXML出力形式を得る。
189      * @return クォータニオン形式ならtrue、YXZオイラー角形式ならfalse。
190      */
191     public boolean isQuaterniomMode(){
192         return this.isQuaternionMode;
193     }
194
195     /**
196      * ファイル変換を行う。
197      * @param is 入力ストリーム
198      * @param os 出力ストリーム
199      * @throws IOException 入力エラー
200      * @throws MmdFormatException フォーマットエラー
201      * @throws SAXException XMLエラー
202      * @throws TogaXmlException XMLエラー
203      * @throws IllegalVmdDataException 内部エラー
204      */
205     public void convert(InputStream is, OutputStream os)
206             throws IOException,
207                    MmdFormatException,
208                    SAXException,
209                    TogaXmlException,
210                    IllegalVmdDataException {
211         VmdMotion motion = readMotion(is);
212         motion.frameSort();
213         writeMotion(motion, os);
214         return;
215     }
216
217     /**
218      * モーションファイルを読み込む。
219      * @param is 入力ストリーム
220      * @return モーションデータ
221      * @throws IOException 入力エラー
222      * @throws MmdFormatException フォーマットエラー
223      * @throws SAXException XMLエラー
224      * @throws TogaXmlException XMLエラー
225      */
226     public VmdMotion readMotion(InputStream is)
227             throws IOException,
228                    MmdFormatException,
229                    SAXException,
230                    TogaXmlException {
231         VmdMotion motion = null;
232
233         if(this.inTypes.isVmd()){
234             motion = vmdRead(is);
235         }else if(this.inTypes.isXml()){
236             motion = xmlRead(is);
237         }else{
238             throw new IllegalStateException();
239         }
240
241         return motion;
242     }
243
244     /**
245      * モーションファイルを出力する。
246      * @param motion モーションデータ
247      * @param os 出力ストリーム
248      * @throws IOException 出力エラー
249      * @throws IllegalVmdDataException データの不備
250      */
251     public void writeMotion(VmdMotion motion, OutputStream os)
252             throws IOException,
253                    IllegalVmdDataException {
254         if(this.outTypes.isVmd()){
255             vmdOut(motion, os);
256         }else if(this.outTypes.isXml()){
257             xmlOut(motion, os);
258         }else{
259             throw new IllegalStateException();
260         }
261
262         return;
263     }
264
265     /**
266      * VMDファイルからモーションデータを読み込む。
267      * @param is 入力ストリーム
268      * @return モーションデータ
269      * @throws IOException 入力エラー
270      * @throws MmdFormatException 不正なVMDファイルフォーマット
271      */
272     private VmdMotion vmdRead(InputStream is)
273             throws IOException, MmdFormatException{
274         VmdLoader loader = new VmdLoader();
275
276         loader.setIgnoreName(true);
277         loader.setRedundantCheck(false);
278
279         VmdMotion motion = loader.load(is);
280
281         return motion;
282     }
283
284     /**
285      * XMLファイルからモーションデータを読み込む。
286      * @param is 入力ストリーム
287      * @return モーションデータ
288      * @throws IOException 入力エラー
289      * @throws SAXException XML構文エラー
290      * @throws TogaXmlException 不正なXMLデータ
291      */
292     private VmdMotion xmlRead(InputStream is)
293             throws IOException,
294                    SAXException,
295                    TogaXmlException {
296         InputSource source = new InputSource(is);
297         VmdMotion result = xmlRead(source);
298         return result;
299     }
300
301     /**
302      * XMLファイルからモーションデータを読み込む。
303      * @param source 入力ソース
304      * @return モーションデータ
305      * @throws IOException 入力エラー
306      * @throws SAXException XML構文エラー
307      * @throws TogaXmlException 不正なXMLデータ
308      */
309     private VmdMotion xmlRead(InputSource source)
310             throws IOException,
311                    SAXException,
312                    TogaXmlException {
313         DocumentBuilder builder = buildBuilder();
314         Xml2VmdLoader loader = new Xml2VmdLoader(builder);
315         VmdMotion motion = loader.parse(source);
316         return motion;
317     }
318
319     /**
320      * モーションデータをVMDファイルに出力する。
321      * @param motion モーションデータ
322      * @param ostream 出力ストリーム
323      * @throws IOException 出力エラー
324      * @throws IllegalVmdDataException 不正なモーションデータ
325      */
326     private void vmdOut(VmdMotion motion, OutputStream ostream)
327             throws IOException, IllegalVmdDataException{
328         VmdExporter exporter = new VmdExporter();
329         exporter.dumpVmdMotion(motion, ostream);
330         ostream.close();
331         return;
332     }
333
334     /**
335      * モーションデータをXMLファイルに出力する。
336      * @param motion モーションデータ
337      * @param ostream 出力ストリーム
338      * @throws IOException 出力エラー
339      * @throws IllegalVmdDataException 不正なモーションデータ
340      */
341     private void xmlOut(VmdMotion motion, OutputStream ostream)
342             throws IOException, IllegalVmdDataException{
343         VmdXmlExporter exporter = new VmdXmlExporter(ostream);
344
345         exporter.setNewLine(this.newLine);
346         exporter.setGenerator(this.generator);
347         exporter.setQuaternionMode(this.isQuaternionMode);
348
349         exporter.putVmdXml(motion);
350
351         exporter.close();
352
353         return;
354     }
355
356 }