001: /*
002: * Hammurapi
003: * Automated Java code review system.
004: * Copyright (C) 2004 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.org
021: * e-Mail: support@hammurapi.biz
022: */
023: package org.hammurapi;
024:
025: import java.util.Collection;
026: import java.util.HashMap;
027: import java.util.HashSet;
028: import java.util.Iterator;
029: import java.util.LinkedList;
030: import java.util.List;
031: import java.util.Map;
032:
033: import javax.xml.transform.TransformerException;
034:
035: import org.apache.xpath.CachedXPathAPI;
036: import org.w3c.dom.Element;
037: import org.w3c.dom.Node;
038: import org.w3c.dom.NodeList;
039: import org.w3c.dom.traversal.NodeIterator;
040:
041: import com.pavelvlasov.config.ConfigurationException;
042: import com.pavelvlasov.config.DomConfigFactory;
043: import com.pavelvlasov.config.Parameterizable;
044: import com.pavelvlasov.xml.dom.AbstractDomObject;
045:
046: /**
047: * @author Pavel Vlasov
048: * @version $Revision: 1.9 $
049: */
050: public class DomInspectorDescriptor extends AbstractDomObject implements
051: InspectorDescriptor {
052: private String fixSample;
053: private String message;
054: private String category;
055: private String name;
056: private Integer order;
057: private String rationale;
058: private String resources;
059: private Integer severity;
060: private String violationSample;
061: private Boolean isEnabled;
062: private Boolean isWaivable;
063: private String description;
064: private Element inspectorElement;
065: private Inspector inspector;
066: private List parameters = new LinkedList();
067: private List waiveCases = new LinkedList();
068: private Map messages = new HashMap();
069:
070: private class FilterNameEntry {
071: boolean exclude;
072: String name;
073: String category;
074: }
075:
076: private Collection filterEntries = new LinkedList();
077:
078: public DomInspectorDescriptor(Element holder)
079: throws HammurapiException {
080: super ();
081: try {
082: CachedXPathAPI cxpa = new CachedXPathAPI();
083: fixSample = getElementText(holder, "fix-sample", cxpa);
084:
085: NodeIterator it = cxpa
086: .selectNodeIterator(holder, "message");
087: Node messageNode;
088: while ((messageNode = it.nextNode()) != null) {
089: if (messageNode instanceof Element) {
090: Element messageElement = (Element) messageNode;
091: if (messageElement.hasAttribute("key")) {
092: messages.put(
093: messageElement.getAttribute("key"),
094: getElementText(messageElement));
095: } else {
096: message = getElementText(messageElement);
097: }
098: }
099: }
100: name = getElementText(holder, "name", cxpa);
101: String orderVal = getElementText(holder, "order", cxpa);
102: if (orderVal != null) {
103: order = new Integer(orderVal);
104: }
105: rationale = getElementText(holder, "rationale", cxpa);
106: category = getElementText(holder, "category", cxpa);
107: resources = getElementText(holder, "resource", cxpa);
108: String severityVal = getElementText(holder, "severity",
109: cxpa);
110: if (severityVal != null) {
111: severity = new Integer(severityVal);
112: }
113: violationSample = getElementText(holder,
114: "violation-sample", cxpa);
115:
116: String enabledVal = getElementText(holder, "enabled", cxpa);
117: if (enabledVal != null) {
118: isEnabled = "yes".equalsIgnoreCase(enabledVal)
119: || "true".equalsIgnoreCase(enabledVal) ? Boolean.TRUE
120: : Boolean.FALSE;
121: }
122:
123: String waivableVal = getElementText(holder, "waivable",
124: cxpa);
125: if (waivableVal != null) {
126: isWaivable = "yes".equalsIgnoreCase(waivableVal)
127: || "true".equalsIgnoreCase(waivableVal) ? Boolean.TRUE
128: : Boolean.FALSE;
129: }
130:
131: description = getElementText(holder, "description", cxpa);
132:
133: inspectorElement = (Element) cxpa.selectSingleNode(holder,
134: "inspector");
135:
136: DomConfigFactory factory = new DomConfigFactory();
137: NodeIterator nit = cxpa.selectNodeIterator(holder,
138: "parameter");
139: Node n;
140: while ((n = nit.nextNode()) != null) {
141: parameters.add(new ParameterEntry(((Element) n)
142: .getAttribute("name"), factory.create(n)));
143: }
144:
145: nit = cxpa.selectNodeIterator(holder, "waive-case");
146: while ((n = nit.nextNode()) != null) {
147: waiveCases.add(cxpa.eval(n, "text()").toString());
148: }
149:
150: nit = cxpa.selectNodeIterator(holder, "waives");
151: while ((n = nit.nextNode()) != null) {
152: if (n instanceof Element) {
153: Element waivesElement = (Element) n;
154: if (waivesElement.hasAttribute("key")) {
155: String wKey = waivesElement.getAttribute("key");
156: String iName = cxpa.eval(n, "name/text()")
157: .toString();
158: if (iName.trim().length() == 0) {
159: throw new HammurapiException(
160: "<waives> must have nested <name> element");
161: }
162:
163: waivedInspectorNames.put(wKey, iName);
164: waiveReasons.put(wKey, cxpa.eval(n,
165: "reason/text()").toString());
166: } else {
167: throw new HammurapiException(
168: "<waives> must have 'key' attribute");
169: }
170: }
171: }
172:
173: nit = cxpa.selectNodeIterator(holder, "after");
174: while ((n = nit.nextNode()) != null) {
175: afterInspectorNames.add(getElementText(n));
176: }
177:
178: NodeList nl = holder.getChildNodes();
179: for (int i = 0; i < nl.getLength(); i++) {
180: Node fn = nl.item(i);
181: if (fn instanceof Element) {
182: Element el = (Element) fn;
183: if ("filter".equals(el.getNodeName())) {
184: FilterNameEntry fne = new FilterNameEntry();
185: if (el.hasAttribute("name")) {
186: fne.name = el.getAttribute("name");
187: } else if (el.hasAttribute("category")) {
188: fne.category = el.getAttribute("category");
189: } else {
190: throw new ConfigurationException(
191: "<filter> element shall have either name or category attribute");
192: }
193: filterEntries.add(fne);
194: } else if ("filter-exclude"
195: .equals(el.getNodeName())) {
196: FilterNameEntry fne = new FilterNameEntry();
197: fne.exclude = true;
198: if (el.hasAttribute("name")) {
199: fne.name = el.getAttribute("name");
200: } else if (el.hasAttribute("category")) {
201: fne.category = el.getAttribute("category");
202: } else {
203: throw new ConfigurationException(
204: "<filter-exclude> element shall have either name or category attribute");
205: }
206: filterEntries.add(fne);
207: }
208: }
209: }
210: //System.out.println(name);
211: } catch (TransformerException e) {
212: throw new HammurapiException(e);
213: } catch (ConfigurationException e) {
214: throw new HammurapiException(e);
215: }
216: }
217:
218: /**
219: * @return Returns the fixSample.
220: */
221: public String getFixSample() {
222: return fixSample;
223: }
224:
225: /**
226: * @return Returns the isEnabled.
227: */
228: public Boolean isEnabled() {
229: return isEnabled;
230: }
231:
232: /**
233: * @return Returns the message.
234: */
235: public String getMessage() {
236: return message;
237: }
238:
239: /**
240: * @return Returns the message.
241: */
242: public String getCategory() {
243: return category;
244: }
245:
246: /**
247: * @return Returns the name.
248: */
249: public String getName() {
250: return name;
251: }
252:
253: /**
254: * @return Returns the order.
255: */
256: public Integer getOrder() {
257: return order;
258: }
259:
260: /**
261: * @return Returns the rationale.
262: */
263: public String getRationale() {
264: return rationale;
265: }
266:
267: /**
268: * @return Returns the resources.
269: */
270: public String getResources() {
271: return resources;
272: }
273:
274: /**
275: * @return Returns the severity.
276: */
277: public Integer getSeverity() {
278: return severity;
279: }
280:
281: /**
282: * @return Returns the violationSample.
283: */
284: public String getViolationSample() {
285: return violationSample;
286: }
287:
288: public String getDescription() {
289: return description;
290: }
291:
292: public Inspector getInspector() throws ConfigurationException {
293: if (inspector == null && inspectorElement != null) {
294: DomConfigFactory factory = new DomConfigFactory();
295: Object o = factory.create(inspectorElement);
296: if (o instanceof Inspector) {
297: inspector = (Inspector) o;
298: if (!getParameters().isEmpty()) {
299: if (inspector instanceof Parameterizable) {
300: Iterator it = getParameters().iterator();
301: while (it.hasNext()) {
302: ParameterEntry pe = (ParameterEntry) it
303: .next();
304: if (!((Parameterizable) inspector)
305: .setParameter(pe.getName(), pe
306: .getValue())) {
307: throw new ConfigurationException(
308: o.getClass().getName()
309: + " does not support parameter "
310: + pe.getName());
311: }
312: }
313: } else {
314: throw new ConfigurationException(inspector
315: .getClass().getName()
316: + " does not implement "
317: + Parameterizable.class.getName());
318: }
319: }
320: } else {
321: throw new ConfigurationException(o.getClass().getName()
322: + " doesn't implement "
323: + Inspector.class.getName());
324: }
325: }
326: return inspector;
327: }
328:
329: public Collection getParameters() {
330: return parameters;
331: }
332:
333: public String getMessage(String key) {
334: return (String) messages.get(key);
335: }
336:
337: public Boolean isWaivable() {
338: return isWaivable;
339: }
340:
341: public Collection getWaiveCases() {
342: return waiveCases;
343: }
344:
345: private Map waivedInspectorNames = new HashMap();
346:
347: public String getWaivedInspectorName(String inspectorKey) {
348: return (String) waivedInspectorNames.get(inspectorKey);
349: }
350:
351: private Map waiveReasons = new HashMap();
352: private Collection afterInspectorNames = new HashSet();
353:
354: public String getWaiveReason(String inspectorKey) {
355: return (String) waiveReasons.get(inspectorKey);
356: }
357:
358: public Collection getWaivedInspectorNames() {
359: return waivedInspectorNames.values();
360: }
361:
362: public Collection getAfterInspectorNames() {
363: return afterInspectorNames;
364: }
365:
366: public Collection getFilteredInspectorDesriptors(
367: InspectorSet inspectorSet, Collection chain) {
368: if (chain == null) {
369: chain = new LinkedList();
370: }
371:
372: Iterator it = filterEntries.iterator();
373: while (it.hasNext()) {
374: FilterNameEntry fne = (FilterNameEntry) it.next();
375: if (fne.exclude) {
376: if (fne.name == null) {
377: Iterator dit = chain.iterator();
378: while (dit.hasNext()) {
379: if (fne.category
380: .equals(((InspectorDescriptor) dit
381: .next()).getCategory())) {
382: dit.remove();
383: }
384: }
385: } else {
386: if ("*".equals(fne.name)) {
387: chain.clear();
388: } else {
389: Iterator dit = chain.iterator();
390: while (dit.hasNext()) {
391: if (fne.name
392: .equals(((InspectorDescriptor) dit
393: .next()).getName())) {
394: dit.remove();
395: }
396: }
397: }
398: }
399: } else {
400: if (fne.name == null) {
401: Iterator dit = inspectorSet.getDescriptors()
402: .iterator();
403: while (dit.hasNext()) {
404: InspectorDescriptor inspectorDescriptor = (InspectorDescriptor) dit
405: .next();
406: if (fne.category.equals(inspectorDescriptor
407: .getCategory())) {
408: chain.add(inspectorDescriptor);
409: }
410: }
411: } else {
412: if ("*".equals(fne.name)) {
413: chain.addAll(inspectorSet.getDescriptors());
414: } else {
415: Iterator dit = inspectorSet.getDescriptors()
416: .iterator();
417: while (dit.hasNext()) {
418: InspectorDescriptor inspectorDescriptor = (InspectorDescriptor) dit
419: .next();
420: if (fne.name.equals(inspectorDescriptor
421: .getName())) {
422: chain.add(inspectorDescriptor);
423: }
424: }
425: }
426: }
427: }
428: }
429:
430: return chain;
431: }
432: }
|