1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 package basicrunner.basichelper;
28 
29 import com.sun.star.lang.XInitialization;
30 import com.sun.star.lang.XSingleServiceFactory;
31 import com.sun.star.lang.XServiceInfo;
32 import com.sun.star.lang.XTypeProvider;
33 import com.sun.star.uno.Type;
34 import com.sun.star.xml.sax.XDocumentHandler;
35 import com.sun.star.container.XNameAccess;
36 import com.sun.star.container.NoSuchElementException;
37 import java.util.Vector;
38 import util.XMLTools.Tag;
39 import util.XMLTools;
40 import java.io.StringWriter;
41 import java.io.PrintWriter;
42 
43 /**
44  * This class provides a handler of the BASIC test document.
45  * @see com.sun.star.lang.XSingleServiceFactory
46  * @see com.sun.star.lang.XServiceInfo
47  */
48 public class DocumentHandler implements XServiceInfo, XSingleServiceFactory {
49     /** The service name of this class **/
50     static final String __serviceName = "basichelper.DocumentHandler";
51     /** The actual handler of the document **/
52     static DocumentHandlerImpl oDocumentHandler = null;
53     /** A string writer **/
54     private StringWriter writer;
55     /** The log writer (just a wrapper around <code>writer</code>) **/
56     private PrintWriter log;
57 
58     /**
59      * Create an instance of the document handler.
60      * @param args A boolean value as <codde>args[0]</code> determines,
61      *             if checked XML data is printed to the log.
62      *             Default is false.
63      * @return The document handler
64      */
65     public Object createInstanceWithArguments(Object[] args) {
66         boolean printXML = false;
67         if (args != null && args.length!=0 && args[0] instanceof Boolean)
68             printXML = ((Boolean)args[0]).booleanValue();
69         writer = new StringWriter();
70         log = new PrintWriter(writer);
71         oDocumentHandler = new DocumentHandlerImpl(log, printXML, writer);
72         return oDocumentHandler;
73     }
74 
75     /**
76      * Create an instance of the document handler.
77      * @return The document handler
78      */
79     public Object createInstance() {
80         return createInstanceWithArguments(null);
81     }
82 
83     /** Get the unique id for this implementation
84      * @return The id.
85      */
86     public byte[] getImplementationId() {
87         return toString().getBytes();
88     }
89 
90     /** Get all implemented types.
91      * @return The implemented UNO types.
92      */
93     public Type[] getTypes() {
94         Class interfaces[] = getClass().getInterfaces();
95         Type types[] = new Type[interfaces.length];
96         for(int i = 0; i < interfaces.length; ++ i)
97             types[i] = new Type(interfaces[i]);
98         return types;
99     }
100 
101     /** Is this servioce supported?
102      * @param name The service name.
103      * @return True, if the service is supported.
104      */
105     public boolean supportsService(String name) {
106         return __serviceName.equals(name);
107     }
108 
109     /**
110      * Get all supported service names.
111      * @return All supported servcices.
112      */
113     public String[] getSupportedServiceNames() {
114         return new String[] {__serviceName};
115     }
116 
117     /**
118      * Get the implementation name of this class.
119      * @return The implementation name.
120      */
121     public String getImplementationName() {
122         return getClass().getName();
123     }
124 }
125 
126 /**
127  * The actual implementation of the document handler
128  * @see util.XMLTools.XMLChecker
129  * @see com.sun.star.lang.XInitialization
130  * @see com.sun.star.xml.sax.XDocumentHandler
131  * @see com.sun.star.container.XNameAccess
132  * @see com.sun.star.lang.XTypeProvider
133  */
134 class DocumentHandlerImpl extends XMLTools.XMLChecker
135                         implements XInitialization, XDocumentHandler,
136                                                 XNameAccess, XTypeProvider {
137     /** A string writer **/
138     private StringWriter writer;
139 
140     /**
141      * Constructor
142      * @param log_ A log writer.
143      * @param printXML Should XML data be printed to the log?
144      * @param logWriter A wrapper around <code>log_</code> for convenience.
145      */
146     public DocumentHandlerImpl(PrintWriter log_,
147                                     boolean printXML, StringWriter logWriter) {
148         super(log_, printXML);
149         writer = logWriter;
150     }
151 
152     /**
153      * Initialize this class with rules.
154      * @param parm1 An array of filter rules:
155      *              <code>processAction()</code> is called for every rule.
156      * @throws com.sun.star.uno.Exception for an incorrect rule.
157      */
158     public void initialize(Object[] parm1) throws com.sun.star.uno.Exception {
159         if (!(parm1[0] instanceof Object[])) return;
160         for (int i=0; i<parm1.length; i++) {
161             processActionForXMLChecker((Object[])parm1[i]);
162         }
163     }
164 
165     /**
166     * Method processes all filters received from basic tests.
167     * Called by initialize().
168     * @param filterRule An array building one filter rule.
169     * @throws com.sun.star.uno.Exception for an incorrect rule.
170     */
171     private void processActionForXMLChecker(Object[] filterRule)
172                                         throws com.sun.star.uno.Exception {
173         int arrLen = filterRule.length;
174         String oTagName;
175         Object[] oTags;
176         Object[] oTag;
177         int tagsNum = arrLen-1;
178         Vector allTags = new Vector();
179         String CDATA = "";
180         String action = "";
181 
182         // First element of rule is RuleName and should be String
183         if (!(filterRule[0] instanceof String)) {
184             throw new com.sun.star.uno.Exception("Error: incorrect filter rule "+
185             "received from basic test! Rule name must be a String.");
186         } else {
187             action = (String) filterRule[0];
188         }
189 
190         // Searching for character data and defining amount of tags received.
191         for (int j=1; j<arrLen; j++) {
192             if ( (filterRule[j] instanceof String) && (j != 1) ) {
193                 CDATA = (String) filterRule[j];
194                 tagsNum--;
195             }
196         }
197 
198         // Adding received tags to internal array.
199         oTags = new Object[tagsNum];
200         for (int j=1; j<=tagsNum; j++) {
201             if (filterRule[j] instanceof Object[]) {
202                 oTags[j-1] = (Object[]) filterRule[j];
203             }
204         }
205 
206         // Process all received tags for a given filter rule
207         for (int i=0; i<oTags.length; i++) {
208             if (oTags[i] instanceof Object[]) {
209                 oTag = (Object[]) oTags[i];
210                 oTagName = (String) oTag[0];
211             } else if (oTags[i] instanceof Object) {
212                 oTag = new Object[1];
213                 oTag[0] = (Object) oTags[i];
214                 oTagName = (String) oTag[0];
215             } else {
216                 throw new com.sun.star.uno.Exception("Error: invalid tag "+
217                                     "received from basic test! Check tag "
218                                     +i+" in rule '"+action+"'.");
219             }
220 
221             // Action for constructor Tag(TagName, attrName, attrValue)
222             if (oTag.length == 3) {
223                 if ((oTag[1] instanceof String)&&(oTag[2] instanceof String)) {
224                     allTags.add(new Tag(oTagName,
225                                     (String) oTag[1], (String) oTag[2]));
226                 } else {
227                     throw new com.sun.star.uno.Exception("Error: invalid tag '"+
228                                     oTagName+"' received from basic test!");
229                 }
230 
231             // Action for constructors:
232             // Tag(TagName, String[][] attrValues )
233             // Tag(TagName, String[] attrNames)
234             // Tag(TagName, String attrName)
235             //
236             } else if (oTag.length == 2) {
237                 if (oTag[1] instanceof String[][]) {
238                     allTags.add(new Tag(oTagName, (String[][]) oTag[1]));
239                 } else if (oTag[1] instanceof String[]) {
240                     allTags.add(new Tag(oTagName, (String[]) oTag[1]));
241                 } else if (oTag[1] instanceof String) {
242                     allTags.add(new Tag(oTagName, (String) oTag[1]));
243                 } else {
244                     throw new com.sun.star.uno.Exception("Error: invalid tag '"+
245                     oTagName+"' received from basic test!");
246                 }
247 
248             // Action for constructor Tag(TagName)
249             } else if (oTag.length == 1) {
250                 if (oTag[0] instanceof String) {
251                     allTags.add(new Tag(oTagName));
252                 } else {
253                     throw new com.sun.star.uno.Exception("Error: invalid tag '"+
254                     oTagName+"' received from basic test!");
255                 }
256             } else {
257                 throw new com.sun.star.uno.Exception("Error: invalid tag '"+
258                 oTagName+"' received from basic test!");
259             }
260         }
261 
262         // Adding tags to XMLChecker
263         if ( action.equals((String)"TagExists") ) {
264             for (int i=0; i<allTags.size(); i++) {
265                 addTag((Tag)allTags.get(i));
266             }
267         } else if (action.equals((String)"TagEnclosed")) {
268             addTagEnclosed((Tag) allTags.get(0), (Tag) allTags.get(1));
269         } else if (action.equals((String)"CharsEnclosed")) {
270             addCharactersEnclosed(CDATA, (Tag) allTags.get(0));
271         } else {
272             throw new com.sun.star.uno.Exception("Error: incorrect rule name '"+
273             action+"' received from basic test!");
274         }
275     }
276 
277     /**
278      * Get the names of the elements.
279      * @return element names.
280      */
281     public String[] getElementNames() {
282         return new String[]{"XMLCode", "XMLIsCorrect"};
283     }
284 
285     /**
286      * Is this an element?
287      * @param name Element name.
288      * @return true, if <code>name>/code> is the name of an element.
289      */
290     public boolean hasByName(String name) {
291         return (name.equals("XMLCode") || name.equals("XMLIsCorrect"));
292     }
293 
294     /**
295      * Get an element by its name.
296      * @param name The element name.
297      * @return The element with the specified <code>name</code>.
298      * @throws NoSuchElementException Is thrown, if name does not exist.
299      */
300     public Object getByName(String name) throws NoSuchElementException{
301         if (name.equals("XMLIsCorrect"))
302             return new Boolean(this.check());
303         else if (name.equals("XMLCode")) {
304             return writer.getBuffer().toString();
305         } else
306             throw new NoSuchElementException();
307     }
308 
309     /**
310      * Are there any elements?
311      * @return Always true.
312      */
313     public boolean hasElements() {
314         return true;
315     }
316 
317     /**
318      * Get the element type.
319      * @return The type.
320      */
321     public Type getElementType() {
322         return new Type(Object.class);
323     }
324 
325     /**
326      * Get a unique id for this implementation.
327      * @return The id.
328      */
329     public byte[] getImplementationId() {
330         return toString().getBytes();
331     }
332 
333     /**
334      * Return all implemented types of this class.
335      * @return The implemented UNO types.
336      */
337     public Type[] getTypes() {
338         Class interfaces[] = getClass().getInterfaces();
339         Type types[] = new Type[interfaces.length];
340         for(int i = 0; i < interfaces.length; ++ i)
341             types[i] = new Type(interfaces[i]);
342         return types;
343     }
344 }
345