diff --git a/src/module-info.java b/src/module-info.java index 6f9cd85..1b9f739 100644 --- a/src/module-info.java +++ b/src/module-info.java @@ -6,6 +6,10 @@ open module org.atriasoft.exml { exports org.atriasoft.exml; + exports org.atriasoft.exml.model; + exports org.atriasoft.exml.exception; + exports org.atriasoft.exml.builder; + exports org.atriasoft.exml.parser; requires transitive org.atriasoft.etk; requires transitive io.scenarium.logger; diff --git a/src/org/atriasoft/exml/Exml.java b/src/org/atriasoft/exml/Exml.java index fd84368..23a8af7 100644 --- a/src/org/atriasoft/exml/Exml.java +++ b/src/org/atriasoft/exml/Exml.java @@ -9,8 +9,13 @@ package org.atriasoft.exml; import org.atriasoft.exml.builder.Builder; import org.atriasoft.exml.builder.BuilderGeneric; import org.atriasoft.exml.exception.ExmlBuilderException; +import org.atriasoft.exml.exception.ExmlParserErrorMulti; import org.atriasoft.exml.internal.Log; +import org.atriasoft.exml.model.XmlElement; +import org.atriasoft.exml.model.XmlNode; import org.atriasoft.exml.parser.ParseXml; +import org.atriasoft.exml.parser.ParsingProperty; +import org.atriasoft.exml.serializer.SerializerXml; public class Exml { /** @@ -28,35 +33,21 @@ public class Exml { * @return false : An error occured * @return true : Parsing is OK */ - public static boolean generate(final StringBuilder _data) { - //return iGenerate(_data, 0); - return false; - } - - public static boolean iGenerate(final StringBuilder _data, final int _indent) { - /* - for (int iii = 0; iii < this.listSub.size(); iii++) { - if (this.listSub.get(iii) != null) { - this.listSub.get(iii).iGenerate(_data, _indent); - } + public static void generate(final XmlNode root, final StringBuilder _data) { + if (root.isElement() == false || ((XmlElement) root).getValue().isEmpty() == false) { + SerializerXml.serialize(root, _data, 0); + } else { + SerializerXml.serializeRoot((XmlElement) root, _data); } - */ - return true; + //return iGenerate(_data, 0); } - public static XmlNode parse(final String data) { - + public static XmlElement parse(final String data) throws ExmlBuilderException, ExmlParserErrorMulti { final Builder builder = new BuilderGeneric(); final ParseXml parser = new ParseXml(builder); - - Object out = null; - try { - out = parser.parse(data); - } catch (final ExmlBuilderException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return (XmlNode) out; + final ParsingProperty property = new ParsingProperty(); + property.setDisplayError(true); + return (XmlElement) parser.parse(data, property); } /** diff --git a/src/org/atriasoft/exml/TextCDATA.java b/src/org/atriasoft/exml/TextCDATA.java deleted file mode 100644 index 832c735..0000000 --- a/src/org/atriasoft/exml/TextCDATA.java +++ /dev/null @@ -1,25 +0,0 @@ -/** @file - * @author Edouard DUPIN - * @copyright 2021, Edouard DUPIN, all right reserved - * @license MPL v2.0 (see license file) - */ -package org.atriasoft.exml; - -public class TextCDATA extends XmlText { - public TextCDATA() { - super(); - } - - public TextCDATA(final String data) { - super(data); - } - - @Override - protected boolean iGenerate(final StringBuilder _data, final int _indent) { - _data.append(""); - return true; - } - -} diff --git a/src/org/atriasoft/exml/builder/Builder.java b/src/org/atriasoft/exml/builder/Builder.java index c82f3ae..c32f419 100644 --- a/src/org/atriasoft/exml/builder/Builder.java +++ b/src/org/atriasoft/exml/builder/Builder.java @@ -1,15 +1,12 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2021, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ package org.atriasoft.exml.builder; import org.atriasoft.exml.exception.ExmlBuilderException; -/** - * @author heero - * - */ -/** - * @author heero - * - */ public interface Builder { /** diff --git a/src/org/atriasoft/exml/builder/BuilderGeneric.java b/src/org/atriasoft/exml/builder/BuilderGeneric.java index 46c901b..a6bbf48 100644 --- a/src/org/atriasoft/exml/builder/BuilderGeneric.java +++ b/src/org/atriasoft/exml/builder/BuilderGeneric.java @@ -1,12 +1,17 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2021, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ package org.atriasoft.exml.builder; -import org.atriasoft.exml.XmlAttribute; -import org.atriasoft.exml.XmlAttributeList; -import org.atriasoft.exml.XmlComment; -import org.atriasoft.exml.XmlDeclaration; -import org.atriasoft.exml.XmlElement; -import org.atriasoft.exml.XmlText; import org.atriasoft.exml.exception.ExmlBuilderException; +import org.atriasoft.exml.model.XmlAttribute; +import org.atriasoft.exml.model.XmlAttributeList; +import org.atriasoft.exml.model.XmlComment; +import org.atriasoft.exml.model.XmlDeclaration; +import org.atriasoft.exml.model.XmlElement; +import org.atriasoft.exml.model.XmlText; public class BuilderGeneric implements Builder { @@ -15,6 +20,7 @@ public class BuilderGeneric implements Builder { if (element instanceof XmlElement) { final XmlElement elem = (XmlElement) element; elem.append(new XmlComment(comment)); + return; } throw new ExmlBuilderException("can not add Comment on something else than Element"); } diff --git a/src/org/atriasoft/exml/exception/ExmlParserError.java b/src/org/atriasoft/exml/exception/ExmlParserError.java new file mode 100644 index 0000000..af6b97a --- /dev/null +++ b/src/org/atriasoft/exml/exception/ExmlParserError.java @@ -0,0 +1,25 @@ +package org.atriasoft.exml.exception; + +import org.atriasoft.exml.parser.FilePos; + +public class ExmlParserError extends ExmlBuilderException { + private static final long serialVersionUID = 1L; + private final String dataLine; //!< Parse line error (copy); + + private final FilePos filePos; //!< position of the error + + public ExmlParserError(final String dataLine, final FilePos filePos, final String comment) { + super(comment); + this.dataLine = dataLine; + this.filePos = filePos.clone(); + } + + public String getDataLine() { + return this.dataLine; + } + + public FilePos getFilePos() { + return this.filePos; + } + +} diff --git a/src/org/atriasoft/exml/exception/ExmlParserErrorMulti.java b/src/org/atriasoft/exml/exception/ExmlParserErrorMulti.java new file mode 100644 index 0000000..19bf26a --- /dev/null +++ b/src/org/atriasoft/exml/exception/ExmlParserErrorMulti.java @@ -0,0 +1,18 @@ +package org.atriasoft.exml.exception; + +import java.util.List; + +public class ExmlParserErrorMulti extends ExmlBuilderException { + private static final long serialVersionUID = 1L; + private final List errors; // list of errors + + public ExmlParserErrorMulti(final String message, final List errors) { + super(message); + this.errors = errors; + } + + public List getErrors() { + return this.errors; + } + +} diff --git a/src/org/atriasoft/exml/XmlAttribute.java b/src/org/atriasoft/exml/model/XmlAttribute.java similarity index 85% rename from src/org/atriasoft/exml/XmlAttribute.java rename to src/org/atriasoft/exml/model/XmlAttribute.java index c6f891e..c4df358 100644 --- a/src/org/atriasoft/exml/XmlAttribute.java +++ b/src/org/atriasoft/exml/model/XmlAttribute.java @@ -3,9 +3,9 @@ * @copyright 2021, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ -package org.atriasoft.exml; +package org.atriasoft.exml.model; -import org.atriasoft.exml.internal.FilePos; +import org.atriasoft.exml.parser.FilePos; /** * Single attribute element @@ -68,15 +68,6 @@ public class XmlAttribute { return this.value; }; - protected boolean iGenerate(final StringBuilder _data, final int _indent) { - _data.append(" "); - _data.append(this.name); - _data.append("=\""); - _data.append(this.value); - _data.append("\""); - return true; - }; - /** * set the name of the attribute * @param[in] _name New name of the attribute diff --git a/src/org/atriasoft/exml/XmlAttributeList.java b/src/org/atriasoft/exml/model/XmlAttributeList.java similarity index 93% rename from src/org/atriasoft/exml/XmlAttributeList.java rename to src/org/atriasoft/exml/model/XmlAttributeList.java index 74797fd..237ac88 100644 --- a/src/org/atriasoft/exml/XmlAttributeList.java +++ b/src/org/atriasoft/exml/model/XmlAttributeList.java @@ -3,9 +3,10 @@ * @copyright 2021, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ -package org.atriasoft.exml; +package org.atriasoft.exml.model; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.ListIterator; @@ -108,7 +109,7 @@ public abstract class XmlAttributeList extends XmlNode { } public List getAttributes() { - return this.listAttribute; + return Collections.unmodifiableList(this.listAttribute); } /** @@ -122,16 +123,6 @@ public abstract class XmlAttributeList extends XmlNode { return new Pair(att.getName(), att.getValue()); } - @Override - protected boolean iGenerate(final StringBuilder _data, final int _indent) { - for (int iii = 0; iii < this.listAttribute.size(); iii++) { - if (this.listAttribute.get(iii) != null) { - this.listAttribute.get(iii).iGenerate(_data, _indent); - } - } - return true; - } - /** * Remove an attribute form the list * @param[in] _name Name of the attribute diff --git a/src/org/atriasoft/exml/XmlComment.java b/src/org/atriasoft/exml/model/XmlComment.java similarity index 68% rename from src/org/atriasoft/exml/XmlComment.java rename to src/org/atriasoft/exml/model/XmlComment.java index de47de1..03b3841 100644 --- a/src/org/atriasoft/exml/XmlComment.java +++ b/src/org/atriasoft/exml/model/XmlComment.java @@ -3,9 +3,7 @@ * @copyright 2021, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ -package org.atriasoft.exml; - -import org.atriasoft.exml.internal.Tools; +package org.atriasoft.exml.model; /** * Comment node: lt;!-- ... --gt; @@ -38,13 +36,4 @@ public class XmlComment extends XmlNode { return XmlNodeType.COMMENT; } - @Override - public boolean iGenerate(final StringBuilder _data, final int _indent) { - Tools.addIndent(_data, _indent); - _data.append("\n"); - return true; - } - }; \ No newline at end of file diff --git a/src/org/atriasoft/exml/XmlDeclaration.java b/src/org/atriasoft/exml/model/XmlDeclaration.java similarity index 80% rename from src/org/atriasoft/exml/XmlDeclaration.java rename to src/org/atriasoft/exml/model/XmlDeclaration.java index bdb56f1..1bc28ce 100644 --- a/src/org/atriasoft/exml/XmlDeclaration.java +++ b/src/org/atriasoft/exml/model/XmlDeclaration.java @@ -3,10 +3,9 @@ * @copyright 2021, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ -package org.atriasoft.exml; +package org.atriasoft.exml.model; import org.atriasoft.exml.internal.Log; -import org.atriasoft.exml.internal.Tools; /** * Declaration node: lt;?XXXXXX ... gt; @@ -57,16 +56,5 @@ public class XmlDeclaration extends XmlAttributeList { @Override public XmlNodeType getType() { return XmlNodeType.DECLARATION; - }; - - @Override - protected boolean iGenerate(final StringBuilder _data, final int _indent) { - Tools.addIndent(_data, _indent); - _data.append("\n"); - return true; } - } diff --git a/src/org/atriasoft/exml/XmlElement.java b/src/org/atriasoft/exml/model/XmlElement.java similarity index 79% rename from src/org/atriasoft/exml/XmlElement.java rename to src/org/atriasoft/exml/model/XmlElement.java index 63e4e8b..010d0ca 100644 --- a/src/org/atriasoft/exml/XmlElement.java +++ b/src/org/atriasoft/exml/model/XmlElement.java @@ -3,15 +3,16 @@ * @copyright 2021, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ -package org.atriasoft.exml; +package org.atriasoft.exml.model; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.ListIterator; import org.atriasoft.exml.exception.ExmlNodeDoesNotExist; import org.atriasoft.exml.internal.Log; -import org.atriasoft.exml.internal.Tools; +import org.atriasoft.exml.serializer.SerializerXml; /** @file * @author Edouard DUPIN @@ -147,12 +148,12 @@ public class XmlElement extends XmlAttributeList { * @return List of current nodes. */ public List getNodes() { - return this.listSub; + return Collections.unmodifiableList(this.listSub); } /** - * get the internal data of the element (if the element has some sub node they are converted in xml string == > like this it is not needed to use - * @return the curent data string. if Only one text node, then we get the parssed data (no amp; ...) if more than one node, then we transform ,",',<,> in xml normal text... + * Get the internal data of the element (if the element has some sub node they are converted in xml string == > like this it is not needed to use + * @return the current data string. if Only one text node, then we get the parsed data (no amp; ...) if more than one node, then we transform ,",',<,> in xml normal text... */ public String getText() { final StringBuilder res = new StringBuilder(); @@ -160,12 +161,12 @@ public class XmlElement extends XmlAttributeList { if (this.listSub.get(0).getType() == XmlNodeType.TEXT) { res.append(this.listSub.get(0).getValue()); } else { - this.listSub.get(0).iGenerate(res, 0); + SerializerXml.serialize(this.listSub.get(0), res, 0); } } else { for (int iii = 0; iii < this.listSub.size(); iii++) { if (this.listSub.get(iii) != null) { - this.listSub.get(iii).iGenerate(res, 0); + SerializerXml.serialize(this.listSub.get(iii), res, 0); } } } @@ -190,36 +191,6 @@ public class XmlElement extends XmlAttributeList { return this.listSub.get(_id).getType(); } - @Override - protected boolean iGenerate(final StringBuilder _data, final int _indent) { - Tools.addIndent(_data, _indent); - _data.append("<"); - _data.append(this.value); - super.iGenerate(_data, _indent); - - if (this.listSub.size() > 0) { - if (this.listSub.size() == 1 && this.listSub.get(0) != null && this.listSub.get(0).getType() == XmlNodeType.TEXT && ((XmlText) this.listSub.get(0)).countLines() == 1) { - _data.append(">"); - this.listSub.get(0).iGenerate(_data, 0); - Log.verbose(" generate : '" + _data + "'"); - } else { - _data.append(">\n"); - for (int iii = 0; iii < this.listSub.size(); iii++) { - if (this.listSub.get(iii) != null) { - this.listSub.get(iii).iGenerate(_data, _indent + 1); - } - } - Tools.addIndent(_data, _indent); - } - _data.append("\n"); - } else { - _data.append("/>\n"); - } - return true; - } - /** * Remove all element with this name * @param[in] _nodeName Name of nodes to remove. diff --git a/src/org/atriasoft/exml/XmlNode.java b/src/org/atriasoft/exml/model/XmlNode.java similarity index 52% rename from src/org/atriasoft/exml/XmlNode.java rename to src/org/atriasoft/exml/model/XmlNode.java index 420bcd3..271322a 100644 --- a/src/org/atriasoft/exml/XmlNode.java +++ b/src/org/atriasoft/exml/model/XmlNode.java @@ -3,63 +3,48 @@ * @copyright 2021, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ -package org.atriasoft.exml; - -import org.atriasoft.exml.internal.FilePos; +package org.atriasoft.exml.model; /** * Basic main object of all xml elements. */ public abstract class XmlNode { - - protected FilePos pos; //!< position in the read file (null if the file is not parsed) - protected String value; //!< value of the node (for element this is the name, for text it is the inside text ...); + /// Value of the node (for element this is the name, for text it is the inside text ...); + protected String value = ""; /** * basic element of a xml structure */ - public XmlNode() { - this.pos = null; - } + public XmlNode() {} /** - * basic element of a xml structure + * Basic element of a xml structure * @param[in] _value value of the node */ public XmlNode(final String _value) { - this.pos = null; this.value = _value; } /** - * clear the Node + * Clear the Node */ public void clear() { this.value = ""; - this.pos = null; } @Override protected XmlNode clone() throws CloneNotSupportedException { - throw new CloneNotSupportedException("Can not clone an abstract class ..."); + throw new CloneNotSupportedException("Can not clone an abs ctract class ..."); } /** - * get the current position where the element is in the file - * @return The file position reference - */ - public FilePos getPos() { - return this.pos; - } - - /** - * get the node type. + * Get the node type. * @return the type of the Node. */ public abstract XmlNodeType getType(); /** - * get the current element Value. + * Get the current element Value. * @return the reference of the string value. */ public String getValue() { @@ -67,26 +52,7 @@ public abstract class XmlNode { } /** - * generate a string with the tree of the xml - * @param[in,out] _data string where to add the elements - * @param[in] _indent current indentation of the file - * @return false if an error occured. - */ - protected abstract boolean iGenerate(final StringBuilder _data, final int _indent); - - /** - * parse the Current node [pure VIRUAL] - * @param[in] _data data string to parse. - * @param[in,out] _pos position in the string to start parse, return the position end of parsing. - * @param[in] _caseSensitive Request a parsion of element that is not case sensitive (all element is in low case) - * @param[in,out] _filePos file parsing position (line x col x) - * @param[in,out] _doc Base document reference - * @return false if an error occured. - */ - //protected abstract boolean iParse(String _data, PositionParsing _pos, boolean _caseSensitive, FilePos _filePos, Document _doc); - - /** - * check if the node is a Comment + * Check if the node is a Comment * @return true if the node is a Comment */ public final boolean isComment() { @@ -101,14 +67,6 @@ public abstract class XmlNode { return this instanceof XmlDeclaration; } - /** - * check if the node is a Document - * @return true if the node is a Document - */ - public final boolean isDocument() { - return this instanceof Document; - } - /** * check if the node is a Element * @return true if the node is a Element @@ -129,7 +87,6 @@ public abstract class XmlNode { * set the value of the node. * @param[in] _value New value of the node. */ - public final void setValue(final String _value) { this.value = _value; } @@ -150,14 +107,6 @@ public abstract class XmlNode { return (XmlDeclaration) this; } - /** - * Cast the element in a Document if it is possible. - * @return pointer on the class or null. - */ - public final Document toDocument() { - return (Document) this; - } - /** * Cast the element in a Element if it is possible. * @return pointer on the class or null. diff --git a/src/org/atriasoft/exml/XmlNodeType.java b/src/org/atriasoft/exml/model/XmlNodeType.java similarity index 84% rename from src/org/atriasoft/exml/XmlNodeType.java rename to src/org/atriasoft/exml/model/XmlNodeType.java index 27f1ed3..b8a317e 100644 --- a/src/org/atriasoft/exml/XmlNodeType.java +++ b/src/org/atriasoft/exml/model/XmlNodeType.java @@ -3,13 +3,12 @@ * @copyright 2021, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ -package org.atriasoft.exml; +package org.atriasoft.exml.model; /** * Type of the XML elements. */ public enum XmlNodeType { - DOCUMENT, //!< all the file main access DECLARATION, //!< <?xml ... ?> ELEMENT, //!< the <XXX> ... </XXX> COMMENT, //!< comment node : <!-- --> diff --git a/src/org/atriasoft/exml/XmlText.java b/src/org/atriasoft/exml/model/XmlText.java similarity index 78% rename from src/org/atriasoft/exml/XmlText.java rename to src/org/atriasoft/exml/model/XmlText.java index b4205da..70a864f 100644 --- a/src/org/atriasoft/exml/XmlText.java +++ b/src/org/atriasoft/exml/model/XmlText.java @@ -3,7 +3,7 @@ * @copyright 2021, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ -package org.atriasoft.exml; +package org.atriasoft.exml.model; /** * Text node interface (internal data between two Marker: <XXX> ALL here </XXX> @@ -27,7 +27,7 @@ public class XmlText extends XmlNode { * count the number of line in the current text * @return The number of lines */ - protected int countLines() { + public int countLines() { int count = 1; for (int iii = 0; iii < this.value.length(); iii++) { if (this.value.charAt(iii) == '\n') { @@ -40,12 +40,6 @@ public class XmlText extends XmlNode { @Override public XmlNodeType getType() { return XmlNodeType.TEXT; - }; - - @Override - protected boolean iGenerate(final StringBuilder _data, final int _indent) { - _data.append(replaceSpecialCharOut(this.value)); - return true; } }; \ No newline at end of file diff --git a/src/org/atriasoft/exml/internal/FilePos.java b/src/org/atriasoft/exml/parser/FilePos.java similarity index 98% rename from src/org/atriasoft/exml/internal/FilePos.java rename to src/org/atriasoft/exml/parser/FilePos.java index ccd1fa2..f5759dd 100644 --- a/src/org/atriasoft/exml/internal/FilePos.java +++ b/src/org/atriasoft/exml/parser/FilePos.java @@ -3,7 +3,7 @@ * @copyright 2021, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ -package org.atriasoft.exml.internal; +package org.atriasoft.exml.parser; /** @file * @author Edouard DUPIN diff --git a/src/org/atriasoft/exml/parser/ParseXml.java b/src/org/atriasoft/exml/parser/ParseXml.java index 1037ac5..ec2f3a2 100644 --- a/src/org/atriasoft/exml/parser/ParseXml.java +++ b/src/org/atriasoft/exml/parser/ParseXml.java @@ -2,10 +2,9 @@ package org.atriasoft.exml.parser; import org.atriasoft.exml.builder.Builder; import org.atriasoft.exml.exception.ExmlBuilderException; -import org.atriasoft.exml.internal.FilePos; +import org.atriasoft.exml.exception.ExmlParserError; +import org.atriasoft.exml.exception.ExmlParserErrorMulti; import org.atriasoft.exml.internal.Log; -import org.atriasoft.exml.internal.PositionParsing; -import org.atriasoft.exml.internal.Tools; public class ParseXml { // global builder that is generate the final Tree @@ -30,27 +29,32 @@ public class ParseXml { } } String name = _data.substring(_pos.value, lastElementName + 1); - String value = ""; - if (parsingProperty.getCaseSensitive() == true) { + if (parsingProperty.getStoreMode() == StoreMode.LOWERCASE) { name = name.toLowerCase(); + } else if (parsingProperty.getStoreMode() == StoreMode.UPPERCASE) { + name = name.toUpperCase(); } + + // TODO check if in the current list of attribute one is not currently set with this value... + + String value = ""; // count white space : final FilePos tmpPos = new FilePos(); int white = Tools.countWhiteChar(_data, lastElementName + 1, tmpPos); _filePos.add(tmpPos); if (lastElementName + white + 1 >= _data.length()) { - parsingProperty.createError(_data, lastElementName + white + 1, _filePos, " parse an xml end with an attribute parsing..."); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, lastElementName + white + 1), _filePos, " parse an xml end with an attribute parsing...")); return false; } if (_data.charAt(lastElementName + white + 1) != '=') { - parsingProperty.createError(_data, lastElementName + white + 1, _filePos, " error attribute parsing == > missing '=' ..."); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, lastElementName + white + 1), _filePos, " error attribute parsing == > missing '=' ...")); return false; } white += Tools.countWhiteChar(_data, lastElementName + white + 2, tmpPos); _filePos.add(tmpPos); if (lastElementName + white + 2 >= _data.length()) { - parsingProperty.createError(_data, lastElementName + white + 2, _filePos, " parse an xml end with an attribute parsing..."); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, lastElementName + white + 2), _filePos, " parse an xml end with an attribute parsing...")); return false; } boolean simpleQuoteCase = false; @@ -64,7 +68,7 @@ public class ParseXml { for (int iii = lastElementName + white + 2; iii < _data.length(); iii++) { Tools.drawElementParsed(_data.charAt(iii), _filePos); if (_filePos.check(_data.charAt(iii)) == true) { - parsingProperty.createError(_data, iii, _filePos, "unexpected '\\n' in an attribute parsing"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, iii), _filePos, "unexpected '\\n' in an attribute parsing")); return false; } if (_data.charAt(iii) != ' ' && _data.charAt(iii) != '/' && _data.charAt(iii) != '?' && _data.charAt(iii) != '>') { @@ -119,7 +123,7 @@ public class ParseXml { return true; } } - parsingProperty.createError(_data, _pos.value, _filePos, "text CDATA got end of file without finding end node"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "text CDATA got end of file without finding end node")); _pos.value = _data.length(); return false; } @@ -156,7 +160,7 @@ public class ParseXml { } } _pos.value = _data.length(); - parsingProperty.createError(_data, _pos.value, _filePos, "comment got end of file without finding end node"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "comment got end of file without finding end node")); return false; } @@ -171,7 +175,7 @@ public class ParseXml { } if (_data.charAt(iii) == '>' || _data.charAt(iii) == '<') { // an error occured : - parsingProperty.createError(_data, _pos.value, _filePos, " find '>' or '<' instead of '?>'"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, " find '>' or '<' instead of '?>'")); return false; } if (_data.charAt(iii) == '?' && _data.charAt(iii + 1) == '>') { @@ -190,7 +194,7 @@ public class ParseXml { continue; } } - parsingProperty.createError(_data, _pos.value, _filePos, "Text got end of file without finding end node"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Text got end of file without finding end node")); _pos.value = _data.length(); return false; } @@ -211,7 +215,7 @@ public class ParseXml { if (_data.charAt(iii) == '/') { // standalone node or error... if (iii + 1 >= _data.length()) { - parsingProperty.createError(_data, _pos.value, _filePos, "Find end of files ... == > bad case"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find end of files ... == > bad case")); return false; } // TODO : Can have white spaces .... @@ -220,7 +224,7 @@ public class ParseXml { return true; } // error - parsingProperty.createError(_data, _pos.value, _filePos, "Find / without > char ..."); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find / without > char ...")); return false; } if (Tools.checkAvaillable(_data.charAt(iii), true) == true) { @@ -233,11 +237,12 @@ public class ParseXml { continue; } if (Tools.isWhiteChar(_data.charAt(iii)) == false) { - parsingProperty.createError(_data, iii, _filePos, "Find an unknow element : '" + _data.charAt(iii) + "'"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, iii), _filePos, "Find an unknow element : '" + _data.charAt(iii) + "'")); return false; } } - parsingProperty.createError(_data, _pos.value, _filePos, "Unexpecting end of parsing exml::internal::Element : '" + nameElement + "' == > check if the '/>' is set or the end of element"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, + "Unexpecting end of parsing exml::internal::Element : '" + nameElement + "' == > check if the '/>' is set or the end of element")); return false; } @@ -269,24 +274,26 @@ public class ParseXml { return true; } } - parsingProperty.createError(_data, _pos.value, _filePos, "Text got end of file without finding end node"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Text got end of file without finding end node")); _pos.value = _data.length(); return false; } - public Object parse(final String data) throws ExmlBuilderException { - + public Object parse(final String data, final ParsingProperty property) throws ExmlBuilderException, ExmlParserErrorMulti { Log.verbose("Start parsing document (type: string) size=" + data.length()); // came from char == > force in utf8 ... final FilePos pos = new FilePos(1, 0); final PositionParsing parsePos = new PositionParsing(); - final ParsingProperty property = new ParsingProperty(); - final Object rootNode = this.builder.newRoot(); - if (subParseElement(rootNode, null, data, parsePos, pos, property) == true) { - return rootNode; - } - return null; + final Object rootNode = this.builder.newRoot(); + subParseElement(rootNode, null, data, parsePos, pos, property); + if (property.isErrorDetected() == true) { + if (property.isThrowOnError() == true) { + throw new ExmlParserErrorMulti("Parsing error multiple error detected", property.getErrors()); + } + return null; + } + return rootNode; } /** @@ -311,14 +318,14 @@ public class ParseXml { final int white = Tools.countWhiteChar(_data, iii + 1, tmpPos); if (iii + white + 1 >= _data.length()) { _filePos.add(tmpPos); - parsingProperty.createError(_data, _pos.value, _filePos, "End file with '<' char == > invalide XML"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "End file with '<' char == > invalide XML")); _pos.value = iii + white; return false; } // Detect type of the element: if (_data.charAt(iii + white + 1) == '>') { _filePos.add(tmpPos); - parsingProperty.createError(_data, _pos.value, _filePos, "Find '>' with no element in the element..."); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find '>' with no element in the element...")); _pos.value = iii + white + 1; return false; } @@ -326,7 +333,7 @@ public class ParseXml { tmpPos.increment(); // TODO : white space ... if (Tools.checkAvaillable(_data.charAt(iii + white + 2), true) == false) { - parsingProperty.createError(_data, _pos.value, _filePos, "Find unavaillable name in the Declaration node..."); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find unavaillable name in the Declaration node...")); _pos.value = iii + white + 1; return false; } @@ -343,8 +350,10 @@ public class ParseXml { tmpPos.check(_data.charAt(jjj)); } String tmpname = _data.substring(iii + white + 2, endPosName + 1); - if (parsingProperty.getCaseSensitive() == true) { + if (parsingProperty.getStoreMode() == StoreMode.LOWERCASE) { tmpname = tmpname.toLowerCase(); + } else if (parsingProperty.getStoreMode() == StoreMode.UPPERCASE) { + tmpname = tmpname.toUpperCase(); } // Find declaration marker final Object declaration = this.builder.newDeclaration(parent, tmpname); @@ -361,17 +370,18 @@ public class ParseXml { tmpPos.increment(); // Find special block element if (iii + white + 2 >= _data.length()) { - parsingProperty.createError(_data, _pos.value, _filePos, "End file with ' invalide XML"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "End file with ' invalide XML")); return false; } if (_data.charAt(iii + white + 2) == '-') { tmpPos.increment(); if (iii + white + 3 >= _data.length()) { - parsingProperty.createError(_data, _pos.value, _filePos, "End file with ' invalide XML"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "End file with ' invalide XML")); return false; } if (_data.charAt(iii + white + 3) != '-') { - parsingProperty.createError(_data, _pos.value, _filePos, "Element parse with ' invalide XML"); + parsingProperty + .createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Element parse with ' invalide XML")); return false; } tmpPos.increment(); @@ -385,13 +395,14 @@ public class ParseXml { } else if (_data.charAt(iii + white + 2) == '[') { tmpPos.increment(); if (iii + white + 8 >= _data.length()) { - parsingProperty.createError(_data, _pos.value, _filePos, "End file with ' invalide XML"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "End file with ' invalide XML")); return false; } if (_data.charAt(iii + white + 3) != 'C' || _data.charAt(iii + white + 4) != 'D' || _data.charAt(iii + white + 5) != 'A' || _data.charAt(iii + white + 6) != 'T' || _data.charAt(iii + white + 7) != 'A' || _data.charAt(iii + white + 8) != '[') { - parsingProperty.createError(_data, _pos.value, _filePos, "Element parse with ' invalide XML"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, + "Element parse with ' invalide XML")); return false; } tmpPos.add(6); @@ -403,7 +414,8 @@ public class ParseXml { } iii = _pos.value; } else { - parsingProperty.createError(_data, _pos.value, _filePos, "End file with ' invalide XML"); + parsingProperty + .createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "End file with ' invalide XML")); return false; } continue; @@ -422,11 +434,14 @@ public class ParseXml { } tmpPos.check(_data.charAt(jjj)); } - String tmpname = _data.substring(iii + white + 2, endPosName + 1); + final String tmpname = _data.substring(iii + white + 2, endPosName + 1); + String tmpnameCheck = tmpname; + String nameElementCheck = nameElement; if (parsingProperty.getCaseSensitive() == true) { - tmpname = tmpname.toLowerCase(); + tmpnameCheck = tmpname.toLowerCase(); + nameElementCheck = nameElement.toLowerCase(); } - if (tmpname.contentEquals(nameElement) == true) { + if (tmpnameCheck.contentEquals(nameElementCheck) == true) { // find end of node : // find > element ... for (int jjj = endPosName + 1; jjj < _data.length(); jjj++) { @@ -440,18 +455,19 @@ public class ParseXml { return true; } else if (_data.charAt(jjj) != '\r' && _data.charAt(jjj) != ' ' && _data.charAt(jjj) != '\t') { _filePos.add(tmpPos); - parsingProperty.createError(_data, jjj, _filePos, "End node error : have data inside end node other than [ \\n\\t\\r] " + nameElement + "'"); + parsingProperty.createError( + new ExmlParserError(Tools.extractLine(_data, jjj), _filePos, "End node error : have data inside end node other than [ \\n\\t\\r] " + nameElement + "'")); return false; } } } else { - parsingProperty.createError(_data, _pos.value, _filePos, "End node error : '" + tmpname + "' != '" + nameElement + "'"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "End node error : '" + tmpname + "' != '" + nameElement + "'")); return false; } } if (_data.charAt(iii + white + 1) == '>') { // end of something == > this is really bad - parsingProperty.createError(_data, _pos.value, _filePos, "Find '>' chars == > invalide XML"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find '>' chars == > invalide XML")); return false; } @@ -470,16 +486,20 @@ public class ParseXml { tmpPos.check(_data.charAt(jjj)); } String tmpname = _data.substring(iii + white + 1, endPosName + 1); - if (parsingProperty.getCaseSensitive() == true) { + final String tmpnameOriginal = tmpname; + if (parsingProperty.getStoreMode() == StoreMode.LOWERCASE) { tmpname = tmpname.toLowerCase(); + } else if (parsingProperty.getStoreMode() == StoreMode.UPPERCASE) { + tmpname = tmpname.toUpperCase(); } + Log.debug("find node named : '" + tmpname + "'"); // find text: final Object element = this.builder.newElement(parent, tmpname); _pos.value = endPosName + 1; _filePos.add(tmpPos); Log.verbose("start parse : 'element' named='" + tmpname + "'"); - if (iParseElement(element, tmpname, _data, _pos, _filePos, parsingProperty) == false) { + if (iParseElement(element, tmpnameOriginal, _data, _pos, _filePos, parsingProperty) == false) { return false; } iii = _pos.value; @@ -487,11 +507,11 @@ public class ParseXml { } _filePos.add(tmpPos); // here we have an error : - parsingProperty.createError(_data, _pos.value, _filePos, "Find an ununderstanding element : '" + _data.charAt(iii + white + 1) + "'"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find an ununderstanding element : '" + _data.charAt(iii + white + 1) + "'")); return false; } else { if (_data.charAt(iii) == '>') { - parsingProperty.createError(_data, _pos.value, _filePos, "Find elemement '>' == > no reason to be here ..."); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Find elemement '>' == > no reason to be here ...")); return false; } // might to be data text ... @@ -511,7 +531,7 @@ public class ParseXml { if (nameElement == null) { return true; } - parsingProperty.createError(_data, _pos.value, _filePos, "Did not find end of the exml::internal::Element : '" + nameElement + "'"); + parsingProperty.createError(new ExmlParserError(Tools.extractLine(_data, _pos.value), _filePos, "Did not find end of the Element : '" + nameElement + "'")); return false; } } diff --git a/src/org/atriasoft/exml/parser/ParsingProperty.java b/src/org/atriasoft/exml/parser/ParsingProperty.java index 33b4578..a7498b6 100644 --- a/src/org/atriasoft/exml/parser/ParsingProperty.java +++ b/src/org/atriasoft/exml/parser/ParsingProperty.java @@ -1,54 +1,78 @@ package org.atriasoft.exml.parser; -import org.atriasoft.exml.internal.FilePos; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.atriasoft.exml.exception.ExmlParserError; import org.atriasoft.exml.internal.Log; -import org.atriasoft.exml.internal.Tools; public class ParsingProperty { - private boolean caseSensitive; //!< check the case sensitive of the nodes and attribute - private boolean writeErrorWhenDetexted; //!< Request print error in parsing just when detected - - private String comment; //!< Comment on the error; - private String Line; //!< Parse line error (copy); - private FilePos filePos; //!< position of the error + /// check the case sensitive of the nodes (end marker) and attribute (duplicates) + private boolean caseSensitive = true; + // Mode to store the Element name or the Attibute name + private StoreMode storeMode = StoreMode.NORMAL; + /// write error when not throw on error. + private boolean writeError = false; + /// throw when an error when it is detected (if permissive XML it throw only at the end of parsing). + private boolean throwOnError = true; + /// Permissive XML parsing (allows some errors must not be critical). + private boolean permisiveXML = false; + // List of all error detected + private final List errors = new ArrayList<>(); /** * Constructor */ - public ParsingProperty() { - this.caseSensitive = false; - this.writeErrorWhenDetexted = true; - this.comment = ""; - this.Line = ""; - this.filePos = new FilePos(0, 0); + public ParsingProperty() {} + + /** + * Constructor + * @param caseSensitive set the parsing of value is case sensitive. + * @param writeError Write all error when detected. + * @param throwOnError throw an error when parsing fail (if permissiveXml, it throw only at the end). + * @param permisiveXML Allow error and try to continue the parsing it is possible. + */ + public ParsingProperty(final boolean caseSensitive, final boolean writeError, final boolean throwOnError, final boolean permisiveXML) { + this.caseSensitive = caseSensitive; + this.writeError = writeError; + this.throwOnError = throwOnError; + this.permisiveXML = permisiveXML; } /** - * Create an error in the parsing (call by the syetm for error management) - * @param[in] _data string of chat is wrong - * @param[in] _pos Position in the file - * @param[in] _filePos human position of the error - * @param[in] _comment Error string to display + * Add an error in the parsing of the XML (the function will select if we need to throw, print or ...) + * @param error the error to throw or keep. + * @return true if the parsing will stop + * @throws ExmlParserError the error injected if user request it. */ - public void createError(final String _data, final int _pos, final FilePos _filePos, final String _comment) { - this.comment = _comment; - this.Line = Tools.extract_line(_data, _pos); - this.filePos = _filePos; - if (this.writeErrorWhenDetexted == true) { - displayError(); + public boolean createError(final ExmlParserError error) throws ExmlParserError { + // need display the error + if (this.writeError == true) { + displayError(error); } + // need throw the error + if (this.throwOnError == true && this.permisiveXML == false) { + throw error; + } + // Keep it in case + this.errors.add(error); + return this.permisiveXML == false; + } + + /** + * Request Display in log all the errors. + */ + public void displayError() { + this.errors.forEach(o -> displayError(o)); } /** * Request display in log of the error + * @param error The error to display. */ - public void displayError() { - if (this.comment.length() == 0) { - Log.error("No error detected ???"); - return; - } - Log.error(this.filePos + " " + this.comment + "\n" + this.Line + "\n" + Tools.createPosPointer(this.Line, this.filePos.getCol())); - //Log.critical("detect error"); + public void displayError(final ExmlParserError error) { + Log.error(error.getFilePos() + " " + error.getMessage() + "\n" + error.getDataLine() + "\n" + Tools.createPosPointer(error.getDataLine(), error.getFilePos().getCol())); } /** @@ -65,14 +89,53 @@ public class ParsingProperty { * @return false Does not display error (get it at end) */ public boolean getDisplayError() { - return this.writeErrorWhenDetexted; + return this.writeError; + } + + /** + * Get all error detected in the XML + * @return Immutable list of error (order by arrival) + */ + public List getErrors() { + return Collections.unmodifiableList(this.errors); + } + + /** + * Get the current storing mode + * @return store element and attribute values + */ + public StoreMode getStoreMode() { + return this.storeMode; + } + + /** + * Check is error has been detected + * @return true if some error are stored. + */ + public boolean isErrorDetected() { + return this.errors.isEmpty() == false; + } + + /** + * Get the permissive value + * @return true if permissive mode is enable + */ + public boolean isPermisiveXML() { + return this.permisiveXML; + } + + /** + * Check if throw on error + * @return true if it throw on error + */ + public boolean isThrowOnError() { + return this.throwOnError; } /** * Enable or diasable the case sensitive (must be done before the call of parsing) * @param[in] _val true if enable; false else. */ - // TODO: Naming error, it is insensitive ... public void setCaseSensitive(final boolean _val) { this.caseSensitive = _val; } @@ -82,6 +145,30 @@ public class ParsingProperty { * @param[in] _value true: display error, false not display error (get it at end) */ public void setDisplayError(final boolean _value) { - this.writeErrorWhenDetexted = _value; + this.writeError = _value; + } + + /** + * Set the permissive value. + * @param permisiveXML new value of permissive parsing. + */ + public void setPermisiveXML(final boolean permisiveXML) { + this.permisiveXML = permisiveXML; + } + + /** + * Set the new storing mode for Element and Attributes + * @param storeMode new Storing mode + */ + public void setStoreMode(final StoreMode storeMode) { + this.storeMode = storeMode; + } + + /** + * Set throwing on error (if permissive, it throw at the end of parsing) + * @param throwOnError true if it throw on error. + */ + public void setThrowOnError(final boolean throwOnError) { + this.throwOnError = throwOnError; } } diff --git a/src/org/atriasoft/exml/internal/PositionParsing.java b/src/org/atriasoft/exml/parser/PositionParsing.java similarity index 59% rename from src/org/atriasoft/exml/internal/PositionParsing.java rename to src/org/atriasoft/exml/parser/PositionParsing.java index 8e12029..8d63e8a 100644 --- a/src/org/atriasoft/exml/internal/PositionParsing.java +++ b/src/org/atriasoft/exml/parser/PositionParsing.java @@ -1,6 +1,5 @@ -package org.atriasoft.exml.internal; +package org.atriasoft.exml.parser; public class PositionParsing { public int value = 0; - } diff --git a/src/org/atriasoft/exml/parser/StoreMode.java b/src/org/atriasoft/exml/parser/StoreMode.java new file mode 100644 index 0000000..0458a40 --- /dev/null +++ b/src/org/atriasoft/exml/parser/StoreMode.java @@ -0,0 +1,7 @@ +package org.atriasoft.exml.parser; + +public enum StoreMode { + NORMAL, + UPPERCASE, + LOWERCASE, +} diff --git a/src/org/atriasoft/exml/internal/Tools.java b/src/org/atriasoft/exml/parser/Tools.java similarity index 96% rename from src/org/atriasoft/exml/internal/Tools.java rename to src/org/atriasoft/exml/parser/Tools.java index f85c7d5..5e05397 100644 --- a/src/org/atriasoft/exml/internal/Tools.java +++ b/src/org/atriasoft/exml/parser/Tools.java @@ -1,4 +1,6 @@ -package org.atriasoft.exml.internal; +package org.atriasoft.exml.parser; + +import org.atriasoft.exml.internal.Log; public class Tools { /** @@ -88,7 +90,7 @@ public class Tools { } } - public static String extract_line(final String data, final int _pos) { + public static String extractLine(final String data, final int _pos) { // search back : '\n' int startPos = data.lastIndexOf('\n', _pos); if (startPos == _pos) { diff --git a/src/org/atriasoft/exml/serializer/SerializerXml.java b/src/org/atriasoft/exml/serializer/SerializerXml.java new file mode 100644 index 0000000..dc7d2e1 --- /dev/null +++ b/src/org/atriasoft/exml/serializer/SerializerXml.java @@ -0,0 +1,112 @@ +package org.atriasoft.exml.serializer; + +import java.util.List; + +import org.atriasoft.exml.internal.Log; +import org.atriasoft.exml.model.XmlAttribute; +import org.atriasoft.exml.model.XmlAttributeList; +import org.atriasoft.exml.model.XmlComment; +import org.atriasoft.exml.model.XmlDeclaration; +import org.atriasoft.exml.model.XmlElement; +import org.atriasoft.exml.model.XmlNode; +import org.atriasoft.exml.model.XmlNodeType; +import org.atriasoft.exml.model.XmlText; +import org.atriasoft.exml.parser.Tools; + +public class SerializerXml { + + public static void serialize(final XmlNode node, final StringBuilder data, final int indent) { + if (node instanceof XmlElement) { + serializeElement((XmlElement) node, data, indent); + } else if (node instanceof XmlText) { + serializeText((XmlText) node, data, indent); + } else if (node instanceof XmlDeclaration) { + serializeDeclaration((XmlDeclaration) node, data, indent); + } else if (node instanceof XmlComment) { + serializeComment((XmlComment) node, data, indent); + } else { + // TODO throw an error ... + } + } + + private static void serializeAttribute(final XmlAttribute attribute, final StringBuilder data, final int indent) { + data.append(" "); + data.append(attribute.getName()); + data.append("=\""); + data.append(attribute.getValue()); + data.append("\""); + } + + private static void serializeAttributeList(final XmlAttributeList list, final StringBuilder data, final int indent) { + for (int iii = 0; iii < list.getAttributes().size(); iii++) { + serializeAttribute(list.getAttributes().get(iii), data, indent); + } + } + + private static void serializeComment(final XmlComment comment, final StringBuilder data, final int indent) { + Tools.addIndent(data, indent); + data.append("\n"); + } + + private static void serializeDeclaration(final XmlDeclaration declaration, final StringBuilder data, final int indent) { + Tools.addIndent(data, indent); + data.append("\n"); + + } + + private static void serializeElement(final XmlElement element, final StringBuilder data, final int indent) { + + Tools.addIndent(data, indent); + data.append("<"); + data.append(element.getValue()); + serializeAttributeList(element, data, indent); + + final List nodes = element.getNodes(); + if (nodes.size() > 0) { + if (nodes.size() == 1 && nodes.get(0) != null && nodes.get(0).getType() == XmlNodeType.TEXT && ((XmlText) nodes.get(0)).countLines() == 1) { + data.append(">"); + serialize(nodes.get(0), data, 0); + Log.verbose(" generate : '" + data + "'"); + } else { + data.append(">\n"); + for (int iii = 0; iii < nodes.size(); iii++) { + if (nodes.get(iii) != null) { + serialize(nodes.get(iii), data, indent + 1); + } + } + Tools.addIndent(data, indent); + } + data.append("\n"); + } else { + data.append("/>\n"); + } + } + + public static void serializeRoot(final XmlElement root, final StringBuilder data) { + for (int iii = 0; iii < root.getNodes().size(); iii++) { + final XmlNode node = root.getNodes().get(iii); + serialize(node, data, 0); + } + + } + + private static void serializeText(final XmlText text, final StringBuilder data, final int indent) { + data.append(Tools.replaceSpecialCharOut(text.getValue())); + } + /* CDATA generation ... maybe to add later ... + @Override + protected boolean iGenerate(final StringBuilder _data, final int _indent) { + _data.append(""); + return true; + } + */ +} diff --git a/test/src/test/atriasoft/exml/ExmlLocal.java b/test/src/test/atriasoft/exml/ExmlLocal.java index 08b539d..14c81cb 100644 --- a/test/src/test/atriasoft/exml/ExmlLocal.java +++ b/test/src/test/atriasoft/exml/ExmlLocal.java @@ -5,8 +5,9 @@ */ package test.atriasoft.exml; -import org.atriasoft.exml.Document; import org.atriasoft.exml.Exml; +import org.atriasoft.exml.exception.ExmlBuilderException; +import org.atriasoft.exml.model.XmlNode; import org.junit.jupiter.api.Assertions; class ExmlLocal { @@ -16,24 +17,25 @@ class ExmlLocal { } public static void test(final String _ref, final String _input, final int _errorPos, final boolean _caseInSensitive) { - final Document doc = new Document(); //doc.setCaseSensitive(!_caseInSensitive); Log.verbose("parse : \n" + _input); - final boolean retParse = Exml.parse(_input); - if (_errorPos == 1) { - Assertions.assertEquals(retParse, false); - return; - } else { - Assertions.assertEquals(retParse, true); + XmlNode root = null; + try { + root = Exml.parse(_input); + if (_errorPos == 1) { + Assertions.fail("Must have detected an error"); + return; + } + } catch (final ExmlBuilderException e) { + if (_errorPos == 1) { + return; + } else { + Assertions.fail("Must have NOT detected an error"); + } } final StringBuilder out = new StringBuilder(); - final boolean retGenerate = doc.generate(out); - if (_errorPos == 2) { - Assertions.assertEquals(retGenerate, false); - return; - } else { - Assertions.assertEquals(retGenerate, true); - } + // TODO: 2 is for failing in generate ... + Exml.generate(root, out); final String data = out.toString(); if (_errorPos == 3) { Assertions.assertNotEquals(_ref, data); diff --git a/test/src/test/atriasoft/exml/ExmlTestAttribute.java b/test/src/test/atriasoft/exml/ExmlTestAttribute.java index ee5316f..4d6aeab 100644 --- a/test/src/test/atriasoft/exml/ExmlTestAttribute.java +++ b/test/src/test/atriasoft/exml/ExmlTestAttribute.java @@ -5,11 +5,10 @@ */ package test.atriasoft.exml; -import org.atriasoft.exml.XmlAttribute; -import org.atriasoft.exml.Document; -import org.atriasoft.exml.XmlElement; +import org.atriasoft.exml.Exml; import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist; -import org.atriasoft.exml.exception.ExmlNodeDoesNotExist; +import org.atriasoft.exml.model.XmlAttribute; +import org.atriasoft.exml.model.XmlElement; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -28,7 +27,6 @@ public class ExmlTestAttribute { @Test public void clear() { - final XmlAttribute myAttribute = new XmlAttribute("nameAttribute", "valueAttribute"); myAttribute.clear(); } @@ -51,7 +49,6 @@ public class ExmlTestAttribute { @Test public void exist() { - final XmlElement elem = new XmlElement("elem"); elem.setAttribute("valA", "plop"); Assertions.assertEquals(elem.existAttribute("valA"), true); @@ -60,43 +57,29 @@ public class ExmlTestAttribute { @Test public void get() { - final XmlElement elem = new XmlElement("elem"); elem.setAttribute("valA", "plop"); - try { - Assertions.assertEquals(elem.getAttribute("valA"), "plop"); - } catch (final ExmlAttributeDoesNotExist e) { - Assertions.fail("Should Not have thrown an exception"); - } + final String attributeValue = Assertions.assertDoesNotThrow(() -> elem.getAttribute("valA")); + Assertions.assertEquals(attributeValue, "plop"); Assertions.assertThrows(ExmlAttributeDoesNotExist.class, () -> elem.getAttribute("qsdfsdf")); } @Test public void getpair() { - final XmlElement elem = new XmlElement("elem"); elem.setAttribute("valA", "coucou"); - try { - Assertions.assertEquals(elem.getAttrPair(0).first, "valA"); - Assertions.assertEquals(elem.getAttrPair(0).second, "coucou"); - } catch (final ExmlAttributeDoesNotExist e) { - Assertions.fail("Should Not have thrown an exception"); - } + final String first = Assertions.assertDoesNotThrow(() -> elem.getAttrPair(0).first); + Assertions.assertEquals(first, "valA"); + final String second = Assertions.assertDoesNotThrow(() -> elem.getAttrPair(0).second); + Assertions.assertEquals(second, "coucou"); Assertions.assertThrows(ExmlAttributeDoesNotExist.class, () -> elem.getAttrPair(1)); Assertions.assertThrows(ExmlAttributeDoesNotExist.class, () -> elem.getAttrPair(-1)); } @Test public void moveInAllElement() { - final Document doc = new Document(); - doc.parse(""); - XmlElement elem; - try { - elem = (XmlElement) doc.getNode("elem"); - } catch (final ExmlNodeDoesNotExist e) { - Assertions.fail("Should Not have thrown an exception"); - return; - } + final XmlElement root = Assertions.assertDoesNotThrow(() -> Exml.parse("")); + final XmlElement elem = Assertions.assertDoesNotThrow(() -> (XmlElement) root.getNode("elem")); for (final XmlAttribute it : elem.getAttributes()) { Assertions.assertEquals(it.getName(), "valA"); Assertions.assertEquals(it.getValue(), "plop"); @@ -114,7 +97,6 @@ public class ExmlTestAttribute { @Test public void setGetName() { - final XmlAttribute myAttribute = new XmlAttribute("nameAttribute", "valueAttribute"); Assertions.assertEquals(myAttribute.getName(), "nameAttribute"); myAttribute.setName("newName"); @@ -123,7 +105,6 @@ public class ExmlTestAttribute { @Test public void setGetValue() { - final XmlAttribute myAttribute = new XmlAttribute("nameAttribute", "valueAttribute"); Assertions.assertEquals(myAttribute.getValue(), "valueAttribute"); myAttribute.setValue("new value"); @@ -132,31 +113,20 @@ public class ExmlTestAttribute { @Test public void setterNew() { - final XmlElement elem = new XmlElement("elem"); elem.setAttribute("valA", "coucou"); - try { - Assertions.assertEquals(elem.getAttribute("valA"), "coucou"); - } catch (final ExmlAttributeDoesNotExist e) { - Assertions.fail("Should Not have thrown an exception"); - } + final String attributeValue = Assertions.assertDoesNotThrow(() -> elem.getAttribute("valA")); + Assertions.assertEquals(attributeValue, "coucou"); } @Test public void setterRewrite() { - final XmlElement elem = new XmlElement("elem"); elem.setAttribute("valA", "coucou"); - try { - Assertions.assertEquals(elem.getAttribute("valA"), "coucou"); - } catch (final ExmlAttributeDoesNotExist e) { - Assertions.fail("Should Not have thrown an exception"); - } + String attributeValue = Assertions.assertDoesNotThrow(() -> elem.getAttribute("valA")); + Assertions.assertEquals(attributeValue, "coucou"); elem.setAttribute("valA", "coucou2"); - try { - Assertions.assertEquals(elem.getAttribute("valA"), "coucou2"); - } catch (final ExmlAttributeDoesNotExist e) { - Assertions.fail("Should Not have thrown an exception"); - } + attributeValue = Assertions.assertDoesNotThrow(() -> elem.getAttribute("valA")); + Assertions.assertEquals(attributeValue, "coucou2"); } } diff --git a/test/src/test/atriasoft/exml/ExmlTestCData.java b/test/src/test/atriasoft/exml/ExmlTestCData.java index 370085c..384edb1 100644 --- a/test/src/test/atriasoft/exml/ExmlTestCData.java +++ b/test/src/test/atriasoft/exml/ExmlTestCData.java @@ -5,9 +5,8 @@ */ package test.atriasoft.exml; -import org.atriasoft.exml.Document; -import org.atriasoft.exml.XmlElement; -import org.atriasoft.exml.TextCDATA; +import org.atriasoft.exml.Exml; +import org.atriasoft.exml.model.XmlElement; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -18,23 +17,10 @@ public class ExmlTestCData { Log.verbose("----------------------------------------------------------------"); } - @Test - public void generate() { - final Document doc = new Document(); - doc.append(new TextCDATA("Text &é<>examp]le]] ...")); - doc.append(new TextCDATA("Text &é<>examp]le]] ...")); - final String out = doc.getText(); - doc.parse("examp]le]] ...]]>"); - Assertions.assertEquals("examp]le]] ...]]>examp]le]] ...]]>", out); - } - @Test public void parseCDATA() { - final Document doc = new Document(); - doc.parse("examp]le]] ...]]>"); - final XmlElement elem = Assertions.assertDoesNotThrow(() -> { - return (XmlElement) doc.getNode("elem"); - }); + final XmlElement root = Assertions.assertDoesNotThrow(() -> Exml.parse("examp]le]] ...]]>")); + final XmlElement elem = Assertions.assertDoesNotThrow(() -> (XmlElement) root.getNode("elem")); Assertions.assertEquals("Text &é<>examp]le]] ...", elem.getText()); } } diff --git a/test/src/test/atriasoft/exml/ExmlTestComment.java b/test/src/test/atriasoft/exml/ExmlTestComment.java index fd652c4..920eb80 100644 --- a/test/src/test/atriasoft/exml/ExmlTestComment.java +++ b/test/src/test/atriasoft/exml/ExmlTestComment.java @@ -5,9 +5,9 @@ */ package test.atriasoft.exml; -import org.atriasoft.exml.XmlComment; -import org.atriasoft.exml.XmlNode; -import org.atriasoft.exml.XmlNodeType; +import org.atriasoft.exml.model.XmlComment; +import org.atriasoft.exml.model.XmlNode; +import org.atriasoft.exml.model.XmlNodeType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; diff --git a/test/src/test/atriasoft/exml/ExmlTestDeclarationXML.java b/test/src/test/atriasoft/exml/ExmlTestDeclarationXML.java index 9ca027b..6147e5b 100644 --- a/test/src/test/atriasoft/exml/ExmlTestDeclarationXML.java +++ b/test/src/test/atriasoft/exml/ExmlTestDeclarationXML.java @@ -5,9 +5,9 @@ */ package test.atriasoft.exml; -import org.atriasoft.exml.DeclarationXML; -import org.atriasoft.exml.XmlNodeType; import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist; +import org.atriasoft.exml.model.XmlDeclaration; +import org.atriasoft.exml.model.XmlNodeType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -20,7 +20,7 @@ public class ExmlTestDeclarationXML { @Test public void create() { - final DeclarationXML myDeclarationXML = new DeclarationXML("1.0", "UTF-8", true); + final XmlDeclaration myDeclarationXML = new XmlDeclaration("1.0", "UTF-8", true); Assertions.assertEquals(myDeclarationXML.getType(), XmlNodeType.DECLARATION); try { Assertions.assertEquals(myDeclarationXML.getAttribute("version"), "1.0"); @@ -34,8 +34,8 @@ public class ExmlTestDeclarationXML { @Test public void createAssignement() { - final DeclarationXML myDeclarationXML = new DeclarationXML("1.0", "UTF-8", true); - final DeclarationXML myOtherDeclarationXML = myDeclarationXML.clone(); + final XmlDeclaration myDeclarationXML = new XmlDeclaration("1.0", "UTF-8", true); + final XmlDeclaration myOtherDeclarationXML = myDeclarationXML.clone(); Assertions.assertEquals(myDeclarationXML.getValue(), myOtherDeclarationXML.getValue()); try { Assertions.assertEquals(myDeclarationXML.getAttribute("version"), myOtherDeclarationXML.getAttribute("version")); @@ -48,8 +48,8 @@ public class ExmlTestDeclarationXML { @Test public void createCopy() { - final DeclarationXML myDeclarationXML = new DeclarationXML("1.0", "UTF-8", true); - final DeclarationXML myOtherDeclarationXML = new DeclarationXML(myDeclarationXML); + final XmlDeclaration myDeclarationXML = new XmlDeclaration("1.0", "UTF-8", true); + final XmlDeclaration myOtherDeclarationXML = new XmlDeclaration(myDeclarationXML); Assertions.assertEquals(myDeclarationXML.getValue(), myOtherDeclarationXML.getValue()); try { Assertions.assertEquals(myDeclarationXML.getAttribute("version"), myOtherDeclarationXML.getAttribute("version")); diff --git a/test/src/test/atriasoft/exml/ExmlTestElement.java b/test/src/test/atriasoft/exml/ExmlTestElement.java index dfa9ac6..e42c689 100644 --- a/test/src/test/atriasoft/exml/ExmlTestElement.java +++ b/test/src/test/atriasoft/exml/ExmlTestElement.java @@ -5,11 +5,11 @@ */ package test.atriasoft.exml; -import org.atriasoft.exml.Document; -import org.atriasoft.exml.XmlElement; -import org.atriasoft.exml.XmlNode; -import org.atriasoft.exml.XmlNodeType; +import org.atriasoft.exml.Exml; import org.atriasoft.exml.exception.ExmlNodeDoesNotExist; +import org.atriasoft.exml.model.XmlElement; +import org.atriasoft.exml.model.XmlNode; +import org.atriasoft.exml.model.XmlNodeType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -114,9 +114,8 @@ public class ExmlTestElement { @Test public void moveInAllElement() { - final Document doc = new Document(); - doc.parse(""); - for (final XmlNode it : doc.getNodes()) { + final XmlElement root = Assertions.assertDoesNotThrow(() -> Exml.parse("")); + for (final XmlNode it : root.getNodes()) { final XmlElement elem = (XmlElement) it; Assertions.assertEquals("elem", elem.getValue()); Assertions.assertEquals(2, elem.getNodes().size()); diff --git a/test/src/test/atriasoft/exml/ExmlTestParseDeclaration.java b/test/src/test/atriasoft/exml/ExmlTestParseDeclaration.java index 0eb5d15..8e24b41 100644 --- a/test/src/test/atriasoft/exml/ExmlTestParseDeclaration.java +++ b/test/src/test/atriasoft/exml/ExmlTestParseDeclaration.java @@ -29,6 +29,11 @@ public class ExmlTestParseDeclaration { ExmlLocal.test("\n", "\n", -1); } + @Test + public void testCaseSensitiveBalise() { + ExmlLocal.test("\n", "\n", -1); + } + @Test public void testMultiline() { ExmlLocal.test("\n", "\n", -1);