View Javadoc

1   package pl.caltha.services.xml.validation;
2   
3   import java.util.HashMap;
4   import java.util.Map;
5   import java.util.Stack;
6   
7   import org.dom4j.Element;
8   import org.dom4j.Node;
9   import org.xml.sax.SAXException;
10  
11  import pl.caltha.services.xml.CollectingErrorHandler;
12  
13  /***
14   * ErrorHandler that collects all errors.
15   *
16   * @author <a href="mailto:zwierzem@ngo.pl">Damian Gajda</a>
17   * @version $Id: DOM4JValidationErrorCollector.java,v 1.4 2005/05/20 00:46:27 rafal Exp $
18   */
19  public class DOM4JValidationErrorCollector
20       extends CollectingErrorHandler
21  implements DOM4JContentHandler, ExtendedContentHandler
22  {
23      //------------------------------------------------------------------------
24      // DOM Nodes information
25      private Stack elementStack =  new Stack();
26      private Node currentNode;
27      private org.dom4j.Attribute currentAttribute;
28      private HashMap errorsByNode = new HashMap();
29      private HashMap warningsByNode = new HashMap();
30  
31      /*** Getter for property errorsByNode.
32       * @return Value of property errorsByNode.
33       */
34      public HashMap getErrorsByNode()
35      {
36          return errorsByNode;
37      }
38  
39      /*** Getter for property warningsByNode.
40       * @return Value of property warningsByNode.
41       */
42      public HashMap getWarningsByNode()
43      {
44          return warningsByNode;
45      }
46  
47      /*** You can call this method to reuse an ErrorHandler. */
48      public void init()
49      {
50          super.init();
51          elementStack.clear();
52          errorsByNode.clear();
53          warningsByNode.clear();
54          currentNode = null;
55          currentAttribute = null;
56      }
57  
58      //------------------------------------------------------------------------
59      // DOMContentHandler methods
60  
61      public void startElementNode(Element node)
62      {
63          currentNode = node;
64          elementStack.push(node);    
65      }
66  
67      public void endElementNode(Element node)
68      {
69          currentNode = null;
70          elementStack.pop();
71      }
72  
73      public void setCurrentNode(Node node)
74      {
75          currentNode = node;
76      }
77  
78      //------------------------------------------------------------------------
79      // TypedContentHandler
80  
81      /*** receives notification of the start of a document.
82       */
83      public void startDocument()
84          throws SAXException
85      {
86          // ignored
87      }
88  
89      /*** receives notification of the end of a document.
90       */
91      public void endDocument()
92          throws SAXException
93      {
94          // ignored
95      }
96  
97      /*** receives notification of the start of an element.
98       *
99       * If this element has attributes, the start/endAttribute methods are
100      * called after this method.
101      */
102     public void startElement(String namespaceURI, String localName, String qName)
103         throws SAXException
104     {
105         // ignored
106     }
107 
108     /*** receives notification of the start of an attribute.
109      *
110      * the value of the attribute is reported through the characterChunk method.
111      */
112     public void startAttribute(String namespaceURI, String localName, String qName)
113     throws SAXException
114     {
115         Element element = (Element)(elementStack.peek());
116         currentAttribute = element.attribute(qName);
117     }
118 
119     /*** receives notification of the end of an attribute.
120      */
121     public void endAttribute(String namespaceURI, String localName, String qName)
122     throws SAXException
123     {
124         currentAttribute = null;
125     }
126 
127     /*** this method is called after the start/endAttribute method are called
128      * for all attributes.
129      */
130     public void endAttributePart()
131         throws SAXException
132     {
133         // ignored
134     }
135 
136     /*** receives notification of the end of an element.
137      */
138     public void endElement(String namespaceURI, String localName, String qName)
139         throws SAXException
140     {
141         // ignored
142     }
143 
144     /*** receives notification of a string.
145      *
146      * @param literal
147      *      the contents.
148      */
149     public void characterChunk(String literal)
150     throws SAXException
151     {
152         // TODO: ????
153     }
154 
155     //------------------------------------------------------------------------
156     // CollectingErrorHandler methods
157     protected ErrorInfo saveError(org.xml.sax.SAXParseException spe)
158     {
159         ErrorInfo ei = super.saveError(spe);
160         return saveErrorOrWarning(ei, errorsByNode);
161     }
162 
163     protected ErrorInfo saveWarning(org.xml.sax.SAXParseException spe)
164     {
165         ErrorInfo ei = super.saveWarning(spe);
166         return saveErrorOrWarning(ei, warningsByNode);
167     }
168 
169     protected ErrorInfo saveErrorOrWarning(ErrorInfo ei, HashMap map)
170     {
171         Node node = null;
172         if(currentAttribute != null)
173         {
174             //save attribute
175             node = currentAttribute;
176         }
177         else
178         {
179             //save element - TODO: What about other nodes?
180             node = (Node)(elementStack.peek());
181         }
182 
183         map.put(node, ei);
184         return ei;
185     }
186 
187     /*** Dumps all errors as a String. Uses ErrorInfo.toString()
188      * @return Errors as a String.
189      */
190     public String dumpErrors()
191     {
192         return dumpErrorsOrWarnings(errorsByNode);
193     }
194 
195     /*** Dumps all warnings as a String. Uses ErrorInfo.toString()
196      * @return Warnings as a String.
197      */
198     public String dumpWarnings()
199     {
200         return dumpErrorsOrWarnings(warningsByNode);
201     }
202 
203     public String dumpErrorsOrWarnings(Map map)
204     {
205         StringBuilder sb = new StringBuilder();
206         for(java.util.Iterator iter = map.keySet().iterator(); iter.hasNext();)
207         {
208             Node node = (Node)(iter.next());
209             sb.append(node.getUniquePath());
210             sb.append(' ');
211             sb.append(map.get(node).toString());
212             sb.append('\n');
213         }
214         return sb.toString();
215     }
216 }