2 * PMD-SAX element listsner
4 * License : The MIT License
5 * Copyright(c) 2013 MikuToga Partners
8 package jp.sfjp.mikutoga.pmd.model.xml;
10 import java.lang.annotation.Annotation;
11 import java.lang.reflect.InvocationTargetException;
12 import java.lang.reflect.Method;
13 import java.lang.reflect.Modifier;
14 import java.util.Collection;
15 import java.util.EnumMap;
16 import java.util.LinkedList;
18 import javax.xml.bind.DatatypeConverter;
19 import jp.sfjp.mikutoga.pmd.model.PmdModel;
20 import org.xml.sax.Attributes;
27 private final Map<PmdTag, Method> openDispatcher;
28 private final Map<PmdTag, Method> closeDispatcher;
30 private PmdModel pmdModel = null;
31 private Attributes currentAttribute = null;
37 protected SaxListener(){
40 Class<?> thisClass = this.getClass();
41 this.openDispatcher = getOpenDispatcher(thisClass);
42 this.closeDispatcher = getCloseDispatcher(thisClass);
49 * 指定された注釈がマークされたインスタンスメソッド群を返す。
54 private static Collection<Method> filtMethod(Class<?> klass,
55 Class<? extends Annotation> filter ){
56 Collection<Method> result = new LinkedList<Method>();
58 for(Method method : klass.getDeclaredMethods()){
59 int modifiers = method.getModifiers();
60 if(Modifier.isStatic(modifiers)) continue;
61 if(Modifier.isPrivate(modifiers)) continue;
62 if(method.getParameterTypes().length > 0) continue;
64 Annotation anno = method.getAnnotation(filter);
65 if(anno == null) continue;
74 * 注釈でマークされた開始タグ通知用ディスパッチテーブルを返す。
78 private static Map<PmdTag, Method> getOpenDispatcher(Class<?> klass){
79 Map<PmdTag, Method> result =
80 new EnumMap<PmdTag, Method>(PmdTag.class);
82 for(Method method : filtMethod(klass, OpenXmlMark.class)){
83 Annotation anno = method.getAnnotation(OpenXmlMark.class);
84 OpenXmlMark mark = (OpenXmlMark) anno;
85 PmdTag tag = mark.value();
86 result.put(tag, method);
93 * 注釈でマークされた終了タグ通知用ディスパッチテーブルを返す。
97 private static Map<PmdTag, Method> getCloseDispatcher(Class<?> klass){
98 Map<PmdTag, Method> result =
99 new EnumMap<PmdTag, Method>(PmdTag.class);
101 for(Method method : filtMethod(klass, CloseXmlMark.class)){
102 Annotation anno = method.getAnnotation(CloseXmlMark.class);
103 CloseXmlMark mark = (CloseXmlMark) anno;
104 PmdTag tag = mark.value();
105 result.put(tag, method);
113 * ディスパッチテーブルに従いディスパッチする。
114 * @param map ディスパッチテーブル
116 * @return ディスパッチが行われなければfalse
118 private boolean dispatch(Map<PmdTag, Method> map, PmdTag tag){
119 Method method = map.get(tag);
120 if(method == null) return false;
124 }catch(IllegalAccessException ex){
126 }catch(InvocationTargetException ex){
127 Throwable cause = ex.getTargetException();
128 if(cause instanceof RuntimeException){
129 throw (RuntimeException) cause;
130 }else if(cause instanceof Error){
142 * @return ディスパッチが行われなければfalse
144 boolean openDispatch(PmdTag tag, Attributes attr){
145 this.currentAttribute = attr;
146 return dispatch(this.openDispatcher, tag);
152 * @return ディスパッチが行われなければfalse
154 boolean closeDispatch(PmdTag tag){
155 return dispatch(this.closeDispatcher, tag);
164 void addCharData(char[] ch, int start, int length){
170 * @param model ビルド対象オブジェクト
171 * @throws NullPointerException 引数がnull
173 void setPmdModel(PmdModel model) throws NullPointerException{
174 if(model == null) throw new NullPointerException();
175 this.pmdModel = model;
181 * @return ビルド対象オブジェクト。未登録の場合はnull。
183 protected PmdModel getPmdModel(){
184 return this.pmdModel;
188 * xsd:string型属性値の読み込み。
190 * @return 属性値。該当する属性が無ければnull。
191 * @see "http://www.w3.org/TR/xmlschema-2/#string"
193 protected String getStringAttr(PmdAttr attr){
194 String attrName = attr.attr();
195 String result = this.currentAttribute.getValue(attrName);
200 * xsd:boolean型属性値の読み込み。
203 * @throws IllegalArgumentException boolean型表記ではない
204 * @see "http://www.w3.org/TR/xmlschema-2/#boolean"
206 protected boolean getBooleanAttr(PmdAttr attr)
207 throws IllegalArgumentException{
208 String attrName = attr.attr();
209 String attrVal = this.currentAttribute.getValue(attrName);
211 bVal = DatatypeConverter.parseBoolean(attrVal);
216 * xsd:float型属性値の読み込み。
219 * @throws NumberFormatException float型表記ではない
220 * @see "http://www.w3.org/TR/xmlschema-2/#float"
222 protected float getFloatAttr(PmdAttr attr)
223 throws NumberFormatException {
224 String attrName = attr.attr();
225 String attrVal = this.currentAttribute.getValue(attrName);
227 fVal = DatatypeConverter.parseFloat(attrVal);
235 * @throws NumberFormatException int型表記ではない
236 * @see "http://www.w3.org/TR/xmlschema-2/#int"
238 protected int getIntAttr(PmdAttr attr)
239 throws NumberFormatException {
240 String attrName = attr.attr();
241 String attrVal = this.currentAttribute.getValue(attrName);
243 iVal = DatatypeConverter.parseInt(attrVal);