diff --git a/.classpath b/.classpath
index 37c8adf..931c5c0 100644
--- a/.classpath
+++ b/.classpath
@@ -10,5 +10,6 @@
+
diff --git a/buildjar.xml b/buildjar.xml
index da1bef1..dee1465 100644
--- a/buildjar.xml
+++ b/buildjar.xml
@@ -121,7 +121,7 @@
-
+
diff --git a/lib/README b/lib/README
index f7df234..429f99f 100644
--- a/lib/README
+++ b/lib/README
@@ -1,4 +1,5 @@
Description of used libraries:
+- commons-lang: useful tools (StringUtils...)
- hamcrest-core: required by junit
- junit: unit tests API
- log4j: log API
diff --git a/lib/commons-lang3-3.1-sources.jar b/lib/commons-lang3-3.1-sources.jar
new file mode 100644
index 0000000..02cd2f2
Binary files /dev/null and b/lib/commons-lang3-3.1-sources.jar differ
diff --git a/lib/commons-lang3-3.1.jar b/lib/commons-lang3-3.1.jar
new file mode 100644
index 0000000..a85e539
Binary files /dev/null and b/lib/commons-lang3-3.1.jar differ
diff --git a/src/fr/devinsy/util/StringList.java b/src/fr/devinsy/util/StringList.java
index fb26648..bd9ea6b 100755
--- a/src/fr/devinsy/util/StringList.java
+++ b/src/fr/devinsy/util/StringList.java
@@ -16,7 +16,7 @@ import java.util.ArrayList;
public class StringList extends ArrayList
{
private static final long serialVersionUID = -1154185934830213732L;
- public String LINE_SEPARATOR = "\n";
+ public static final String LINE_SEPARATOR = "\n";
/**
*
@@ -34,6 +34,22 @@ public class StringList extends ArrayList
super(size);
}
+ /**
+ *
+ */
+ public StringList(final String[] source)
+ {
+ super();
+
+ if (source != null)
+ {
+ for (String string : source)
+ {
+ this.add(string);
+ }
+ }
+ }
+
/**
*
*/
@@ -49,6 +65,37 @@ public class StringList extends ArrayList
return (result);
}
+ /**
+ *
+ */
+ public StringList append(final double value)
+ {
+ StringList result;
+
+ result = this.append(String.valueOf(value));
+
+ //
+ return (result);
+ }
+
+ /**
+ *
+ */
+ public StringList append(final Double value)
+ {
+ StringList result;
+
+ if (value != null)
+ {
+ this.append(String.valueOf(value));
+ }
+
+ result = this;
+
+ //
+ return (result);
+ }
+
/**
*
*/
@@ -117,15 +164,15 @@ public class StringList extends ArrayList
/**
*
*/
- public StringList append(final StringList string)
+ public StringList append(final StringList strings)
{
StringList result;
- if (string != null)
+ if (strings != null)
{
- for (int nString = 0; nString < string.size(); nString++)
+ for (String string : strings)
{
- this.add(string.getByIndex(nString));
+ this.add(string);
}
}
@@ -163,6 +210,19 @@ public class StringList extends ArrayList
return (result);
}
+ /**
+ *
+ */
+ public StringList appendln(final double value)
+ {
+ StringList result;
+
+ result = this.append(value).appendln();
+
+ //
+ return (result);
+ }
+
/**
*
*/
@@ -248,9 +308,9 @@ public class StringList extends ArrayList
{
int result = 0;
- for (int nString = 0; nString < this.size(); nString++)
+ for (String string : this)
{
- result += this.getByIndex(nString).length();
+ result += string.length();
}
@@ -284,27 +344,64 @@ public class StringList extends ArrayList
{
String result;
- StringBuffer preResult = new StringBuffer(this.lenght());
+ StringBuffer buffer = new StringBuffer(this.lenght());
- for (int nString = 0; nString < this.size(); nString++)
+ for (String string : this)
{
- preResult.append(this.getByIndex(nString));
+ buffer.append(string);
}
- result = new String(preResult);
+ result = buffer.toString();
//
return (result);
}
+ /**
+ *
+ */
+ public String toStringSeparatedBy(final String separator)
+ {
+ String result;
+
+ //
+ StringList buffer = new StringList(this.lenght() * 2);
+ for (String string : this)
+ {
+ buffer.append(string);
+ buffer.append(separator);
+ }
+
+ if (separator != null)
+ {
+ buffer.removeLast();
+ }
+
+ result = buffer.toString();
+
+ //
+ return (result);
+ }
+
+ /**
+ *
+ */
+ public void writeInto(final java.io.PrintWriter out) throws IOException
+ {
+ for (String string : this)
+ {
+ out.write(string);
+ }
+ }
+
/**
*
*/
public void writeInto(final java.io.Writer out) throws IOException
{
- for (int nString = 0; nString < this.size(); nString++)
+ for (String string : this)
{
- out.write(this.getByIndex(nString));
+ out.write(string);
}
}
@@ -315,7 +412,7 @@ public class StringList extends ArrayList
{
String result;
- StringList strings = new StringList();
+ StringList strings = new StringList(number);
for (int index = 0; index < number; index++)
{
strings.append(source);
@@ -330,29 +427,17 @@ public class StringList extends ArrayList
/**
*
*/
- static public String toString(final String[] strings)
+ static public String toString(final String[] source)
{
String result;
- if (strings == null)
+ if (source == null)
{
result = null;
}
else
{
- StringConcatenator string = new StringConcatenator();
-
- for (int nString = 0; nString < strings.length; nString++)
- {
- string.append(strings[nString]);
-
- if (nString < strings.length - 1)
- {
- string.append(' ');
- }
- }
-
- result = string.toString();
+ result = new StringList(source).toString();
}
//
@@ -424,19 +509,19 @@ public class StringList extends ArrayList
/**
*
*/
- static public String toStringWithBrackets(final String[] strings)
+ static public String toStringWithBrackets(final String[] source)
{
String result;
- if (strings == null)
+ if (source == null)
{
result = null;
}
else
{
- StringConcatenator merge = new StringConcatenator();
+ StringList merge = new StringList();
- for (String string : strings)
+ for (String string : source)
{
merge.append("[").append(string).append("]");
}
@@ -451,29 +536,17 @@ public class StringList extends ArrayList
/**
*
*/
- static public String toStringWithCommas(final String[] strings)
+ static public String toStringWithCommas(final String[] source)
{
String result;
- if (strings == null)
+ if (source == null)
{
result = null;
}
else
{
- StringConcatenator merge = new StringConcatenator();
-
- for (String string : strings)
- {
- if (merge.size() != 0)
- {
- merge.append(",");
- }
-
- merge.append(string);
- }
-
- result = merge.toString();
+ result = new StringList(source).toStringSeparatedBy(",");
}
//
@@ -483,29 +556,17 @@ public class StringList extends ArrayList
/**
*
*/
- static public String toStringWithFrenchCommas(final String[] strings)
+ static public String toStringWithFrenchCommas(final String[] source)
{
String result;
- if (strings == null)
+ if (source == null)
{
result = null;
}
else
{
- StringConcatenator merge = new StringConcatenator();
-
- for (String string : strings)
- {
- if (merge.size() != 0)
- {
- merge.append(", ");
- }
-
- merge.append(string);
- }
-
- result = merge.toString();
+ result = new StringList(source).toStringSeparatedBy(", ");
}
//
diff --git a/src/fr/devinsy/util/ToolBox.java b/src/fr/devinsy/util/ToolBox.java
new file mode 100644
index 0000000..fd7f6fa
--- /dev/null
+++ b/src/fr/devinsy/util/ToolBox.java
@@ -0,0 +1,404 @@
+package fr.devinsy.util;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ *
+ @author christian.momon@devinsy.fr, June 2008, copyright.
+ *
+ * This file is free software under the terms of the GNU Library General
+ * Public License as published by the Free Software Foundation version 3
+ * or any later version.
+ *
+ */
+public class ToolBox
+{
+
+ /**
+ *
+ *
+ * @param file
+ * Source.
+ *
+ * @return Extension value or null.
+ */
+ public static File addToName(final File file, final String addition)
+ {
+ File result;
+
+ if (file == null)
+ {
+ result = null;
+ }
+ else if (addition == null)
+ {
+ result = file;
+ }
+ else
+ {
+ //
+ String sourceFileName = file.getAbsolutePath();
+ int separatorIndex = sourceFileName.lastIndexOf('.');
+
+ //
+ String targetFileName;
+ if (separatorIndex > 0)
+ {
+ targetFileName = sourceFileName.substring(0, separatorIndex) + addition + sourceFileName.substring(separatorIndex);
+ }
+ else
+ {
+ targetFileName = sourceFileName + addition;
+ }
+
+ //
+ result = new File(targetFileName);
+ }
+
+ //
+ return result;
+ }
+
+ public static String clean(final String source)
+ {
+ String result;
+
+ result = source.replaceAll("[^\\w ]", " ");
+
+ //
+ return result;
+ }
+
+ /**
+ * Returns information about the calling class of a calledClass.
+ *
+ * @param calledClassName
+ * the class name which is the subject of the search.
+ *
+ * @return information about the calling class.
+ */
+ public static StackTraceElement getCaller(final String calledClassName)
+ {
+ StackTraceElement result;
+
+ //
+ StackTraceElement[] stack = Thread.currentThread().getStackTrace();
+ // System.out.println("////////////////////////////");
+ // for (int i = 0; (i < stack.length) && (i < 4); i++) {
+ // System.out.println(i + " " + stack[i].getClassName());
+ // }
+
+ // Search for first entry of class called.
+ boolean ended = false;
+ Integer indexOfCalled = null;
+ int depth = 1;
+ while (!ended)
+ {
+ if (depth < stack.length)
+ {
+ String currentClassName = stack[depth].getClassName();
+ if (currentClassName.equals(calledClassName))
+ {
+ ended = true;
+ indexOfCalled = Integer.valueOf(depth);
+ }
+ else
+ {
+ depth += 1;
+ }
+ }
+ else
+ {
+ ended = true;
+ result = null;
+ }
+ }
+
+ // Search for caller of class called.
+ if (indexOfCalled == null)
+ {
+ result = null;
+ }
+ else
+ {
+ result = null;
+ ended = false;
+ depth = indexOfCalled;
+ while (!ended)
+ {
+ if (depth < stack.length)
+ {
+ String currentClassName = stack[depth].getClassName();
+ if (currentClassName.equals(calledClassName))
+ {
+ depth += 1;
+ }
+ else
+ {
+ ended = true;
+ result = stack[depth];
+ }
+ }
+ else
+ {
+ ended = true;
+ result = null;
+ }
+ }
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ * Get the extension of a file.
+ *
+ * @param file
+ * Source.
+ *
+ * @return Extension value or null.
+ */
+ public static String getExtension(final File file)
+ {
+ String result;
+
+ if (file == null)
+ {
+ result = null;
+ }
+ else
+ {
+ int separatorIndex = file.getName().lastIndexOf('.');
+ if (separatorIndex > 0)
+ {
+ result = file.getName().substring(separatorIndex + 1).toLowerCase();
+ }
+ else
+ {
+ result = null;
+ }
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @param pattern
+ * @param source
+ * @return
+ */
+ public static int indexOf(final String pattern, final List source)
+ {
+ int result;
+
+ if (source == null)
+ {
+ result = -1;
+ }
+ else
+ {
+ boolean ended = false;
+ result = -1;
+ int currentIndex = 0;
+ while (!ended)
+ {
+ if (currentIndex < source.size())
+ {
+ String sourceString = source.get(currentIndex);
+ if (StringUtils.equals(sourceString, pattern))
+ {
+ ended = true;
+ result = currentIndex;
+ }
+ else
+ {
+ currentIndex += 1;
+ }
+ }
+ else
+ {
+ ended = true;
+ currentIndex = -1;
+ }
+ }
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @param file
+ * @throws FileNotFoundException
+ * @throws UnsupportedEncodingException
+ */
+ public static void save(final File file, final String string) throws UnsupportedEncodingException, FileNotFoundException
+ {
+ PrintWriter out = null;
+ try
+ {
+ out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
+
+ out.println(string);
+ }
+ finally
+ {
+ if (out != null)
+ {
+ out.close();
+ }
+ }
+ }
+
+ /**
+ *
+ * @param source
+ * @param extension
+ * @return
+ */
+ public static File setExtension(final File source, final String extension)
+ {
+ File result;
+
+ if ((source == null) || (extension == null))
+ {
+ result = source;
+ }
+ else
+ {
+ String sourceFileName = source.getAbsolutePath();
+ int separatorIndex = sourceFileName.lastIndexOf('.');
+
+ //
+ String targetFileName;
+ if (separatorIndex > 0)
+ {
+ targetFileName = sourceFileName.substring(0, separatorIndex) + extension;
+ }
+ else
+ {
+ targetFileName = sourceFileName + extension;
+ }
+
+ //
+ result = new File(targetFileName);
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public static Double[] sort(final Set source)
+ {
+ Double[] result;
+
+ if (source == null)
+ {
+ result = null;
+ }
+ else
+ {
+ result = new Double[source.size()];
+
+ source.toArray(result);
+ Arrays.sort(result);
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ * Concatenates int values from an array, adding decoration strings.
+ *
+ * @param values
+ * Source of int values.
+ * @param prefix
+ * Decoration to put on start.
+ * @param separator
+ * Decoration to put between values.
+ * @param postfix
+ * Decoration to put on end.
+ *
+ * @return A decorated string representing the int values.
+ */
+ public static String toString(final int[] values, final String prefix, final String separator, final String postfix)
+ {
+ String result;
+
+ StringList buffer = new StringList();
+
+ //
+ if (prefix != null)
+ {
+ buffer.append(prefix);
+ }
+
+ //
+ boolean firstPassed = false;
+ for (int value : values)
+ {
+ if (firstPassed)
+ {
+ buffer.append(separator);
+ }
+ else
+ {
+ firstPassed = true;
+ }
+ buffer.append(value);
+ }
+
+ //
+ if (postfix != null)
+ {
+ buffer.append(postfix);
+ }
+
+ //
+ result = buffer.toString();
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @param source
+ * @return
+ */
+ public static String toString(final String source)
+ {
+ String result;
+
+ if (source == null)
+ {
+ result = "";
+ }
+ else
+ {
+ result = source;
+ }
+
+ //
+ return result;
+ }
+}
diff --git a/src/fr/devinsy/util/xml/XMLAttributes.java b/src/fr/devinsy/util/xml/XMLAttributes.java
new file mode 100644
index 0000000..9b982fa
--- /dev/null
+++ b/src/fr/devinsy/util/xml/XMLAttributes.java
@@ -0,0 +1,131 @@
+package fr.devinsy.util.xml;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.stream.events.Attribute;
+
+/**
+ *
+ * @author christian.momon@devinsy.fr, 2013, copyright.
+ *
+ * This file is free software under the terms of the GNU Library General
+ * Public License as published by the Free Software Foundation version 3
+ * or any later version.
+ */
+public class XMLAttributes extends HashMap implements Iterable {
+
+ private static final long serialVersionUID = 8456469741805779474L;
+
+ /**
+ *
+ */
+ public XMLAttributes() {
+ super();
+ }
+
+ /**
+ *
+ */
+ public XMLAttributes(final int capacity) {
+ super(capacity);
+ }
+
+ /**
+ *
+ */
+ public XMLAttributes(final Iterator source) {
+ super();
+ if (source != null) {
+ while (source.hasNext()) {
+ Attribute attribute = source.next();
+
+ add(attribute);
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ public XMLAttributes(final XMLAttributes source) {
+ super();
+ addAll(source);
+ }
+
+ /**
+ *
+ * @param attribute
+ */
+ public void add(final Attribute attribute) {
+ if (attribute != null) {
+ put(attribute.getName().getLocalPart(), attribute);
+ }
+ }
+
+ /**
+ *
+ * @param source
+ */
+ public void addAll(final XMLAttributes source) {
+ for (Attribute attribute : source) {
+ this.add(attribute);
+ }
+ }
+
+ /**
+ *
+ * @param label
+ * @return
+ */
+ public Attribute getByLabel(final String label) {
+ Attribute result;
+
+ result = get(label);
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ */
+ @Override
+ public Iterator iterator() {
+ Iterator result;
+
+ result = this.values().iterator();
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public Set labels() {
+ Set result;
+
+ result = this.keySet();
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public List toList() {
+ List result;
+
+ result = new ArrayList(values());
+
+ //
+ return result;
+ }
+}
diff --git a/src/fr/devinsy/util/xml/XMLBadFormatException.java b/src/fr/devinsy/util/xml/XMLBadFormatException.java
new file mode 100644
index 0000000..e360fbc
--- /dev/null
+++ b/src/fr/devinsy/util/xml/XMLBadFormatException.java
@@ -0,0 +1,32 @@
+package fr.devinsy.util.xml;
+
+/**
+ * @author christian.momon@devinsy.fr, 2013, copyright.
+ *
+ * This file is free software under the terms of the GNU Library General
+ * Public License as published by the Free Software Foundation version 3
+ * or any later version.
+ */
+public class XMLBadFormatException extends Exception {
+
+ private static final long serialVersionUID = 768256303984176512L;
+
+ /**
+ *
+ * @param code
+ * @param message
+ */
+ public XMLBadFormatException(final String message) {
+ super(message);
+ }
+
+ /**
+ *
+ * @param code
+ * @param message
+ * @param exception
+ */
+ public XMLBadFormatException(final String message, final Exception exception) {
+ super(message, exception);
+ }
+}
diff --git a/src/fr/devinsy/util/xml/XMLReader.java b/src/fr/devinsy/util/xml/XMLReader.java
new file mode 100644
index 0000000..aee7919
--- /dev/null
+++ b/src/fr/devinsy/util/xml/XMLReader.java
@@ -0,0 +1,497 @@
+package fr.devinsy.util.xml;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.XMLEvent;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import fr.devinsy.util.xml.XMLTag.TagType;
+
+/**
+ *
+ @author christian.momon@devinsy.fr, 2013, copyright.
+ *
+ * This file is free software under the terms of the GNU Library General
+ * Public License as published by the Free Software Foundation version 3
+ * or any later version.
+ */
+public class XMLReader {
+
+ static private final Logger logger = LoggerFactory.getLogger(XMLReader.class);
+
+ protected XMLEventReader in;
+ private XMLEvent nextEvent;
+
+ /**
+ *
+ */
+ protected XMLReader() {
+ this.in = null;
+ this.nextEvent = null;
+ }
+
+ /**
+ *
+ * @param file
+ * @throws XMLStreamException
+ * @throws FileNotFoundException
+ * @throws UnsupportedEncodingException
+ */
+ public XMLReader(final File file) throws FileNotFoundException, XMLStreamException {
+
+ this.nextEvent = null;
+ XMLInputFactory factory = XMLInputFactory.newInstance();
+ this.in = factory.createXMLEventReader(new FileInputStream(file), "UTF-8");
+ }
+
+ /**
+ *
+ * @param target
+ * @throws XMLStreamException
+ * @throws UnsupportedEncodingException
+ */
+ public XMLReader(final InputStream source) throws XMLStreamException {
+
+ this.nextEvent = null;
+ XMLInputFactory factory = XMLInputFactory.newInstance();
+ this.in = factory.createXMLEventReader(source);
+ }
+
+ /**
+ * @throws XMLStreamException
+ *
+ */
+ public void close() {
+ if (this.in != null) {
+ try {
+ this.in.close();
+ } catch (XMLStreamException exception) {
+ exception.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * This methods does a premonition act. Useful to detect end of a list.
+ *
+ * @param label
+ * @return
+ * @throws XMLStreamException
+ */
+ public boolean hasNextStartTag(final String label) throws XMLStreamException {
+ boolean result;
+
+ // Load next event.
+ if (this.nextEvent == null) {
+ if (in.hasNext()) {
+ this.nextEvent = in.nextEvent();
+ }
+ }
+
+ // Analyze next event.
+ if (this.nextEvent == null) {
+ result = false;
+ } else if ((this.nextEvent.isStartElement()) && (StringUtils.equals(this.nextEvent.asStartElement().getName().getLocalPart(), label))) {
+ result = true;
+ } else {
+ result = false;
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @param label
+ * @return
+ * @throws XMLBadFormatException
+ * @throws XMLStreamException
+ */
+ public XMLTag readContentTag(final String label) throws XMLBadFormatException, XMLStreamException {
+ XMLTag result;
+
+ //
+ result = readTag();
+
+ //
+ if (result == null) {
+ throw new XMLBadFormatException("XML file ends prematurely, content tag [" + label + "] is expected.");
+ } else if (result.getType() != TagType.CONTENT) {
+ throw new XMLBadFormatException("Content tag [" + label + "] is missing.");
+ } else if (!StringUtils.equals(label, result.getLabel())) {
+ throw new XMLBadFormatException("Tag with label [" + label + "] is missing.");
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @param label
+ * @return
+ * @throws XMLStreamException
+ * @throws XMLBadFormatException
+ */
+ public XMLTag readEndTag(final String label) throws XMLStreamException, XMLBadFormatException {
+ XMLTag result;
+
+ //
+ result = readTag();
+
+ //
+ if (result == null) {
+ throw new XMLBadFormatException("XML file ends prematurely, end tag [" + label + "] is expected.");
+ } else if (result.getType() != TagType.END) {
+ throw new XMLBadFormatException("End tag [" + label + "] is missing.");
+ } else if (!StringUtils.equals(result.getLabel(), label)) {
+ throw new XMLBadFormatException("Tag with label [" + label + "] is missing.");
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @param label
+ * @return
+ * @throws XMLStreamException
+ * @throws XMLBadFormatException
+ * @throws Exception
+ */
+ public XMLTag readListTag(final String label) throws XMLStreamException, XMLBadFormatException {
+ XMLTag result;
+
+ //
+ result = readTag();
+
+ //
+ if (result == null) {
+ throw new XMLBadFormatException("XML file ends prematurely, tag [" + label + "] is expected.");
+ } else if ((result.getType() != TagType.START) && (result.getType() != TagType.EMPTY)) {
+ throw new XMLBadFormatException("List tag [" + label + "] is missing.");
+ } else if (!StringUtils.equals(label, result.getLabel())) {
+ throw new XMLBadFormatException("Tag with label [" + label + "] is missing.");
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @param label
+ * @return
+ * @throws XMLStreamException
+ * @throws XMLBadFormatException
+ * @throws Exception
+ */
+ public XMLTag readNullableContentTag(final String label) throws XMLStreamException, XMLBadFormatException {
+ XMLTag result;
+
+ //
+ result = readTag();
+
+ //
+ if (result == null) {
+ throw new XMLBadFormatException("XML file ends prematurely, tag [" + label + "] is expected.");
+ } else if (!StringUtils.equals(label, result.getLabel())) {
+ throw new XMLBadFormatException("Nullable content tag [" + label + "] is missing.");
+ } else if ((result.getType() != TagType.EMPTY) && (result.getType() != TagType.CONTENT)) {
+ throw new XMLBadFormatException("Nullable content tag [" + label + "] is missing.");
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @param label
+ * @return
+ * @throws XMLStreamException
+ * @throws XMLBadFormatException
+ * @throws Exception
+ */
+ public XMLTag readStartTag(final String label) throws XMLStreamException, XMLBadFormatException {
+ XMLTag result;
+
+ //
+ result = readTag();
+
+ //
+ if (result == null) {
+ throw new XMLBadFormatException("XML file ends prematurely, start tag [" + label + "] is expected.");
+ } else if (result.getType() != TagType.START) {
+ throw new XMLBadFormatException("Start tag [" + label + "] is missing.");
+ } else if (!StringUtils.equals(result.getLabel(), label)) {
+ throw new XMLBadFormatException("Tag with label [" + label + "] is missing.");
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ * Transducer graph :
+ *
+ * - START_DOCUMENT => HEADER TAG
+ *
- START_ELEMENT(X) + START_ELEMENT(Y) => => START TAG
+ *
- START_ELEMENT(X) + CHARACTERS(C) + START_ELEMENT(Y) => SPACES=>
+ * START TAG
+ *
- START_ELEMENT(X) + CHARACTERS(C) + END_ELEMENT(X) => C =>
+ * CONTENT TAG
+ *
- START_ELEMENT(X) + END_ELEMENT(X) => => => EMPTY
+ *
- END_ELEMENT(X) =>
=> END TAG
+ * - END_DOCUMENT => FOOTER TAG
+ *
+ *
+ * @throws XMLStreamException
+ * @throws XMLBadFormatException
+ *
+ */
+ public XMLTag readTag() throws XMLStreamException, XMLBadFormatException {
+ XMLTag result;
+
+ int level = 1;
+ boolean ended = false;
+ result = null;
+ XMLAttributes attributesBuffer = null;
+ QName nameBuffer = null;
+ String contentBuffer = null;
+ while (!ended) {
+ //
+ XMLEvent event;
+ if (this.nextEvent != null) {
+ event = this.nextEvent;
+ this.nextEvent = null;
+ } else if (in.hasNext()) {
+ event = in.nextEvent();
+ } else {
+ event = null;
+ }
+
+ if (event == null) {
+ result = null;
+ } else {
+ logger.debug("eventType=" + XMLTools.toString(event));
+ switch (level) {
+ case 1:
+ switch (event.getEventType()) {
+ case XMLEvent.START_DOCUMENT:
+ // START_DOCUMENT => START DOCUMENT TAG
+ ended = true;
+ result = new XMLTag(null, TagType.HEADER, null);
+ break;
+ case XMLEvent.START_ELEMENT:
+ // START_ELEMENT(X) => ...
+ nameBuffer = event.asStartElement().getName();
+ attributesBuffer = new XMLAttributes(event.asStartElement().getAttributes());
+ level += 1;
+ break;
+ case XMLEvent.END_ELEMENT:
+ // END_ELEMENT(X) => => END TAG
+ ended = true;
+ result = new XMLTag(event.asEndElement().getName(), TagType.END, null);
+ break;
+ case XMLEvent.END_DOCUMENT:
+ // END_DOCUMENT => END DOCUMENT TAG
+ ended = true;
+ result = new XMLTag(null, TagType.FOOTER, null);
+ break;
+ }
+ break;
+ case 2:
+ switch (event.getEventType()) {
+ case XMLEvent.START_ELEMENT:
+ // START_ELEMENT(X) + START_ELEMENT(Y) =>
+ // => START TAG
+ ended = true;
+ result = new XMLTag(nameBuffer, TagType.START, attributesBuffer);
+ this.nextEvent = event;
+ break;
+ case XMLEvent.CHARACTERS:
+ // START_ELEMENT(X) + CHARACTERS(C) => ...
+ contentBuffer = event.asCharacters().getData();
+ level += 1;
+ break;
+ case XMLEvent.END_ELEMENT:
+ // START_ELEMENT(X) + END_ELEMENT(X) =>
+ // => => EMPTY
+ ended = true;
+ result = new XMLTag(nameBuffer, TagType.EMPTY, attributesBuffer);
+ break;
+ default:
+ throw new XMLBadFormatException("Unexpected XMLEvent [" + event.getEventType() + "].");
+ }
+ break;
+ case 3:
+ switch (event.getEventType()) {
+ case XMLEvent.START_ELEMENT:
+ // START_ELEMENT(X) + CHARACTERS(C) +
+ // START_ELEMENT(Y) =>
+ // SPACES => START TAG
+ ended = true;
+ result = new XMLTag(nameBuffer, TagType.START, attributesBuffer);
+ this.nextEvent = event;
+ break;
+ case XMLEvent.CHARACTERS:
+ // START_ELEMENT(X) + CHARACTERS(C1) +
+ // CHARACTERS(C2)=> ...
+ contentBuffer += event.asCharacters().getData();
+ break;
+ case XMLEvent.END_ELEMENT:
+ // START_ELEMENT(X) + CHARACTERS(C) +
+ // END_ELEMENT(X) => C
+ // => CONTENT TAG
+ ended = true;
+ result = new XMLTag(nameBuffer, TagType.CONTENT, attributesBuffer);
+ result.setContent(contentBuffer);
+ break;
+ default:
+ throw new XMLBadFormatException("Unexpected XMLEvent [" + event.getEventType() + "].");
+ }
+ break;
+ default:
+ throw new XMLBadFormatException("Unexpected level [" + level + "].");
+ }
+ }
+ }
+
+ logger.debug("=> " + XMLTools.toString(result));
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @param label
+ * @return
+ * @throws XMLStreamException
+ * @throws XMLBadFormatException
+ */
+ public XMLTag readXMLFooter() throws XMLStreamException, XMLBadFormatException {
+ XMLTag result;
+
+ //
+ result = readTag();
+
+ //
+ if (result == null) {
+ throw new XMLBadFormatException("XML file ends prematurely, end document event is expected.");
+ } else if (result.getType() != TagType.FOOTER) {
+ throw new XMLBadFormatException("End document tag is missing.");
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @return
+ * @throws XMLException
+ * @throws XMLStreamException
+ * @throws XMLBadFormatException
+ */
+ public XMLTag readXMLHeader() throws XMLStreamException, XMLBadFormatException {
+ XMLTag result;
+
+ //
+ result = readTag();
+
+ //
+ //
+ if (result == null) {
+ throw new XMLBadFormatException("XML file ends prematurely, start document event is expected.");
+ } else if (result.getType() != TagType.HEADER) {
+ throw new XMLBadFormatException("XML header is missing.");
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @param args
+ * @throws Exception
+ */
+ public static void main(final String args[]) throws Exception {
+
+ XMLInputFactory factory = XMLInputFactory.newInstance();
+ XMLEventReader in = factory.createXMLEventReader(new FileReader("/home/cpm/C/Puck/Dev/Puck/test/TT/t3.puc"));
+
+ XMLEvent event;
+ while (in.hasNext()) {
+ event = in.nextEvent();
+
+ switch (event.getEventType()) {
+ case XMLEvent.ATTRIBUTE:
+ System.out.println("ATTRIBUTE ");
+ break;
+ case XMLEvent.CDATA:
+ System.out.println("CDATA");
+ break;
+ case XMLEvent.CHARACTERS:
+ System.out.println("CHARACTERS [" + event.asCharacters().getData() + "]");
+ break;
+ case XMLEvent.COMMENT:
+ System.out.println("COMMENT");
+ break;
+ case XMLEvent.DTD:
+ System.out.println("DTD");
+ break;
+ case XMLEvent.END_DOCUMENT:
+ System.out.println("END_DOCUMENT");
+ break;
+ case XMLEvent.END_ELEMENT:
+ System.out.println("END_ELEMENT " + event.asEndElement().getName());
+ break;
+ case XMLEvent.ENTITY_DECLARATION:
+ System.out.println("ENTITY_DECLARATION");
+ break;
+ case XMLEvent.ENTITY_REFERENCE:
+ System.out.println("ENTITY_REFERENCE");
+ break;
+ case XMLEvent.NAMESPACE:
+ System.out.println("NAMESPACE");
+ break;
+ case XMLEvent.NOTATION_DECLARATION:
+ System.out.println("NOTATION_DECLARATION");
+ break;
+ case XMLEvent.PROCESSING_INSTRUCTION:
+ System.out.println("PROCESSING_INSTRUCTION");
+ break;
+ case XMLEvent.SPACE:
+ System.out.println("SPACE");
+ break;
+ case XMLEvent.START_DOCUMENT:
+ System.out.println("START_DOCUMENT");
+ break;
+ case XMLEvent.START_ELEMENT:
+ System.out.println("START_ELEMENT [name=" + event.asStartElement().getName() + "][namespaceURI="
+ + event.asStartElement().getName().getNamespaceURI() + "][prefix=" + event.asStartElement().getName().getPrefix() + "][localPart="
+ + event.asStartElement().getName().getLocalPart() + "]");
+ break;
+ default:
+ System.out.println("DEFAULT");
+ }
+ }
+ }
+}
diff --git a/src/fr/devinsy/util/xml/XMLTag.java b/src/fr/devinsy/util/xml/XMLTag.java
new file mode 100644
index 0000000..b92f1b6
--- /dev/null
+++ b/src/fr/devinsy/util/xml/XMLTag.java
@@ -0,0 +1,117 @@
+package fr.devinsy.util.xml;
+
+import javax.xml.namespace.QName;
+
+/**
+ *
+ @author christian.momon@devinsy.fr, 2013, copyright.
+ *
+ * This file is free software under the terms of the GNU Library General
+ * Public License as published by the Free Software Foundation version 3
+ * or any later version.
+ */
+public class XMLTag {
+
+ public enum TagType {
+ HEADER,
+ START,
+ END,
+ EMPTY,
+ CONTENT,
+ FOOTER
+ }
+
+ private QName name;
+ private TagType type;
+ private XMLAttributes attributes;
+ private String content;
+
+ /**
+ *
+ */
+ public XMLTag(final QName name, final TagType type, final XMLAttributes attributes) {
+ this.name = name;
+ this.type = type;
+ this.attributes = attributes;
+ this.content = null;
+ }
+
+ public XMLAttributes attributes() {
+ return this.attributes;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public String getLabel() {
+ String result;
+
+ if (this.name == null) {
+ result = "";
+ } else {
+ result = this.name.getLocalPart();
+ }
+
+ //
+ return result;
+ }
+
+ public QName getName() {
+ return name;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public String getNamespaceURI() {
+ String result;
+
+ if (this.name == null) {
+ result = "";
+ } else {
+ result = this.name.getNamespaceURI();
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @return
+ */
+ public String getPrefix() {
+ String result;
+
+ if (this.name == null) {
+ result = "";
+ } else {
+ result = this.name.getPrefix();
+ }
+
+ //
+ return result;
+ }
+
+ public TagType getType() {
+ return type;
+ }
+
+ public void setContent(final String content) {
+ this.content = content;
+ }
+
+ public void setName(final QName name) {
+ this.name = name;
+ }
+
+ public void setType(final TagType type) {
+ this.type = type;
+ }
+}
diff --git a/src/fr/devinsy/util/xml/XMLTools.java b/src/fr/devinsy/util/xml/XMLTools.java
new file mode 100644
index 0000000..fffe435
--- /dev/null
+++ b/src/fr/devinsy/util/xml/XMLTools.java
@@ -0,0 +1,303 @@
+package fr.devinsy.util.xml;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.ZipInputStream;
+
+import javax.xml.stream.events.XMLEvent;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * @author christian.momon@devinsy.fr, 2013, copyright.
+ *
+ * This file is free software under the terms of the GNU Library General
+ * Public License as published by the Free Software Foundation version 3
+ * or any later version.
+ */
+public class XMLTools
+{
+ /**
+ *
+ *
+ * @param source
+ * @throws SAXException
+ * @throws IOException
+ * @throws PuckException
+ */
+ static public boolean isValid(final File xmlFile, final File xsdFile) throws SAXException, IOException
+ {
+ boolean result;
+
+ //
+ InputStream xmlSource;
+ if (isZipFile(xmlFile))
+ {
+ ZipInputStream zin = new ZipInputStream(new FileInputStream(xmlFile));
+ zin.getNextEntry();
+ xmlSource = zin;
+ }
+ else
+ {
+ xmlSource = new FileInputStream(xmlFile);
+ }
+
+ //
+ result = isValid(xmlSource, new FileInputStream(xsdFile));
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ *
+ * @param source
+ * @throws SAXException
+ * @throws IOException
+ * @throws PuckException
+ */
+ static public boolean isValid(final File xmlFile, final InputStream xsdSource) throws SAXException, IOException
+ {
+ boolean result;
+
+ //
+ InputStream xmlSource;
+ if (isZipFile(xmlFile))
+ {
+ ZipInputStream zin = new ZipInputStream(new FileInputStream(xmlFile));
+ zin.getNextEntry();
+ xmlSource = zin;
+ }
+ else
+ {
+ xmlSource = new FileInputStream(xmlFile);
+ }
+
+ //
+ result = isValid(xmlSource, xsdSource);
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ *
+ * @param source
+ * @throws SAXException
+ * @throws IOException
+ * @throws PuckException
+ */
+ static public boolean isValid(final InputStream xmlSource, final InputStream xsdSource) throws SAXException, IOException
+ {
+ boolean result;
+
+ if (xmlSource == null)
+ {
+ result = false;
+ }
+ else
+ {
+ try
+ {
+ //
+ SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
+ InputSource sourceentree = new InputSource(xsdSource);
+ SAXSource sourceXSD = new SAXSource(sourceentree);
+ Schema schema = factory.newSchema(sourceXSD);
+ Validator validator = schema.newValidator();
+
+ //
+ validator.validate(new StreamSource(xmlSource));
+ result = true;
+
+ }
+ catch (final IllegalArgumentException exception)
+ {
+ exception.printStackTrace();
+ result = false;
+ }
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @param file
+ * @return
+ * @throws IOException
+ */
+ public static boolean isZipFile(final File file) throws IOException
+ {
+ boolean result;
+
+ //
+ byte[] buffer = new byte[4];
+ FileInputStream is = null;
+ try
+ {
+ is = new FileInputStream(file);
+ is.read(buffer);
+ }
+ finally
+ {
+ if (is != null)
+ {
+ is.close();
+ }
+ }
+
+ // 50 4B 3 4
+ if ((buffer[0] == 0x50) && (buffer[1] == 0x4B) && (buffer[2] == 0x03) && (buffer[3] == 0x04))
+ {
+ result = true;
+ }
+ else
+ {
+ result = false;
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ */
+ static public String readTag(final BufferedReader in) throws Exception
+ {
+ String result;
+
+ Pattern TAG_PATTERN = Pattern.compile("^<([\\w-_\\.]+)>.*([\\w-_\\.]+)>$");
+ Pattern SHORT_TAG_PATTERN = Pattern.compile("^<.+/>$");
+
+ result = in.readLine();
+ boolean ended = false;
+ while (!ended)
+ {
+ /*
+ * DEBUG Matcher tagMatcher2 = TAG_PATTERN.matcher(result); if
+ * (tagMatcher2.find()) { logger.info("group count,0,1,2 = [" +
+ * tagMatcher2.groupCount() + "][" + tagMatcher2.group(0) + "][" +
+ * tagMatcher2.group(1) + "][" + tagMatcher2.group(2) + "]"); }
+ */
+
+ Matcher tagMatcher = TAG_PATTERN.matcher(result);
+ Matcher shortTagMatcher = SHORT_TAG_PATTERN.matcher(result);
+
+ if ((tagMatcher.find()) && (tagMatcher.groupCount() == 2) && (tagMatcher.group(1).equals(tagMatcher.group(2))))
+ {
+ ended = true;
+ }
+ else if (shortTagMatcher.matches())
+ {
+ ended = true;
+ }
+ else
+ {
+ result += in.readLine();
+ }
+ }
+
+ //
+ return (result);
+ }
+
+ /**
+ *
+ * @param value
+ * @return
+ */
+ public static String toString(final XMLEvent source)
+ {
+ String result;
+
+ switch (source.getEventType())
+ {
+ case XMLEvent.ATTRIBUTE:
+ result = "ATTRIBUTE ";
+ break;
+ case XMLEvent.CDATA:
+ result = "CDATA";
+ break;
+ case XMLEvent.CHARACTERS:
+ result = "CHARACTERS [" + source.asCharacters().getData() + "]";
+ break;
+ case XMLEvent.COMMENT:
+ result = "COMMENT";
+ break;
+ case XMLEvent.DTD:
+ result = "DTD";
+ break;
+ case XMLEvent.END_DOCUMENT:
+ result = "END_DOCUMENT";
+ break;
+ case XMLEvent.END_ELEMENT:
+ result = "END_ELEMENT " + source.asEndElement().getName();
+ break;
+ case XMLEvent.ENTITY_DECLARATION:
+ result = "ENTITY_DECLARATION";
+ break;
+ case XMLEvent.ENTITY_REFERENCE:
+ result = "ENTITY_REFERENCE";
+ break;
+ case XMLEvent.NAMESPACE:
+ result = "NAMESPACE";
+ break;
+ case XMLEvent.NOTATION_DECLARATION:
+ result = "NOTATION_DECLARATION";
+ break;
+ case XMLEvent.PROCESSING_INSTRUCTION:
+ result = "PROCESSING_INSTRUCTION";
+ break;
+ case XMLEvent.SPACE:
+ result = "SPACE";
+ break;
+ case XMLEvent.START_DOCUMENT:
+ result = "START_DOCUMENT";
+ break;
+ case XMLEvent.START_ELEMENT:
+ result = "START_ELEMENT [name=" + source.asStartElement().getName() + "][namespaceURI=" + source.asStartElement().getName().getNamespaceURI() + "][prefix="
+ + source.asStartElement().getName().getPrefix() + "][localPart=" + source.asStartElement().getName().getLocalPart() + "]";
+ break;
+ default:
+ result = null;
+ }
+
+ //
+ return result;
+ }
+
+ /**
+ *
+ * @param event
+ * @return
+ */
+ public static String toString(final XMLTag source)
+ {
+ String result;
+
+ if (source == null)
+ {
+ result = "null";
+ }
+ result = "[label=" + source.getLabel() + "][type=" + source.getType().toString() + "][content=" + source.getContent() + "]";
+
+ //
+ return result;
+ }
+}
diff --git a/src/fr/devinsy/util/xml/XMLWriter.java b/src/fr/devinsy/util/xml/XMLWriter.java
new file mode 100644
index 0000000..2b4396a
--- /dev/null
+++ b/src/fr/devinsy/util/xml/XMLWriter.java
@@ -0,0 +1,209 @@
+package fr.devinsy.util.xml;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+/**
+ * @author christian.momon@devinsy.fr, 2013, copyright.
+ *
+ * This file is free software under the terms of the GNU Library General
+ * Public License as published by the Free Software Foundation version 3
+ * or any later version.
+ */
+public class XMLWriter {
+
+ protected PrintWriter out;
+
+ /**
+ *
+ */
+ protected XMLWriter() {
+ this.out = null;
+ }
+
+ /**
+ *
+ * @param file
+ * @throws FileNotFoundException
+ * @throws UnsupportedEncodingException
+ */
+ public XMLWriter(final File file) throws UnsupportedEncodingException, FileNotFoundException {
+ this.out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
+ }
+
+ /**
+ *
+ * @param target
+ * @throws UnsupportedEncodingException
+ */
+ public XMLWriter(final OutputStream target) throws UnsupportedEncodingException {
+ this.out = new PrintWriter(new OutputStreamWriter(target, "UTF-8"));
+ }
+
+ /**
+ *
+ */
+ public void close() {
+ if (this.out != null) {
+ this.out.flush();
+ this.out.close();
+ }
+ }
+
+ /**
+ *
+ */
+ public void flush() {
+ if (this.out != null) {
+ this.out.flush();
+ }
+ }
+
+ /**
+ *
+ * @param comment
+ */
+ public void writeComment(final String comment) {
+ out.print("");
+ }
+
+ /**
+ *
+ */
+ public void writeEmptyTag(final String label, final String... attributes) {
+ out.print("<");
+ out.print(label);
+ writeTagAttributes(attributes);
+ out.print("/>");
+ }
+
+ /**
+ *
+ */
+ public void writeEndTag(final String label) {
+ out.print("");
+ out.print(label);
+ out.print(">");
+ }
+
+ /**
+ *
+ */
+ public void writeStartTag(final String label, final String... attributes) {
+ out.print("<");
+ out.print(label);
+ writeTagAttributes(attributes);
+ out.print(">");
+ }
+
+ /**
+ *
+ */
+ public void writeTag(final String label, final String content, final String... attributes) {
+
+ if (content == null) {
+ writeEmptyTag(label, attributes);
+ } else {
+ writeStartTag(label, attributes);
+ writeTagContent(content);
+ writeEndTag(label);
+ }
+ }
+
+ /**
+ *
+ */
+ public void writeTagAttributes(final String... attributes) {
+ //
+ if ((attributes != null) && (attributes.length > 0)) {
+ for (int count = 0; count < attributes.length; count += 2) {
+ out.print(" ");
+ out.print(attributes[count]);
+ out.print("=\"");
+ out.print(attributes[count + 1]);
+ out.print("\"");
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ public void writeTagContent(final String content) {
+ //
+ for (int count = 0; count < content.length(); count++) {
+ //
+ char car = content.charAt(count);
+
+ switch (car) {
+ case '<':
+ out.print("<");
+ break;
+ case '>':
+ out.print(">");
+ break;
+ case '&':
+ out.print("&");
+ break;
+ case '"':
+ out.print(""");
+ break;
+ case '\'':
+ out.print("'");
+ break;
+ default:
+ out.print(car);
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ public void writeXMLHeader(final String... attributes) {
+
+ //
+ out.print("");
+ }
+}
diff --git a/src/fr/devinsy/util/xml/XMLZipReader.java b/src/fr/devinsy/util/xml/XMLZipReader.java
new file mode 100644
index 0000000..b5f10aa
--- /dev/null
+++ b/src/fr/devinsy/util/xml/XMLZipReader.java
@@ -0,0 +1,51 @@
+package fr.devinsy.util.xml;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipInputStream;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+
+/**
+ *
+ @author christian.momon@devinsy.fr, 2013, copyright.
+ *
+ * This file is free software under the terms of the GNU Library General
+ * Public License as published by the Free Software Foundation version 3
+ * or any later version.
+ */
+public class XMLZipReader extends XMLReader {
+
+ /**
+ *
+ * @param file
+ * @throws IOException
+ * @throws XMLStreamException
+ */
+ public XMLZipReader(final File file) throws IOException, XMLStreamException {
+ super();
+
+ XMLInputFactory factory = XMLInputFactory.newInstance();
+ ZipInputStream zis = new ZipInputStream(new FileInputStream(file));
+ zis.getNextEntry();
+ this.in = factory.createXMLEventReader(zis, "UTF-8");
+ }
+
+ /**
+ *
+ * @param target
+ * @throws IOException
+ * @throws XMLStreamException
+ */
+ public XMLZipReader(final InputStream source) throws IOException, XMLStreamException {
+ super();
+
+ XMLInputFactory factory = XMLInputFactory.newInstance();
+ ZipInputStream zis = new ZipInputStream(source);
+ zis.getNextEntry();
+ this.in = factory.createXMLEventReader(zis, "UTF-8");
+ }
+}
diff --git a/src/fr/devinsy/util/xml/XMLZipWriter.java b/src/fr/devinsy/util/xml/XMLZipWriter.java
new file mode 100644
index 0000000..b6e1ebb
--- /dev/null
+++ b/src/fr/devinsy/util/xml/XMLZipWriter.java
@@ -0,0 +1,52 @@
+package fr.devinsy.util.xml;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ *
+ @author christian.momon@devinsy.fr, 2013, copyright.
+ *
+ * This file is free software under the terms of the GNU Library General
+ * Public License as published by the Free Software Foundation version 3
+ * or any later version.
+ */
+public class XMLZipWriter extends XMLWriter {
+
+ /**
+ *
+ * @param file
+ * @throws IOException
+ */
+ public XMLZipWriter(final File file) throws IOException {
+ super();
+
+ ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(file));
+ zos.setLevel(Deflater.BEST_COMPRESSION);
+ zos.setMethod(ZipOutputStream.DEFLATED);
+ zos.setComment("Generated by PUCK");
+ zos.putNextEntry(new ZipEntry(file.getName() + ".xml"));
+ this.out = new PrintWriter(new OutputStreamWriter(zos, "UTF-8"));
+ }
+
+ /**
+ *
+ * @param target
+ * @throws IOException
+ */
+ public XMLZipWriter(final OutputStream target) throws IOException {
+ super();
+ ZipOutputStream zos = new ZipOutputStream(target);
+ zos.setLevel(Deflater.BEST_COMPRESSION);
+ zos.setMethod(ZipOutputStream.DEFLATED);
+ zos.putNextEntry(new ZipEntry("noname"));
+ this.out = new PrintWriter(new OutputStreamWriter(zos, "UTF-8"));
+ }
+}