/*
* 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.component.dynwrapper;
import java.io.StringWriter;
import java.util.logging.Logger;
import org.exolab.castor.xml.Marshaller;
import alma.acs.entityutil.EntityException;
import alma.acs.entityutil.EntityTFinder;
import alma.entities.commonentity.EntityT;
import alma.xmlentity.XmlEntityStruct;
/**
* A type mapper that can marshal a Castor generated entity object
* to the IDL struct used for CORBA transport (<code>XmlEntityStruct</code>).
*
* @author hsommer
*/
public class CastorMarshalMapper extends TypeMapper
{
private EntityTFinder m_entityTFinder;
/**
* @see alma.acs.component.dynwrapper.TypeMapper#TypeMapper(java.lang.Object, Logger)
*/
public CastorMarshalMapper(Object delegate, Logger logger)
{
super(delegate, logger);
m_entityTFinder = new EntityTFinder(logger);
m_entityTFinder.setVerbose(m_verbose);
}
/**
* True if <code>oldObjClass</code> is a Castor generated entity class
* that has a child of type <code>EntityT</code>,
* and if <code>newObjClass</code> is the <code>XmlEntityStruct</code> class.
*
* @see alma.acs.component.dynwrapper.TypeMapper#canTranslate(java.lang.Class, java.lang.Class,
* alma.acs.component.dynwrapper.ComponentInvocationHandler)
*/
public boolean canTranslate(Class<?> oldObjClass, Class<?> newObjClass, ComponentInvocationHandler invHandler)
{
boolean canTranslate = true;
try
{
// check if oldObjClass has a child of type EntityT (or subtype)
m_entityTFinder.getEntityTMethod(oldObjClass);
// check if newObjClass is XmlEntityStruct
// we don't trust Class#equals() here; we really want it to be XmlEntityStruct and not a subclass,
// but that can't happen anyway since IDL structs can't be subclassed.
if (!XmlEntityStruct.class.isAssignableFrom(newObjClass))
{
throw new DynWrapperException();
}
}
catch (Exception ex)
{
canTranslate = false;
}
if (m_verbose)
{
m_logger.finest("can " + (canTranslate ? "" : "not ") + "translate from class '" + oldObjClass.getName() +
"' to class '" + newObjClass.getName());
}
return canTranslate;
}
/**
* Converts a Castor generated entity object to the marshalled representation as
* an <code>XmlEntityStruct</code>.
*
* @see alma.acs.component.dynwrapper.TypeMapper#translate(java.lang.Object, java.lang.Object, java.lang.Class,
* alma.acs.component.dynwrapper.ComponentInvocationHandler)
*/
@SuppressWarnings("unchecked")
public Object translate(Object oldObject, Object newObjectTemplate,
Class newObjectClass, ComponentInvocationHandler invHandler)
throws DynWrapperException
{
if (oldObject == null) {
return null;
}
EntityT entityMeta;
try
{
entityMeta = m_entityTFinder.extractEntityT(oldObject);
}
catch (EntityException e)
{
String extractionErrMsg = "failed to extract EntityT object from " +
oldObject.getClass().getName();
throw new DynWrapperException(extractionErrMsg, e);
}
if (entityMeta == null)
{
String extractionNullErrMsg = "entity object of type " + oldObject.getClass().getName() +
" must have a non-null child assignable to " + EntityT.class.getName() + " to be serialized.";
throw new DynWrapperException(extractionNullErrMsg);
}
XmlEntityStruct entStruct = null;
// TODO: check if newObjectTemplate is needed here at all, or if those cases would always be
// dealt with using a Holder class. Just confused right now...
if (newObjectTemplate != null)
{
if (!XmlEntityStruct.class.isInstance(newObjectTemplate))
{
throw new DynWrapperException("invalid template for XmlEntityStruct object");
}
entStruct = (XmlEntityStruct) newObjectTemplate;
}
else
{
entStruct = new XmlEntityStruct();
}
entStruct.entityId = entityMeta.getEntityId();
entStruct.entityTypeName = entityMeta.getEntityTypeName();
entStruct.schemaVersion = ( entityMeta.getSchemaVersion() != null ? entityMeta.getSchemaVersion() : "");
try
{
StringWriter wr = new StringWriter();
Marshaller marsh = new Marshaller(wr);
marsh.setValidation(false);
marsh.marshal(oldObject);
entStruct.xmlString = wr.toString();
}
catch (Exception e)
{
String msg = "failed to marshal entity object with id='" + entityMeta.getEntityId() +
"' using the Castor Marshaller without validation.";
throw new DynWrapperException(msg);
}
if (m_verbose)
{
m_logger.finer("successfully translated from '" + oldObject.getClass().getName() + "' to '" +
entStruct.getClass().getName() + "'.");
}
return entStruct;
}
}