1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
|
23 | |
|
24 | |
|
25 | |
|
26 | |
|
27 | |
|
28 | |
|
29 | |
|
30 | |
|
31 | |
|
32 | |
|
33 | |
package com.jeantessier.dependency; |
34 | |
|
35 | |
import java.util.*; |
36 | |
|
37 | |
import org.apache.log4j.*; |
38 | |
import org.xml.sax.*; |
39 | |
import org.xml.sax.helpers.*; |
40 | |
|
41 | |
public class NodeHandler extends DefaultHandler { |
42 | |
private static final int PACKAGE = 1; |
43 | |
private static final int CLASS = 2; |
44 | |
private static final int FEATURE = 3; |
45 | |
|
46 | |
private NodeFactory factory; |
47 | |
|
48 | |
private int currentNodeType; |
49 | |
private int currentDependencyType; |
50 | |
private Attributes currentDependencyAttributes; |
51 | |
private Node currentNode; |
52 | |
private Attributes currentPackageAttributes; |
53 | |
private Attributes currentClassAttributes; |
54 | |
private Attributes currentFeatureAttributes; |
55 | 31 | private StringBuffer currentName = new StringBuffer(); |
56 | |
|
57 | 31 | private HashSet<DependencyListener> dependencyListeners = new HashSet<DependencyListener>(); |
58 | |
|
59 | |
public NodeHandler() { |
60 | 30 | this(new NodeFactory()); |
61 | 30 | } |
62 | |
|
63 | 31 | public NodeHandler(NodeFactory factory) { |
64 | 31 | this.factory = factory; |
65 | 31 | } |
66 | |
|
67 | |
public NodeFactory getFactory() { |
68 | 301 | return factory; |
69 | |
} |
70 | |
|
71 | |
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { |
72 | 137 | Logger.getLogger(getClass()).debug("qName = " + qName); |
73 | |
|
74 | 204 | for (int i=0; i<atts.getLength(); i++) { |
75 | 67 | Logger.getLogger(getClass()).debug(" " + atts.getQName(i) + ": " + atts.getValue(i)); |
76 | |
} |
77 | |
|
78 | 137 | currentName.delete(0, currentName.length()); |
79 | |
|
80 | 137 | if ("dependencies".equals(qName)) { |
81 | 29 | fireBeginSession(); |
82 | 108 | } else if ("package".equals(qName)) { |
83 | 29 | currentNodeType = PACKAGE; |
84 | 29 | currentPackageAttributes = new AttributesImpl(atts); |
85 | 79 | } else if ("class".equals(qName)) { |
86 | 8 | currentNodeType = CLASS; |
87 | 8 | currentClassAttributes = new AttributesImpl(atts); |
88 | 71 | } else if ("feature".equals(qName)) { |
89 | 5 | currentNodeType = FEATURE; |
90 | 5 | currentFeatureAttributes = new AttributesImpl(atts); |
91 | 66 | } else if ("inbound".equals(qName) || "outbound".equals(qName)) { |
92 | 24 | if ("package".equals(atts.getValue("type"))) { |
93 | 8 | currentDependencyType = PACKAGE; |
94 | 16 | } else if ("class".equals(atts.getValue("type"))) { |
95 | 8 | currentDependencyType = CLASS; |
96 | 8 | } else if ("feature".equals(atts.getValue("type"))) { |
97 | 8 | currentDependencyType = FEATURE; |
98 | |
} |
99 | 24 | currentDependencyAttributes = new AttributesImpl(atts); |
100 | |
} |
101 | |
|
102 | 137 | Logger.getLogger(getClass()).debug(" current node type: " + currentNodeType); |
103 | 137 | Logger.getLogger(getClass()).debug(" current dependency type: " + currentDependencyType); |
104 | 137 | } |
105 | |
|
106 | |
public void endElement(String namespaceURI, String localName, String qName) throws SAXException { |
107 | 137 | Logger.getLogger(getClass()).debug("qName = " + qName); |
108 | |
|
109 | 137 | if ("dependencies".equals(qName)) { |
110 | 29 | fireEndSession(); |
111 | 108 | } else if ("name".equals(qName)) { |
112 | 42 | Logger.getLogger(getClass()).debug(" Processing <name> tag:"); |
113 | 42 | Logger.getLogger(getClass()).debug(" current name: " + currentName); |
114 | 42 | Logger.getLogger(getClass()).debug(" current node type: " + currentNodeType); |
115 | |
|
116 | 42 | switch (currentNodeType) { |
117 | |
case PACKAGE: |
118 | 29 | currentNode = getFactory().createPackage(currentName.toString(), isConfirmed(currentPackageAttributes)); |
119 | 29 | break; |
120 | |
case CLASS: |
121 | 8 | currentNode = getFactory().createClass(currentName.toString(), isConfirmed(currentClassAttributes)); |
122 | 8 | fireBeginClass(currentNode.getName()); |
123 | 8 | break; |
124 | |
case FEATURE: |
125 | 5 | currentNode = getFactory().createFeature(currentName.toString(), isConfirmed(currentFeatureAttributes)); |
126 | 42 | break; |
127 | |
} |
128 | 66 | } else if ("outbound".equals(qName)) { |
129 | 12 | Logger.getLogger(getClass()).debug(" Processing <outbound> tag:"); |
130 | 12 | Logger.getLogger(getClass()).debug(" current_name: " + currentName); |
131 | 12 | Logger.getLogger(getClass()).debug(" current_dependency_type: " + currentDependencyType); |
132 | |
|
133 | 12 | Node other = null; |
134 | 12 | switch (currentDependencyType) { |
135 | |
case PACKAGE: |
136 | 4 | other = getFactory().createPackage(currentName.toString(), isConfirmed(currentDependencyAttributes)); |
137 | 4 | break; |
138 | |
case CLASS: |
139 | 4 | other = getFactory().createClass(currentName.toString(), isConfirmed(currentDependencyAttributes)); |
140 | 4 | break; |
141 | |
case FEATURE: |
142 | 4 | other = getFactory().createFeature(currentName.toString(), isConfirmed(currentDependencyAttributes)); |
143 | |
break; |
144 | |
} |
145 | 12 | currentNode.addDependency(other); |
146 | 12 | fireDependency(currentNode, other); |
147 | 12 | } else if ("inbound".equals(qName)) { |
148 | 12 | Logger.getLogger(getClass()).debug(" Processing <inbound> tag:"); |
149 | 12 | Logger.getLogger(getClass()).debug(" current_name: " + currentName); |
150 | 12 | Logger.getLogger(getClass()).debug(" current_dependency_type: " + currentDependencyType); |
151 | |
|
152 | 12 | Node other = null; |
153 | 12 | switch (currentDependencyType) { |
154 | |
case PACKAGE: |
155 | 4 | other = getFactory().createPackage(currentName.toString(), isConfirmed(currentDependencyAttributes)); |
156 | 4 | break; |
157 | |
case CLASS: |
158 | 4 | other = getFactory().createClass(currentName.toString(), isConfirmed(currentDependencyAttributes)); |
159 | 4 | break; |
160 | |
case FEATURE: |
161 | 4 | other = getFactory().createFeature(currentName.toString(), isConfirmed(currentDependencyAttributes)); |
162 | |
break; |
163 | |
} |
164 | 12 | other.addDependency(currentNode); |
165 | 12 | fireDependency(other, currentNode); |
166 | |
} |
167 | 137 | } |
168 | |
|
169 | |
public void characters(char[] ch, int start, int length) throws SAXException { |
170 | 91 | currentName.append(ch, start, length); |
171 | 91 | Logger.getLogger(getClass()).debug("characters: \"" + new String(ch, start, length) + "\""); |
172 | 91 | } |
173 | |
|
174 | |
public void addDependencyListener(DependencyListener listener) { |
175 | 0 | synchronized(dependencyListeners) { |
176 | 0 | dependencyListeners.add(listener); |
177 | 0 | } |
178 | 0 | } |
179 | |
|
180 | |
public void removeDependencyListener(DependencyListener listener) { |
181 | 0 | synchronized(dependencyListeners) { |
182 | 0 | dependencyListeners.remove(listener); |
183 | 0 | } |
184 | 0 | } |
185 | |
|
186 | |
protected void fireBeginSession() { |
187 | 29 | DependencyEvent event = new DependencyEvent(this); |
188 | |
|
189 | |
HashSet<DependencyListener> listeners; |
190 | 29 | synchronized(dependencyListeners) { |
191 | 29 | listeners = (HashSet<DependencyListener>) dependencyListeners.clone(); |
192 | 29 | } |
193 | |
|
194 | 29 | for (DependencyListener listener : listeners) { |
195 | 0 | listener.beginSession(event); |
196 | |
} |
197 | 29 | } |
198 | |
|
199 | |
protected void fireBeginClass(String classname) { |
200 | 8 | DependencyEvent event = new DependencyEvent(this, classname); |
201 | |
|
202 | |
HashSet<DependencyListener> listeners; |
203 | 8 | synchronized(dependencyListeners) { |
204 | 8 | listeners = (HashSet<DependencyListener>) dependencyListeners.clone(); |
205 | 8 | } |
206 | |
|
207 | 8 | for (DependencyListener listener : listeners) { |
208 | 0 | listener.beginClass(event); |
209 | |
} |
210 | 8 | } |
211 | |
|
212 | |
protected void fireDependency(Node dependent, Node dependable) { |
213 | 24 | DependencyEvent event = new DependencyEvent(this, dependent, dependable); |
214 | |
|
215 | |
HashSet<DependencyListener> listeners; |
216 | 24 | synchronized(dependencyListeners) { |
217 | 24 | listeners = (HashSet<DependencyListener>) dependencyListeners.clone(); |
218 | 24 | } |
219 | |
|
220 | 24 | for (DependencyListener listener : listeners) { |
221 | 0 | listener.dependency(event); |
222 | |
} |
223 | 24 | } |
224 | |
|
225 | |
protected void fireEndClass(String classname) { |
226 | 0 | DependencyEvent event = new DependencyEvent(this, classname); |
227 | |
|
228 | |
HashSet<DependencyListener> listeners; |
229 | 0 | synchronized(dependencyListeners) { |
230 | 0 | listeners = (HashSet<DependencyListener>) dependencyListeners.clone(); |
231 | 0 | } |
232 | |
|
233 | 0 | for (DependencyListener listener : listeners) { |
234 | 0 | listener.endClass(event); |
235 | |
} |
236 | 0 | } |
237 | |
|
238 | |
protected void fireEndSession() { |
239 | 29 | DependencyEvent event = new DependencyEvent(this); |
240 | |
|
241 | |
HashSet<DependencyListener> listeners; |
242 | 29 | synchronized(dependencyListeners) { |
243 | 29 | listeners = (HashSet<DependencyListener>) dependencyListeners.clone(); |
244 | 29 | } |
245 | |
|
246 | 29 | for (DependencyListener listener : listeners) { |
247 | 0 | listener.endSession(event); |
248 | |
} |
249 | 29 | } |
250 | |
|
251 | |
private boolean isConfirmed(Attributes atts) { |
252 | 66 | return atts.getValue("confirmed") == null || "yes".equalsIgnoreCase(atts.getValue("confirmed")); |
253 | |
} |
254 | |
} |