OSDN Git Service

ローカルスキーマ参照処理の共通化
[mikutoga/TogaGem.git] / src / main / java / jp / sourceforge / mikutoga / xml / LocalSchema.java
1 /*
2  * local xml schema
3  *
4  * License : The MIT License
5  * Copyright(c) 2013 MikuToga Partners
6  */
7
8 package jp.sourceforge.mikutoga.xml;
9
10 import java.io.BufferedInputStream;
11 import java.io.IOException;
12 import java.io.InputStream;
13 import java.net.MalformedURLException;
14 import java.net.URI;
15 import java.net.URL;
16 import java.util.LinkedList;
17 import java.util.List;
18 import javax.xml.XMLConstants;
19 import javax.xml.transform.Source;
20 import javax.xml.transform.stream.StreamSource;
21 import javax.xml.validation.Schema;
22 import javax.xml.validation.SchemaFactory;
23 import org.xml.sax.SAXException;
24
25 /**
26  * XML用各種スキーマのローカル参照解決基盤。
27  */
28 public abstract class LocalSchema {
29
30     /**
31      * コンストラクタ。
32      */
33     protected LocalSchema(){
34         super();
35         return;
36     }
37
38
39     /**
40      * XML Schema 用のスキーマファクトリを返す。
41      * @return スキーマファクトリ
42      */
43     private static SchemaFactory newSchemaFactory(){
44         SchemaFactory schemaFactory =
45                 SchemaFactory.newInstance(
46                     XMLConstants.W3C_XML_SCHEMA_NS_URI
47                 );
48
49 //      schemaFactory.setFeature(name, value);
50 //      schemaFactory.setProperty(name, object);
51
52         schemaFactory.setErrorHandler(BotherHandler.HANDLER);
53
54         return schemaFactory;
55     }
56
57     /**
58      * ローカルスキーマをロードする。
59      * <p>任意のリゾルバを指定可能
60      * @param resolver リゾルバ
61      * @param lscs ローカルスキーマ情報の配列
62      * @return スキーマ
63      */
64     public static Schema newSchema(XmlResourceResolver resolver,
65                                     LocalSchema... lscs ){
66         List<Source> sourceList = new LinkedList<Source>();
67         for(LocalSchema lsc : lscs){
68             if(lsc == null) continue;
69             lsc.appendToUriMap(resolver);
70
71             Source local = lsc.getLocalSchemaSource();
72             if(local == null) continue;
73             sourceList.add(local);
74         }
75
76         SchemaFactory schemaFactory = newSchemaFactory();
77         schemaFactory.setResourceResolver(resolver);
78
79         Source[] sources = new Source[sourceList.size()];
80         sourceList.toArray(sources);
81
82         Schema result;
83         try{
84             if(sources.length <= 0){
85                 result = schemaFactory.newSchema();
86             }else{
87                 result = schemaFactory.newSchema(sources);
88             }
89         }catch(SAXException e){   // Build error
90             assert false;
91             throw new AssertionError(e);
92         }
93
94         return result;
95     }
96
97     /**
98      * オリジナル版スキーマ定義のURIを返す。
99      * <p>nullを返す場合は
100      * スキーマの自動判定&ダウンロードが求められていると見なされる。
101      * <p>このクラスの実装では常にnullを返す。
102      * @return オリジナル版スキーマのURL。
103      */
104     public abstract URI getOriginalSchema();
105
106     /**
107      * ローカルリソース版スキーマ定義のURIを返す。
108      * <p>nullを返す場合は
109      * スキーマの自動判定&ダウンロードが求められていると見なされる。
110      * <p>このクラスの実装では常にnullを返す。
111      * @return ローカルリソース版スキーマのURL。
112      */
113     public abstract URI getLocalSchema();
114
115     /**
116      * スキーマのSourceを返す。
117      * <p>ローカルスキーマのSourceを返す。
118      * @return Source 見つからなければnull
119      */
120     public Source getLocalSchemaSource(){
121         URI uri;
122
123         uri = getLocalSchema();
124         if(uri == null) return null;
125
126         URL url;
127         try{
128             url = uri.toURL();
129         }catch(MalformedURLException e){      // Build error
130             assert false;
131             throw new AssertionError(e);
132         }
133
134         InputStream is;
135         try{
136             is = url.openStream();
137         }catch(IOException e){              // Build error
138             assert false;
139             throw new AssertionError(e);
140         }
141         is = new BufferedInputStream(is);
142
143         Source result = new StreamSource(is);
144
145         return result;
146     }
147
148     /**
149      * ローカルで解決可能なリソース参照をリゾルバに追加登録する。
150      * @param resolver リゾルバ
151      */
152     public void appendToUriMap(XmlResourceResolver resolver){
153         URI original = getOriginalSchema();
154         URI local    = getLocalSchema();
155
156         if(original == null) return;
157
158         resolver.putRedirected(original, local);
159
160         return;
161     }
162
163 }