Gtk-WARNING gtktreestore.c:1047: Invalid column number 1 added to iter
[LibreOffice.git] / qadevOOo / runner / util / XMLTools.java
blobfc821b9ffae080d70d396cadbd4903670937423d
1 /*
2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 package util;
21 import java.io.PrintWriter;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.Iterator;
27 import com.sun.star.beans.PropertyValue;
28 import com.sun.star.xml.sax.XAttributeList;
29 import com.sun.star.xml.sax.XDocumentHandler;
30 import com.sun.star.xml.sax.XLocator;
33 public class XMLTools {
35 /**
36 * The implementation of <code>com.sun.star.xml.sax.XAttributeList</code>
37 * where attributes and their values can be added.
39 public static class AttributeList implements XAttributeList {
40 private static class Attribute {
41 public String Name ;
42 public String Type ;
43 public String Value ;
45 private final HashMap<String, Attribute> attrByName = new HashMap<String, Attribute>() ;
46 private final ArrayList<Attribute> attributes = new ArrayList<Attribute>() ;
48 /**
49 * Creates a class instance.
51 public AttributeList() {}
53 private AttributeList(XAttributeList list) {
54 if (list == null) return ;
55 for (short i = 0; i < list.getLength(); i++) {
56 add(list.getNameByIndex(i), list.getTypeByIndex(i),
57 list.getValueByIndex(i)) ;
61 /**
62 * Adds an attribute with type and value specified.
63 * @param name The attribute name.
64 * @param type Value type (usually 'CDATA' used).
65 * @param value Attribute value.
67 public void add(String name, String type, String value) {
68 Attribute attr = new Attribute() ;
69 attr.Name = name ;
70 attr.Type = type ;
71 attr.Value = value ;
72 attributes.add(attr) ;
73 attrByName.put(attr.Name, attr) ;
80 /***************************************
81 * XAttributeList methods
82 ****************************************/
84 public short getLength() {
85 return (short) attributes.size() ;
88 public String getNameByIndex(short idx) {
89 String name = attributes.get(idx).Name ;
90 return name ;
93 public String getTypeByIndex(short idx) {
94 String type = attributes.get(idx).Type ;
95 return type;
98 public String getTypeByName(String name) {
99 String type = attrByName.get(name).Type ;
100 return type;
102 public String getValueByIndex(short idx) {
103 String value = attributes.get(idx).Value ;
104 return value;
107 public String getValueByName(String name) {
108 String value = attrByName.get(name).Value ;
109 return value;
114 * This class writes all XML data handled into a stream specified
115 * in the constructor.
117 private static class XMLWriter implements XDocumentHandler {
118 private PrintWriter _log = null ;
119 private String align = "" ;
122 * Creates a SAX handler which writes all XML data
123 * handled into a <code>log</code> stream specified.
125 private XMLWriter(PrintWriter log) {
126 _log = log ;
130 * Creates a SAX handler which does nothing.
132 public XMLWriter() {
135 public void processingInstruction(String appl, String data) {
136 if (_log == null) return ;
137 _log.println(align + "<?" + appl + " " + data + "?>") ;
139 public void startDocument() {
140 if (_log == null) return ;
141 _log.println("START DOCUMENT:") ;
143 public void endDocument() {
144 if (_log == null) return ;
145 _log.println("END DOCUMENT:") ;
147 public void setDocumentLocator(XLocator loc) {
148 if (_log == null) return ;
149 _log.println("DOCUMENT LOCATOR: ('" + loc.getPublicId() +
150 "','" + loc.getSystemId() + "')") ;
152 public void startElement(String name, XAttributeList attr) {
153 if (_log == null) return ;
154 _log.print(align + "<" + name + " ") ;
155 if (attr != null) {
156 short attrLen = attr.getLength() ;
157 for (short i = 0; i < attrLen; i++) {
158 if (i != 0) _log.print(align + " ") ;
159 _log.print(attr.getNameByIndex(i) + "[" +
160 attr.getTypeByIndex(i) + "]=\"" +
161 attr.getValueByIndex(i) + "\"") ;
162 if (i+1 != attrLen) {
163 _log.println() ;
167 _log.println(">") ;
169 align += " " ;
172 public void endElement(String name) {
173 if (_log == null) return ;
174 align = align.substring(3) ;
175 _log.println(align + "</" + name + ">") ;
178 public void characters(String chars) {
179 if (_log == null) return ;
180 _log.println(align + chars) ;
182 public void ignorableWhitespace(String sp) {
183 if (_log == null) return ;
184 _log.println(sp) ;
189 * Checks if the XML structure is well formed (i.e. all tags opened must be
190 * closed and all tags opened inside a tag must be closed
191 * inside the same tag). It also checks parameters passed.
192 * If any collisions found appropriate error message is
193 * output into a stream specified. No XML data output, i.e.
194 * no output will be performed if no errors occur.<p>
195 * After document is completed there is a way to check
196 * if the XML data and structure was valid.
198 private static class XMLWellFormChecker extends XMLWriter {
199 private boolean docStarted = false ;
200 private boolean docEnded = false ;
201 ArrayList<String> tagStack = new ArrayList<String>() ;
202 private boolean wellFormed = true ;
203 private boolean noOtherErrors = true ;
204 PrintWriter log = null ;
205 private boolean printXMLData = false ;
207 private XMLWellFormChecker(PrintWriter log) {
208 super() ;
209 this.log = log ;
212 private XMLWellFormChecker(PrintWriter log_, boolean printXMLData) {
213 super(printXMLData ? log_ : null) ;
214 this.printXMLData = printXMLData ;
215 this.log = log_ ;
219 * Reset all values. This is important e.g. for test of XFilter
220 * interface, where 'filter()' method is started twice.
222 void reset() {
223 docStarted = false ;
224 docEnded = false ;
225 tagStack = new ArrayList<String>() ;
226 wellFormed = true ;
227 noOtherErrors = true ;
228 printXMLData = false ;
231 @Override
232 public void startDocument() {
233 super.startDocument();
235 if (docStarted) {
236 printError("Document is started twice.") ;
237 wellFormed = false ;
240 docStarted = true ;
242 @Override
243 public void endDocument() {
244 super.endDocument();
245 if (!docStarted) {
246 wellFormed = false ;
247 printError("Document ended but not started.") ;
249 docEnded = true ;
251 @Override
252 public void startElement(String name, XAttributeList attr) {
253 super.startElement(name, attr);
254 if (attr == null) {
255 printError("attribute list passed as parameter to startElement()"+
256 " method has null value for tag <" + name + ">") ;
257 noOtherErrors = false ;
259 tagStack.add(0, name) ;
261 @Override
262 public void endElement(String name) {
263 super.endElement(name);
264 if (wellFormed) {
265 if (tagStack.isEmpty()) {
266 wellFormed = false ;
267 printError("No tags to close (bad closing tag </" + name + ">)") ;
268 } else {
269 String startTag = tagStack.get(0) ;
270 tagStack.remove(0) ;
271 if (!startTag.equals(name)) {
272 wellFormed = false ;
273 printError("Bad closing tag: </" + name +
274 ">; tag expected: </" + startTag + ">");
281 * Checks if there were no errors during document handling.
282 * I.e. startDocument() and endDocument() must be called,
283 * XML must be well formed, parameters must be valid.
285 public boolean isWellFormed() {
286 if (!docEnded) {
287 printError("Document was not ended.") ;
288 wellFormed = false ;
291 return wellFormed && noOtherErrors ;
295 * Prints error message and all tags where error occurred inside.
296 * Also prints "Tag trace" in case if the full XML data isn't
297 * printed.
299 void printError(String msg) {
300 log.println("!!! Error: " + msg) ;
301 if (printXMLData) return ;
302 log.println(" Tag trace :") ;
303 for (int i = 0; i < tagStack.size(); i++) {
304 String tag = tagStack.get(i) ;
305 log.println(" <" + tag + ">") ;
311 * Beside structure of XML this class also can check existence
312 * of tags, inner tags, and character data. After document
313 * completion there is a way to check if required tags and
314 * character data was found. If there any error occurs an
315 * appropriate message is output.
317 public static class XMLTagsChecker extends XMLWellFormChecker {
318 private final HashMap<String,String> tags = new HashMap<String,String>() ;
319 private final HashMap<String,String> chars = new HashMap<String,String>() ;
320 private boolean allOK = true ;
322 public XMLTagsChecker(PrintWriter log) {
323 super(log) ;
327 * Adds a tag name which must be contained in the XML data.
329 public void addTag(String tag) {
330 tags.put(tag, "") ;
333 * Adds a tag name which must be contained in the XML data and
334 * must be inside the tag with name <code>outerTag</code>.
336 public void addTagEnclosed(String tag, String outerTag) {
337 tags.put(tag, outerTag) ;
341 * Adds a character data which must be contained in the XML data and
342 * must be inside the tag with name <code>outerTag</code>.
344 public void addCharactersEnclosed(String ch, String outerTag) {
345 chars.put(ch, outerTag) ;
348 @Override
349 public void startElement(String name, XAttributeList attrs) {
350 super.startElement(name, attrs) ;
351 if (tags.containsKey(name)) {
352 String outerTag = tags.get(name);
353 if (outerTag.length() != 0) {
354 boolean isInTag = false ;
355 for (int i = 0; i < tagStack.size(); i++) {
356 if (outerTag.equals(tagStack.get(i))) {
357 isInTag = true ;
358 break ;
361 if (!isInTag) {
362 printError("Required tag <" + name + "> found, but is not enclosed in tag <" +
363 outerTag + ">") ;
364 allOK = false ;
367 tags.remove(name) ;
371 @Override
372 public void characters(String ch) {
373 super.characters(ch) ;
375 if (chars.containsKey(ch)) {
376 String outerTag = chars.get(ch);
377 if (outerTag.length() != 0) {
378 boolean isInTag = false ;
379 for (int i = 0; i < tagStack.size(); i++) {
380 if (outerTag.equals(tagStack.get(i))) {
381 isInTag = true ;
382 break ;
385 if (!isInTag) {
386 printError("Required characters '" + ch + "' found, but are not enclosed in tag <" +
387 outerTag + ">") ;
388 allOK = false ;
391 chars.remove(ch) ;
396 * Checks if the XML data was valid and well formed and if
397 * all necessary tags and character data was found.
399 public boolean checkTags() {
400 if (!isWellFormed())
401 allOK = false ;
403 Iterator<String> badTags = tags.keySet().iterator() ;
404 Iterator<String> badChars = chars.keySet().iterator() ;
406 if (badTags.hasNext()) {
407 allOK = false ;
408 log.println("Required tags were not found in export :") ;
409 while(badTags.hasNext()) {
410 log.println(" <" + badTags.next() + ">") ;
413 if (badChars.hasNext()) {
414 allOK = false ;
415 log.println("Required characters were not found in export :") ;
416 while(badChars.hasNext()) {
417 log.println(" <" + badChars.next() + ">") ;
420 reset();
421 return allOK ;
426 * Represents an XML tag which must be found in XML data written.
427 * This tag can contain only its name or tag name and attribute
428 * name, or attribute value additionally.
430 public static class Tag {
431 private final String name;
432 private String[][] attrList = new String[0][3] ;
435 * Creates tag which has only a name. Attributes don't make sense.
436 * @param tagName The name of the tag.
438 public Tag(String tagName) {
439 name = tagName ;
443 * Creates a tag with the name specified, which must have an
444 * attribute with the value specified. The type of value
445 * assumed to be 'CDATA'.
446 * @param tagName The name of the tag.
447 * @param attrName The name of attribute which must be contained
448 * in the tag.
449 * @param attrValue Attribute value.
451 public Tag(String tagName, String attrName, String attrValue) {
452 name = tagName ;
453 attrList = new String[1][3] ;
454 attrList[0][0] = attrName ;
455 attrList[0][1] = "CDATA" ;
456 attrList[0][2] = attrValue ;
460 * Gets tag String description.
462 @Override
463 public String toString() {
464 StringBuffer ret = new StringBuffer("<" + name);
465 for (int i = 0; i < attrList.length; i++) {
466 ret.append(" ").append(attrList[i][0]).append("=");
467 if (attrList[i][2] == null) {
468 ret.append("(not specified)");
469 } else {
470 ret.append("\"").append(attrList[i][2]).append("\"");
473 ret.append(">");
475 return ret.toString();
478 private boolean checkAttr(int attrListIdx, XAttributeList list) {
479 short j = 0 ;
480 int listLen = list.getLength();
481 while(j < listLen) {
482 if (attrList[attrListIdx][0].equals(list.getNameByIndex(j))) {
483 if (attrList[attrListIdx][2] == null) return true ;
484 return attrList[attrListIdx][2].equals(list.getValueByIndex(j)) ;
486 j++ ;
488 return false ;
492 * Checks if this tag matches tag passed in parameters.
493 * I.e. if tag specifies only its name it matches if names
494 * are equal (attributes don't make sense). If there are
495 * some attributes names specified in this tag method checks
496 * if all names present in attribute list <code>list</code>
497 * (attributes' values don't make sense). If attributes specified
498 * with values method checks if these attributes exist and
499 * have appropriate values.
501 private boolean isMatchTo(String tagName, XAttributeList list) {
502 if (!name.equals(tagName)) return false;
503 boolean result = true ;
504 for (int i = 0; i < attrList.length; i++) {
505 result &= checkAttr(i, list) ;
507 return result ;
512 * Class realises extended XML data checking. It has possibilities
513 * to check if a tag exists, if it has some attributes with
514 * values, and if this tag is contained in another tag (which
515 * also can specify any attributes). It can check if some
516 * character data exists inside any tag specified.
518 public static class XMLChecker extends XMLWellFormChecker {
519 private final HashSet<String> tagSet = new HashSet<String>() ;
520 private final ArrayList<Tag[]> tags = new ArrayList<Tag[]>() ;
521 private final ArrayList<Object[]> chars = new ArrayList<Object[]>() ;
522 private final ArrayList<String> tagStack = new ArrayList<String>() ;
523 private final ArrayList<AttributeList> attrStack = new ArrayList<AttributeList>() ;
525 public XMLChecker(PrintWriter log, boolean writeXML) {
526 super(log, writeXML) ;
529 public void addTag(Tag tag) {
530 tags.add(new Tag[] {tag, null}) ;
531 tagSet.add(tag.name) ;
534 public void addTagEnclosed(Tag tag, Tag outerTag) {
535 tags.add(new Tag[] {tag, outerTag}) ;
536 tagSet.add(tag.name) ;
541 public void addCharactersEnclosed(String ch, Tag outerTag) {
542 chars.add(new Object[] {ch.trim(), outerTag}) ;
545 @Override
546 public void startElement(String name, XAttributeList attr) {
547 try {
548 super.startElement(name, attr);
550 if (tagSet.contains(name)) {
551 for (int i = 0; i < tags.size(); i++) {
552 Tag[] tag = tags.get(i);
553 if (tag[0].isMatchTo(name, attr)) {
554 if (tag[1] == null) {
555 tags.remove(i--);
556 } else {
557 boolean isInStack = false ;
558 for (int j = 0; j < tagStack.size(); j++) {
559 if (tag[1].isMatchTo(tagStack.get(j),
560 attrStack.get(j))) {
562 isInStack = true ;
563 break ;
566 if (isInStack) {
567 tags.remove(i--) ;
574 tagStack.add(0, name) ;
575 attrStack.add(0, new AttributeList(attr));
576 } catch (Exception e) {
577 e.printStackTrace(log);
581 @Override
582 public void characters(String ch) {
583 super.characters(ch) ;
584 for (int i = 0; i < chars.size(); i++) {
585 Object[] chr = chars.get(i);
586 if (((String) chr[0]).equals(ch)) {
587 if (chr[1] == null) {
588 chars.remove(i--);
589 } else {
590 boolean isInStack = false ;
591 for (int j = 0; j < tagStack.size(); j++) {
592 if (((Tag) chr[1]).isMatchTo(tagStack.get(j),
593 attrStack.get(j))) {
595 isInStack = true ;
596 break ;
599 if (isInStack) {
600 chars.remove(i--) ;
607 @Override
608 public void endElement(String name) {
609 try {
610 super.endElement(name);
612 if (tagStack.size() > 0) {
613 tagStack.remove(0) ;
614 attrStack.remove(0) ;
616 } catch(Exception e) {
617 e.printStackTrace(log) ;
621 public boolean check() {
622 if (tags.size()> 0) {
623 log.println("!!! Error: Some tags were not found :") ;
624 for (int i = 0; i < tags.size(); i++) {
625 Tag[] tag = tags.get(i) ;
626 log.println(" Tag " + tag[0] + " was not found");
627 if (tag[1] != null)
628 log.println(" inside tag " + tag[1]) ;
631 if (chars.size() > 0) {
632 log.println("!!! Error: Some character data blocks were not found :") ;
633 for (int i = 0; i < chars.size(); i++) {
634 Object[] ch = chars.get(i) ;
635 log.println(" Character data \"" + ch[0] + "\" was not found ") ;
636 if (ch[1] != null)
637 log.println(" inside tag " + ch[1]) ;
641 if (!isWellFormed())
642 log.println("!!! Some errors were found in XML structure") ;
644 boolean result = tags.isEmpty() && chars.isEmpty() && isWellFormed();
645 reset();
646 return result;
652 public static PropertyValue[] createMediaDescriptor(String[] propNames, Object[] values) {
653 PropertyValue[] props = new PropertyValue[propNames.length] ;
655 for (int i = 0; i < props.length; i++) {
656 props[i] = new PropertyValue() ;
657 props[i].Name = propNames[i] ;
658 if (values != null && i < values.length) {
659 props[i].Value = values[i] ;
663 return props ;