com.tangosol.run.xml.IterableAdapter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of coherence Show documentation
Show all versions of coherence Show documentation
Oracle Coherence Community Edition
/*
* 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;
/**
* An IterableAdapter is the base class for any data type that must be
* iterated over to serialize/deserialize, such as arrays, collections
* and maps.
*
*
* <property>
* <name>People</name>
* <xml-name>people</xml-name> <!-- optional, empty name indicates anonymous element -->
* <adapter>...</adapter> <!-- optional -->
* <type>...</type> <!-- defaults via reflection -->
* <class>...</class> <!-- defaults to <type> -->
* <sparse>true</sparse> <!-- defaults to false -->
* <empty-is-null>true</empty-is-null> <!-- defaults to false -->
* <element> <!-- optional, depends on the adapter -->
* <xml-name>person</xml-name> <!-- optional, nests the elements -->
* </element>
* <property>
*
* Example of collection/array nested within collection tags:
*
* <doc>
* <people>
* <person>...</person>
* <person>...</person>
* ...
* </people>
* </doc>
*
* Example of collection/array nested directly within the document:
*
* <doc>
* <person>...</person>
* <person>...</person>
* ...
* </doc>
*
* Example of map nested within collection tags:
*
* <doc>
* <people>
* <person>
* <name>...</name>
* <number>...</number>
* </person>
* <person>
* <name>...</name>
* <number>...</number>
* </person>
* ...
* </people>
* </doc>
*
* Example of map nested directly within the document:
*
* <doc>
* <person>
* <name>...</name>
* <number>...</number>
* </person>
* <person>
* <name>...</name>
* <number>...</number>
* </person>
* ...
* </doc>
*
*
* @version 1.00 2001.03.18
* @author cp
*/
public abstract class IterableAdapter
extends PropertyAdapter
{
// ----- constructors ---------------------------------------------------
/**
* Construct a IterableAdapter.
*
* @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 IterableAdapter(XmlBean.BeanInfo infoBean, Class clzType, String sName, String sXml, XmlElement xml)
{
super(infoBean, clzType, sName, sXml, xml);
// determine if sparse array storage is desired
m_fSparse = xml.getSafeElement("sparse").getBoolean();
// determine if empty and null are synonymous
m_fEmptyIsNull = xml.getSafeElement("empty-is-null").getBoolean();
// determine if the elements will be nested (true if there is
// a sub-element name)
XmlElement xmlElement = xml.findElement("element/xml-name");
if (xmlElement == null)
{
// sparse requires the elements to be nested one level down
azzert(!m_fSparse);
}
else
{
m_sElement = xmlElement.getString();
}
}
// ----- accessors ------------------------------------------------------
/**
* @return true if the property value must be "deep" cloned when the
* containing object is cloned
*/
public boolean isCloneRequired()
{
return true;
}
/**
* @return true if the iterable data should be stored in a sparse format
* in XML
*/
public boolean isSparse()
{
return m_fSparse;
}
/**
* @return true if the iterable data should not be stored at all if it
* is empty, such as a zero-length array or empty collection
*/
public boolean isEmptyIsNull()
{
return m_fEmptyIsNull;
}
/**
* @return the local XML name of the individual array elements
* (null if the array elements are nested directly within
* the document)
*/
public String getElementName()
{
return m_sElement;
}
/**
* @return true only if this adapter creates a single XML element on
* writeXml and reads from a single XML element on readXml
*/
public boolean isNested()
{
return getElementName() != null;
}
// ----- XmlSerializable helpers ----------------------------------------
/**
* Deserialize an object from an XML element.
*
* @param xml the XML element to deserialize from
*
* @return the object deserialized from the XML element
*
* @exception UnsupportedOperationException if the property cannot be
* read from a single XML element
*/
public Object fromXml(XmlElement xml)
{
return readElements(xml);
}
/**
* Serialize an object into an XML element.
*
* @param o the object to serialize
*
* @return the XML element representing the serialized form of the
* passed object
*
* @exception UnsupportedOperationException if the property cannot be
* written to a single XML element
*/
public XmlElement toXml(Object o)
{
// anonymous element's name must be discarded by the caller
XmlElement xml = new SimpleElement(getXmlName());
writeElements(xml, o);
return xml;
}
/**
* @param xml the XML element containing the XML elements to deserialize
* from
*
* @return the object deserialized from the XML (not null)
*/
protected abstract Object readElements(XmlElement xml);
/**
* @param xml the XML element to which the iterable elements are written
* @param o the object to serialize (not null)
*/
protected abstract void writeElements(XmlElement xml, Object o);
// ----- helpers --------------------------------------------------------
/**
* Obtain a PropertyAdapapter for a map entry key or value
*
* @param infoBean BeanInfo for a bean containing this property
* @param xml the information about the map entry key or value
*
* @return a PropertyAdapter for the map entry key or value
*/
protected PropertyAdapter findAdapter(XmlBean.BeanInfo infoBean, XmlElement xml)
{
azzert(xml != null);
String sName = null;
XmlValue xmlName = xml.getElement("xml-name");
if (xmlName != null)
{
sName = xmlName.getString();
}
XmlValue xmlType = xml.getElement("type");
azzert(xmlType != null);
Class clz = infoBean.resolveClass(xmlType.getString());
return infoBean.makeAdapter(clz, null, sName, xml);
}
// ----- data members ---------------------------------------------------
/**
* Sparse array storage option.
*/
protected boolean m_fSparse;
/**
* Empty-is-null option: Empty iterable values are not stored in the
* serialized form of the XmlBean nor in the XML form of the XmlBean.
*/
protected boolean m_fEmptyIsNull;
/**
* Name used for each element of the array when formatted into XML. If
* null, then the elements are placed directly into the document using the
* adapter's XML name.
*/
protected String m_sElement;
}