OSDN Git Service

@throwsコメント修正
[mikutoga/TogaGem.git] / src / main / java / jp / sourceforge / mikutoga / xml / DomUtils.java
1 /*\r
2  * XML DOM utilities\r
3  *\r
4  * License : The MIT License\r
5  * Copyright(c) 2010 MikuToga Partners\r
6  */\r
7 \r
8 package jp.sourceforge.mikutoga.xml;\r
9 \r
10 import java.util.Iterator;\r
11 import java.util.LinkedList;\r
12 import java.util.List;\r
13 import java.util.NoSuchElementException;\r
14 import javax.xml.bind.DatatypeConverter;\r
15 import org.w3c.dom.Element;\r
16 import org.w3c.dom.Node;\r
17 \r
18 /**\r
19  * DOMユーティリティ。\r
20  */\r
21 public final class DomUtils {\r
22 \r
23     /**\r
24      * 隠しコンストラクタ。\r
25      */\r
26     private DomUtils(){\r
27         super();\r
28         assert false;\r
29         throw new AssertionError();\r
30     }\r
31 \r
32     /**\r
33      * 要素からxsd:string型属性値を読み取る。\r
34      * @param elem 要素\r
35      * @param attrName 属性名\r
36      * @return 文字列\r
37      * @throws TogaXmlException 属性値が見つからなかった。\r
38      */\r
39     public static String getStringAttr(Element elem, String attrName)\r
40             throws TogaXmlException{\r
41         if( ! elem.hasAttribute(attrName) ){\r
42             String message = "Attr:[" + attrName + "] "\r
43                     + "was not found in "\r
44                     + "Elem:[" + elem.getTagName()+"]";\r
45             throw new TogaXmlException(message);\r
46         }\r
47 \r
48         String result;\r
49         try{\r
50             result = elem.getAttribute(attrName);\r
51         }catch(IllegalArgumentException e){\r
52             String message = "Invalid attribute form [" + attrName + "]";\r
53             throw new TogaXmlException(message, e);\r
54         }\r
55 \r
56         return result;\r
57     }\r
58 \r
59     /**\r
60      * 要素からxsd:boolean型属性値を読み取る。\r
61      * @param elem 要素\r
62      * @param attrName 属性名\r
63      * @return 真ならtrue\r
64      * @throws TogaXmlException 属性値が見つからなかった。\r
65      */\r
66     public static boolean getBooleanAttr(Element elem, String attrName)\r
67             throws TogaXmlException{\r
68         String value = getStringAttr(elem, attrName);\r
69 \r
70         boolean result;\r
71         try{\r
72             result = DatatypeConverter.parseBoolean(value);\r
73         }catch(IllegalArgumentException e){\r
74             String message =\r
75                     "Invalid boolean attribute form "\r
76                     + "[" + attrName + "][" + value + "]";\r
77             throw new TogaXmlException(message, e);\r
78         }\r
79 \r
80         return result;\r
81     }\r
82 \r
83     /**\r
84      * 要素からxsd:integer型属性値を読み取る。\r
85      * @param elem 要素\r
86      * @param attrName 属性名\r
87      * @return int値\r
88      * @throws TogaXmlException 属性値が見つからなかった。\r
89      */\r
90     public static int getIntegerAttr(Element elem, String attrName)\r
91             throws TogaXmlException{\r
92         String value = getStringAttr(elem, attrName);\r
93 \r
94         int result;\r
95         try{\r
96             result = DatatypeConverter.parseInt(value);\r
97         }catch(IllegalArgumentException e){\r
98             String message =\r
99                     "Invalid integer attribute form "\r
100                     + "[" + attrName + "][" + value + "]";\r
101             throw new TogaXmlException(message, e);\r
102         }\r
103 \r
104         return result;\r
105     }\r
106 \r
107     /**\r
108      * 要素からxsd:float型属性値を読み取る。\r
109      * @param elem 要素\r
110      * @param attrName 属性名\r
111      * @return float値\r
112      * @throws TogaXmlException 属性値が見つからなかった。\r
113      */\r
114     public static float getFloatAttr(Element elem, String attrName)\r
115             throws TogaXmlException{\r
116         String value = getStringAttr(elem, attrName);\r
117 \r
118         float result;\r
119         try{\r
120             result = DatatypeConverter.parseFloat(value);\r
121         }catch(IllegalArgumentException e){\r
122             String message =\r
123                     "Invalid float attribute form "\r
124                     + "[" + attrName + "][" + value + "]";\r
125             throw new TogaXmlException(message, e);\r
126         }\r
127 \r
128         return result;\r
129     }\r
130 \r
131     /**\r
132      * 要素から日本語Windows用ファイル名を属性値として読み取る。\r
133      * 念のため文字U+00A5は文字U-005Cに変換される。\r
134      * @param elem 要素\r
135      * @param attrName 属性名\r
136      * @return ファイル名\r
137      * @throws TogaXmlException 属性値が見つからなかった。\r
138      */\r
139     public static String getSjisFileNameAttr(Element elem, String attrName)\r
140             throws TogaXmlException{\r
141         String result;\r
142         try{\r
143             result = getStringAttr(elem, attrName);\r
144         }catch(IllegalArgumentException e){\r
145             String message =\r
146                     "Invalid winfile attribute form "\r
147                     + "[" + attrName + "]";\r
148             throw new TogaXmlException(message, e);\r
149         }\r
150 \r
151         result.replace("" + '\u00a5', "" + '\u005c\u005c');\r
152 \r
153         return result;\r
154     }\r
155 \r
156     /**\r
157      * 指定された名前の子要素を1つだけ返す。\r
158      * @param parent 親要素\r
159      * @param tagName 子要素名\r
160      * @return 子要素\r
161      * @throws TogaXmlException 1つも見つからなかった\r
162      */\r
163     public static Element getChild(Element parent, String tagName)\r
164             throws TogaXmlException{\r
165         Element result = null;\r
166 \r
167         for(Node node = parent.getFirstChild();\r
168             node != null;\r
169             node = node.getNextSibling() ){\r
170 \r
171             if(node.getNodeType() != Node.ELEMENT_NODE) continue;\r
172             Element elem = (Element) node;\r
173 \r
174             String elemTagName = elem.getTagName();\r
175             if( tagName.equals(elemTagName) ){\r
176                 result = elem;\r
177                 break;\r
178             }\r
179         }\r
180 \r
181         if(result == null){\r
182             String message =\r
183                     "Elem:[" + tagName + "] was not found in "\r
184                     +"Elem:[" + parent.getTagName() + "]";\r
185             throw new TogaXmlException(message);\r
186         }\r
187 \r
188         return result;\r
189     }\r
190 \r
191     /**\r
192      * 親要素が指定された名前の子要素を持つか判定する。\r
193      * @param parent 親要素\r
194      * @param tagName 子要素名\r
195      * @return 指定名の子要素が存在すればtrue\r
196      */\r
197     public static boolean hasChild(Element parent, String tagName){\r
198         for(Node node = parent.getFirstChild();\r
199             node != null;\r
200             node = node.getNextSibling() ){\r
201 \r
202             if(node.getNodeType() != Node.ELEMENT_NODE) continue;\r
203             Element elem = (Element) node;\r
204 \r
205             String elemTagName = elem.getTagName();\r
206             if( tagName.equals(elemTagName) ) return true;\r
207         }\r
208 \r
209         return false;\r
210     }\r
211 \r
212     /**\r
213      * 指定された名前の子要素のリストを返す。\r
214      * @param parent 親要素\r
215      * @param childTag 子要素名\r
216      * @return 子要素のリスト\r
217      */\r
218     public static List<Element> getChildList(Element parent,\r
219                                                String childTag){\r
220         List<Element> result = new LinkedList<Element>();\r
221 \r
222         for(Node node = parent.getFirstChild();\r
223             node != null;\r
224             node = node.getNextSibling() ){\r
225 \r
226             if(node.getNodeType() != Node.ELEMENT_NODE) continue;\r
227             Element elem = (Element) node;\r
228 \r
229             String tagName = elem.getTagName();\r
230             if( ! childTag.equals(tagName) ) continue;\r
231 \r
232             result.add(elem);\r
233         }\r
234 \r
235         return result;\r
236     }\r
237 \r
238     /**\r
239      * 指定された名前の子要素の列挙子を返す。\r
240      * @param parent 親要素\r
241      * @param childTag 子要素名\r
242      * @return 子要素の列挙子\r
243      */\r
244     public static Iterator<Element> getChildIterator(Element parent,\r
245                                                        String childTag){\r
246         Element firstElem;\r
247         try{\r
248             firstElem = getChild(parent, childTag);\r
249         }catch(TogaXmlException e){\r
250             firstElem = null;\r
251         }\r
252 \r
253         Iterator<Element> result = new ElemIterator(firstElem);\r
254 \r
255         return result;\r
256     }\r
257 \r
258     /**\r
259      * 指定された名前の子要素のforeachを返す。\r
260      * @param parent 親要素\r
261      * @param childTag 子要素名\r
262      * @return 子要素のforeach\r
263      */\r
264     public static Iterable<Element> getEachChild(Element parent,\r
265                                                    String childTag){\r
266         final Iterator<Element> iterator = getChildIterator(parent, childTag);\r
267         Iterable<Element> result = new Iterable<Element>(){\r
268             @Override\r
269             public Iterator<Element> iterator(){\r
270                 return iterator;\r
271             }\r
272         };\r
273         return result;\r
274     }\r
275 \r
276     /**\r
277      * 要素の次の要素を返す。\r
278      * @param elem 要素\r
279      * @return 次の要素。なければnull\r
280      */\r
281     public static Element nextElement(Element elem){\r
282         Node nextNode = elem;\r
283         for(;;){\r
284             nextNode = nextNode.getNextSibling();\r
285             if(nextNode == null) break;\r
286             if(nextNode.getNodeType() == Node.ELEMENT_NODE){\r
287                 break;\r
288             }\r
289         }\r
290 \r
291         return (Element) nextNode;\r
292     }\r
293 \r
294     /**\r
295      * 同じ要素名を持つ次の要素を返す。\r
296      * @param elem 要素\r
297      * @return 次の要素。なければnull\r
298      */\r
299     public static Element nextNamedElement(Element elem){\r
300         String tagName = elem.getTagName();\r
301         Element nextElem = elem;\r
302         for(;;){\r
303             nextElem = nextElement(nextElem);\r
304             if(nextElem == null) break;\r
305             if(tagName.equals(nextElem.getTagName())) break;\r
306         }\r
307 \r
308         return nextElem;\r
309     }\r
310 \r
311     /**\r
312      * 同じ親要素と同じ要素名を持つ兄弟要素を列挙する列挙子。\r
313      */\r
314     private static class ElemIterator implements Iterator<Element>{\r
315         private Element next;\r
316 \r
317         /**\r
318          * コンストラクタ。\r
319          * @param elem 最初の要素。nullを指定すれば空列挙子となる。\r
320          */\r
321         private ElemIterator(Element elem){\r
322             super();\r
323             this.next = elem;\r
324         }\r
325 \r
326         /**\r
327          * {@inheritDoc}\r
328          * @return {@inheritDoc}\r
329          */\r
330         @Override\r
331         public boolean hasNext(){\r
332             if(this.next == null) return false;\r
333             return true;\r
334         }\r
335 \r
336         /**\r
337          * {@inheritDoc}\r
338          * @return {@inheritDoc}\r
339          * @throws NoSuchElementException {@inheritDoc}\r
340          */\r
341         @Override\r
342         public Element next() throws NoSuchElementException{\r
343             if(this.next == null) throw new NoSuchElementException();\r
344             Element result = this.next;\r
345             this.next = nextNamedElement(this.next);\r
346             return result;\r
347         }\r
348 \r
349         /**\r
350          * {@inheritDoc}\r
351          * ※ 未サポート。\r
352          */\r
353         @Override\r
354         public void remove(){\r
355             throw new UnsupportedOperationException();\r
356         }\r
357 \r
358     }\r
359 \r
360 }\r