/*
* Copyright 2002 Draagon Software LLC. All Rights Reserved.
*
* This software is the proprietary information of Draagon Software LLC.
* Use is subject to license terms.
*/
package com.draagon.meta.object;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.draagon.meta.BeanMetaClass;
import com.draagon.meta.MetaClass;
import com.draagon.meta.MetaException;
import com.draagon.meta.MetaField;
import com.draagon.meta.StatefulMetaClass;
import com.draagon.meta.field.*;
//import com.draagon.meta.manager.ManagedMetaClass;
//import com.draagon.meta.manager.ObjectManager;
import com.draagon.meta.util.Converter;
@SuppressWarnings("serial")
public class MetaObjectClass extends BeanMetaClass implements StatefulMetaClass //, ManagedMetaClass
{
private static Log log = LogFactory.getLog( MetaObjectClass.class );
public final static String CACHE_PARAM_HAS_GETTER_METHOD = "hasGetterMethod";
public final static String CACHE_PARAM_HAS_SETTER_METHOD = "hasSetterMethod";
/** Object class name attribute */
public final static String ATTR_OBJECT = "object";
/**
* Constructs the MetaClassObject for MetaObjects
*/
public MetaObjectClass()
{
}
public static MetaClass createFromTemplate( String name, String template )
{
// Let's create one from scratch
MetaObjectClass mc = new MetaObjectClass();
mc.setName( name );
if ( template.length() == 0 ) template = null;
while( template != null )
{
String param = null;
int i = template.indexOf( ',' );
if ( i >= 0 ) {
param = template.substring( 0, i ).trim();
template = template.substring( i + 1 ).trim();
if ( template.length() == 0 ) template = null;
}
else {
param = template.trim();
template = null;
}
i = param.indexOf( ':' );
if ( i <= 0 )
throw new IllegalArgumentException( "Malformed template field parameter [" + param + "]" );
String field = param.substring( 0, i ).trim();
String type = param.substring( i + 1 ).trim();
if ( field.length() == 0 )
throw new IllegalArgumentException( "Malformed template field name parameter [" + param + "]" );
if ( type.length() == 0 )
throw new IllegalArgumentException( "Malformed template field type parameter [" + param + "]" );
MetaField mf = null;
if ( type.equals( "int" ))
mf = new IntegerField();
else if ( type.equals( "long" ))
mf = new LongField();
else if ( type.equals( "short" ))
mf = new ShortField();
else if ( type.equals( "byte" ))
mf = new ByteField();
else if ( type.equals( "boolean" ))
mf = new BooleanField();
else if ( type.equals( "float" ))
mf = new FloatField();
else if ( type.equals( "double" ))
mf = new DoubleField();
else if ( type.equals( "date" ))
mf = new DateField();
else
mf = new StringField();
mf.setName( field );
mc.addMetaField( mf );
}
return mc;
}
/**
* Retrieves the attribute options expected for this class
*/
public Collection<AttributeOption> getAttributeOptions()
{
ArrayList<AttributeOption> al = new ArrayList<AttributeOption>();
al.add( new AttributeOption( ATTR_OBJECT, String.class, true, "The object class to instantiate" ));
return al;
}
/**
* Retrieves the object class of an object
*/
protected Class<?> getObjectClass()
throws ClassNotFoundException
{
Class<?> c = super.getObjectClass();
if ( c != null ) return c;
return MetaObject.class;
}
/**
* Whether the MetaClass handles the object specified
*/
public boolean produces( Object obj )
{
if ( obj == null ) return false;
if ( obj instanceof MetaObject )
{
MetaObject mo = (MetaObject) obj;
if ( mo.getMetaClassName() == null )
{
log.warn( "MetaObject with no MetaClassName: [" + obj.getClass() + "]" );
return false;
}
// TODO: WARNING: This doesn't match up class loaders!
if ( mo.getMetaClassName().equals( getName() ))
return true;
}
return false;
}
////////////////////////////////////////////////////
// PERSISTENCE METHODS
/**
* Attaches a Object Manager to the object
*/
/*public void attachManager( ObjectManager mm, Object obj )
{
try { getMetaObject( obj ).attachObjectManager( mm ); }
catch( MetaException e ) { log.error( e.getMessage(), e ); }
}*/
/**
* Gets the Object Manager for the object
*/
/*public ObjectManager getManager( Object obj )
{
try { return getMetaObject( obj ).getObjectManager(); }
catch( MetaException e ) { log.error( e.getMessage(), e ); }
return null;
}*/
private MetaObject getMetaObject( Object o )
throws MetaException
{
if ( o == null )
throw new MetaException( "Null value found, MetaObject expected" );
if (! ( o instanceof MetaObject ))
throw new MetaException( "MetaObject expected, not [" + o.getClass().getName() + "]" );
return (MetaObject) o;
}
/**
* Retrieve the id of the object
*/
//public String getId( Object obj )
// throws MetaException
//{
// return getMetaObject( obj ).getObjectId();
//}
/**
* Retrieve the id of the object
*/
//public void setId( Object obj, String id )
// throws MetaException
//{
// getMetaObject( obj ).setObjectId( id );
//}
////////////////////////////////////////////////////
// PERSISTENCE METHODS
private MetaObject.Value getAttributeValue( MetaField f, Object obj )
throws MetaException
{
if (! ( obj instanceof MetaObject ))
throw new MetaException( "MetaObject expected, not [" + obj.getClass().getName() + "]" );
return ((MetaObject) obj ).getObjectAttributeValue( f.getName() );
}
protected boolean hasGetterMethod( MetaField f, Class<?> objClass ) {
// Try the cache value first
Boolean b = (Boolean) f.getCacheValue( CACHE_PARAM_HAS_GETTER_METHOD + "." + objClass.getName() );
if ( b != null ) return b.booleanValue();
// Now try to actually get the method
Method m = null;
try { m = retrieveGetterMethod(f, objClass ); }
catch( NoSuchMethodError e ) {}
// Return whether the setter existed
if ( m != null ) {
f.setCacheValue( CACHE_PARAM_HAS_GETTER_METHOD + "." + objClass.getName(), Boolean.TRUE );
return true;
}
else {
f.setCacheValue( CACHE_PARAM_HAS_GETTER_METHOD + "." + objClass.getName(), Boolean.FALSE );
return false;
}
}
protected boolean hasSetterMethod( MetaField f, Class<?> objClass ) {
// Try the cache value first
Boolean b = (Boolean) f.getCacheValue( CACHE_PARAM_HAS_SETTER_METHOD + "." + objClass.getName() );
if ( b != null ) return b.booleanValue();
// Now try to actually get the method
Method m = null;
try { m = retrieveSetterMethod(f, objClass ); }
catch( NoSuchMethodError e ) {}
// Return whether the setter existed
if ( m != null ) {
f.setCacheValue( CACHE_PARAM_HAS_SETTER_METHOD + "." + objClass.getName(), Boolean.TRUE );
return true;
}
else {
f.setCacheValue( CACHE_PARAM_HAS_SETTER_METHOD + "." + objClass.getName(), Boolean.FALSE );
return false;
}
}
/**
* Gets the object attribute represented by this MetaField
*/
public Object getValue( MetaField f, Object obj )
//throws MetaException
{
if ( !( obj instanceof MetaObject ))
throw new IllegalArgumentException( "MetaObject expected, Invalid object of class [" + obj.getClass().getName() + "]" );
if ( hasGetterMethod(f, obj.getClass() )) {
return super.getValue( f, obj );
} else {
return ((MetaObject) obj ).getObjectAttribute( f.getName() );
}
}
/**
* Sets the object attribute represented by this MetaField
*/
public void setValue( MetaField f, Object obj, Object value )
//throws MetaException
{
if ( !( obj instanceof MetaObject ))
throw new IllegalArgumentException( "MetaObject expected, Invalid object of class [" + obj.getClass().getName() + "]" );
// Convert the value to the appropriate type
if ( value != null && f.getValueClass() != value.getClass() ) {
value = Converter.toType( f.getType(), value );
}
if ( hasSetterMethod(f, obj.getClass() )) {
super.setValue( f, obj, value );
} else {
((MetaObject) obj ).setObjectAttribute( f.getName(), value );
}
}
//////////////////////////////////////////////////////////////
// Stateful methods
public boolean isNew( Object obj )
throws MetaException
{
return getMetaObject( obj ).isNew();
}
public boolean isModified( Object obj )
throws MetaException
{
return getMetaObject( obj ).isModified();
}
public boolean isDeleted( Object obj )
throws MetaException
{
return getMetaObject( obj ).isDeleted();
}
public void setNew( Object obj, boolean state )
throws MetaException
{
getMetaObject( obj ).setNew( state );
}
public void setModified( Object obj, boolean state )
throws MetaException
{
getMetaObject( obj ).setModified( state );
}
public void setDeleted( Object obj, boolean state )
throws MetaException
{
getMetaObject( obj ).setDeleted( state );
}
public long getCreationTime( Object obj )
throws MetaException
{
return getMetaObject( obj ).getCreationTime();
}
public long getModifiedTime( Object obj )
throws MetaException
{
return getMetaObject( obj ).getModifiedTime();
}
public long getDeletedTime( Object obj )
throws MetaException
{
return getMetaObject( obj ).getDeletedTime();
}
/**
* Returns whether the field on the object was modified
*/
public boolean isFieldModified( MetaField f, Object obj )
throws MetaException
{
return getAttributeValue( f, obj ).isModified();
}
/**
* Sets whether the field is modified
*/
public void setFieldModified( MetaField f, Object obj, boolean state )
throws MetaException
{
getAttributeValue( f, obj ).setModified( state );
}
/**
* Gets the time the field was modified
*/
public long getFieldModifiedTime( MetaField f, Object obj )
throws MetaException
{
return getAttributeValue( f, obj ).getModifiedTime();
}
}