Author: tchemit Date: 2009-09-08 00:54:20 +0200 (Tue, 08 Sep 2009) New Revision: 569 Added: trunk/src/main/java/org/nuiton/io/ trunk/src/main/java/org/nuiton/io/xpp3/ trunk/src/main/java/org/nuiton/io/xpp3/AbstractXpp3Reader.java trunk/src/main/java/org/nuiton/io/xpp3/DataConverter.java trunk/src/main/java/org/nuiton/io/xpp3/PropertyMapper.java trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Helper.java trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Reader.java Modified: trunk/changelog.txt Log: [FEATURE #46] ajout d'un contrat pour faire des parseurs xpp3 Modified: trunk/changelog.txt =================================================================== --- trunk/changelog.txt 2009-09-06 20:27:59 UTC (rev 568) +++ trunk/changelog.txt 2009-09-07 22:54:20 UTC (rev 569) @@ -1,5 +1,6 @@ maven-helper-plugin (1.0.3) stable; urgency=high + * [FEATURE #46] ajout d'un contrat pour faire des parseurs xpp3 * [FEATURE #45] utiliser des generics dans le framework de test de mojos -- chemit -- Added: trunk/src/main/java/org/nuiton/io/xpp3/AbstractXpp3Reader.java =================================================================== --- trunk/src/main/java/org/nuiton/io/xpp3/AbstractXpp3Reader.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/xpp3/AbstractXpp3Reader.java 2009-09-07 22:54:20 UTC (rev 569) @@ -0,0 +1,338 @@ +package org.nuiton.io.xpp3; + +import java.beans.IntrospectionException; +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +/** + * An abstract xpp3Reader based on {@link PropertyMapper} to set properties of + * the objects to build. + * + * To implements a new parser, just implements method {@link #initMappers()} to + * see authorized mapping from tag to pojo properties. + * + * The logic of setting properties from xml (tag and attributes) is done in + * + * <ul> + * <li>{@link #read(org.codehaus.plexus.util.xml.pull.XmlPullParser, boolean)} </li> + * <li>{@link #readArray(org.codehaus.plexus.util.xml.pull.XmlPullParser, boolean)} </li> + * </ul> + * + * The default implementation is to map tag text to a pojo's property. + * + * If you want to do something more complex, override these methods. + * + * @author chemit + * @since 1.0.0 + * @see PropertyMapper + * @see Xpp3Reader + */ +public abstract class AbstractXpp3Reader implements Xpp3Reader { + + /** + * If set the parser will be loaded with all single characters + * from the XHTML specification. + * The entities used: + * <ul> + * <li>http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent</li> + * <li>http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent</li> + * <li>http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent</li> + * </ul> + */ + protected boolean addDefaultEntities = true; + /** + * the type of the object to produce from the xml streams. + */ + protected final Class<?> type; + /** + * the root tag of an object to retreave from xml streams. + * + */ + protected final String rootTagName; + /** + * the univers of mappers availables, initialized in {@link #initMappers()}. + * + * Each mapper of the dictionary is associated to the fully qualified name + * of the target class # the tag name or attribute name. + * + * Example : + * <pre> + * org.nuiton.util.MyPojo#my-tag + * org.nuiton.util.MyPojo#my-attribute + * </pre> + */ + protected final Map<String, PropertyMapper> allMappers; + /** + * a flag to display in console the generated code : + * an easy way to build to generate java pojos mocks from xml file (to test the parser for example :) + */ + protected boolean showGeneratedCode; + + protected abstract void initMappers() throws IntrospectionException; + + protected AbstractXpp3Reader(Class<?> type, String rootTagName) { + this.type = type; + this.rootTagName = rootTagName; + this.allMappers = new TreeMap<String, PropertyMapper>(); + try { + initMappers(); + } catch (IntrospectionException e) { + throw new IllegalStateException("could not init " + this + " for reason " + e.getMessage(), e); + } + } + + @Override + public Class<?> getType() { + return type; + } + + public String getRootTagName() { + return rootTagName; + } + + public String getArrayRootTagName() { + return rootTagName + "s"; + } + + @Override + public boolean isAddDefaultEntities() { + return addDefaultEntities; + } + + public boolean isShowGeneratedCode() { + return showGeneratedCode; + } + + public void setShowGeneratedCode(boolean showGeneratedCode) { + this.showGeneratedCode = showGeneratedCode; + } + + @Override + public void setAddDefaultEntities(boolean addDefaultEntities) { + this.addDefaultEntities = addDefaultEntities; + } + + @Override + public Object read(Reader reader) throws IOException, XmlPullParserException { + return read(reader, true); + } + + @Override + public Object read(Reader reader, boolean strict) throws IOException, XmlPullParserException { + XmlPullParser parser = new MXParser(); + + parser.setInput(reader); + + if (addDefaultEntities) { + + Xpp3Helper.addDefaultEntities(parser); + + } + + parser.next(); + return read(parser, strict); + } + + @Override + public Object[] readArray(Reader reader) throws IOException, XmlPullParserException { + return readArray(reader, true); + } + + @Override + public Object[] readArray(Reader reader, boolean strict) throws IOException, XmlPullParserException { + XmlPullParser parser = new MXParser(); + + parser.setInput(reader); + + if (addDefaultEntities) { + + Xpp3Helper.addDefaultEntities(parser); + + } + + parser.next(); + return readArray(parser, strict); + } + + /** + * Obtain all mappers for a given type. + * + * In the result, the keys are now the tag-name of attribute-name. + * + * Example : + * <pre> + * my-tag + * my-attribute + * </pre> + * + * @param srcType the target type of the searched mappers + * @return the dictionnary of mappers for the given type. + */ + public Map<String, PropertyMapper> getMappers(Class<?> srcType) { + Map<String, PropertyMapper> result = new TreeMap<String, PropertyMapper>(); + String prefix = srcType.getName() + "#"; + for (Entry<String, PropertyMapper> e : this.allMappers.entrySet()) { + if (e.getKey().startsWith(prefix)) { + result.put(e.getValue().getTagName(), e.getValue()); + } + } + return result; + } + + /** + * Parse the xml stream from the given parser and a build the associated object. + * + * This default implementation just match a tag text content to a pojo property. + * + * No work is done on attribute values here. + * + * Note: The xml stream must contains one object to build on the root node. + * + * the root node name is given by <code>getRootTagName()</code> + * + * Example : + * <pre> + * <my-pojo> + * <my-property>myValue</my-property> + * </my-pojo> + * </pre> + * + * @param parser the xpp3 parser + * @param strict flag to indicate if should fail if a unknown tag (or attribute ?) is scanned + * @return the single object build from the xml stream. + * @throws IOException if any io pb + * @throws XmlPullParserException if any parsing pb + */ + protected Object read(XmlPullParser parser, boolean strict) throws IOException, XmlPullParserException { + + Object result; + try { + result = getType().newInstance(); + } catch (Exception ex) { + // should never happens! + throw new RuntimeException("could not instanciate a new " + getType().getName() + " for reason : " + ex.getMessage(), ex); + } + + java.util.Set<String> parsed = new java.util.HashSet<String>(); + int eventType = parser.getEventType(); + boolean foundRoot = false; + + Map<String, PropertyMapper> mappers = getMappers(getType()); + if (showGeneratedCode) { + System.out.println(getType().getName() + " i = new " + getType().getSimpleName() + "();"); + } + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals(rootTagName)) { + foundRoot = true; + } else { + PropertyMapper mapper = mappers.get(parser.getName()); + if (mapper != null) { + mapper.setProperty(result, parser, parsed, strict); + } else if (strict) { + throw new XmlPullParserException("Unrecognised tag: '" + parser.getName() + "'", parser, null); + } + } + } + eventType = parser.next(); + } + return result; + } + + /** + * Parse the xml stream from the given parser and a build an array of associated object. + * + * This default implementation just match a tag text content to a pojo property. + * + * No work is done on attribute values here. + * + * Note: The xml stream must contains a root node. + * + * the root node name is given by <code>getArrayRootTagName()</code> + * + * and sub nodes with names <code>getRootTagName()</code> + * + * Example : + * <pre> + * <my-pojos> + * <my-pojo> + * <my-property>myValue</my-property> + * </my-pojo> + * <my-pojo> + * <my-property>myValue2</my-property> + * </my-pojo> + * </my-pojos> + * </pre> + * + * @param parser the xpp3 parser + * @param strict flag to indicate if should fail if a unknown tag (or attribute ?) is scanned + * @return the single object build from the xml stream. + * @throws IOException if any io pb + * @throws XmlPullParserException if any parsing pb + */ + protected Object[] readArray(XmlPullParser parser, boolean strict) throws IOException, XmlPullParserException { + + List<Object> results = new ArrayList<Object>(); + + + java.util.Set<String> parsed = new java.util.HashSet<String>(); + int eventType = parser.getEventType(); + boolean foundRoot = false; + + Map<String, PropertyMapper> mappers = getMappers(getType()); + Object result = null; + String root = getArrayRootTagName(); + if (showGeneratedCode) { + System.out.println(getType().getSimpleName() + " i = null;"); + } + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals(root)) { + foundRoot = true; + if (showGeneratedCode) { + System.out.println("List<" + getType().getSimpleName() + "> list = new ArrayList<" + getType().getSimpleName() + ">();"); + } + } else if (parser.getName().equals(this.rootTagName)) { + try { + result = getType().newInstance(); + if (showGeneratedCode) { + System.out.println("i = new " + getType().getSimpleName() + "();"); + } + } catch (Exception ex) { + // should never happens! + throw new RuntimeException("could not instanciate a new " + getType().getName() + " for reason : " + ex.getMessage(), ex); + } + + } else { + PropertyMapper mapper = mappers.get(parser.getName()); + if (mapper != null) { + mapper.setProperty(result, parser, parsed, strict); + + } else if (strict) { + throw new XmlPullParserException("Unrecognised tag: '" + parser.getName() + "'", parser, null); + } + } + } else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals(this.rootTagName)) { + // save it + results.add(result); + // clear parsed attributes + parsed.clear(); + if (showGeneratedCode) { + System.out.println("list.add(i);"); + } + } + } + eventType = parser.next(); + } + return results.toArray(new Object[results.size()]); + } +} Property changes on: trunk/src/main/java/org/nuiton/io/xpp3/AbstractXpp3Reader.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/io/xpp3/DataConverter.java =================================================================== --- trunk/src/main/java/org/nuiton/io/xpp3/DataConverter.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/xpp3/DataConverter.java 2009-09-07 22:54:20 UTC (rev 569) @@ -0,0 +1,15 @@ +package org.nuiton.io.xpp3; + +/** + * A contract to a data converter from a text value to a typed value. + * + * We does not here use the commons-beans classes, since we could have different + * types of converter for a same type.... + * + * @author chemit + * @since 1.0.3 + */ +public interface DataConverter { + + Object convert(String t) throws Exception; +} Property changes on: trunk/src/main/java/org/nuiton/io/xpp3/DataConverter.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/io/xpp3/PropertyMapper.java =================================================================== --- trunk/src/main/java/org/nuiton/io/xpp3/PropertyMapper.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/xpp3/PropertyMapper.java 2009-09-07 22:54:20 UTC (rev 569) @@ -0,0 +1,134 @@ +package org.nuiton.io.xpp3; + +import java.beans.PropertyDescriptor; +import java.io.IOException; +import java.text.ParseException; +import java.util.Set; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +/** + * A abstract object to map an xml value (tag or attribute, or esle?) to a pojo property. + * + * Two implementations are given : + * + * <ul> + * <li>{@link TagTextContentToProperty} to map the text content of a tag to a pojo's property</li> + * <li>{@link AttributeValueToProperty} to map the text content of a tag to a pojo's property</li> + * </ul> + * + * @author chemit + * @since 1.0.3 + */ +public abstract class PropertyMapper { + + public static class TagTextContentToProperty extends PropertyMapper { + + public TagTextContentToProperty(String tagName, String propertyName, DataConverter type, boolean onlyOne, PropertyDescriptor descriptor) { + super(tagName, propertyName, type, onlyOne, descriptor); + } + + @Override + protected Object getDataFromXml(XmlPullParser parser) throws XmlPullParserException, Exception { + String t = parser.nextText(); + Object result = null; + if (t != null && !(t = t.trim()).isEmpty()) { + result = type.convert(t); + } + return result; + } + } + + public static class AttributeValueToProperty extends PropertyMapper { + + public AttributeValueToProperty(String tagName, String propertyName, DataConverter type, boolean onlyOne, PropertyDescriptor descriptor) { + super(tagName, propertyName, type, onlyOne, descriptor); + } + + @Override + protected Object getDataFromXml(XmlPullParser parser) throws XmlPullParserException, Exception { + String t = parser.getAttributeValue("", name); + Object result = null; + if (t != null && !(t = t.trim()).isEmpty()) { + result = type.convert(t); + } + return result; + } + } + /** + * name of tag (or attribute to deal with) + */ + protected final String name; + /** + * the pojo's property to set + */ + protected final String propertyName; + /** + * the converter from xml to pojo's property type + */ + protected final DataConverter type; + /** + * the pojo's property descriptor + */ + protected final PropertyDescriptor descriptor; + /** + * a flag to check to use only once the mapper. (should not be used for + * attributes implementations). + */ + protected final boolean onlyOne; + + protected PropertyMapper(String tagName, String propertyName, DataConverter type, boolean onlyOne, PropertyDescriptor descriptor) { + this.name = tagName; + this.propertyName = propertyName; + this.type = type; + this.onlyOne = onlyOne; + this.descriptor = descriptor; + } + + protected abstract Object getDataFromXml(XmlPullParser parser) throws XmlPullParserException, Exception; + + public void setProperty(Object src, XmlPullParser parser, Set<String> parsed, boolean strict) throws XmlPullParserException, IOException, IOException { + if (onlyOne && parsed.contains(name)) { + throw new XmlPullParserException("Duplicated tag: \'" + parser.getName() + "\'", parser, null); + } + parsed.add(name); + try { + Object r = getDataFromXml(parser); + if (r != null) { + descriptor.getWriteMethod().invoke(src, r); + } + } catch (XmlPullParserException e) { + throw e; + } catch (NumberFormatException e) { + if (strict) { + throw new XmlPullParserException(e.getMessage()); + } + } catch (ParseException e) { + if (strict) { + throw new XmlPullParserException(e.getMessage()); + } + } catch (Exception e) { + throw new XmlPullParserException(e.getMessage()); + } + } + + public PropertyDescriptor getDescriptor() { + return descriptor; + } + + public boolean isOnlyOne() { + return onlyOne; + } + + public String getPropertyName() { + return propertyName; + } + + public String getTagName() { + return name; + } + + public DataConverter getType() { + return type; + } +} Property changes on: trunk/src/main/java/org/nuiton/io/xpp3/PropertyMapper.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Helper.java =================================================================== --- trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Helper.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Helper.java 2009-09-07 22:54:20 UTC (rev 569) @@ -0,0 +1,424 @@ +package org.nuiton.io.xpp3; + +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.ServiceLoader; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; + +/** + * A Helper to read some data stored in xml with a {@link Xpp3Reader}. + * + * In this class, there is some methods to obtain a discovered {@link Xpp3Reader} + * registred by a {@link ServiceLoader} mecanism. + * + * @author chemit + * @since 1.0.3 + * @see Xpp3Reader + */ +public class Xpp3Helper { + + /** + * les readers enregistres via un {@link ServiceLoader} + * sur le contrat {@link Xpp3Reader}. + */ + protected static Map<Class<?>, Xpp3Reader> readers; + + /** + * Read a single object from a xml stream. + * + * @param klass the type of object to read + * @param reader the reader where to parse the xml + * @return the loaded object + * @throws IOException if any io pb + * @throws XmlPullParserException if any parsing pb + */ + public static Object readObject(Class<?> klass, Reader reader) throws IOException, XmlPullParserException { + + Object result = null; + + try { + + StringWriter sWriter = new StringWriter(); + + IOUtil.copy(reader, sWriter); + + String rawInput = sWriter.toString(); + + StringReader sReader = new StringReader(rawInput); + + Xpp3Reader modelReader = getReader(klass); + + result = modelReader.read(sReader); + + } finally { + IOUtil.close(reader); + } + + return result; + } + + /** + * Read an array of objects from a xml stream. + * + * @param klass the type of object to read + * @param reader the reader where to parse the xml + * @return the loaded objects + * @throws IOException if any io pb + * @throws XmlPullParserException if any parsing pb + */ + public static Object[] readObjects(Class<?> klass, Reader reader) throws IOException, XmlPullParserException { + + Object[] result = null; + + try { + + StringWriter sWriter = new StringWriter(); + + IOUtil.copy(reader, sWriter); + + String rawInput = sWriter.toString(); + + StringReader sReader = new StringReader(rawInput); + + Xpp3Reader modelReader = getReader(klass); + + result = modelReader.readArray(sReader); + + } finally { + IOUtil.close(reader); + } + + return result; + } + + /** + * + * @return an iterator on all registred {@link Xpp3Reader}. + */ + public static Iterator<Xpp3Reader> getReaderItetator() { + return getReaders().values().iterator(); + } + + /** + * Obtain the loaded reader which match his {@link Xpp3Reader#getType()} whith + * the given type. + * + * @param <T> the type of the data which should be parsed by the researched parser + * @param klass the type of the data which should be parsed by the researched parser + * @return the parser for the given type + */ + public static <T> Xpp3Reader getReader(Class<?> klass) { + Xpp3Reader reader = getReaders().get(klass); + return reader; + } + + /** + * Clean all the registred readers. + * + * To reload them, just call a {@link #getReader(java.lang.Class)}. + * + */ + public static void clearReaders() { + if (readers != null) { + readers.clear(); + readers = null; + } + } + + /** + * Add to the parser, the default replacers for all single characters + * from the XHTML specification. + * The entities used: + * <ul> + * <li>http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent</li> + * <li>http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent</li> + * <li>http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent</li> + * </ul> + * @param parser the parser to configure + * @throws XmlPullParserException if any pb + */ + public static void addDefaultEntities(XmlPullParser parser) throws XmlPullParserException { + // ---------------------------------------------------------------------- + // Latin 1 entities + // ---------------------------------------------------------------------- + parser.defineEntityReplacementText("nbsp", "\u00a0"); + parser.defineEntityReplacementText("iexcl", "\u00a1"); + parser.defineEntityReplacementText("cent", "\u00a2"); + parser.defineEntityReplacementText("pound", "\u00a3"); + parser.defineEntityReplacementText("curren", "\u00a4"); + parser.defineEntityReplacementText("yen", "\u00a5"); + parser.defineEntityReplacementText("brvbar", "\u00a6"); + parser.defineEntityReplacementText("sect", "\u00a7"); + parser.defineEntityReplacementText("uml", "\u00a8"); + parser.defineEntityReplacementText("copy", "\u00a9"); + parser.defineEntityReplacementText("ordf", "\u00aa"); + parser.defineEntityReplacementText("laquo", "\u00ab"); + parser.defineEntityReplacementText("not", "\u00ac"); + parser.defineEntityReplacementText("shy", "\u00ad"); + parser.defineEntityReplacementText("reg", "\u00ae"); + parser.defineEntityReplacementText("macr", "\u00af"); + parser.defineEntityReplacementText("deg", "\u00b0"); + parser.defineEntityReplacementText("plusmn", "\u00b1"); + parser.defineEntityReplacementText("sup2", "\u00b2"); + parser.defineEntityReplacementText("sup3", "\u00b3"); + parser.defineEntityReplacementText("acute", "\u00b4"); + parser.defineEntityReplacementText("micro", "\u00b5"); + parser.defineEntityReplacementText("para", "\u00b6"); + parser.defineEntityReplacementText("middot", "\u00b7"); + parser.defineEntityReplacementText("cedil", "\u00b8"); + parser.defineEntityReplacementText("sup1", "\u00b9"); + parser.defineEntityReplacementText("ordm", "\u00ba"); + parser.defineEntityReplacementText("raquo", "\u00bb"); + parser.defineEntityReplacementText("frac14", "\u00bc"); + parser.defineEntityReplacementText("frac12", "\u00bd"); + parser.defineEntityReplacementText("frac34", "\u00be"); + parser.defineEntityReplacementText("iquest", "\u00bf"); + parser.defineEntityReplacementText("Agrave", "\u00c0"); + parser.defineEntityReplacementText("Aacute", "\u00c1"); + parser.defineEntityReplacementText("Acirc", "\u00c2"); + parser.defineEntityReplacementText("Atilde", "\u00c3"); + parser.defineEntityReplacementText("Auml", "\u00c4"); + parser.defineEntityReplacementText("Aring", "\u00c5"); + parser.defineEntityReplacementText("AElig", "\u00c6"); + parser.defineEntityReplacementText("Ccedil", "\u00c7"); + parser.defineEntityReplacementText("Egrave", "\u00c8"); + parser.defineEntityReplacementText("Eacute", "\u00c9"); + parser.defineEntityReplacementText("Ecirc", "\u00ca"); + parser.defineEntityReplacementText("Euml", "\u00cb"); + parser.defineEntityReplacementText("Igrave", "\u00cc"); + parser.defineEntityReplacementText("Iacute", "\u00cd"); + parser.defineEntityReplacementText("Icirc", "\u00ce"); + parser.defineEntityReplacementText("Iuml", "\u00cf"); + parser.defineEntityReplacementText("ETH", "\u00d0"); + parser.defineEntityReplacementText("Ntilde", "\u00d1"); + parser.defineEntityReplacementText("Ograve", "\u00d2"); + parser.defineEntityReplacementText("Oacute", "\u00d3"); + parser.defineEntityReplacementText("Ocirc", "\u00d4"); + parser.defineEntityReplacementText("Otilde", "\u00d5"); + parser.defineEntityReplacementText("Ouml", "\u00d6"); + parser.defineEntityReplacementText("times", "\u00d7"); + parser.defineEntityReplacementText("Oslash", "\u00d8"); + parser.defineEntityReplacementText("Ugrave", "\u00d9"); + parser.defineEntityReplacementText("Uacute", "\u00da"); + parser.defineEntityReplacementText("Ucirc", "\u00db"); + parser.defineEntityReplacementText("Uuml", "\u00dc"); + parser.defineEntityReplacementText("Yacute", "\u00dd"); + parser.defineEntityReplacementText("THORN", "\u00de"); + parser.defineEntityReplacementText("szlig", "\u00df"); + parser.defineEntityReplacementText("agrave", "\u00e0"); + parser.defineEntityReplacementText("aacute", "\u00e1"); + parser.defineEntityReplacementText("acirc", "\u00e2"); + parser.defineEntityReplacementText("atilde", "\u00e3"); + parser.defineEntityReplacementText("auml", "\u00e4"); + parser.defineEntityReplacementText("aring", "\u00e5"); + parser.defineEntityReplacementText("aelig", "\u00e6"); + parser.defineEntityReplacementText("ccedil", "\u00e7"); + parser.defineEntityReplacementText("egrave", "\u00e8"); + parser.defineEntityReplacementText("eacute", "\u00e9"); + parser.defineEntityReplacementText("ecirc", "\u00ea"); + parser.defineEntityReplacementText("euml", "\u00eb"); + parser.defineEntityReplacementText("igrave", "\u00ec"); + parser.defineEntityReplacementText("iacute", "\u00ed"); + parser.defineEntityReplacementText("icirc", "\u00ee"); + parser.defineEntityReplacementText("iuml", "\u00ef"); + parser.defineEntityReplacementText("eth", "\u00f0"); + parser.defineEntityReplacementText("ntilde", "\u00f1"); + parser.defineEntityReplacementText("ograve", "\u00f2"); + parser.defineEntityReplacementText("oacute", "\u00f3"); + parser.defineEntityReplacementText("ocirc", "\u00f4"); + parser.defineEntityReplacementText("otilde", "\u00f5"); + parser.defineEntityReplacementText("ouml", "\u00f6"); + parser.defineEntityReplacementText("divide", "\u00f7"); + parser.defineEntityReplacementText("oslash", "\u00f8"); + parser.defineEntityReplacementText("ugrave", "\u00f9"); + parser.defineEntityReplacementText("uacute", "\u00fa"); + parser.defineEntityReplacementText("ucirc", "\u00fb"); + parser.defineEntityReplacementText("uuml", "\u00fc"); + parser.defineEntityReplacementText("yacute", "\u00fd"); + parser.defineEntityReplacementText("thorn", "\u00fe"); + parser.defineEntityReplacementText("yuml", "\u00ff"); + // ---------------------------------------------------------------------- + // Special entities + // ---------------------------------------------------------------------- + parser.defineEntityReplacementText("OElig", "\u0152"); + parser.defineEntityReplacementText("oelig", "\u0153"); + parser.defineEntityReplacementText("Scaron", "\u0160"); + parser.defineEntityReplacementText("scaron", "\u0161"); + parser.defineEntityReplacementText("Yuml", "\u0178"); + parser.defineEntityReplacementText("circ", "\u02c6"); + parser.defineEntityReplacementText("tilde", "\u02dc"); + parser.defineEntityReplacementText("ensp", "\u2002"); + parser.defineEntityReplacementText("emsp", "\u2003"); + parser.defineEntityReplacementText("thinsp", "\u2009"); + parser.defineEntityReplacementText("zwnj", "\u200c"); + parser.defineEntityReplacementText("zwj", "\u200d"); + parser.defineEntityReplacementText("lrm", "\u200e"); + parser.defineEntityReplacementText("rlm", "\u200f"); + parser.defineEntityReplacementText("ndash", "\u2013"); + parser.defineEntityReplacementText("mdash", "\u2014"); + parser.defineEntityReplacementText("lsquo", "\u2018"); + parser.defineEntityReplacementText("rsquo", "\u2019"); + parser.defineEntityReplacementText("sbquo", "\u201a"); + parser.defineEntityReplacementText("ldquo", "\u201c"); + parser.defineEntityReplacementText("rdquo", "\u201d"); + parser.defineEntityReplacementText("bdquo", "\u201e"); + parser.defineEntityReplacementText("dagger", "\u2020"); + parser.defineEntityReplacementText("Dagger", "\u2021"); + parser.defineEntityReplacementText("permil", "\u2030"); + parser.defineEntityReplacementText("lsaquo", "\u2039"); + parser.defineEntityReplacementText("rsaquo", "\u203a"); + parser.defineEntityReplacementText("euro", "\u20ac"); + // ---------------------------------------------------------------------- + // Symbol entities + // ---------------------------------------------------------------------- + parser.defineEntityReplacementText("fnof", "\u0192"); + parser.defineEntityReplacementText("Alpha", "\u0391"); + parser.defineEntityReplacementText("Beta", "\u0392"); + parser.defineEntityReplacementText("Gamma", "\u0393"); + parser.defineEntityReplacementText("Delta", "\u0394"); + parser.defineEntityReplacementText("Epsilon", "\u0395"); + parser.defineEntityReplacementText("Zeta", "\u0396"); + parser.defineEntityReplacementText("Eta", "\u0397"); + parser.defineEntityReplacementText("Theta", "\u0398"); + parser.defineEntityReplacementText("Iota", "\u0399"); + parser.defineEntityReplacementText("Kappa", "\u039a"); + parser.defineEntityReplacementText("Lambda", "\u039b"); + parser.defineEntityReplacementText("Mu", "\u039c"); + parser.defineEntityReplacementText("Nu", "\u039d"); + parser.defineEntityReplacementText("Xi", "\u039e"); + parser.defineEntityReplacementText("Omicron", "\u039f"); + parser.defineEntityReplacementText("Pi", "\u03a0"); + parser.defineEntityReplacementText("Rho", "\u03a1"); + parser.defineEntityReplacementText("Sigma", "\u03a3"); + parser.defineEntityReplacementText("Tau", "\u03a4"); + parser.defineEntityReplacementText("Upsilon", "\u03a5"); + parser.defineEntityReplacementText("Phi", "\u03a6"); + parser.defineEntityReplacementText("Chi", "\u03a7"); + parser.defineEntityReplacementText("Psi", "\u03a8"); + parser.defineEntityReplacementText("Omega", "\u03a9"); + parser.defineEntityReplacementText("alpha", "\u03b1"); + parser.defineEntityReplacementText("beta", "\u03b2"); + parser.defineEntityReplacementText("gamma", "\u03b3"); + parser.defineEntityReplacementText("delta", "\u03b4"); + parser.defineEntityReplacementText("epsilon", "\u03b5"); + parser.defineEntityReplacementText("zeta", "\u03b6"); + parser.defineEntityReplacementText("eta", "\u03b7"); + parser.defineEntityReplacementText("theta", "\u03b8"); + parser.defineEntityReplacementText("iota", "\u03b9"); + parser.defineEntityReplacementText("kappa", "\u03ba"); + parser.defineEntityReplacementText("lambda", "\u03bb"); + parser.defineEntityReplacementText("mu", "\u03bc"); + parser.defineEntityReplacementText("nu", "\u03bd"); + parser.defineEntityReplacementText("xi", "\u03be"); + parser.defineEntityReplacementText("omicron", "\u03bf"); + parser.defineEntityReplacementText("pi", "\u03c0"); + parser.defineEntityReplacementText("rho", "\u03c1"); + parser.defineEntityReplacementText("sigmaf", "\u03c2"); + parser.defineEntityReplacementText("sigma", "\u03c3"); + parser.defineEntityReplacementText("tau", "\u03c4"); + parser.defineEntityReplacementText("upsilon", "\u03c5"); + parser.defineEntityReplacementText("phi", "\u03c6"); + parser.defineEntityReplacementText("chi", "\u03c7"); + parser.defineEntityReplacementText("psi", "\u03c8"); + parser.defineEntityReplacementText("omega", "\u03c9"); + parser.defineEntityReplacementText("thetasym", "\u03d1"); + parser.defineEntityReplacementText("upsih", "\u03d2"); + parser.defineEntityReplacementText("piv", "\u03d6"); + parser.defineEntityReplacementText("bull", "\u2022"); + parser.defineEntityReplacementText("hellip", "\u2026"); + parser.defineEntityReplacementText("prime", "\u2032"); + parser.defineEntityReplacementText("Prime", "\u2033"); + parser.defineEntityReplacementText("oline", "\u203e"); + parser.defineEntityReplacementText("frasl", "\u2044"); + parser.defineEntityReplacementText("weierp", "\u2118"); + parser.defineEntityReplacementText("image", "\u2111"); + parser.defineEntityReplacementText("real", "\u211c"); + parser.defineEntityReplacementText("trade", "\u2122"); + parser.defineEntityReplacementText("alefsym", "\u2135"); + parser.defineEntityReplacementText("larr", "\u2190"); + parser.defineEntityReplacementText("uarr", "\u2191"); + parser.defineEntityReplacementText("rarr", "\u2192"); + parser.defineEntityReplacementText("darr", "\u2193"); + parser.defineEntityReplacementText("harr", "\u2194"); + parser.defineEntityReplacementText("crarr", "\u21b5"); + parser.defineEntityReplacementText("lArr", "\u21d0"); + parser.defineEntityReplacementText("uArr", "\u21d1"); + parser.defineEntityReplacementText("rArr", "\u21d2"); + parser.defineEntityReplacementText("dArr", "\u21d3"); + parser.defineEntityReplacementText("hArr", "\u21d4"); + parser.defineEntityReplacementText("forall", "\u2200"); + parser.defineEntityReplacementText("part", "\u2202"); + parser.defineEntityReplacementText("exist", "\u2203"); + parser.defineEntityReplacementText("empty", "\u2205"); + parser.defineEntityReplacementText("nabla", "\u2207"); + parser.defineEntityReplacementText("isin", "\u2208"); + parser.defineEntityReplacementText("notin", "\u2209"); + parser.defineEntityReplacementText("ni", "\u220b"); + parser.defineEntityReplacementText("prod", "\u220f"); + parser.defineEntityReplacementText("sum", "\u2211"); + parser.defineEntityReplacementText("minus", "\u2212"); + parser.defineEntityReplacementText("lowast", "\u2217"); + parser.defineEntityReplacementText("radic", "\u221a"); + parser.defineEntityReplacementText("prop", "\u221d"); + parser.defineEntityReplacementText("infin", "\u221e"); + parser.defineEntityReplacementText("ang", "\u2220"); + parser.defineEntityReplacementText("and", "\u2227"); + parser.defineEntityReplacementText("or", "\u2228"); + parser.defineEntityReplacementText("cap", "\u2229"); + parser.defineEntityReplacementText("cup", "\u222a"); + parser.defineEntityReplacementText("int", "\u222b"); + parser.defineEntityReplacementText("there4", "\u2234"); + parser.defineEntityReplacementText("sim", "\u223c"); + parser.defineEntityReplacementText("cong", "\u2245"); + parser.defineEntityReplacementText("asymp", "\u2248"); + parser.defineEntityReplacementText("ne", "\u2260"); + parser.defineEntityReplacementText("equiv", "\u2261"); + parser.defineEntityReplacementText("le", "\u2264"); + parser.defineEntityReplacementText("ge", "\u2265"); + parser.defineEntityReplacementText("sub", "\u2282"); + parser.defineEntityReplacementText("sup", "\u2283"); + parser.defineEntityReplacementText("nsub", "\u2284"); + parser.defineEntityReplacementText("sube", "\u2286"); + parser.defineEntityReplacementText("supe", "\u2287"); + parser.defineEntityReplacementText("oplus", "\u2295"); + parser.defineEntityReplacementText("otimes", "\u2297"); + parser.defineEntityReplacementText("perp", "\u22a5"); + parser.defineEntityReplacementText("sdot", "\u22c5"); + parser.defineEntityReplacementText("lceil", "\u2308"); + parser.defineEntityReplacementText("rceil", "\u2309"); + parser.defineEntityReplacementText("lfloor", "\u230a"); + parser.defineEntityReplacementText("rfloor", "\u230b"); + parser.defineEntityReplacementText("lang", "\u2329"); + parser.defineEntityReplacementText("rang", "\u232a"); + parser.defineEntityReplacementText("loz", "\u25ca"); + parser.defineEntityReplacementText("spades", "\u2660"); + parser.defineEntityReplacementText("clubs", "\u2663"); + parser.defineEntityReplacementText("hearts", "\u2665"); + parser.defineEntityReplacementText("diams", "\u2666"); + } + + /** + * + * @return all the {@link Xpp3Reader} registred via a {@link ServiceLoader} + * on the contract {@link Xpp3Reader}. + * + */ + protected static Map<Class<?>, Xpp3Reader> getReaders() { + if (readers == null) { + readers = new HashMap<Class<?>, Xpp3Reader>(); + ServiceLoader<Xpp3Reader> load = ServiceLoader.load(Xpp3Reader.class); + for (Xpp3Reader r : load) { + readers.put(r.getType(), r); + } + } + return readers; + } +} Property changes on: trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Helper.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Added: trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Reader.java =================================================================== --- trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Reader.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Reader.java 2009-09-07 22:54:20 UTC (rev 569) @@ -0,0 +1,89 @@ +package org.nuiton.io.xpp3; + +import java.io.IOException; +import java.io.Reader; +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +/** + * A simple contract to mark all xpp readers. + * + * a such reader is associated to a {@link #getType()}. + * + * The implementations of such readers must be register in a file + * <pre> + * META-INF/services.org.nuiton.io.xpp3.Xpp3Reader + * </pre> + * + * to make possible auto-discovering of availables reader at runtime. + * + * See {@link Xpp3Helper#getReader(java.lang.Class)}. + * + * + * @author chemit + * @since 1.0.3 + */ +public interface Xpp3Reader { + + /** + * + * @return the type of main object to read + */ + Class<?> getType(); + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader + * @throws IOException + * @throws XmlPullParserException + * @return Settings + */ + Object read(Reader reader) throws IOException, XmlPullParserException; + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader + * @param strict + * @throws IOException + * @throws XmlPullParserException + * @return Settings + */ + Object read(Reader reader, boolean strict) throws IOException, XmlPullParserException; + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader + * @throws IOException + * @throws XmlPullParserException + * @return Settings + */ + Object[] readArray(Reader reader) throws IOException, XmlPullParserException; + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader + * @param strict + * @throws IOException + * @throws XmlPullParserException + * @return Settings + */ + Object[] readArray(Reader reader, boolean strict) throws IOException, XmlPullParserException; + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + boolean isAddDefaultEntities(); + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities + */ + void setAddDefaultEntities(boolean addDefaultEntities); +} Property changes on: trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Reader.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL