r841 - in trunk: . src/main/java/org/nuiton/io/xpp3 src/test/java/org/nuiton/io/xpp3 src/test/resources/org/nuiton/io/xpp3
Author: tchemit Date: 2012-03-25 16:23:27 +0200 (Sun, 25 Mar 2012) New Revision: 841 Url: http://nuiton.org/repositories/revision/maven-helper-plugin/841 Log: fixes #2031 (improve the xpp3 reader api) Added: trunk/src/main/java/org/nuiton/io/xpp3/AttributeValueToProperty.java trunk/src/main/java/org/nuiton/io/xpp3/TagContentToProperty.java trunk/src/main/java/org/nuiton/io/xpp3/TagTextContentToProperty.java trunk/src/test/java/org/nuiton/io/xpp3/CountryRef.java trunk/src/test/java/org/nuiton/io/xpp3/CountryRefXpp3Reader.java Modified: trunk/pom.xml trunk/src/main/java/org/nuiton/io/xpp3/AbstractXpp3Reader.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 trunk/src/test/java/org/nuiton/io/xpp3/Identity.java trunk/src/test/java/org/nuiton/io/xpp3/IdentityXpp3Reader.java trunk/src/test/java/org/nuiton/io/xpp3/Xpp3ReaderTest.java trunk/src/test/resources/org/nuiton/io/xpp3/identities.xml trunk/src/test/resources/org/nuiton/io/xpp3/identities2.xml trunk/src/test/resources/org/nuiton/io/xpp3/identity.xml Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2012-02-29 12:55:42 UTC (rev 840) +++ trunk/pom.xml 2012-03-25 14:23:27 UTC (rev 841) @@ -34,7 +34,7 @@ <parent> <groupId>org.nuiton</groupId> <artifactId>mavenpom4redmineAndCentral</artifactId> - <version>3.1.1</version> + <version>3.2</version> </parent> <artifactId>helper-maven-plugin</artifactId> @@ -46,6 +46,11 @@ <!-- compile dependencies --> <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + + <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </dependency> Modified: trunk/src/main/java/org/nuiton/io/xpp3/AbstractXpp3Reader.java =================================================================== --- trunk/src/main/java/org/nuiton/io/xpp3/AbstractXpp3Reader.java 2012-02-29 12:55:42 UTC (rev 840) +++ trunk/src/main/java/org/nuiton/io/xpp3/AbstractXpp3Reader.java 2012-03-25 14:23:27 UTC (rev 841) @@ -25,6 +25,7 @@ package org.nuiton.io.xpp3; +import com.google.common.collect.Sets; import org.codehaus.plexus.util.xml.pull.MXParser; import org.codehaus.plexus.util.xml.pull.XmlPullParser; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; @@ -33,8 +34,13 @@ import java.io.IOException; import java.io.Reader; import java.lang.reflect.Array; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; /** * An abstract xpp3Reader based on {@link PropertyMapper} to set properties of @@ -54,8 +60,8 @@ * <p/> * If you want to do something more complex, override these methods. * + * @param <O> the type of object to be build by the reader * @author tchemit <chemit@codelutin.com> - * @param <O> the type of object to be build by the reader * @see PropertyMapper * @see Xpp3Reader * @since 1.0.0 @@ -249,6 +255,34 @@ } /** + * Obtain all mappers for a given type. + * <p/> + * In the result, the keys are now the tag-name of attribute-name. + * <p/> + * Example : + * <pre> + * my-tag + * my-attribute + * </pre> + * + * @param srcType the target type of the searched mappers + * @param tagName the tag target of the searched mappers + * @return the dictionnary of mappers for the given type. + */ + public Map<String, PropertyMapper> getMappers(Class<?> srcType, String tagName) { + Map<String, PropertyMapper> result = + new TreeMap<String, PropertyMapper>(); + String prefix = srcType.getName() + "#" + tagName + "#"; + for (Entry<String, PropertyMapper> e : allMappers.entrySet()) { + if (e.getKey().startsWith(prefix)) { + + result.put(((AttributeValueToProperty) e.getValue()).getAttributeName(), e.getValue()); + } + } + return result; + } + + /** * Parse the xml stream from the given parser and a build the associated * object. * <p/> @@ -279,17 +313,17 @@ * @throws IOException if any io pb * @throws XmlPullParserException if any parsing pb */ - protected <T> T read(String rootTagName, - Class<T> type, - XmlPullParser parser, - boolean strict) + public <T> T read(String rootTagName, + Class<T> type, + XmlPullParser parser, + boolean strict) throws XmlPullParserException, IOException { // search open tag rootTagName gotoNextOpenTag(rootTagName, parser); // can init result - T result = null; + T result; try { result = type.newInstance(); } catch (Exception ex) { @@ -303,6 +337,20 @@ Map<String, PropertyMapper> mappers = getMappers(type); Set<String> parsed = new HashSet<String>(); + + // deal with all attributes + { + Set<String> attributeParsed = Sets.newHashSet(); + Map<String, PropertyMapper> attributeMappers = getMappers(type, rootTagName); + int attributeCount = parser.getAttributeCount(); + for (int i = 0; i < attributeCount; i++) { + String attributeName = parser.getAttributeName(i); + PropertyMapper mapper = attributeMappers.get(attributeName); + if (mapper != null) { + mapper.setProperty(result, parser, attributeParsed, strict); + } + } + } try { // go to next tag int eventType = parser.next(); @@ -312,7 +360,6 @@ checkNotEndOfXml(parser, rootTagName); if (eventType == XmlPullParser.START_TAG) { -// System.out.println("reading tag " + parser.getName()); PropertyMapper mapper = mappers.get(parser.getName()); if (mapper != null) { mapper.setProperty(result, parser, parsed, strict); @@ -321,6 +368,20 @@ "Unrecognised tag: '" + parser.getName() + "'", parser, null); } + + // deal with all attributes + { + Set<String> attributeParsed = Sets.newHashSet(); + Map<String, PropertyMapper> attributeMappers = getMappers(type, rootTagName); + int attributeCount = parser.getAttributeCount(); + for (int i = 0; i < attributeCount; i++) { + String attributeName = parser.getAttributeName(i); + PropertyMapper attributeMapper = attributeMappers.get(attributeName); + if (attributeMapper != null) { + attributeMapper.setProperty(result, parser, attributeParsed, strict); + } + } + } } else if (eventType == XmlPullParser.END_TAG) { if (parser.getName().equals(rootTagName)) { // have reach the end of the object @@ -376,11 +437,11 @@ * @throws IOException if any io pb * @throws XmlPullParserException if any parsing pb */ - protected <T> T[] readArray(String parentRootTagName, - String rootTagName, - Class<T> type, - XmlPullParser parser, - boolean strict) + public <T> T[] readArray(String parentRootTagName, + String rootTagName, + Class<T> type, + XmlPullParser parser, + boolean strict) throws XmlPullParserException, IOException { // search open tag parentRootTagName @@ -501,4 +562,57 @@ parser.getName()); } } + + protected void addTagTextContentMappers(DataConverter type, + boolean onlyOne, + String... tagNames) throws IntrospectionException { + TagTextContentToProperty.addMapper( + getType(), + type, + onlyOne, + allMappers, + tagNames + ); + } + + protected void addAttributeValueMappers(DataConverter type, + boolean onlyOne, + String... attributeNames) throws IntrospectionException { + AttributeValueToProperty.addMapper( + getType(), + type, + onlyOne, + allMappers, + getRootTagName(), + attributeNames + ); + } + + protected <O> void addTagContentMapper(Class<O> type, + boolean onlyOne, + Xpp3Reader<O> reader) throws IntrospectionException { + TagContentToProperty.addMapper( + getType(), + type, + onlyOne, + allMappers, + reader.getRootTagName(), + reader, + false + ); + } + + protected <O> void addTagContentsMapper(Class<O> type, + boolean onlyOne, + Xpp3Reader<O> reader) throws IntrospectionException { + TagContentToProperty.addMapper( + getType(), + type, + onlyOne, + allMappers, + reader.getArrayRootTagName(), + reader, + true + ); + } } Added: trunk/src/main/java/org/nuiton/io/xpp3/AttributeValueToProperty.java =================================================================== --- trunk/src/main/java/org/nuiton/io/xpp3/AttributeValueToProperty.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/xpp3/AttributeValueToProperty.java 2012-03-25 14:23:27 UTC (rev 841) @@ -0,0 +1,109 @@ +/* + * #%L + * Maven helper plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.io.xpp3; + +import org.codehaus.plexus.util.xml.pull.XmlPullParser; + +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; +import java.util.Map; + +/** + * Property mapper from a attribute content. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.5 + */ +public class AttributeValueToProperty extends PropertyMapper { + + protected final String attributeName; + + public AttributeValueToProperty(String tagName, + String attributeName, + String propertyName, + Class<?> containerType, + DataConverter type, + boolean onlyOne, + PropertyDescriptor descriptor) { + super(tagName, + propertyName, + containerType, + type, + onlyOne, + descriptor + ); + this.attributeName = attributeName; + } + + public String getAttributeName() { + return attributeName; + } + + protected String getXmlName() { + return attributeName; + } + + @Override + protected Object getDataFromXml(XmlPullParser parser) + throws Exception { + String t = parser.getAttributeValue("", attributeName); + Object result = null; + if (t != null && !(t = t.trim()).isEmpty()) { + result = type.convert(t); + } + return result; + } + + public static void addMapper(Class<?> containerType, + DataConverter type, + boolean onlyOne, + Map<String, PropertyMapper> allMappers, + String tagName, + String... attributeNames) throws IntrospectionException, + IllegalArgumentException { + + for (String attributeName : attributeNames) { + + // the tag-name is transformed to tagName + String propertyName = TAG_NAME_TRANSFORMER.apply(attributeName); + + PropertyDescriptor descriptor = getDescriptor(containerType, + propertyName); + + PropertyMapper mapper = new AttributeValueToProperty( + tagName, + attributeName, + propertyName, + containerType, + type, + onlyOne, + descriptor + ); + mapper.registerMapper(allMappers, containerType, tagName, attributeName); + } + + } + +} Property changes on: trunk/src/main/java/org/nuiton/io/xpp3/AttributeValueToProperty.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Modified: trunk/src/main/java/org/nuiton/io/xpp3/PropertyMapper.java =================================================================== --- trunk/src/main/java/org/nuiton/io/xpp3/PropertyMapper.java 2012-02-29 12:55:42 UTC (rev 840) +++ trunk/src/main/java/org/nuiton/io/xpp3/PropertyMapper.java 2012-03-25 14:23:27 UTC (rev 841) @@ -25,10 +25,17 @@ package org.nuiton.io.xpp3; +import com.google.common.base.Function; +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.codehaus.plexus.util.xml.pull.XmlPullParser; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.io.IOException; import java.text.ParseException; @@ -46,78 +53,16 @@ * <li>{@link AttributeValueToProperty} to map the text content of a tag * to a pojo's property</li> * </ul> - * <p/> - * There is two convinient factory methods in {@link Xpp3Helper} to add some new mappers into a given - * dictionnary of mappers. - * <ul> - * <li> {@link Xpp3Helper#addTagTextContentMappers(Class, DataConverter, boolean, Map, String...)}</li> - * <li>{@link Xpp3Helper#addAttributeValueMappers(Class, DataConverter, boolean, Map, String...)}</li> - * </ul> * * @author tchemit <chemit@codelutin.com> * @since 1.0.3 */ public abstract class PropertyMapper { - public static class TagTextContentToProperty extends PropertyMapper { + /** Logger. */ + private static final Log log = LogFactory.getLog(PropertyMapper.class); - public TagTextContentToProperty(String tagName, - String propertyName, - Class<?> containerType, - DataConverter type, - boolean onlyOne, - PropertyDescriptor descriptor) { - super(tagName, - propertyName, - containerType, - type, - onlyOne, - descriptor - ); - } - - @Override - protected Object getDataFromXml(XmlPullParser parser) - throws 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, - Class<?> containerType, - DataConverter type, - boolean onlyOne, - PropertyDescriptor descriptor) { - super(tagName, - propertyName, - containerType, - type, - onlyOne, - descriptor - ); - } - - @Override - protected Object getDataFromXml(XmlPullParser parser) - throws 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) */ + /** name of tag. */ protected final String name; /** the pojo's property to set */ @@ -152,6 +97,10 @@ this.descriptor = descriptor; } + protected String getXmlName() { + return name; + } + protected abstract Object getDataFromXml(XmlPullParser parser) throws Exception; @@ -159,15 +108,18 @@ XmlPullParser parser, Set<String> parsed, boolean strict) throws XmlPullParserException, IOException { - if (onlyOne && parsed.contains(name)) { + if (onlyOne && parsed.contains(getXmlName())) { throw new XmlPullParserException( "Duplicated tag: \'" + parser.getName() + "\'", parser, null ); } - parsed.add(name); + parsed.add(getXmlName()); try { + if (log.isInfoEnabled()) { + log.info(getXmlName()); + } Object r = getDataFromXml(parser); if (r != null) { descriptor.getWriteMethod().invoke(src, r); @@ -183,7 +135,7 @@ throw new XmlPullParserException(e.getMessage()); } } catch (Exception e) { - throw new XmlPullParserException(e.getMessage()); + throw new XmlPullParserException(e.getMessage(), parser, e); } } @@ -225,4 +177,72 @@ toStringBuilder.append("containerType", containerType); return toStringBuilder.toString(); } + + public static final Function<String, String> TAG_NAME_TRANSFORMER = new Function<String, String>() { + @Override + public String apply(String input) { + String[] parts = input.split("-"); + StringBuilder buffer = new StringBuilder(); + for (int i = 0, j = parts.length; i < j; i++) { + if (i == 0) { + buffer.append(parts[i]); + } else { + buffer.append(StringUtils.capitalize(parts[i])); + } + } + parts = buffer.toString().split("_"); + buffer = new StringBuilder(); + for (int i = 0, j = parts.length; i < j; i++) { + if (i == 0) { + buffer.append(parts[i]); + } else { + buffer.append(StringUtils.capitalize(parts[i])); + } + } + String result = buffer.toString(); + return result; + } + }; + + public static String getMapperForTag(Class<?> type) { + return type.getName() + "#"; + } + + public static String getMapperForAttribute(Class<?> type, String attributeName) { + return type.getName() + "#" + attributeName + "#"; + } + + protected static PropertyDescriptor getDescriptor(Class<?> containerType, + String propertyName) throws IntrospectionException { + BeanInfo beanInfo = Introspector.getBeanInfo(containerType); + PropertyDescriptor descriptor = null; + for (PropertyDescriptor propertyDescriptor : + beanInfo.getPropertyDescriptors()) { + if (propertyDescriptor.getName().equals(propertyName)) { + descriptor = propertyDescriptor; + break; + } + } + if (descriptor == null) { + throw new IllegalArgumentException( + "could not find a property descriptor for property " + + propertyName + " of " + containerType); + } + return descriptor; + } + + protected void registerMapper(Map<String, PropertyMapper> allMappers, + Class<?> containerType, + String tagName, + String attributeName) { + String key; + if (attributeName == null) { + // tag scope + key = getMapperForTag(containerType) + tagName; + } else { + // attribute scope + key = getMapperForAttribute(containerType, tagName) + attributeName; + } + allMappers.put(key, this); + } } Added: trunk/src/main/java/org/nuiton/io/xpp3/TagContentToProperty.java =================================================================== --- trunk/src/main/java/org/nuiton/io/xpp3/TagContentToProperty.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/xpp3/TagContentToProperty.java 2012-03-25 14:23:27 UTC (rev 841) @@ -0,0 +1,118 @@ +/* + * #%L + * Maven helper plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.io.xpp3; + +import org.codehaus.plexus.util.xml.pull.XmlPullParser; + +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; +import java.util.Map; + +/** + * Property mapper from a tag content to an object. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.5 + */ +public class TagContentToProperty<O> extends PropertyMapper { + + private final Xpp3Reader<O> reader; + + private final Class<O> datatype; + + private final boolean multiple; + + public TagContentToProperty(String tagName, + String propertyName, + Class<?> containerType, + Class<O> type, + boolean onlyOne, + PropertyDescriptor descriptor, + Xpp3Reader<O> reader, + boolean multiple) { + super(tagName, + propertyName, + containerType, + null, + onlyOne, + descriptor + ); + datatype = type; + this.reader = reader; + this.multiple = multiple; + } + + @Override + protected Object getDataFromXml(XmlPullParser parser) + throws Exception { + Object result; + if (multiple) { + result = reader.readArray( + reader.getArrayRootTagName(), + reader.getRootTagName(), + datatype, + parser, + true + ); + } else { + result = reader.read( + reader.getRootTagName(), + datatype, + parser, + true + ); + } + return result; + } + + public static <O> void addMapper(Class<?> containerType, + Class<O> type, + boolean onlyOne, + Map<String, PropertyMapper> allMappers, + String tagName, + Xpp3Reader<O> reader, + boolean multiple + ) throws IntrospectionException, + IllegalArgumentException { + + // the tag-name is transformed to tagName + String propertyName = TAG_NAME_TRANSFORMER.apply(tagName); + + PropertyDescriptor descriptor = getDescriptor(containerType, + propertyName); + + PropertyMapper mapper = new TagContentToProperty<O>( + tagName, + propertyName, + containerType, + type, + onlyOne, + descriptor, + reader, + multiple + ); + mapper.registerMapper(allMappers, containerType, tagName, null); + } +} Property changes on: trunk/src/main/java/org/nuiton/io/xpp3/TagContentToProperty.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: trunk/src/main/java/org/nuiton/io/xpp3/TagTextContentToProperty.java =================================================================== --- trunk/src/main/java/org/nuiton/io/xpp3/TagTextContentToProperty.java (rev 0) +++ trunk/src/main/java/org/nuiton/io/xpp3/TagTextContentToProperty.java 2012-03-25 14:23:27 UTC (rev 841) @@ -0,0 +1,92 @@ +/* + * #%L + * Maven helper plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.io.xpp3; + +import org.codehaus.plexus.util.xml.pull.XmlPullParser; + +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; +import java.util.Map; + +/** + * Property mapp from a tag text content. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.5 + */ +public class TagTextContentToProperty extends PropertyMapper { + + public TagTextContentToProperty(String tagName, + String propertyName, + Class<?> containerType, + DataConverter type, + boolean onlyOne, + PropertyDescriptor descriptor) { + super(tagName, + propertyName, + containerType, + type, + onlyOne, + descriptor + ); + } + + @Override + protected Object getDataFromXml(XmlPullParser parser) + throws Exception { + String t = parser.nextText(); + Object result = null; + if (t != null && !(t = t.trim()).isEmpty()) { + result = type.convert(t); + } + return result; + } + + public static void addMapper(Class<?> containerType, + DataConverter type, + boolean onlyOne, + Map<String, PropertyMapper> allMappers, + String... tagNames) throws IntrospectionException { + for (String tagName : tagNames) { + + // the tag-name is transformed to tagName + String propertyName = TAG_NAME_TRANSFORMER.apply(tagName); + + PropertyDescriptor descriptor = getDescriptor(containerType, + propertyName); + + + PropertyMapper mapper = new TagTextContentToProperty( + tagName, + propertyName, + containerType, + type, + onlyOne, + descriptor + ); + mapper.registerMapper(allMappers, containerType, tagName, null); + } + } +} Property changes on: trunk/src/main/java/org/nuiton/io/xpp3/TagTextContentToProperty.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Modified: trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Helper.java =================================================================== --- trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Helper.java 2012-02-29 12:55:42 UTC (rev 840) +++ trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Helper.java 2012-03-25 14:23:27 UTC (rev 841) @@ -25,25 +25,16 @@ package org.nuiton.io.xpp3; -import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.xml.pull.XmlPullParser; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; -import org.nuiton.io.xpp3.PropertyMapper.AttributeValueToProperty; -import org.nuiton.io.xpp3.PropertyMapper.TagTextContentToProperty; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -60,6 +51,7 @@ * @since 1.0.3 */ public class Xpp3Helper { + /** Logger */ private static final Log log = LogFactory.getLog(Xpp3Helper.class); @@ -194,7 +186,7 @@ /** * Clean all the registred readers. * <p/> - * To reload them, just call a {@link #getReader(java.lang.Class)}. + * To reload them, just call a {@link #getReader(Class)}. */ public static void clearReaders() { if (readers != null) { @@ -477,111 +469,6 @@ parser.defineEntityReplacementText("diams", "\u2666"); } - public static void addTagTextContentMappers( - Class<?> containerType, - DataConverter type, - boolean onlyOne, - Map<String, PropertyMapper> allMappers, - String... tagNames) throws IntrospectionException { - try { - addMappers(TagTextContentToProperty.class, - containerType, - type, - onlyOne, - allMappers, - tagNames - ); - } catch (Exception ex) { - throw new RuntimeException( - "could not addMappers for reason : " + ex.getMessage(), ex); - } - } - - public static void addAttributeValueMappers( - Class<?> containerType, - DataConverter type, - boolean onlyOne, - Map<String, PropertyMapper> allMappers, - String... tagNames) throws IntrospectionException { - try { - addMappers(AttributeValueToProperty.class, - containerType, - type, - onlyOne, - allMappers, - tagNames - ); - } catch (Exception ex) { - throw new RuntimeException( - "could not addMappers for reason : " + ex.getMessage(), ex); - } - } - - protected static void addMappers( - Class<? extends PropertyMapper> mapperClass, - Class<?> containerType, - DataConverter type, - boolean onlyOne, - Map<String, PropertyMapper> allMappers, - String... tagNames) - throws IntrospectionException, - NoSuchMethodException, - InstantiationException, - IllegalAccessException, - IllegalArgumentException, - InvocationTargetException { - for (String tagName : tagNames) { - - // the tag-name is transformed to tagName - String[] parts = tagName.split("-"); - StringBuilder buffer = new StringBuilder(); - for (int i = 0, j = parts.length; i < j; i++) { - if (i == 0) { - buffer.append(parts[i]); - } else { - buffer.append(StringUtils.capitalize(parts[i])); - } - } - String propertyName = buffer.toString(); - BeanInfo beanInfo = Introspector.getBeanInfo(containerType); - PropertyDescriptor descriptor = null; - for (PropertyDescriptor propertyDescriptor : - beanInfo.getPropertyDescriptors()) { - if (propertyDescriptor.getName().equals(propertyName)) { - descriptor = propertyDescriptor; - break; - } - } - if (descriptor == null) { - throw new IllegalArgumentException( - "could not find a property descriptor for property " + - propertyName + " of " + containerType); - } - Constructor<? extends PropertyMapper> constructor = - mapperClass.getConstructor( - String.class, - String.class, - Class.class, - DataConverter.class, - boolean.class, - PropertyDescriptor.class - ); - - PropertyMapper mapper = - constructor.newInstance( - tagName, - propertyName, - containerType, - type, - onlyOne, - descriptor - ); -// System.out.println("adding a mapper " + mapper); - - allMappers.put(containerType.getName() + "#" + tagName, mapper); - } - } - /** * Load (if {@link #readers} is {@code null} the readers via a * {@link ServiceLoader} of contract {@link Xpp3Reader} and returns Modified: trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Reader.java =================================================================== --- trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Reader.java 2012-02-29 12:55:42 UTC (rev 840) +++ trunk/src/main/java/org/nuiton/io/xpp3/Xpp3Reader.java 2012-03-25 14:23:27 UTC (rev 841) @@ -25,6 +25,7 @@ package org.nuiton.io.xpp3; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import java.io.IOException; @@ -178,4 +179,17 @@ * @param addDefaultEntities the new value. */ void setAddDefaultEntities(boolean addDefaultEntities); + + <T> T[] readArray(String parentRootTagName, + String rootTagName, + Class<T> type, + XmlPullParser parser, + boolean strict) + throws XmlPullParserException, IOException; + + <T> T read(String rootTagName, + Class<T> type, + XmlPullParser parser, + boolean strict) + throws XmlPullParserException, IOException; } Added: trunk/src/test/java/org/nuiton/io/xpp3/CountryRef.java =================================================================== --- trunk/src/test/java/org/nuiton/io/xpp3/CountryRef.java (rev 0) +++ trunk/src/test/java/org/nuiton/io/xpp3/CountryRef.java 2012-03-25 14:23:27 UTC (rev 841) @@ -0,0 +1,60 @@ +/* + * #%L + * Maven helper plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.io.xpp3; + +/** + * Define a country ref + * + * @author tchemit <chemit@codelutin.com> + * @since 1.5 + */ +public class CountryRef { + + protected int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CountryRef)) return false; + + CountryRef that = (CountryRef) o; + + return id == that.id; + + } + + @Override + public int hashCode() { + return id; + } +} Property changes on: trunk/src/test/java/org/nuiton/io/xpp3/CountryRef.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Added: trunk/src/test/java/org/nuiton/io/xpp3/CountryRefXpp3Reader.java =================================================================== --- trunk/src/test/java/org/nuiton/io/xpp3/CountryRefXpp3Reader.java (rev 0) +++ trunk/src/test/java/org/nuiton/io/xpp3/CountryRefXpp3Reader.java 2012-03-25 14:23:27 UTC (rev 841) @@ -0,0 +1,51 @@ +/* + * #%L + * Maven helper plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.io.xpp3; + +import java.beans.IntrospectionException; + +/** + * To read {@link CountryRef}. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.5 + */ +public class CountryRefXpp3Reader extends AbstractXpp3Reader<CountryRef> { + + public CountryRefXpp3Reader() { + this("countryRefs", "country"); + } + + public CountryRefXpp3Reader(String root, String tag) { + super(CountryRef.class, root, tag); + } + + @Override + protected void initMappers() throws IntrospectionException { + + addAttributeValueMappers(DefaultDataConverter.Integer, true, + "id"); + } +} \ No newline at end of file Property changes on: trunk/src/test/java/org/nuiton/io/xpp3/CountryRefXpp3Reader.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Modified: trunk/src/test/java/org/nuiton/io/xpp3/Identity.java =================================================================== --- trunk/src/test/java/org/nuiton/io/xpp3/Identity.java 2012-02-29 12:55:42 UTC (rev 840) +++ trunk/src/test/java/org/nuiton/io/xpp3/Identity.java 2012-03-25 14:23:27 UTC (rev 841) @@ -44,7 +44,10 @@ protected int age = 51; + protected int id; + protected CountryRef country; + PropertyChangeSupport p; public Identity() { @@ -67,6 +70,9 @@ p.removePropertyChangeListener(propertyName, listener); } + public int getId() { + return id; + } public String getFirstName() { return firstName; @@ -84,6 +90,17 @@ return age; } + public CountryRef getCountry() { + return country; + } + + public void setId(int id) { + int oldId = this.id; + this.id = id; + p.firePropertyChange("id", oldId, firstName); + + } + public void setFirstName(String firstName) { String oldFirstName = this.firstName; this.firstName = firstName; @@ -107,4 +124,8 @@ this.age = age; p.firePropertyChange("age", oldAge, age); } + + public void setCountry(CountryRef country) { + this.country = country; + } } Modified: trunk/src/test/java/org/nuiton/io/xpp3/IdentityXpp3Reader.java =================================================================== --- trunk/src/test/java/org/nuiton/io/xpp3/IdentityXpp3Reader.java 2012-02-29 12:55:42 UTC (rev 840) +++ trunk/src/test/java/org/nuiton/io/xpp3/IdentityXpp3Reader.java 2012-03-25 14:23:27 UTC (rev 841) @@ -33,7 +33,7 @@ * Time: 20:37:56 */ public class IdentityXpp3Reader extends AbstractXpp3Reader<Identity> { - + public IdentityXpp3Reader() { this("identities"); } @@ -45,13 +45,20 @@ @Override protected void initMappers() throws IntrospectionException { - org.nuiton.io.xpp3.Xpp3Helper.addTagTextContentMappers(Identity.class, DefaultDataConverter.Text, true, allMappers, - "firstName", - "lastName", - "email"); + addAttributeValueMappers(DefaultDataConverter.Integer, true, + "id"); - org.nuiton.io.xpp3.Xpp3Helper.addTagTextContentMappers(Identity.class, DefaultDataConverter.Integer, true, allMappers, - "age"); + addTagTextContentMappers(DefaultDataConverter.Text, true, + "firstName", + "lastName", + "email"); + addTagTextContentMappers(DefaultDataConverter.Integer, true, + "age"); + + addTagContentMapper(CountryRef.class, true, + new CountryRefXpp3Reader(null, "country")); + } + } Modified: trunk/src/test/java/org/nuiton/io/xpp3/Xpp3ReaderTest.java =================================================================== --- trunk/src/test/java/org/nuiton/io/xpp3/Xpp3ReaderTest.java 2012-02-29 12:55:42 UTC (rev 840) +++ trunk/src/test/java/org/nuiton/io/xpp3/Xpp3ReaderTest.java 2012-03-25 14:23:27 UTC (rev 841) @@ -44,7 +44,6 @@ */ public class Xpp3ReaderTest { - protected static File dir; protected Xpp3Reader<Identity> r = new IdentityXpp3Reader("identities"); @@ -75,10 +74,14 @@ } Assert.assertNotNull(result); Identity expected = new Identity(); + expected.setId(1); expected.setFirstName("first name"); expected.setLastName("last name"); expected.setEmail("noway@bishop.uk"); expected.setAge(29); + CountryRef country = new CountryRef(); + country.setId(1); + expected.setCountry(country); assertEqualsIdentity(result, expected); } @@ -156,16 +159,21 @@ Assert.assertEquals(expected.getLastName(), result.getLastName()); Assert.assertEquals(expected.getEmail(), result.getEmail()); Assert.assertEquals(expected.getAge(), result.getAge()); + Assert.assertEquals(expected.getCountry(), result.getCountry()); } protected static void assertEqualsSimpleIdentity(Identity result) { Assert.assertNotNull(result); Identity expected = new Identity(); + expected.setId(1); expected.setFirstName("first name"); expected.setLastName("last name"); expected.setEmail("noway@bishop.uk"); expected.setAge(29); + CountryRef country = new CountryRef(); + country.setId(1); + expected.setCountry(country); assertEqualsIdentity(result, expected); } @@ -174,18 +182,26 @@ Assert.assertNotNull(result); Assert.assertEquals(2, result.length); Identity expected = new Identity(); + expected.setId(1); expected.setFirstName("first name"); expected.setLastName("last name"); expected.setEmail("noway@bishop.uk"); expected.setAge(29); + CountryRef country = new CountryRef(); + country.setId(1); + expected.setCountry(country); assertEqualsIdentity(result[0], expected); expected = new Identity(); + expected.setId(2); expected.setFirstName("first name2"); expected.setLastName("last name2"); expected.setEmail("noway2@bishop.uk"); expected.setAge(31); + country = new CountryRef(); + country.setId(2); + expected.setCountry(country); assertEqualsIdentity(result[1], expected); } Modified: trunk/src/test/resources/org/nuiton/io/xpp3/identities.xml =================================================================== --- trunk/src/test/resources/org/nuiton/io/xpp3/identities.xml 2012-02-29 12:55:42 UTC (rev 840) +++ trunk/src/test/resources/org/nuiton/io/xpp3/identities.xml 2012-03-25 14:23:27 UTC (rev 841) @@ -23,16 +23,18 @@ #L% --> <identities> - <identity> - <firstName>first name</firstName> - <lastName>last name</lastName> - <email>noway@bishop.uk</email> - <age>29</age> - </identity> - <identity> - <firstName>first name2</firstName> - <lastName>last name2</lastName> - <email>noway2@bishop.uk</email> - <age>31</age> - </identity> + <identity id="1"> + <country id="1"/> + <firstName>first name</firstName> + <lastName>last name</lastName> + <email>noway@bishop.uk</email> + <age>29</age> + </identity> + <identity id="2"> + <country id="2"/> + <firstName>first name2</firstName> + <lastName>last name2</lastName> + <email>noway2@bishop.uk</email> + <age>31</age> + </identity> </identities> \ No newline at end of file Modified: trunk/src/test/resources/org/nuiton/io/xpp3/identities2.xml =================================================================== --- trunk/src/test/resources/org/nuiton/io/xpp3/identities2.xml 2012-02-29 12:55:42 UTC (rev 840) +++ trunk/src/test/resources/org/nuiton/io/xpp3/identities2.xml 2012-03-25 14:23:27 UTC (rev 841) @@ -23,16 +23,18 @@ #L% --> <identity> - <identity> - <firstName>first name</firstName> - <lastName>last name</lastName> - <email>noway@bishop.uk</email> - <age>29</age> - </identity> - <identity> - <firstName>first name2</firstName> - <lastName>last name2</lastName> - <email>noway2@bishop.uk</email> - <age>31</age> - </identity> + <identity id="1"> + <country id="1"/> + <firstName>first name</firstName> + <lastName>last name</lastName> + <email>noway@bishop.uk</email> + <age>29</age> + </identity> + <identity id="2"> + <country id="2"/> + <firstName>first name2</firstName> + <lastName>last name2</lastName> + <email>noway2@bishop.uk</email> + <age>31</age> + </identity> </identity> \ No newline at end of file Modified: trunk/src/test/resources/org/nuiton/io/xpp3/identity.xml =================================================================== --- trunk/src/test/resources/org/nuiton/io/xpp3/identity.xml 2012-02-29 12:55:42 UTC (rev 840) +++ trunk/src/test/resources/org/nuiton/io/xpp3/identity.xml 2012-03-25 14:23:27 UTC (rev 841) @@ -22,9 +22,10 @@ <http://www.gnu.org/licenses/lgpl-3.0.html>. #L% --> -<identity> - <firstName>first name</firstName> - <lastName>last name</lastName> - <email>noway@bishop.uk</email> - <age>29</age> +<identity id="1"> + <country id="1"/> + <firstName>first name</firstName> + <lastName>last name</lastName> + <email>noway@bishop.uk</email> + <age>29</age> </identity> \ No newline at end of file
participants (1)
-
tchemit@users.nuiton.org