All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tangosol.run.xml.CollectionAdapter Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

package com.tangosol.run.xml;


import com.tangosol.util.ClassHelper;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;


/**
* A CollectionAdapter supports properties whose types implement the
* java.util.Collection interface.
* 

* <property>
*   <name>People</name>
*   <xml-name>people</xml-name>         <!-- defaults to <name> -->
*   <type>java.util.Collection</type>   <!-- defaults via reflection -->
*   <class>java.util.LinkedList</class> <!-- defaults to <type> -->
*   <empty-is-null>true</empty-is-null> <!-- defaults to false -->
*   <element>
*     <xml-name>person</xml-name>       <!-- optional, nests the elements -->
*     <type>com...PersonBean</type>     <!-- required -->
*     <adapter>...</adapter>            <!-- optional -->
*     <...>                             <!-- for the type-specific adapter -->
*   </element>
* </property>
* 
* * Example of collection nested within collection tags: *

*   <doc>
*     <people>
*       <person>
*         <...>
*       </person>
*       <person>
*         <...>
*       </person>
*       ...
*     </people>
*   </doc>
* 
* * @version 1.00 2001.03.18 * @author cp */ public class CollectionAdapter extends IterableAdapter { // ----- constructors --------------------------------------------------- /** * Construct a CollectionAdapter. * * @param infoBean BeanInfo for a bean containing this property * @param clzType the type of the property * @param sName the property name * @param sXml the XML tag name * @param xml additional XML information */ public CollectionAdapter(XmlBean.BeanInfo infoBean, Class clzType, String sName, String sXml, XmlElement xml) { super(infoBean, clzType, sName, sXml, xml); azzert(Collection.class.isAssignableFrom(clzType)); // determine the collection class used Class clzCollection = getType(); XmlValue xmlClz = xml.getElement("class"); if (xmlClz != null) { clzCollection = infoBean.resolveClass(xmlClz.getString()); } m_clzCollection = clzCollection; XmlElement xmlElement = xml.getElement("element"); if (xmlElement == null) { throw new IllegalStateException( "Missing the \"\" information for the \"" + sName + "\" property of the \"" + ClassHelper.getSimpleName(infoBean.getType()) + "\" XmlBean."); } m_adapterElement = findAdapter(infoBean, xmlElement); } // ----- Object method helpers ------------------------------------------ /** * Make a clone of the passed object. * * @param o the object to clone * * @return a clone of the passed object */ public Object clone(Object o) { if (o == null) { return null; } PropertyAdapter adapterElement = m_adapterElement; Collection colOld = (Collection) o; Collection colNew = instantiateCollection(); for (Iterator iter = colOld.iterator(); iter.hasNext(); ) { Object oElement = iter.next(); if (oElement != null) { oElement = adapterElement.clone(oElement); } colNew.add(oElement); } return colNew; } // ----- XmlSerializable helpers ---------------------------------------- /** * @param xml the XML element containing the XML elements to deserialize * from * * @return the object deserialized from the XML (not null) */ protected Object readElements(XmlElement xml) { Collection collection = instantiateCollection(); PropertyAdapter adapterElement = m_adapterElement; boolean fAnonymous = adapterElement.isAnonymous(); Iterator iter = fAnonymous ? xml.getElementList().iterator() : XmlHelper.getElements( xml, getElementName(), adapterElement.getNamespaceUri()); while (iter.hasNext()) { XmlElement xmlElement = (XmlElement) iter.next(); Object oElement = adapterElement.fromXml(xmlElement); // anonymous collections do not allow null elements if (!fAnonymous || oElement != null) { collection.add(oElement); } } return collection; } /** * @param xml the XML element to which the iterable elements are written * @param o the object to serialize (not null) */ protected void writeElements(XmlElement xml, Object o) { Collection collection = (Collection) o; if (collection.isEmpty()) { return; } PropertyAdapter adapterElement = m_adapterElement; boolean fAnonymous = adapterElement.isAnonymous(); String sNmsPrefix = null; String sElement = null; if (!fAnonymous) { sNmsPrefix = adapterElement.getNamespacePrefix(); sElement = XmlHelper.getUniversalName(getElementName(), sNmsPrefix); } List list = xml.getElementList(); for (Iterator iter = ((Collection) o).iterator(); iter.hasNext();) { Object oElement = iter.next(); // the following is almost identical to a call // adapterElement.writeXml(xml, oElement); // except that the element name could be different XmlElement xmlElement = adapterElement.toXml(oElement); if (xmlElement != null) { if (fAnonymous) { List listElement = xmlElement.getElementList(); int cElements = listElement.size(); if (cElements == 1) { list.add(listElement.get(0)); } else if (cElements > 1) { throw new IllegalStateException("Too many elements: " + xmlElement + "\nadapter=" + adapterElement); } } else { xmlElement.setName(sElement); list.add(xmlElement); } } } /* if (sNmsPrefix != null) { XmlHelper.ensureNamespace(xml, sNmsPrefix, adapterElement.getNamespaceUri()); XmlHelper.purgeChildrenNamespace(xml); } */ } // ----- ExternalizableLite helpers ------------------------------------- /** * Read a value from the passed DataInput object. * * @param in the DataInput stream to read property data from * * @return the data read from the DataInput; never null * * @exception IOException if an I/O exception occurs */ public Object readExternal(DataInput in) throws IOException { Collection collection = instantiateCollection(); PropertyAdapter adapter = getElementAdapter(); // "in" contains a collection size and, for each element, a non-null // indicator and (if non-null) the object for (int i = 0, c = readInt(in); i < c; ++i) { collection.add(in.readBoolean() ? adapter.readExternal(in) : null); } return collection; } /** * Write the specified data to the passed DataOutput object. * * @param out the DataOutput stream to write to * @param o the data to write to the DataOutput; never null * * @exception IOException if an I/O exception occurs */ public void writeExternal(DataOutput out, Object o) throws IOException { Collection collection = (Collection) o; PropertyAdapter adapter = getElementAdapter(); int c = collection.size(); writeInt(out, c); int cActual = 0; for (Iterator iter = collection.iterator(); iter.hasNext(); ) { Object oElement = iter.next(); boolean fExists = (oElement != null); out.writeBoolean(fExists); if (fExists) { adapter.writeExternal(out, oElement); } ++cActual; } if (c != cActual) { throw new IOException("expected " + c + " elements, but wrote " + cActual); } } // ----- PropertyAdapter methods ---------------------------------------- /** * Determine if the specified value is empty. * * @param o the value * * @return true if the object is considered to be empty for persistence * and XML-generation purposes */ public boolean isEmpty(Object o) { return o == null || isEmptyIsNull() && ((Collection) o).isEmpty(); } // ----- internal helpers ----------------------------------------------- /** * @return a PropertyAdapter for collection elements */ public PropertyAdapter getElementAdapter() { return m_adapterElement; } /** * @return a new Collection instance */ protected Collection instantiateCollection() { try { return (Collection) m_clzCollection.newInstance(); } catch (Throwable e) { throw ensureRuntimeException(e); } } // ----- data members --------------------------------------------------- private Class m_clzCollection; private PropertyAdapter m_adapterElement; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy