/* * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2002 * Copyright by ESO (in the framework of the ALMA collaboration), * All rights reserved * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ package alma.acs.entityutil; import java.io.StringReader; import java.util.logging.Level; import java.util.logging.Logger; import org.exolab.castor.xml.Unmarshaller; import alma.entities.commonentity.EntityT; import alma.xmlentity.XmlEntityStruct; /** * Helper class to convert serialized XML entities from the ALMA project data model (APDM) * to their Java binding class representations. *
* Note that normally a Java component does not need to explicitly perform this conversion, * since the Java container translates between the XML-string representation that goes over CORBA, * and the binding class (tree) that the custom-generated component's Java interface uses * as parameters or return value. *
* However, there is a case where a Java component should use the EntityDeserializer
:
* Applications receiving XML data from the ALMA archive: the archive does currently not offer a type-safe
* interface for APDM entities. Use {@link #deserializeEntity(XmlEntityStruct, Class)} to convert
* the XmlEntityStruct
you get from the archive into a Java binding object tree
* whose root node is an instance of the specified Class
.
*
* @author hsommer May 6, 2003 5:31:57 PM
*/
public class EntityDeserializer
{
private Logger m_logger;
private static EntityDeserializer s_entityDeserializer;
private EntityTFinder m_finder;
/**
* Singleton accessor.
*
* @param logger Logger to be used
* (may be null in subsequent invocations since only one instance of
* EntityDeserializer is constructed and then reused)
*
* @return single instance
*/
public static EntityDeserializer getEntityDeserializer(Logger logger)
{
if (s_entityDeserializer == null)
{
s_entityDeserializer = new EntityDeserializer(logger);
}
return s_entityDeserializer;
}
/**
* @param logger
*/
private EntityDeserializer(Logger logger)
{
m_logger = logger;
m_finder = new EntityTFinder(m_logger);
}
/**
* Deserializes (parses) an entity xml and instantiates the binding objects.
*
* @param xmlString the stringified xml.
* @param entityClass the binding class of which we want an instance
* filled with the xml data.
* @param timestamp the timestamp to be stored in the entity object, for later serialization.
* @return the binding class instance (should be casted by the caller).
* @throws EntityException if the binding class instance can't be constructed from the xml.
* Note that this exception is only logged at FINER level by this method, so make sure to log it appropriately.
*/
private Object deserializeEntity(String xmlString, Class entityClass, String timestamp)
throws EntityException
{
if (xmlString == null)
throw new EntityException("xmlString was null.");
if (entityClass == null)
throw new EntityException("entityClass was null.");
if (timestamp == null)
timestamp = "";
Object entity;
try
{
Unmarshaller unmarsh = new Unmarshaller(entityClass);
unmarsh.setValidation(false);
unmarsh.setWhitespacePreserve(true);
// unmarsh.setIgnoreExtraAttributes(true);
// unmarsh.setIgnoreExtraElements(true);
entity = unmarsh.unmarshal(new StringReader(xmlString));
}
catch (Exception e)
{
String xmlStringStart = xmlString.substring(0, Math.min(512, xmlString.length())); // trim huge xml to avoid overly long log message
String msg = "Failed to parse xml into entity binding class '" + entityClass.getName() + "'. The xml data was " + xmlStringStart;
m_logger.log(Level.FINER, msg, e);
throw new EntityException(msg, e);
}
// store the timestamp in the entity; this is a temporary storage, until
// the entity is converted back into an XmlEntityStruct; then the timestamp
// becomes irrelevant.
if (entity != null)
{
EntityT entityMeta = m_finder.extractEntityT(entity);
if (entityMeta != null)
{
entityMeta.setTimestamp(timestamp);
}
}
return entity;
}
/**
* Deserializes (parses) the entity xml contained in xes
* and instantiates the binding objects.
*
* @param xes the struct used for CORBA transport of serialized entity objects.
* @param entityClass the binding class of which we want an instance
* filled with the xml data, e.g. SchedBlock.class
.
* @return the binding class instance (should be cast to entityClass
by the caller).
* @throws EntityException
*/
public Object deserializeEntity(XmlEntityStruct xes, Class entityClass)
throws EntityException
{
String xml = xes.xmlString;
String timestamp = xes.timeStamp;
return deserializeEntity(xml, entityClass, timestamp);
}
}