package org.bifrost.xmlio.impl;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.logging.Logger;
import org.bifrost.xmlio.XmlException;
import org.bifrost.xmlio.config.Converter;
import org.bifrost.xmlio.config.ObjectMap;
import org.bifrost.xmlio.config.PropertyMap;
import org.bifrost.xmlio.config.XmlIOConfig;
/**
* <p>This utility class helps find mutators for attributes and will use the
* Converter class to convert string values and pass converted parameters to
* those muators.</p>
* <p>
* Created: Apr 12, 2004<br/>
* Copyright: Copyright (c) 2004<br/>
* Assumptions: none<br/>
* Requires: Converter<br/>
* Required by: ReaderContentHelper<br/>
* Revision History:<br/>
* <br/>
* </p>
* @author Donald Kittle <dkittle@mintinc.ca> (last commit: $Author: donald $)
* @version 1.0 (revision $Revision: 1.4 $)
* @stereotype Util
*/
public class PropertyHelper
{
/**
* CVS version information.
*/
private final static String _VERSION =
"$Id: PropertyHelper.java,v 1.4 2004/05/26 22:05:10 donald Exp $";
private Logger logger = Logger.getLogger(this.getClass().getName());
/**
* An instance of the XmlIOConfig object
*/
private XmlIOConfig config = XmlIOConfig.getInstance();
private static PropertyHelper instance = new PropertyHelper();
/**
* Returns a singleton instance of this class
* @return PropertyHelper a singleton instance of this class
*/
public static PropertyHelper getInstance()
{
return instance;
} // end getInstance()
/**
* Constructor
*/
public PropertyHelper()
{
} // end Constructor()
/**
* Sets a certain attribute in an object to the specified value. If the
* attribute does not exist in the object, assume that the attribute is a
* object (rather than a primative) and see if there is a mutator matching
* the name of one of the attribute's superclasses.
* For example, if attributeName is Foo and Foo extends Bar, this method
* will first try to find a mutator called setFoo() and will then try
* addFoo(). If such a mutator could not be found, the method will then
* try to find setBar() and then addBar().
* @param object the object which the attribute is in
* @param method the setter method to call
* @param value the value that should be passed to the setter
* @throws XmlException if there was a problem
*/
public void setAttribute(PropertyMap pmap, Object object, Method method, Object value)
throws XmlException
{
if (object == null)
throw new XmlException("Must pass an object whose attribute will be set.");
Class paramClass = null;
String paramClassName = null;
Class[] paramTypes = null;
if (method != null)
{
paramTypes = method.getParameterTypes();
if (paramTypes != null && paramTypes.length == 1)
{
paramClass = paramTypes[0];
paramClassName = paramClass.getName();
}
}
// We've got the type, figure out what converter to use
Converter converter = pmap.getConverter();
if (converter == null)
converter = config.getConverter(paramClassName);
// else
// {
// if (!pmap.getPropertyType().equals(paramClassName))
// {
// pmap.setPropertyType(paramClass);
// converter = config.getConverter(paramClassName);
// pmap.setConverter(converter);
// }
// }
// If no converter is found, make sure we are not processing a text
// node, we must be processing a subtag (an object).
if (converter == null)
{
if (value instanceof java.lang.String)
{
logger.info("Warning, processing text but no converter found for "
+ paramClassName);
return;
}
}
// Found a setter so now lets make sure the attribute value is of the
// correct type and then call the setter.
Object[] params = null;
if (value != null && paramClassName != null)
{
params = new Object[1];
// Converter converter = config.getConverter(paramClass);
if (converter == null)
{
params[0] = value;
}
else
{
Object converterImpl = null;
if (converter.getClass().getName().equals(converter.getClassname()))
converterImpl = converter;
else
{
ObjectFactory factory = config.getObjectFactory();
converterImpl = factory.getInstance(converter.getClassname());
}
try
{
Class[] convTypes = new Class[1];
convTypes[0] = value.getClass();
Method parseMethod =
converterImpl.getClass().getMethod(converter.getParseMethod(),
convTypes);
Object[] convParams = new Object[1];
convParams[0] = value;
params[0] = parseMethod.invoke(converterImpl, convParams);
}
catch(NoSuchMethodException nsme)
{
logger.info("No such method " + converter.getParseMethod());
}
catch (InvocationTargetException ite)
{
logger.info("Called method threw an exception.");
}
catch(Exception e)
{
logger.info("Some other exception: " + e.toString());
}
}
}
else if (paramClassName != null)
{
params = new Object[1];
params[0] = null;
}
try
{
method.invoke(object, params);
} catch (IllegalArgumentException e)
{
logger.info("Some other exception: " + e.toString());
} catch (IllegalAccessException e)
{
logger.info("Some other exception: " + e.toString());
} catch (InvocationTargetException e)
{
logger.info("Some other exception: " + e.toString());
}
} // end setAttribute()
/**
* Given a property name, return the alias for this property, if it exists.
* An alias for the specific class will be given preference to a 'global'
* property mapping.
* @param classAlias the object alias whose mapping should be used, the
* object mapping is not check if this is null
* @param alias the alias the property is known by
* @return String the name if found or the value of the alias otherwise
*/
public String getPropertyNameFromAlias(String classAlias, String alias)
{
if (alias == null)
{
logger.fine("No alias name passed");
return null;
}
String result = alias;
// Check to see is this attribute has a mapping.
if (config.getPropertyMapByAlias(alias) != null)
{
PropertyMap map = config.getPropertyMapByAlias(alias);
if (map != null && map.getPropertyName() != null)
{
result = map.getPropertyName();
logger.fine("Found global property map for " + alias);
}
}
// See if this property is actually an object in the mapping
if (config.getObjectMapByAlias(alias) != null)
{
ObjectMap map = config.getObjectMapByAlias(alias);
logger.fine("Found map for " + alias + " as an object (" +
map.getName() + ")");
result = map.getName();
return result;
}
if (classAlias == null)
{
logger.fine("No class alias name passed");
return result;
}
// See if the current object is in the mapping and if this property is
// also mapped...
if (config.getObjectMapByAlias(classAlias) != null)
{
ObjectMap map = config.getObjectMapByAlias(classAlias);
if (map != null && map.getPropertyMapFromAlias(alias) != null)
{
PropertyMap pMap = map.getPropertyMapFromAlias(alias);
if (pMap.getPropertyName() != null)
{
logger.fine("Found property map for " + alias +
" as part of map for " + classAlias);
result = pMap.getPropertyName();
}
} // end property map found
} // end object map found
if (result == null || result.length() == 0)
logger.fine("No mapping found for " + classAlias + "/" + alias);
return result;
} // end getpropertyNameFromAlias()
} // end PropertyHelper Class