[Practicalxml-commits] SF.net SVN: practicalxml:[173] branches/dev-1.1/src
Brought to you by:
kdgregory
From: Auto-Generated S. C. M. <pra...@li...> - 2009-10-27 18:43:11
|
Revision: 173 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=173&view=rev Author: kdgregory Date: 2009-10-27 18:43:03 +0000 (Tue, 27 Oct 2009) Log Message: ----------- Move all converter-managed attributes into their own namespace Replace use of xsi:type with practicalxml:type Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlConverter.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlOptions.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanConverter.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanOptions.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/package.html branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionStrings.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionUtils.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/JavaConversionUtils.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Json2XmlConverter.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/package.html branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractConversionTestCase.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/AbstractBeanConverterTestCase.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBean2XmlAppenders.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBean2XmlConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBeanConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestXml2BeanConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/internal/TestJavaConversionUtils.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestXml2JsonConverter.java Added Paths: ----------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/TypeUtils.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/internal/TestTypeUtils.java Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-10-27 18:43:03 UTC (rev 173) @@ -21,6 +21,7 @@ import net.sf.practicalxml.converter.ConversionException; import net.sf.practicalxml.converter.internal.ConversionStrings; import net.sf.practicalxml.converter.internal.ConversionUtils; +import net.sf.practicalxml.converter.internal.TypeUtils; /** @@ -44,9 +45,8 @@ * associated text, but no other children. * * @param name Name to be associated with the node. - * @param type Type to be associated with the node; may or may - * not be written to the output, depending on the - * appender's options. + * @param klass Java class for this node. May (depending on options) + * be stored in the <code>type</code> attribute. * @param value The node's value. May be <code>null</code>, in * which case the appender decides whether or not * to actually append the node. @@ -56,7 +56,7 @@ * super has done the work of appending the element. * @throws ConversionException if unable to append the node. */ - public Element appendValue(String name, String type, String value); + public Element appendValue(String name, Class<?> klass, String value); /** @@ -64,7 +64,7 @@ * elements have other elements as children, and may have a type, * but do not have an associated value. */ - public Element appendContainer(String name, String type); + public Element appendContainer(String name, Class<?> klass); } @@ -93,10 +93,10 @@ && !_options.contains(Bean2XmlOptions.NULL_AS_XSI_NIL); } - protected void setType(Element elem, String type) + protected void setType(Element elem, Class<?> klass) { - if (isOptionSet(Bean2XmlOptions.XSI_TYPE)) - ConversionUtils.setXsiType(elem, type); + if (isOptionSet(Bean2XmlOptions.USE_TYPE_ATTR)) + TypeUtils.setType(elem, klass); } protected void setValue(Element elem, String value) @@ -125,7 +125,7 @@ _parent = parent; } - public Element appendValue(String name, String type, String value) + public Element appendValue(String name, Class<?> klass, String value) { if (shouldSkip(value)) return null; @@ -133,7 +133,7 @@ try { Element child = DomUtil.appendChildInheritNamespace(_parent, name); - setType(child, type); + setType(child, klass); setValue(child, value); return child; } @@ -143,10 +143,10 @@ } } - public Element appendContainer(String name, String type) + public Element appendContainer(String name, Class<?> klass) { Element child = DomUtil.appendChildInheritNamespace(_parent, name); - setType(child, type); + setType(child, klass); return child; } } @@ -169,11 +169,14 @@ @Override - public Element appendValue(String name, String type, String value) + public Element appendValue(String name, Class<?> klass, String value) { - Element child = super.appendValue(name, type, value); - if ((child != null) && isOptionSet(Bean2XmlOptions.SEQUENCE_INDEXES)) - child.setAttribute(ConversionStrings.AT_ARRAY_INDEX, String.valueOf(_index++)); + Element child = super.appendValue(name, klass, value); + if ((child != null) && isOptionSet(Bean2XmlOptions.USE_INDEX_ATTR)) + ConversionUtils.setAttribute( + child, + ConversionStrings.AT_ARRAY_INDEX, + String.valueOf(_index++)); return child; } } @@ -194,18 +197,21 @@ @Override - public Element appendValue(String name, String type, String value) + public Element appendValue(String name, Class<?> klass, String value) { Element child = null; if (isOptionSet(Bean2XmlOptions.INTROSPECT_MAPS)) { - child = super.appendValue(name, type, value); + child = super.appendValue(name, klass, value); } else { - child = super.appendValue(ConversionStrings.EL_COLLECTION_ITEM, type, value); + child = super.appendValue(ConversionStrings.EL_COLLECTION_ITEM, klass, value); if (child != null) - child.setAttribute(ConversionStrings.AT_MAP_KEY, name); + ConversionUtils.setAttribute( + child, + ConversionStrings.AT_MAP_KEY, + name); } return child; } @@ -227,20 +233,20 @@ _elem = elem; } - public Element appendValue(String name, String type, String value) + public Element appendValue(String name, Class<?> klass, String value) { if (!shouldSkip(value)) { - setType(_elem, type); + setType(_elem, klass); setValue(_elem, value); } return _elem; } - public Element appendContainer(String name, String type) + public Element appendContainer(String name, Class<?> klass) { - setType(_elem, type); + setType(_elem, klass); return _elem; } } -} +} \ No newline at end of file Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlConverter.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlConverter.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlConverter.java 2009-10-27 18:43:03 UTC (rev 173) @@ -75,7 +75,7 @@ public Element convert(Object obj, String nsUri, String rootName) { Element root = DomUtil.newDocument(nsUri, rootName); - doXsiNamespaceHack(root); + doNamespaceHack(root); convert(obj, rootName, new DirectAppender(root, _options)); return root; } @@ -110,50 +110,49 @@ private boolean shouldUseXsdFormatting() { return _options.contains(Bean2XmlOptions.XSD_FORMAT) - || _options.contains(Bean2XmlOptions.XSI_TYPE); + || _options.contains(Bean2XmlOptions.USE_TYPE_ATTR); } /** - * Introduces the XML Schema Instance namespace into the DOM tree using a - * meaningless attribute. The Xerces serializer does not attempt to promote - * namespace definitions above the subtree in which they first appear, which - * means that the XSI definition could be repeated many times throughout the - * serialized tree, adding bulk to the serialized representation. + * Introduces namespaces at the root level, because the Xerces serializer + * does not attempt to promote namespace definitions above the element in + * which they first appear. This means that the same declaration may be + * repeated at multiple places throughout a tree. * <p> - * By putting "nil=false" at the root element, we will keep the serializer - * from inserting all these definitions. This has to happen <em>before</em> - * any actual conversion, in case some bozo passes <code>null</code> to - * the top-level conversion routine. - * <p> - * Note that we only do this if <code>xsi:nil</code> is enabled by itself. - * If <code>xsi:type</code> is enabled, the converter will attach that - * attribute to the root instead, thereby establishing the namespace context. + * Will only introduce namespaces appropriate to the options in effect + * (ie, if you don't enable <code>xsi:nil</code>, then there's no need + * to declare the XML Schema Instance namespace). */ - private void doXsiNamespaceHack(Element root) + private void doNamespaceHack(Element root) { - if (_options.contains(Bean2XmlOptions.NULL_AS_XSI_NIL) - && !_options.contains(Bean2XmlOptions.XSI_TYPE)) + if (_options.contains(Bean2XmlOptions.NULL_AS_XSI_NIL)) { ConversionUtils.setXsiNil(root, false); } + + // I think it's more clear to express the rules this way, rather than + // as an if-condition with nested sub-conditions + boolean addCnvNS = _options.contains(Bean2XmlOptions.USE_INDEX_ATTR); + addCnvNS |= !_options.contains(Bean2XmlOptions.INTROSPECT_MAPS); + addCnvNS &= _options.contains(Bean2XmlOptions.USE_TYPE_ATTR); + if (addCnvNS) + { + ConversionUtils.setAttribute(root, ConversionStrings.AT_DUMMY, ""); + } } private void convertAsNull(Class<?> klass, String name, Appender appender) { - appender.appendValue( - name, - JavaConversionUtils.java2XsiType(klass), - null); + appender.appendValue(name, klass, null); } private void convertAsPrimitive(Object obj, String name, Appender appender) { appender.appendValue( - name, - JavaConversionUtils.java2XsiType(obj), + name, obj.getClass(), JavaConversionUtils.stringify(obj, _useXsdFormatting)); } @@ -164,7 +163,7 @@ Appender childAppender = appender; if (!_options.contains(Bean2XmlOptions.SEQUENCE_AS_REPEATED_ELEMENTS)) { - Element parent = appender.appendContainer(name, JavaConversionUtils.java2XsiType(array)); + Element parent = appender.appendContainer(name, array.getClass()); childAppender = new IndexedAppender(parent, _options); } @@ -179,7 +178,7 @@ private void convertAsMap(Object obj, String name, Appender appender) { - Element parent = appender.appendContainer(name, JavaConversionUtils.java2XsiType(obj)); + Element parent = appender.appendContainer(name, obj.getClass()); Appender childAppender = new MapAppender(parent, _options); for (Map.Entry<?,?> entry : ((Map<?,?>)obj).entrySet()) { @@ -194,7 +193,7 @@ Appender childAppender = appender; if (!_options.contains(Bean2XmlOptions.SEQUENCE_AS_REPEATED_ELEMENTS)) { - Element parent = appender.appendContainer(name, JavaConversionUtils.java2XsiType(obj)); + Element parent = appender.appendContainer(name, obj.getClass()); childAppender = new IndexedAppender(parent, _options); } @@ -207,7 +206,7 @@ private void convertAsBean(Object bean, String name, Appender appender) { - Element parent = appender.appendContainer(name, JavaConversionUtils.java2XsiType(bean)); + Element parent = appender.appendContainer(name, bean.getClass()); Appender childAppender = new BasicAppender(parent, _options); Introspection ispec = _introspections.lookup(bean.getClass()); for (String propName : ispec.propertyNames()) Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlOptions.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlOptions.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlOptions.java 2009-10-27 18:43:03 UTC (rev 173) @@ -64,21 +64,29 @@ SEQUENCE_AS_REPEATED_ELEMENTS, /** + * Sequences (arrays, lists, sets) will name their elements according to + * the parent element, with any trailing "s" removed. For example, if the + * parent is named "products", each child will be named "product", rather + * than the default "data". If the parent is named "foo", each child will + * also be named "foo" (since there's no "s" to remove). + */ + SEQUENCE_NAMED_BY_PARENT, + + /** * Will add an <code>index</code> attribute to the child elements of * sequences (arrays, lists, sets); the value of this attribute is the * element's position in the sequence (numbered from 0). This index is * not terribly useful, so is no longer default behavior. */ - SEQUENCE_INDEXES, + USE_INDEX_ATTR, /** - * Sequences (arrays, lists, sets) will name their elements according to - * the parent element, with any trailing "s" removed. For example, if the - * parent is named "products", each child will be named "product", rather - * than the default "data". If the parent is named "foo", each child will - * also be named "foo" (since there's no "s" to remove). + * Will add a <code>type</code> attribute to each element; see package + * docs for more details. + * <p> + * <em>This option implies {@link #XSD_FORMAT}</em>. */ - SEQUENCE_NAMED_BY_PARENT, + USE_TYPE_ATTR, /** * Outputs values using formats defined by XML Schema, rather than Java's @@ -86,16 +94,5 @@ * flagged in the element, so sender and receiver will have to agree on * the format. */ - XSD_FORMAT, - - /** - * Will add an <code>xsi:type</code> attribute to each element. For values - * covered by the XML Schema simple types, this attribute's value will be - * "<code>xsd:TYPE</code>", where TYPE is the XSD type name. For complex - * types, this attribute's value will be "<code>java:TYPE</code>", where - * TYPE is the fully-qualified classname. - * <p> - * <em>This option implies {@link #XSD_FORMAT} for simple types</em>. - */ - XSI_TYPE + XSD_FORMAT } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanConverter.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanConverter.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanConverter.java 2009-10-27 18:43:03 UTC (rev 173) @@ -34,6 +34,7 @@ import net.sf.practicalxml.converter.internal.ConversionStrings; import net.sf.practicalxml.converter.internal.ConversionUtils; import net.sf.practicalxml.converter.internal.JavaConversionUtils; +import net.sf.practicalxml.converter.internal.TypeUtils; import net.sf.practicalxml.internal.StringUtils; import org.w3c.dom.Element; @@ -161,9 +162,7 @@ List<Element> children = DomUtil.getChildren(elem); for (Element child : children) { - Class<?> childClass = getClassFromXsiType(child); - if (childClass == null) - childClass = String.class; + Class<?> childClass = getCollectionElementClass(child); result.add(convertWithoutCast(child, childClass)); } return result; @@ -179,12 +178,10 @@ List<Element> children = DomUtil.getChildren(elem); for (Element child : children) { - String key = child.getAttribute(ConversionStrings.AT_MAP_KEY); + String key = ConversionUtils.getAttribute(child, ConversionStrings.AT_MAP_KEY); if (StringUtils.isEmpty(key)) key = DomUtil.getLocalName(child); - Class<?> childClass = getClassFromXsiType(child); - if (childClass == null) - childClass = String.class; + Class<?> childClass = getCollectionElementClass(child); result.put(key, convertWithoutCast(child, childClass)); } return result; @@ -227,47 +224,19 @@ } - /** - * Examines an element's <code>xsi:type</code> attribute, if any, and - * returns the Java class corresponding to it. Used when converting - * collection types, which don't have type information that can be - * introspected, and also to validate non-XSD types. - */ - private Class<?> getClassFromXsiType(Element elem) + private void validateXsiType(Element elem, Class<?> klass) { - String xsiType = ConversionUtils.getXsiType(elem); - if (xsiType == null) - return null; - - Class<?> klass = JavaConversionUtils.xsiType2JavaClass(xsiType); - if (klass != null) - return klass; - - throw new ConversionException( - "invalid Java type specification: " + xsiType, - elem); + if (_options.contains(Xml2BeanOptions.REQUIRE_TYPE)) + TypeUtils.validateType(elem, klass); } - private void validateXsiType(Element elem, Class<?> klass) + private Class<?> getCollectionElementClass(Element child) { - if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_TYPE)) - return; - - String xsiType = ConversionUtils.getXsiType(elem); - if (xsiType == null) - throw new ConversionException("missing xsi:type", elem); - - if (xsiType.equals(JavaConversionUtils.java2XsiType(klass))) - return; - - Class<?> xsiKlass = getClassFromXsiType(elem); - if (klass.isAssignableFrom(xsiKlass)) - return; - - throw new ConversionException( - "invalid xsi:type: \"" + xsiType + "\" for " + klass.getName(), - elem); + Class<?> childClass = TypeUtils.getType(child, false); + return (childClass != null) + ? childClass + : String.class; } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanOptions.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanOptions.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanOptions.java 2009-10-27 18:43:03 UTC (rev 173) @@ -49,19 +49,18 @@ */ IGNORE_MISSING_PROPERTIES, + /** + * If present, the converter requires a <code>type</code> attribute on + * each element, and will use that attribute to verify that the element + * can be converted to the desired type. + */ + REQUIRE_TYPE, + /** * If present, the converter requires an <code>xsi:nil</code> attribute * on any empty nodes, and will throw if it's not present. Default is to * treat empty nodes as <code>null</code>. */ - REQUIRE_XSI_NIL, - - /** - * If present, the converter requires an <code>xsi:type</code> attribute - * on each element, and will throw if it's not present. Default behavior - * uses the <code>xsi:type</code> value to choose between different setter - * methods, but otherwise ignores it. - */ - REQUIRE_XSI_TYPE + REQUIRE_XSI_NIL } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/package.html =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/package.html 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/package.html 2009-10-27 18:43:03 UTC (rev 173) @@ -10,22 +10,25 @@ Objects are processed recursively, and cycles are <em>not</em> detected (although this may change). <p> -XML may be generated with namespaces. However, namespaces are ignored when -converting to Java objects; the local names drive conversion. +On output, the caller may specify a namespace: all elements will have this +namespace. On input, namespaces are ignored: bean properties are identified +by element local names. The converter will use its own namespace for any +converter-specific attributes (eg, <code>type</code>); this namespace is +defined by {@link net.sf.practicalxml.converter.internal.ConversionStrings#NS_CONVERSION}). The converter will also apply attributes from the XML Schema Instance +namespace; all documentation refers to these attributes with an "xsi" prefix +(eg: <code>xsi:nil</code>). <p> -Each element may have an <code>xsi:type</code> attribute (where <code>xsi -</code> references to the XML Schema instance namespace). This attribute -is optional for both output and input; if used for output, it is merely -informational, but for input will be examined to validate that the XML is -appropriate for the desired object type. For primitive types, wrappers, -and strings, it takes the form "<code>xsd:TYPE</code>", where <code>TYPE -</code> is one of the simple types defined by XML schema. For other Java -types, it takes the form "<code>java:TYPE</code>", where <code>TYPE</code> -is the fully qualified Java classname. +The most important of the converter-specific attributes is <code>type</code>. +For primitive types, wrappers, and strings, it takes the form +"<code>xsd:TYPE</code>", where <code>TYPE</code> is one of the simple types +defined by XML schema. For other Java types, it takes the form +"<code>java:TYPE</code>", where <code>TYPE</code> is the fully qualified +Java classname. <p> -On input, the desired type is specified by the caller or by introspection -(except in the case of collection elements; see below). The <code>xsi:type -</code> value, if any, is ignored except for validation. +On input, the desired type is specified by the caller or by introspection. +The <code>type</code> attribute, if any, is used to validate whether the +element matches this desired type (except in the case of collection elements, +described below). <p> Additional conversion rules are as follows: @@ -75,8 +78,8 @@ output in iterator order. <td>The collection is processed as it if were an array (qv), with one (major) difference: since all collections inherently contain Objects, there is no - type information to drive conversion. If an <code>xsi:type</code> attribute - is present, it will be used to drive conversion. Otherwise, the element will + type information to drive conversion. If a <code>type</code> attribute is + present, it will be used to drive conversion. Otherwise, the element will be converted as a <code>String</code> (which will fail for complex types, because string conversion assumes a single text node). <p> @@ -107,10 +110,10 @@ Otherwise, it will use the element name. If your maps are being reduced to a single entry, look for a missing attribute. <p> - If an <code>xsi:type</code> attribute is present, it will be used - to drive conversion of the element. Otherwise, the element will be - converted as a <code>String</code> (which will fail for complex - types, because string conversion assumes a single text node). + If the <code>type</code> attribute is present, it will be used to drive + conversion of the element. Otherwise, the element will be converted as + a <code>String</code> (which will fail for complex types, because string + conversion assumes a single text node). <p> Where the caller specifies an interface as the conversion class, the converter will choose an appropriate implementation class: Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionStrings.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionStrings.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionStrings.java 2009-10-27 18:43:03 UTC (rev 173) @@ -23,38 +23,46 @@ public class ConversionStrings { /** + * Namespace for attributes defined by the converter. + */ + public final static String NS_CONVERSION = "http://practicalxml.sourceforge.net/Converter"; + + + /** + * Name of root element, where not specified by caller. + */ + public final static String EL_DEFAULT_ROOT = "data"; + + + /** * Element name used to hold unnamed items from collections and arrays. */ public final static String EL_COLLECTION_ITEM = "data"; /** - * Attribute used to hold the element index number for collections and arrays. + * A dummy attribute used to declare the conversion namespace at the root. */ - public final static String AT_ARRAY_INDEX = "index"; + public final static String AT_DUMMY = "ix"; /** - * Attribute used to hold the item key value for maps. + * Attribute used to hold the type of an element. Belongs to the + * {@link #NS_CONVERSION} namespace. */ - public final static String AT_MAP_KEY = "key"; + public final static String AT_TYPE = "type"; /** - * Prefix for <code>xsi:type</code> values for elements holding primitive - * values as defined by XML Schema. Note that we define a specific prefix - * that may or may not correspond to a namespace defined in the instance - * doc; we do not do namespace resolution on the value. Instance documents - * produced by tools other than <code>BeanConverter</code> must use the - * same prefix. + * Attribute used to hold the element index number for collections and + * arrays. Belongs to the {@link #NS_CONVERSION} namespace. */ - public final static String XSD_TYPE_PREFIX = "xsd:"; + public final static String AT_ARRAY_INDEX = "index"; /** - * Prefix for <code>xsi:type</code> values for elements holding Java - * objects as serialized by <code>BeanConverter</code>. Again, this is - * an explicit value, and does not correspond to any namespace. + * Attribute used to hold the item key value for maps. Belongs to the + * {@link #NS_CONVERSION} namespace. */ - public final static String JAVA_TYPE_PREFIX = "java:"; + public final static String AT_MAP_KEY = "key"; } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionUtils.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionUtils.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionUtils.java 2009-10-27 18:43:03 UTC (rev 173) @@ -18,7 +18,6 @@ import org.w3c.dom.Element; -import net.sf.practicalxml.internal.StringUtils; /** @@ -36,44 +35,40 @@ public class ConversionUtils { /** - * Sets the <code>xsi:nil</code> attribute to the passed value. + * Retrieves an arbitrary attribute within the "conversion" namespace. */ - public static void setXsiNil(Element elem, boolean isNil) + public static String getAttribute(Element elem, String name) { - String value = isNil ? "true" : "false"; - elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", value); + return elem.getAttributeNS(ConversionStrings.NS_CONVERSION, name); } /** - * Returns the value of the <code>xsi:nil</code> attribute on the passed - * element, <code>false</code> if the attribute is not set. + * Sets an arbitrary attribute within the "conversion" namespace. */ - public static boolean getXsiNil(Element elem) + public static void setAttribute(Element elem, String name, String value) { - String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"); - return attr.equals("true"); + elem.setAttributeNS(ConversionStrings.NS_CONVERSION, name, value); } /** - * Sets the <code>xsi:type</code> attribute to the passed value. + * Sets the <code>xsi:nil</code> attribute to the passed value. */ - public static void setXsiType(Element elem, String xsiType) + public static void setXsiNil(Element elem, boolean isNil) { - elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type", xsiType); + String value = isNil ? "true" : "false"; + elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", value); } /** - * Returns the value of the <code>xsi:type</code> attribute on the passed - * element, <code>null</code> if the attribute is not set. + * Returns the value of the <code>xsi:nil</code> attribute on the passed + * element, <code>false</code> if the attribute is not set. */ - public static String getXsiType(Element elem) + public static boolean getXsiNil(Element elem) { - String xsiType = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); - return StringUtils.isEmpty(xsiType) - ? null - : xsiType; + String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"); + return attr.equals("true"); } } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/JavaConversionUtils.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/JavaConversionUtils.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/JavaConversionUtils.java 2009-10-27 18:43:03 UTC (rev 173) @@ -23,83 +23,20 @@ import java.util.HashMap; import java.util.Map; + import net.sf.practicalxml.XmlUtil; import net.sf.practicalxml.converter.ConversionException; -import net.sf.practicalxml.internal.StringUtils; /** - * Static utility methods for conversion to/from Java. - * <p> - * Many of these methods deal with <code>xsi:type</code> attribute values - * ("<code>xsi</code>" being any prefix that refers to the XML Schema - * Instance namespace). The conversion library deals with two sets of values - * for this attribute: those beginning with "xsd:", and those beginning with - * "java:". These prefixes are literal values; we do not do any sort of - * namespace resolution. - * <p> - * In the case of "<code>xsd:</code>" values, the portion after the prefix - * corresponds to a subset of the built-in datatypes defined by - * <a href="http://www.w3.org/TR/xmlschema-2/#built-in-datatypes">XML Schema - * Part 2</a>. In the case of "<code>java:</code>" values, the portion after - * the prefix must be a fully-qualified Java classname (which need not be - * resolvable by the current JVM). + * Handles conversion of primitive Java types to and from a string value. In + * this usage, "primitive" indicates that the Java object has a simple string + * serialization; this includes, for example, <code>java.util.Date</code>. */ public class JavaConversionUtils { - /** - * Translation from <code>xsi:type</code> values to Java primitive - * (wrapper) classes. Note the lack of any prefix -- and that we - * don't support the full set of primitives defined for XML Schema. - */ - private static Map<String,Class<?>> _xsiType2Java - = new HashMap<String,Class<?>>(); - static - { - _xsiType2Java.put("string", String.class); - _xsiType2Java.put("boolean", Boolean.class); - _xsiType2Java.put("byte", Byte.class); - _xsiType2Java.put("short", Short.class); - _xsiType2Java.put("int", Integer.class); - _xsiType2Java.put("long", Long.class); - _xsiType2Java.put("decimal", BigDecimal.class); - _xsiType2Java.put("dateTime", Date.class); - } - /** - * Translation from Java primitive wrappers (and the associated non- - * wrapper "class") to an appropriate <code>xsi:type</code> value. - * Again, note the lack of prefix. - */ - private static Map<Class<?>,String> _java2XsiType - = new HashMap<Class<?>,String>(); - static - { - _java2XsiType.put(String.class, "string"); - _java2XsiType.put(Character.class, "string"); - _java2XsiType.put(Boolean.class, "boolean"); - _java2XsiType.put(Byte.class, "byte"); - _java2XsiType.put(Short.class, "short"); - _java2XsiType.put(Integer.class, "int"); - _java2XsiType.put(Long.class, "long"); - _java2XsiType.put(Float.class, "decimal"); - _java2XsiType.put(Double.class, "decimal"); - _java2XsiType.put(BigInteger.class, "decimal"); - _java2XsiType.put(BigDecimal.class, "decimal"); - _java2XsiType.put(Date.class, "dateTime"); - - _java2XsiType.put(Character.TYPE, "string"); - _java2XsiType.put(Boolean.TYPE, "boolean"); - _java2XsiType.put(Byte.TYPE, "byte"); - _java2XsiType.put(Short.TYPE, "short"); - _java2XsiType.put(Integer.TYPE, "int"); - _java2XsiType.put(Long.TYPE, "long"); - _java2XsiType.put(Float.TYPE, "decimal"); - _java2XsiType.put(Double.TYPE, "decimal"); - } - - private static Map<Class<?>,ConversionHandler<?>> _helpers = new HashMap<Class<?>,ConversionHandler<?>>(); static @@ -149,88 +86,11 @@ */ public static boolean isPrimitive(Class<?> klass) { - return _java2XsiType.containsKey(klass); + return _helpers.containsKey(klass); } /** - * Returns the <code>xsi:type</code> value for an arbitrary Java class, - * <code>null</code> if passed <code>null</code>. - */ - public static String java2XsiType(Class<?> klass) - { - if (klass == null) - return null; - - String type = _java2XsiType.get(klass); - return (type != null) - ? ConversionStrings.XSD_TYPE_PREFIX + type - : ConversionStrings.JAVA_TYPE_PREFIX + klass.getName(); - } - - - /** - * Returns the <code>xsi:type</code> value for a Java object, - * <code>null</code> if passed <code>null</code>. - */ - public static String java2XsiType(Object obj) - { - return (obj == null) - ? null - : java2XsiType(obj.getClass()); - } - - - /** - * Returns the Java classname to be used for a given <code>xsi:type</code> - * value, <code>null</code> if unable to determine the type (typically - * because it doesn't follow the expected format). - */ - public static String xsiType2JavaClassname(String xsiType) - { - if (StringUtils.isEmpty(xsiType)) - return null; - - if (xsiType.startsWith(ConversionStrings.XSD_TYPE_PREFIX)) - { - String typeSansPrefix = xsiType.substring(ConversionStrings.XSD_TYPE_PREFIX.length()); - Class<?> klass = _xsiType2Java.get(typeSansPrefix); - return (klass == null) - ? null - : klass.getName(); - } - else if (xsiType.startsWith(ConversionStrings.JAVA_TYPE_PREFIX)) - { - return xsiType.substring(ConversionStrings.JAVA_TYPE_PREFIX.length()); - } - - return null; - } - - - /** - * Returns the Java class object to be used for a given <code>xsi:type</code>. - * - * @throws ConversionException if unable to determine or resolve the type. - */ - public static Class<?> xsiType2JavaClass(String xsiType) - { - String className = xsiType2JavaClassname(xsiType); - if (className == null) - throw new ConversionException("null type specification"); - - try - { - return Class.forName(className); - } - catch (ClassNotFoundException ee) - { - throw new ConversionException("invalid type specification: " + xsiType, ee); - } - } - - - /** * Converts a Java primitive object to a string representation. Returns * <code>null</code> if passed <code>null</code>. * @@ -240,7 +100,7 @@ * String.valueOf()</code>. If <code>true</code>, * will attempt to use the format specified by XML * Schema for the datatype returned from {@link - * #java2XsiType}. + * TypeUtils#java2XsiType}. * * @throws ConversionException if the passed object does not have a string * representation (ie, is not a primitive value). @@ -267,7 +127,7 @@ * Parses the passed string as a Java primitive object of the specified * type. Will attempt to use the built-in parsing functions for the type, * or a format defined by XML Schema for the type that would be returned - * by {@link #java2XsiType} for the passed class. Returns <code>null</code> + * by {@link TypeUtils#java2XsiType} for the passed class. Returns <code>null</code> * if passed <code>null</code>. * * @param value String representation. Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/TypeUtils.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/TypeUtils.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/TypeUtils.java 2009-10-27 18:43:03 UTC (rev 173) @@ -0,0 +1,245 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.internal; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.w3c.dom.Element; + +import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.internal.StringUtils; + + +/** + * Constants and static methods for working with elements that declare their + * type using the <code>{practicalxml}:type</code> attribute (the actual + * namespace is defined by + * {@link net.sf.practicalxml.converter.internal.ConversionStrings}). + * <p> + * The values for this attribute take two forms: those representing simple + * types defined by XML Schema, indicated by the prefix "xsd:", and those + * representing arbitrary Java types, indicated by the prefix "java:". In + * the latter case, the post-prefix portion contains the value returned by + * <code>Class.getName()</code>. + */ +public class TypeUtils +{ + /** + * Translation from <code>xsi:type</code> values to Java primitive + * (wrapper) classes. Note the lack of any prefix -- and that we + * don't support the full set of primitives defined for XML Schema. + */ + private static Map<String,Class<?>> _xsiType2Java + = new HashMap<String,Class<?>>(); + + static + { + _xsiType2Java.put("string", String.class); + _xsiType2Java.put("boolean", Boolean.class); + _xsiType2Java.put("byte", Byte.class); + _xsiType2Java.put("short", Short.class); + _xsiType2Java.put("int", Integer.class); + _xsiType2Java.put("long", Long.class); + _xsiType2Java.put("decimal", BigDecimal.class); + _xsiType2Java.put("dateTime", Date.class); + } + + + /** + * Translation from Java primitive wrappers (and the associated non- + * wrapper "class") to an appropriate <code>xsi:type</code> value. + * Again, note the lack of prefix. + */ + private static Map<Class<?>,String> _java2XsiType + = new HashMap<Class<?>,String>(); + static + { + _java2XsiType.put(String.class, "string"); + _java2XsiType.put(Character.class, "string"); + _java2XsiType.put(Boolean.class, "boolean"); + _java2XsiType.put(Byte.class, "byte"); + _java2XsiType.put(Short.class, "short"); + _java2XsiType.put(Integer.class, "int"); + _java2XsiType.put(Long.class, "long"); + _java2XsiType.put(Float.class, "decimal"); + _java2XsiType.put(Double.class, "decimal"); + _java2XsiType.put(BigInteger.class, "decimal"); + _java2XsiType.put(BigDecimal.class, "decimal"); + _java2XsiType.put(Date.class, "dateTime"); + + _java2XsiType.put(Character.TYPE, "string"); + _java2XsiType.put(Boolean.TYPE, "boolean"); + _java2XsiType.put(Byte.TYPE, "byte"); + _java2XsiType.put(Short.TYPE, "short"); + _java2XsiType.put(Integer.TYPE, "int"); + _java2XsiType.put(Long.TYPE, "long"); + _java2XsiType.put(Float.TYPE, "decimal"); + _java2XsiType.put(Double.TYPE, "decimal"); + } + + +//---------------------------------------------------------------------------- +// Constants +//---------------------------------------------------------------------------- + + /** + * Prefix for <code>xsi:type</code> values for elements holding primitive + * values as defined by XML Schema. Note that we define a specific prefix + * that may or may not correspond to a namespace defined in the instance + * doc; we do not do namespace resolution on the value. Instance documents + * produced by tools other than <code>BeanConverter</code> must use the + * same prefix. + */ + public final static String XSD_TYPE_PREFIX = "xsd:"; + + + /** + * Prefix for <code>xsi:type</code> values for elements holding Java + * objects as serialized by <code>BeanConverter</code>. Again, this is + * an explicit value, and does not correspond to any namespace. + */ + public final static String JAVA_TYPE_PREFIX = "java:"; + + +//---------------------------------------------------------------------------- +// Public Methods +//---------------------------------------------------------------------------- + + /** + * Returns the <code>{practicalxml}:type</code> value for the passed + * Java class. + */ + public static String class2type(Class<?> klass) + { + String type = _java2XsiType.get(klass); + return (type != null) + ? XSD_TYPE_PREFIX + type + : JAVA_TYPE_PREFIX + klass.getName(); + } + + + /** + * Sets the <code>{practicalxml}:type</code> attribute to a value + * appropriate for the passed Java class. Does nothing if passed + * <code>null</code> + */ + public static void setType(Element elem, Class<?> klass) + { + if (klass == null) + return; + ConversionUtils.setAttribute(elem, ConversionStrings.AT_TYPE, class2type(klass)); + } + + + /** + * Returns the value of the passed element's <code>{practicalxml}:type</code> + * attribute, <code>null</code> if the attribute is not set or contains + * an empty string. + * <p> + * Most callers should use {@link #getType} rather than this method. + */ + public static String getTypeValue(Element elem) + { + String type = ConversionUtils.getAttribute(elem, ConversionStrings.AT_TYPE); + return (StringUtils.isEmpty(type)) + ? null + : type; + } + + + /** + * Returns the Java class corresponding to the passed element's + * <code>{practicalxml}:type</code> attribute. Optionally returns + * <code>null</code> or throws if unable to convert the attribute. + * + * @throws ConversionException if unable to determine Java type for + * any reason, when <code>throwIfFail</code> is set. + */ + public static Class<?> getType(Element elem, boolean throwIfFail) + { + String type = getTypeValue(elem); + if (type == null) + { + if (throwIfFail) + throw new ConversionException("missing type", elem); + else + return null; + } + + Class<?> klass = null; + if (type.startsWith(XSD_TYPE_PREFIX)) + klass = lookupXsdType(type); + else if (type.startsWith(JAVA_TYPE_PREFIX)) + klass = resolveJavaType(type); + + if (klass == null) + throw new ConversionException("unable to resolve type: " + type, elem); + + return klass; + } + + + /** + * Validates that the stated type of the element is assignable to the + * passed class. + * + * @throws ConversionException if unable to resolve element's type or if + * an object of that type is not assignable to the passed class. + */ + public static void validateType(Element elem, Class<?> klass) + { + Class<?> elemKlass = getType(elem, true); + if (klass.isAssignableFrom(elemKlass)) + return; + + // the primitive "TYPE" classes aren't assignable to the primitive + // wrapper class returned in previous step, so handle that case here + if (class2type(klass).equals(class2type(elemKlass))) + return; + + throw new ConversionException( + "invalid type: \"" + getTypeValue(elem) + "\" for " + klass.getName(), + elem); + } + + +//---------------------------------------------------------------------------- +// Internals +//---------------------------------------------------------------------------- + + private static Class<?> lookupXsdType(String value) + { + value = value.substring(XSD_TYPE_PREFIX.length()); + return _xsiType2Java.get(value); + } + + + private static Class<?> resolveJavaType(String value) + { + value = value.substring(JAVA_TYPE_PREFIX.length()); + try + { + return Class.forName(value); + } + catch (ClassNotFoundException ee) + { + return null; + } + } +} Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Json2XmlConverter.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Json2XmlConverter.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Json2XmlConverter.java 2009-10-27 18:43:03 UTC (rev 173) @@ -21,6 +21,7 @@ import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.internal.ConversionStrings; import net.sf.practicalxml.converter.internal.JsonUtils; @@ -64,7 +65,7 @@ */ public Element convert() { - return convert("data"); + return convert(ConversionStrings.EL_DEFAULT_ROOT); } @@ -162,7 +163,7 @@ private void parseArray(Element parent) { - String childName = "data"; + String childName = ConversionStrings.EL_COLLECTION_ITEM; if (_options.contains(Json2XmlOptions.ARRAYS_AS_REPEATED_ELEMENTS)) { // we come in here with the assumption that array elements will Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java 2009-10-27 18:43:03 UTC (rev 173) @@ -24,9 +24,8 @@ import java.util.Set; import net.sf.practicalxml.DomUtil; -import net.sf.practicalxml.converter.internal.ConversionUtils; import net.sf.practicalxml.converter.internal.JsonUtils; -import net.sf.practicalxml.internal.StringUtils; +import net.sf.practicalxml.converter.internal.TypeUtils; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -129,7 +128,7 @@ private StringBuilder appendText(StringBuilder buf, Element elem) { String text = DomUtil.getText(elem); - String type = ConversionUtils.getXsiType(elem); + String type = TypeUtils.getTypeValue(elem); String quote = "\""; if (_options.contains(Xml2JsonOptions.USE_XSI_TYPE) && _unquotedXsd.contains(type)) quote = ""; @@ -268,10 +267,10 @@ if (!_options.contains(Xml2JsonOptions.USE_XSI_TYPE)) return false; - String type = ConversionUtils.getXsiType(elem); - if (StringUtils.isEmpty(type)) + Class<?> klass = TypeUtils.getType(elem, false); + if (klass == null) return false; - if (type.startsWith("java:[")) + if (klass.isArray()) return true; return false; Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/package.html =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/package.html 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/package.html 2009-10-27 18:43:03 UTC (rev 173) @@ -22,7 +22,8 @@ <dd> JSON supports numbers and boolean literals in addition to quote-delimited strings. The JSON to XML conversion will handle these values transparently. The default XML to JSON conversion writes all content as quote-delimited - strings (although this may change). + strings, will optionally look for a <code>type</code> attribute and use it + to generate unquoted values. <dt> Arrays, XML to JSON <dd> XML does not have a defined array construct, but may repeat elements; JSON has a defined array construct, and repeated elements will overwrite the Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractConversionTestCase.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractConversionTestCase.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractConversionTestCase.java 2009-10-27 18:43:03 UTC (rev 173) @@ -21,6 +21,7 @@ import org.w3c.dom.Element; import net.sf.practicalxml.AbstractTestCase; +import net.sf.practicalxml.converter.internal.ConversionStrings; /** @@ -34,18 +35,23 @@ super(testName); } + //---------------------------------------------------------------------------- // Support Code //---------------------------------------------------------------------------- - protected static net.sf.practicalxml.builder.Node xsiType(String typeName) + protected static net.sf.practicalxml.builder.Node conversionAttr(String name, String value) { - return attribute(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, - "type", - typeName); + return attribute(ConversionStrings.NS_CONVERSION, name, value); } + protected static net.sf.practicalxml.builder.Node conversionType(String value) + { + return conversionAttr(ConversionStrings.AT_TYPE, value); + } + + protected static net.sf.practicalxml.builder.Node xsiNil(boolean isNil) { return attribute(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, @@ -58,10 +64,9 @@ // Assertions //---------------------------------------------------------------------------- - protected void assertXsiType(String message, Element elem, String expectedType) + protected void assertAttribute(Element elem, String name, String expected) { - String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); - assertEquals(message, expectedType, attr); + assertEquals(expected, elem.getAttributeNS(ConversionStrings.NS_CONVERSION, name)); } Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/AbstractBeanConverterTestCase.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/AbstractBeanConverterTestCase.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/AbstractBeanConverterTestCase.java 2009-10-27 18:43:03 UTC (rev 173) @@ -26,6 +26,7 @@ import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.AbstractConversionTestCase; +import net.sf.practicalxml.converter.internal.ConversionStrings; /** @@ -184,7 +185,7 @@ { assertName(message, elem, expectedName); assertValue(message, elem, expectedValue); - assertXsiType(message, elem, expectedType); + assertType(message, elem, expectedType); assertXsiNil(message, elem, isNil); } @@ -205,7 +206,7 @@ message += " "; assertName(message + "name", elem, expectedName); - assertXsiType(message + "xsi:type", elem, expectedType); + assertType(message + "type", elem, expectedType); assertValue(message + "value", elem, expectedValue); } @@ -216,6 +217,13 @@ } + protected void assertType(String message, Element elem, String expected) + { + String attr = elem.getAttributeNS(ConversionStrings.NS_CONVERSION, "type"); + assertEquals(message, expected, attr); + } + + protected void assertValue(String message, Element elem, String expectedValue) { assertEquals(message, expectedValue, DomUtil.getText(elem)); Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBean2XmlAppenders.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBean2XmlAppenders.java 2009-10-26 15:03:54 UTC (rev 172) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBean2XmlAppenders.java 2009-10-27 18:43:03 UTC (rev 173) @@ -56,7 +56,7 @@ Element root = DomUtil.newDocument("root"); Appender appender = new BasicAppender(root, useOptions()); - Element child = appender.appendValue("foo", "bar", "baz"); + Element child = appender.appendValue("foo", String.class, "baz"); assertNull(child.getNamespaceURI()); assertNameTypeValue(child, "foo", "", "baz"); @@ -72,11 +72,11 @@ { Element root = DomUtil.newDocument("root"); - Appender appender = new BasicAppender(root, useOptions(Bean2XmlOptions.XSI_TYPE)); - Element child = appender.appendValue("foo", "bar", "baz"); + Appender appender = new BasicAppender(root, useOptions(Bean2XmlOptions.USE_TYPE_ATTR)); + Element child = appender.appendValue("foo", String.class, "baz"); assertNull(child.getNamespaceURI()); - assertNameTypeValue(child, "foo", "bar", "baz"); + assertNameTypeValue(child, "foo", "xsd:string", "baz"); } @@ -85,7 +85,7 @@ Element root = DomUtil.newDocument("root"); Appender appender = new BasicAppender(root, useOptions()); - Element child = appender.appendValue("foo", "bar", null); + Element child = appender.appendValue("foo", null, null); assertNull(child); @@ -99,13 +99,13 @@ Element root = DomUtil.newDocument("root"); Appender appender = new BasicAppender(root, useOptions(Bean2XmlOptions.NULL_AS_XSI_NIL)); - Element child0 = appender.appendValue("foo", "bar", "baz"); - Element child1 = appender.appendValue("argle", "bargle", null); + Element child0 = appender.appendValue("foo", null, "baz"); + Element child1 = appender.appendValue("argle", null, null); assertXsiNil(child0, false); assertNull(child1.getNamespaceURI()); - assertNameTypeValue(child1, "argle","", null); + assertNameTypeValue(child1, "argle", "", null); assertXsiNil(child1, true); } @@ -115,8 +115,8 @@ Element root = DomUtil.newDocument("root"); Appender appender = new BasicAppender(root, useOptions()); - Element child0 = appender.appendContainer("foo", "bar"); - Element child1 = appender.appendContainer("argle", "bargle"); + Element child0 = appender.appendContainer("foo", String[].class); + Element child1 = appender.appendContainer("argle", String[].class); assertChildCount(root, 2); assertNameTypeValue(child0, "foo", "", null); @@ -128,13 +128,13 @@ { Element root = DomUtil.newDocument("root"); - Appender appender = new BasicAppender(root, useOptions(Bean2XmlOptions.XSI_TYPE)); - Element child0 = appender.appendContainer("foo", "bar"); - Element child1 = appender.appendContainer("argle", "bargle"); + Appender appender = new BasicAppender(root, useOptions(Bean2XmlOptions.USE_TYPE_ATTR)); + Element child0 = appender.appendContainer("foo", String[].class); + E... [truncated message content] |