[Practicalxml-commits] SF.net SVN: practicalxml:[100] branches/dev-1.1/src
Brought to you by:
kdgregory
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-14 18:41:56
|
Revision: 100 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=100&view=rev Author: kdgregory Date: 2009-08-14 18:41:47 +0000 (Fri, 14 Aug 2009) Log Message: ----------- repackage Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlAppenders.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanHandler.java Added Paths: ----------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlAppenders.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlOptions.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java Removed Paths: ------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlAppenders.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlAppenders.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlAppenders.java 2009-08-14 18:27:36 UTC (rev 99) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlAppenders.java 2009-08-14 18:41:47 UTC (rev 100) @@ -1,235 +0,0 @@ -// 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; - -import java.util.EnumSet; - -import javax.xml.XMLConstants; - -import org.w3c.dom.Element; - -import net.sf.practicalxml.DomUtil; - - -/** - * Packaging class used for XML output appenders. This class is a temporary - * hack, as I move intelligence into {@link Bean2XmlDriver}; the contained - * classes will end up in a new package, once I figure out what the package - * structure should be. - */ -public abstract class Bean2XmlAppenders -{ - /** - * An <code>Appender</code> appends children to a single node of the - * output tree. The driver is responsible for creating new appenders - * for each compound element, including the root, and providing those - * appenders with options to control output generation. - */ - public interface Appender - { - /** - * Appends a value element to the current element. Value elements have - * 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 value The node's value. May be <code>null</code>, in - * which case the appender decides whether or not - * to actually append the node. - * - * @return The appended element. This is a convenience for subclasses, - * which may want to set additional attributes after their - * 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); - - - /** - * Appends a container element to the current element. Container - * 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); - } - - - /** - * Base class for XML appenders, providing helper methods for subclasses. - */ - private static abstract class AbstractAppender - implements Appender - { - private EnumSet<Bean2XmlOptions> _options; - - public AbstractAppender(EnumSet<Bean2XmlOptions> options) - { - _options = options; - } - - protected boolean isOptionSet(Bean2XmlOptions option) - { - return _options.contains(option); - } - - protected boolean shouldSkip(Object value) - { - return (value == null) && !_options.contains(Bean2XmlOptions.XSI_NIL); - } - - protected void setType(Element elem, String type) - { - if (isOptionSet(Bean2XmlOptions.XSI_TYPE)) - elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type", type); - } - - protected void setValue(Element elem, String value) - { - if (value != null) - DomUtil.setText(elem, value); - else if (isOptionSet(Bean2XmlOptions.XSI_NIL)) - elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", "true"); - } - } - - - /** - * Basic appender, which appends new elements to a parent. - */ - public static class BasicAppender - extends AbstractAppender - { - private Element _parent; - - public BasicAppender(Element parent, EnumSet<Bean2XmlOptions> options) - { - super(options); - _parent = parent; - } - - public Element appendValue(String name, String type, String value) - { - if (shouldSkip(value)) - return null; - - Element child = DomUtil.appendChildInheritNamespace(_parent, name); - setType(child, type); - setValue(child, value); - return child; - } - - public Element appendContainer(String name, String type) - { - Element child = DomUtil.appendChildInheritNamespace(_parent, name); - setType(child, type); - return child; - } - } - - - /** - * Appender for children of an indexed/iterated item (array, list, or set). - * Each element will have an incremented <code>index</code> attribute that - * indicates the position of the element within the iteration. - */ - public static class IndexedAppender - extends BasicAppender - { - int _index = 0; - - public IndexedAppender(Element parent, EnumSet<Bean2XmlOptions> options) - { - super(parent, options); - } - - - @Override - public Element appendValue(String name, String type, String value) - { - Element child = super.appendValue(name, type, value); - if (child != null) - child.setAttribute("index", String.valueOf(_index++)); - return child; - } - } - - - /** - * Appender for children of a <code>Map</code>. Depending on options, - * will either create children named after the key, or a generic "data" - * child with the key as an attribute. - */ - public static class MapAppender - extends BasicAppender - { - public MapAppender(Element parent, EnumSet<Bean2XmlOptions> options) - { - super(parent, options); - } - - - @Override - public Element appendValue(String name, String type, String value) - { - Element child = null; - if (isOptionSet(Bean2XmlOptions.INTROSPECT_MAPS)) - { - child = super.appendValue(name, type, value); - } - else - { - child = super.appendValue("data", type, value); - if (child != null) - child.setAttribute("key", name); - } - return child; - } - } - - - /** - * An appender that sets values directly on the "parent" element. Used for - * the conversion root element. - */ - public static class DirectAppender - extends AbstractAppender - { - private Element _elem; - - public DirectAppender(Element elem, EnumSet<Bean2XmlOptions> options) - { - super(options); - _elem = elem; - } - - public Element appendValue(String name, String type, String value) - { - if (!shouldSkip(value)) - { - setType(_elem, type); - setValue(_elem, value); - } - return _elem; - } - - public Element appendContainer(String name, String type) - { - setType(_elem, type); - return _elem; - } - } -} Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java 2009-08-14 18:27:36 UTC (rev 99) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java 2009-08-14 18:41:47 UTC (rev 100) @@ -1,234 +0,0 @@ -// 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; - -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Array; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.EnumSet; -import java.util.Map; - -import org.w3c.dom.Element; - -import net.sf.practicalxml.DomUtil; -import net.sf.practicalxml.converter.Bean2XmlAppenders.Appender; -import net.sf.practicalxml.converter.Bean2XmlAppenders.BasicAppender; -import net.sf.practicalxml.converter.Bean2XmlAppenders.DirectAppender; -import net.sf.practicalxml.converter.Bean2XmlAppenders.IndexedAppender; -import net.sf.practicalxml.converter.Bean2XmlAppenders.MapAppender; - - -/** - * Driver class for converting bean data to an XML representation. In normal - * usage, an instance of this class is constructed with the desired conversion - * options, then {@link #convert} is called with the compound object to be - * converted. The driver may be reused for multiple conversions, and is - * thread-safe. - */ -public class Bean2XmlDriver -{ - private EnumSet<Bean2XmlOptions> _options = EnumSet.noneOf(Bean2XmlOptions.class); - private PrimitiveConversionHelper _primitiveHelper; - - public Bean2XmlDriver(Bean2XmlOptions... options) - { - for (Bean2XmlOptions option : options) - _options.add(option); - _primitiveHelper = new PrimitiveConversionHelper(shouldUseXsdFormatting()); - } - - -//---------------------------------------------------------------------------- -// Public methods -//---------------------------------------------------------------------------- - - /** - * Creates an XML DOM with the specified root element name, and fills it - * by introspecting the passed object (see {@link #introspect} for - * treatment of simple objects). - */ - public Element convert(Object obj, String rootName) - { - return convert(obj, null, rootName); - } - - - /** - * Creates an XML DOM with the specified root element name and namespace - * URI, and fills it by introspecting the passed object (see {@link - * #introspect} for treatment of simple objects). The namespace URI (and - * prefix, if provided) will be used for all child elements. - */ - public Element convert(Object obj, String nsUri, String rootName) - { - Element root = DomUtil.newDocument(nsUri, rootName); - convert(obj, "", new DirectAppender(root, _options)); - return root; - } - - - /** - * Introspects the passed object, and appends its contents to the output. - * This method is public to allow non-standard conversions, such as - * appending into an existing tree, or (in the future, if we introduce an - * appender factory) producing non-XML output. - */ - public void convert(Object obj, String name, Appender appender) - { - // these methods have side effects! - // empty blocks and comments are there to keep Eclipse happy - if (tryToConvertAsPrimitiveOrNull(obj, null, name, appender)) - { /* it was converted */ } - else if (tryToConvertAsArray(obj, name, appender)) - { /* it was converted */ } - else if (tryToConvertAsMap(obj, name, appender)) - { /* it was converted */ } - else if (tryToConvertAsCollection(obj, name, appender)) - { /* it was converted */ } - else if (tryToConvertAsBean(obj, name, appender)) - { /* it was converted */ } - else - throw new ConversionException("unable to convert: " + obj.getClass().getName()); - } - - -//---------------------------------------------------------------------------- -// Internals -//---------------------------------------------------------------------------- - - private boolean shouldUseXsdFormatting() - { - return _options.contains(Bean2XmlOptions.XSD_FORMAT) - || _options.contains(Bean2XmlOptions.XSI_TYPE); - } - - - private String getJavaXsiType(Object obj) - { - return "java:" + obj.getClass().getName(); - } - - - private boolean tryToConvertAsPrimitiveOrNull( - Object obj, Class<?> klass, String name, Appender appender) - { - if (obj != null) - klass = obj.getClass(); - - String objType = _primitiveHelper.getXsdType(klass); - if ((obj == null) || (objType != null)) - { - appender.appendValue(name, objType, _primitiveHelper.stringify(obj)); - return true; - } - - return false; - } - - - private boolean tryToConvertAsArray(Object array, String name, Appender appender) - { - if (!array.getClass().isArray()) - return false; - - Element parent = appender.appendContainer(name, getJavaXsiType(array)); - Appender childAppender = new IndexedAppender(parent, _options); - int length = Array.getLength(array); - for (int idx = 0 ; idx < length ; idx++) - { - Object value = Array.get(array, idx); - convert(value, "data", childAppender); - } - return true; - } - - - private boolean tryToConvertAsMap(Object obj, String name, Appender appender) - { - if (!(obj instanceof Map)) - return false; - - Element parent = appender.appendContainer(name, getJavaXsiType(obj)); - Appender childAppender = new MapAppender(parent, _options); - for (Map.Entry<?,?> entry : ((Map<?,?>)obj).entrySet()) - { - convert(entry.getValue(), String.valueOf(entry.getKey()), childAppender); - } - return true; - } - - - private boolean tryToConvertAsCollection(Object obj, String name, Appender appender) - { - if (!(obj instanceof Collection)) - return false; - - Element parent = appender.appendContainer(name, getJavaXsiType(obj)); - Appender childAppender = new IndexedAppender(parent, _options); - for (Object value : (Collection<?>)obj) - { - convert(value, "data", childAppender); - } - return true; - } - - - private boolean tryToConvertAsBean(Object bean, String name, Appender appender) - { - Element parent = appender.appendContainer(name, getJavaXsiType(bean)); - Appender childAppender = new BasicAppender(parent, _options); - try - { - BeanInfo info = Introspector.getBeanInfo(bean.getClass(), Object.class); - PropertyDescriptor[] props = info.getPropertyDescriptors(); - for (int ii = 0 ; ii < props.length ; ii++) - convertBeanProperty(bean, props[ii], childAppender); - } - catch (IntrospectionException ee) - { - throw new ConversionException("introspection failure", ee); - } - return true; - } - - - private void convertBeanProperty( - Object bean, PropertyDescriptor propDesc, Appender appender) - { - String name = propDesc.getName(); - Class<?> type = propDesc.getPropertyType(); - Object value; - try - { - Method getter = propDesc.getReadMethod(); - if (getter == null) - return; - value = getter.invoke(bean); - } - catch (Exception ee) - { - throw new ConversionException("unable to retrieve bean value", ee); - } - - if (value == null) - tryToConvertAsPrimitiveOrNull(value, type, name, appender); - else - convert(value, name, appender); - } -} Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java 2009-08-14 18:27:36 UTC (rev 99) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java 2009-08-14 18:41:47 UTC (rev 100) @@ -1,55 +0,0 @@ -// 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; - - -/** - * Options used by {@link Bean2XmlHandler} to control the structure of the - * DOM tree. - */ -public enum Bean2XmlOptions -{ - /** - * Outputs values using formats defined by XML Schema, rather than Java's - * <code>String.valueOf()</code> method. Note that these formats are not - * 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:XXX</code>", where XXX is the XSD type name. For complex - * types, this attribute's value will be "<code>java:XXX</code>", where - * XXX is the fully-qualified classname. - * <p> - * <em>This option implies {@link #XSD_FORMAT} for simple types</em>. - */ - XSI_TYPE, - - /** - * Report null values using the <code>xsi:nil="true"</code> attribute. If - * not present, null values are ignored, and not added to DOM tree. - */ - XSI_NIL, - - /** - * Output maps in an "introspected" format, where the name of each item - * is the map key (rather than "data"), and the "key" attribute is omitted. - * If any key is not a valid XML identifier, the converter will throw. - */ - INTROSPECT_MAPS -} Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-08-14 18:27:36 UTC (rev 99) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-08-14 18:41:47 UTC (rev 100) @@ -16,7 +16,10 @@ import org.w3c.dom.Document; +import net.sf.practicalxml.converter.bean2xml.Bean2XmlDriver; +import net.sf.practicalxml.converter.bean2xml.Bean2XmlOptions; + /** * Converts Java objects (not just beans) to and from an XML representation. * This was originally developed to support RESTful web services, without the Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java 2009-08-14 18:27:36 UTC (rev 99) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java 2009-08-14 18:41:47 UTC (rev 100) @@ -1,35 +0,0 @@ -// 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; - -import org.w3c.dom.Element; - - -/** - * Driver class for converting an XML DOM into a Java bean, using a {@link - * Xml2BeanHandler} to manage data conversion. - */ -public class Xml2BeanDriver -{ - /** - * Fills a bean-style object from an XML element. For each child of the - * passed element, tries to find a property with the same name, invokes - * the appropriate conversion handler method, and sets the property from - * the result. - */ - public void dispatch(Element elem, Object bean) - { - } -} Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java 2009-08-14 18:27:36 UTC (rev 99) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java 2009-08-14 18:41:47 UTC (rev 100) @@ -1,192 +0,0 @@ -// 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; - -import net.sf.practicalxml.DomUtil; -import net.sf.practicalxml.XmlException; -import net.sf.practicalxml.XmlUtil; -import net.sf.practicalxml.internal.StringUtils; - -import java.util.Arrays; -import java.util.Date; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.xml.XMLConstants; - -import org.w3c.dom.Element; - - -/** - * Invoked by {@link Xml2BeanDriver} to convert a DOM <code>Element</code> - * into the appropriate Java object. Unlike {@link Bean2XmlHandler}, there - * will only be one instance of this object created during conversion; all - * intermediate data can be held on the stack. - */ -public class Xml2BeanHandler -{ - private EnumSet<Xml2BeanOptions> _options; - private PrimitiveConversionHelper _primitiveHelper; - - - /** - * Public constructor, allowing various options specifications. - */ - public Xml2BeanHandler(Xml2BeanOptions... options) - { - _options = EnumSet.noneOf(Xml2BeanOptions.class); - for (Xml2BeanOptions option : options) - _options.add(option); - - _primitiveHelper = new PrimitiveConversionHelper(true); - } - - -//---------------------------------------------------------------------------- -// Public Methods -//---------------------------------------------------------------------------- - - public Boolean convertBoolean(Element elem) - { - return (Boolean)_primitiveHelper.parse(getText(elem), Boolean.class); - } - - - public Byte convertByte(Element elem) - { - return (Byte)_primitiveHelper.parse(getText(elem), Byte.class); - } - - - public Character convertCharacter(Element elem) - { - return (Character)_primitiveHelper.parse(getText(elem), Character.class); - } - - - public Date convertDate(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - - public Double convertDouble(Element elem) - { - return (Double)_primitiveHelper.parse(getText(elem), Double.class); - } - - - public Float convertFloat(Element elem) - { - return (Float)_primitiveHelper.parse(getText(elem), Float.class); - } - - - public Integer convertInteger(Element elem) - { - return (Integer)_primitiveHelper.parse(getText(elem), Integer.class); - } - - - public Long convertLong(Element elem) - { - return (Long)_primitiveHelper.parse(getText(elem), Long.class); - } - - - public Number convertNumber(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - - public Short convertShort(Element elem) - { - return (Short)_primitiveHelper.parse(getText(elem), Short.class); - } - - - public String convertString(Element elem) - { - return (String)_primitiveHelper.parse(getText(elem), String.class); - } - - - public List<?> convertList(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - - public Set<?> convertSet(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - - public Map<?,?> convertMap(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - - public Object convertObject(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - - public Object[] convertObjectArray(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - -//---------------------------------------------------------------------------- -// Internals -//---------------------------------------------------------------------------- - - /** - * Returns the text from a passed element, applying any low-level options - * along the way. - */ - private String getText(Element elem) - { - String text = DomUtil.getText(elem); - if (_options.contains(Xml2BeanOptions.CONVERT_BLANK_AS_NULL) && StringUtils.isBlank(text)) - text = null; - validateXsiNil(elem, text); - return text; - } - - - /** - * Checks for elements that require <code>xsi:nil</code>, and throws if missing. - */ - private void validateXsiNil(Element elem, String text) - { - if (text != null) - return; - if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_NIL)) - return; - - String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"); - if ((attr == null) || !attr.equals("true")) - throw new ConversionException("empty element without required xsi:nil"); - } - -} Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java 2009-08-14 18:27:36 UTC (rev 99) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java 2009-08-14 18:41:47 UTC (rev 100) @@ -1,71 +0,0 @@ -// 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; - - -/** - * Options used by {@link Xml2BeanHandler} to control the way that DOM trees - * are translated to Java beans. - */ -public enum Xml2BeanOptions -{ - /** - * If present, the converter will treat all elements with empty text nodes - * as if they were empty elements -- in other words, <code>null</code>. - * Note that this flag will interact with <code>REQUIRE_XSI_NIL</code>. - */ - CONVERT_BLANK_AS_NULL, - - - /** - * If present, the converter ignores elements that don't correspond to - * settable properties of the bean. - */ - IGNORE_MISSING_PROPERTIES, - - - /** - * If present, the converter will ignore any objects that cannot be - * converted (many of the JDK-provided classes fall into this category, - * because they're not bean-structured). - */ - IGNORE_UNCONVERTIBLE_OBJECTS, - - - /** - * If present, the converter will use a setter method taking a String, in - * preference to any other type. Default behavior is to pick the method - * with the most restrictive type (and considering numeric types as more - * restrictive than <code>String</code>). - */ - PREFER_STRING_SETTER, - - - /** - * 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 -} Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlAppenders.java (from rev 99, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlAppenders.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlAppenders.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlAppenders.java 2009-08-14 18:41:47 UTC (rev 100) @@ -0,0 +1,235 @@ +// 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.bean2xml; + +import java.util.EnumSet; + +import javax.xml.XMLConstants; + +import org.w3c.dom.Element; + +import net.sf.practicalxml.DomUtil; + + +/** + * Packaging class used for XML output appenders. This class is a temporary + * hack, as I move intelligence into {@link Bean2XmlDriver}; the contained + * classes will end up in a new package, once I figure out what the package + * structure should be. + */ +public abstract class Bean2XmlAppenders +{ + /** + * An <code>Appender</code> appends children to a single node of the + * output tree. The driver is responsible for creating new appenders + * for each compound element, including the root, and providing those + * appenders with options to control output generation. + */ + public interface Appender + { + /** + * Appends a value element to the current element. Value elements have + * 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 value The node's value. May be <code>null</code>, in + * which case the appender decides whether or not + * to actually append the node. + * + * @return The appended element. This is a convenience for subclasses, + * which may want to set additional attributes after their + * 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); + + + /** + * Appends a container element to the current element. Container + * 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); + } + + + /** + * Base class for XML appenders, providing helper methods for subclasses. + */ + private static abstract class AbstractAppender + implements Appender + { + private EnumSet<Bean2XmlOptions> _options; + + public AbstractAppender(EnumSet<Bean2XmlOptions> options) + { + _options = options; + } + + protected boolean isOptionSet(Bean2XmlOptions option) + { + return _options.contains(option); + } + + protected boolean shouldSkip(Object value) + { + return (value == null) && !_options.contains(Bean2XmlOptions.XSI_NIL); + } + + protected void setType(Element elem, String type) + { + if (isOptionSet(Bean2XmlOptions.XSI_TYPE)) + elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type", type); + } + + protected void setValue(Element elem, String value) + { + if (value != null) + DomUtil.setText(elem, value); + else if (isOptionSet(Bean2XmlOptions.XSI_NIL)) + elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", "true"); + } + } + + + /** + * Basic appender, which appends new elements to a parent. + */ + public static class BasicAppender + extends AbstractAppender + { + private Element _parent; + + public BasicAppender(Element parent, EnumSet<Bean2XmlOptions> options) + { + super(options); + _parent = parent; + } + + public Element appendValue(String name, String type, String value) + { + if (shouldSkip(value)) + return null; + + Element child = DomUtil.appendChildInheritNamespace(_parent, name); + setType(child, type); + setValue(child, value); + return child; + } + + public Element appendContainer(String name, String type) + { + Element child = DomUtil.appendChildInheritNamespace(_parent, name); + setType(child, type); + return child; + } + } + + + /** + * Appender for children of an indexed/iterated item (array, list, or set). + * Each element will have an incremented <code>index</code> attribute that + * indicates the position of the element within the iteration. + */ + public static class IndexedAppender + extends BasicAppender + { + int _index = 0; + + public IndexedAppender(Element parent, EnumSet<Bean2XmlOptions> options) + { + super(parent, options); + } + + + @Override + public Element appendValue(String name, String type, String value) + { + Element child = super.appendValue(name, type, value); + if (child != null) + child.setAttribute("index", String.valueOf(_index++)); + return child; + } + } + + + /** + * Appender for children of a <code>Map</code>. Depending on options, + * will either create children named after the key, or a generic "data" + * child with the key as an attribute. + */ + public static class MapAppender + extends BasicAppender + { + public MapAppender(Element parent, EnumSet<Bean2XmlOptions> options) + { + super(parent, options); + } + + + @Override + public Element appendValue(String name, String type, String value) + { + Element child = null; + if (isOptionSet(Bean2XmlOptions.INTROSPECT_MAPS)) + { + child = super.appendValue(name, type, value); + } + else + { + child = super.appendValue("data", type, value); + if (child != null) + child.setAttribute("key", name); + } + return child; + } + } + + + /** + * An appender that sets values directly on the "parent" element. Used for + * the conversion root element. + */ + public static class DirectAppender + extends AbstractAppender + { + private Element _elem; + + public DirectAppender(Element elem, EnumSet<Bean2XmlOptions> options) + { + super(options); + _elem = elem; + } + + public Element appendValue(String name, String type, String value) + { + if (!shouldSkip(value)) + { + setType(_elem, type); + setValue(_elem, value); + } + return _elem; + } + + public Element appendContainer(String name, String type) + { + setType(_elem, type); + return _elem; + } + } +} Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java (from rev 99, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlDriver.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java 2009-08-14 18:41:47 UTC (rev 100) @@ -0,0 +1,232 @@ +// 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.bean2xml; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Map; + +import org.w3c.dom.Element; + +import net.sf.practicalxml.DomUtil; +import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.PrimitiveConversionHelper; +import net.sf.practicalxml.converter.bean2xml.Bean2XmlAppenders.*; + + +/** + * Driver class for converting bean data to an XML representation. In normal + * usage, an instance of this class is constructed with the desired conversion + * options, then {@link #convert} is called with the compound object to be + * converted. The driver may be reused for multiple conversions, and is + * thread-safe. + */ +public class Bean2XmlDriver +{ + private EnumSet<Bean2XmlOptions> _options = EnumSet.noneOf(Bean2XmlOptions.class); + private PrimitiveConversionHelper _primitiveHelper; + + public Bean2XmlDriver(Bean2XmlOptions... options) + { + for (Bean2XmlOptions option : options) + _options.add(option); + _primitiveHelper = new PrimitiveConversionHelper(shouldUseXsdFormatting()); + } + + +//---------------------------------------------------------------------------- +// Public methods +//---------------------------------------------------------------------------- + + /** + * Creates an XML DOM with the specified root element name, and fills it + * by introspecting the passed object (see {@link #introspect} for + * treatment of simple objects). + */ + public Element convert(Object obj, String rootName) + { + return convert(obj, null, rootName); + } + + + /** + * Creates an XML DOM with the specified root element name and namespace + * URI, and fills it by introspecting the passed object (see {@link + * #introspect} for treatment of simple objects). The namespace URI (and + * prefix, if provided) will be used for all child elements. + */ + public Element convert(Object obj, String nsUri, String rootName) + { + Element root = DomUtil.newDocument(nsUri, rootName); + convert(obj, "", new DirectAppender(root, _options)); + return root; + } + + + /** + * Introspects the passed object, and appends its contents to the output. + * This method is public to allow non-standard conversions, such as + * appending into an existing tree, or (in the future, if we introduce an + * appender factory) producing non-XML output. + */ + public void convert(Object obj, String name, Appender appender) + { + // these methods have side effects! + // empty blocks and comments are there to keep Eclipse happy + if (tryToConvertAsPrimitiveOrNull(obj, null, name, appender)) + { /* it was converted */ } + else if (tryToConvertAsArray(obj, name, appender)) + { /* it was converted */ } + else if (tryToConvertAsMap(obj, name, appender)) + { /* it was converted */ } + else if (tryToConvertAsCollection(obj, name, appender)) + { /* it was converted */ } + else if (tryToConvertAsBean(obj, name, appender)) + { /* it was converted */ } + else + throw new ConversionException("unable to convert: " + obj.getClass().getName()); + } + + +//---------------------------------------------------------------------------- +// Internals +//---------------------------------------------------------------------------- + + private boolean shouldUseXsdFormatting() + { + return _options.contains(Bean2XmlOptions.XSD_FORMAT) + || _options.contains(Bean2XmlOptions.XSI_TYPE); + } + + + private String getJavaXsiType(Object obj) + { + return "java:" + obj.getClass().getName(); + } + + + private boolean tryToConvertAsPrimitiveOrNull( + Object obj, Class<?> klass, String name, Appender appender) + { + if (obj != null) + klass = obj.getClass(); + + String objType = _primitiveHelper.getXsdType(klass); + if ((obj == null) || (objType != null)) + { + appender.appendValue(name, objType, _primitiveHelper.stringify(obj)); + return true; + } + + return false; + } + + + private boolean tryToConvertAsArray(Object array, String name, Appender appender) + { + if (!array.getClass().isArray()) + return false; + + Element parent = appender.appendContainer(name, getJavaXsiType(array)); + Appender childAppender = new IndexedAppender(parent, _options); + int length = Array.getLength(array); + for (int idx = 0 ; idx < length ; idx++) + { + Object value = Array.get(array, idx); + convert(value, "data", childAppender); + } + return true; + } + + + private boolean tryToConvertAsMap(Object obj, String name, Appender appender) + { + if (!(obj instanceof Map)) + return false; + + Element parent = appender.appendContainer(name, getJavaXsiType(obj)); + Appender childAppender = new MapAppender(parent, _options); + for (Map.Entry<?,?> entry : ((Map<?,?>)obj).entrySet()) + { + convert(entry.getValue(), String.valueOf(entry.getKey()), childAppender); + } + return true; + } + + + private boolean tryToConvertAsCollection(Object obj, String name, Appender appender) + { + if (!(obj instanceof Collection)) + return false; + + Element parent = appender.appendContainer(name, getJavaXsiType(obj)); + Appender childAppender = new IndexedAppender(parent, _options); + for (Object value : (Collection<?>)obj) + { + convert(value, "data", childAppender); + } + return true; + } + + + private boolean tryToConvertAsBean(Object bean, String name, Appender appender) + { + Element parent = appender.appendContainer(name, getJavaXsiType(bean)); + Appender childAppender = new BasicAppender(parent, _options); + try + { + BeanInfo info = Introspector.getBeanInfo(bean.getClass(), Object.class); + PropertyDescriptor[] props = info.getPropertyDescriptors(); + for (int ii = 0 ; ii < props.length ; ii++) + convertBeanProperty(bean, props[ii], childAppender); + } + catch (IntrospectionException ee) + { + throw new ConversionException("introspection failure", ee); + } + return true; + } + + + private void convertBeanProperty( + Object bean, PropertyDescriptor propDesc, Appender appender) + { + String name = propDesc.getName(); + Class<?> type = propDesc.getPropertyType(); + Object value; + try + { + Method getter = propDesc.getReadMethod(); + if (getter == null) + return; + value = getter.invoke(bean); + } + catch (Exception ee) + { + throw new ConversionException("unable to retrieve bean value", ee); + } + + if (value == null) + tryToConvertAsPrimitiveOrNull(value, type, name, appender); + else + convert(value, name, appender); + } +} Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlOptions.java (from rev 93, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Bean2XmlOptions.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlOptions.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlOptions.java 2009-08-14 18:41:47 UTC (rev 100) @@ -0,0 +1,55 @@ +// 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.bean2xml; + + +/** + * Options used by {@link Bean2XmlHandler} to control the structure of the + * DOM tree. + */ +public enum Bean2XmlOptions +{ + /** + * Outputs values using formats defined by XML Schema, rather than Java's + * <code>String.valueOf()</code> method. Note that these formats are not + * 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:XXX</code>", where XXX is the XSD type name. For complex + * types, this attribute's value will be "<code>java:XXX</code>", where + * XXX is the fully-qualified classname. + * <p> + * <em>This option implies {@link #XSD_FORMAT} for simple types</em>. + */ + XSI_TYPE, + + /** + * Report null values using the <code>xsi:nil="true"</code> attribute. If + * not present, null values are ignored, and not added to DOM tree. + */ + XSI_NIL, + + /** + * Output maps in an "introspected" format, where the name of each item + * is the map key (rather than "data"), and the "key" attribute is omitted. + * If any key is not a valid XML identifier, the converter will throw. + */ + INTROSPECT_MAPS +} Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java (from rev 96, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanDriver.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java 2009-08-14 18:41:47 UTC (rev 100) @@ -0,0 +1,35 @@ +// 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.xml2bean; + +import org.w3c.dom.Element; + + +/** + * Driver class for converting an XML DOM into a Java bean, using a {@link + * Xml2BeanHandler} to manage data conversion. + */ +public class Xml2BeanDriver +{ + /** + * Fills a bean-style object from an XML element. For each child of the + * passed element, tries to find a property with the same name, invokes + * the appropriate conversion handler method, and sets the property from + * the result. + */ + public void dispatch(Element elem, Object bean) + { + } +} Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java (from rev 98, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanHandler.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java 2009-08-14 18:41:47 UTC (rev 100) @@ -0,0 +1,194 @@ +// 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.xml2bean; + +import net.sf.practicalxml.DomUtil; +import net.sf.practicalxml.XmlException; +import net.sf.practicalxml.XmlUtil; +import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.PrimitiveConversionHelper; +import net.sf.practicalxml.internal.StringUtils; + +import java.util.Arrays; +import java.util.Date; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.xml.XMLConstants; + +import org.w3c.dom.Element; + + +/** + * Invoked by {@link Xml2BeanDriver} to convert a DOM <code>Element</code> + * into the appropriate Java object. Unlike {@link Bean2XmlHandler}, there + * will only be one instance of this object created during conversion; all + * intermediate data can be held on the stack. + */ +public class Xml2BeanHandler +{ + private EnumSet<Xml2BeanOptions> _options; + private PrimitiveConversionHelper _primitiveHelper; + + + /** + * Public constructor, allowing various options specifications. + */ + public Xml2BeanHandler(Xml2BeanOptions... options) + { + _options = EnumSet.noneOf(Xml2BeanOptions.class); + for (Xml2BeanOptions option : options) + _options.add(option); + + _primitiveHelper = new PrimitiveConversionHelper(true); + } + + +//---------------------------------------------------------------------------- +// Public Methods +//---------------------------------------------------------------------------- + + public Boolean convertBoolean(Element elem) + { + return (Boolean)_primitiveHelper.parse(getText(elem), Boolean.class); + } + + + public Byte convertByte(Element elem) + { + return (Byte)_primitiveHelper.parse(getText(elem), Byte.class); + } + + + public Character convertCharacter(Element elem) + { + return (Character)_primitiveHelper.parse(getText(elem), Character.class); + } + + + public Date convertDate(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public Double convertDouble(Element elem) + { + return (Double)_primitiveHelper.parse(getText(elem), Double.class); + } + + + public Float convertFloat(Element elem) + { + return (Float)_primitiveHelper.parse(getText(elem), Float.class); + } + + + public Integer convertInteger(Element elem) + { + return (Integer)_primitiveHelper.parse(getText(elem), Integer.class); + } + + + public Long convertLong(Element elem) + { + return (Long)_primitiveHelper.parse(getText(elem), Long.class); + } + + + public Number convertNumber(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public Short convertShort(Element elem) + { + return (Short)_primitiveHelper.parse(getText(elem), Short.class); + } + + + public String convertString(Element elem) + { + return (String)_primitiveHelper.parse(getText(elem), String.class); + } + + + public List<?> convertList(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public Set<?> convertSet(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public Map<?,?> convertMap(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public Object convertObject(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public Object[] convertObjectArray(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + +//---------------------------------------------------------------------------- +// Internals +//---------------------------------------------------------------------------- + + /** + * Returns the text from a passed element, applying any low-level options + * along the way. + */ + private String getText(Element elem) + { + String text = DomUtil.getText(elem); + if (_options.contains(Xml2BeanOptions.CONVERT_BLANK_AS_NULL) && StringUtils.isBlank(text)) + text = null; + validateXsiNil(elem, text); + return text; + } + + + /** + * Checks for elements that require <code>xsi:nil</code>, and throws if missing. + */ + private void validateXsiNil(Element elem, String text) + { + if (text != null) + return; + if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_NIL)) + return; + + String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"); + if ((attr == null) || !attr.equals("true")) + throw new ConversionException("empty element without required xsi:nil"); + } + +} Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java (from rev 98, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/Xml2BeanOptions.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java 2009-08-14 18:41:47 UTC (rev 100) @@ -0,0 +1,71 @@ +// 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 CONDITI... [truncated message content] |