OSDN Git Service

Merge release/v3.122.2
[mikutoga/TogaGem.git] / src / main / java / jp / sfjp / mikutoga / typical / I18nAlias.java
1 /*
2  * internationalization name alias
3  *
4  * License : The MIT License
5  * Copyright(c) 2011 MikuToga Partners
6  */
7
8 package jp.sfjp.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.Comparator;
15 import java.util.LinkedList;
16 import java.util.List;
17 import javax.xml.XMLConstants;
18 import javax.xml.parsers.DocumentBuilder;
19 import javax.xml.parsers.DocumentBuilderFactory;
20 import javax.xml.parsers.ParserConfigurationException;
21 import org.w3c.dom.Document;
22 import org.w3c.dom.Element;
23 import org.xml.sax.SAXException;
24
25 /**
26  * 国際化&別名管理オブジェクトの実装基板。
27  *
28  * <p>別名管理オブジェクトは、
29  * 各々のリストの先頭が代表名となる、
30  * プライマリ名の不変リストとグローバル名の不変リストを持つ。
31  *
32  * <p>国産モデルではプライマリ名に日本語名が収められることが多い。
33  * プライマリ名は必ず一つ以上なければならない。
34  *
35  * <p>国産モデルではグローバル名に英語名が収められることが多いが、
36  * プライマリ名と同一の日本語名が収められている場合も多い。
37  *
38  * <p>別名管理オブジェクトは、
39  * インスタンス間での順序を定義するためのオーダー番号を持つ。
40  */
41 class I18nAlias {
42
43     /** オーダ番号によるコンパレータ。 */
44     public static final Comparator<I18nAlias> ORDER_COMPARATOR =
45             new OrderComparator();
46
47     private static final String F_DISALLOW_DOCTYPE_DECL =
48             "http://apache.org/xml/features/disallow-doctype-decl";
49     private static final String F_EXTERNAL_GENERAL_ENTITIES =
50             "http://xml.org/sax/features/external-general-entities";
51     private static final String F_EXTERNAL_PARAMETER_ENTITIES =
52             "http://xml.org/sax/features/external-parameter-entities";
53     private static final String F_LOAD_EXTERNAL_DTD =
54             "http://apache.org/xml/features/nonvalidating/load-external-dtd";
55
56
57     private int orderNo;
58
59     private final List<String> primaryNameList;
60     private final List<String> globalNameList;
61
62     private final List<String> umodPrimaryNameList;
63     private final List<String> umodGlobalNameList;
64
65
66     /**
67      * コンストラクタ。
68      *
69      * <p>各初期数が0以下の場合は、
70      * 状況に応じて伸長する連結リストが用意される。
71      *
72      * @param primaryNum プライマリ名初期数。
73      * @param globalNum グローバル名初期数。
74      */
75     protected I18nAlias(int primaryNum, int globalNum){
76         super();
77
78         if(primaryNum <= 0){
79             this.primaryNameList = new LinkedList<>();
80         }else{
81             this.primaryNameList = new ArrayList<>(primaryNum);
82         }
83
84         if(globalNum <= 0){
85             this.globalNameList  = new LinkedList<>();
86         }else{
87             this.globalNameList  = new ArrayList<>(globalNum);
88         }
89
90         this.umodPrimaryNameList =
91                 Collections.unmodifiableList(this.primaryNameList);
92         this.umodGlobalNameList =
93                 Collections.unmodifiableList(this.globalNameList);
94
95         return;
96     }
97
98     /**
99      * コンストラクタ。
100      *
101      * <p>プライマリ名、グローバル名共、
102      * 状況に応じて伸長する連結リストが用意される。
103      */
104     protected I18nAlias(){
105         this(0, 0);
106         return;
107     }
108
109
110     /**
111      * XMLドキュメントをロードする。
112      * @param is 入力
113      * @return 最上位要素
114      * @throws ParserConfigurationException XMLの構成が変
115      * @throws SAXException XMLの内容が変
116      * @throws IOException 入力エラー
117      */
118     protected static Element loadXml(InputStream is)
119             throws ParserConfigurationException, SAXException, IOException {
120         DocumentBuilderFactory factory;
121         factory = DocumentBuilderFactory.newInstance();
122
123         factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
124         factory.setFeature(F_EXTERNAL_GENERAL_ENTITIES, false);
125         factory.setFeature(F_EXTERNAL_PARAMETER_ENTITIES, false);
126         factory.setFeature(F_LOAD_EXTERNAL_DTD, false);
127
128         // unsafe but we use DOCTYPE
129         factory.setFeature(F_DISALLOW_DOCTYPE_DECL, false);
130
131         factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
132         factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
133
134         factory.setXIncludeAware(false);
135         factory.setExpandEntityReferences(false);
136
137         DocumentBuilder builder = factory.newDocumentBuilder();
138         Document doc = builder.parse(is);
139
140         Element top = doc.getDocumentElement();
141
142         return top;
143     }
144
145
146     /**
147      * オーダー番号を返す。
148      * @return オーダー番号
149      */
150     protected int getOrderNo(){
151         return this.orderNo;
152     }
153
154     /**
155      * オーダー番号を設定する。
156      * @param orderNo オーダー番号
157      */
158     protected void setOrderNo(int orderNo){
159         this.orderNo = orderNo;
160         return;
161     }
162
163     /**
164      * プライマリ名の代表をひとつ返す。
165      *
166      * <p>必ず存在しなければならない。
167      *
168      * @return 最初のプライマリ名
169      */
170     public String getTopPrimaryName(){
171         String result = this.primaryNameList.get(0);
172         return result;
173     }
174
175     /**
176      * グローバル名の代表をひとつ返す。
177      * @return 最初のグローバル名。ひとつもなければnull
178      */
179     public String getTopGlobalName(){
180         if(this.globalNameList.isEmpty()) return null;
181
182         String result = this.globalNameList.get(0);
183
184         return result;
185     }
186
187     /**
188      * プライマリ名の全別名リストを返す。
189      * @return 全別名リスト。(不可変)
190      */
191     public List<String> getPrimaryNameList(){
192         return this.umodPrimaryNameList;
193     }
194
195     /**
196      * プライマリ名を追加。
197      * @param primaryName プライマリ名
198      */
199     protected void addPrimaryName(String primaryName){
200         this.primaryNameList.add(primaryName);
201         return;
202     }
203
204     /**
205      * グローバル名の全別名リストを返す。
206      * @return 全別名リスト。(不可変)
207      */
208     public List<String> getGlobalNameList(){
209         return this.umodGlobalNameList;
210     }
211
212     /**
213      * グローバル名を追加。
214      * @param globalName グローバル名
215      */
216     protected void addGlobalName(String globalName){
217         this.globalNameList.add(globalName);
218         return;
219     }
220
221     /**
222      * オーダ番号によるコンパレータ。
223      */
224     @SuppressWarnings("serial")
225     private static class OrderComparator
226             implements Comparator<I18nAlias> {
227
228         /**
229          * コンストラクタ。
230          */
231         OrderComparator(){
232             super();
233             return;
234         }
235
236         /**
237          * オーダ番号を順序づける。
238          * @param o1 {@inheritDoc}
239          * @param o2 {@inheritDoc}
240          * @return {@inheritDoc}
241          */
242         @Override
243         public int compare(I18nAlias o1, I18nAlias o2){
244             int result = o1.getOrderNo() - o2.getOrderNo();
245             return result;
246         }
247
248     }
249
250 }