package com.eucalyptus.configurable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import javax.persistence.Entity;
import javax.persistence.PersistenceContext;
import javax.persistence.Transient;
import org.apache.log4j.Logger;
import com.eucalyptus.entities.EntityWrapper;
public class SingletonDatabasePropertyEntry extends AbstractConfigurableProperty implements ConfigurableProperty {
private static Logger LOG = Logger.getLogger( SingletonDatabasePropertyEntry.class );
private String baseMethodName;
private Method get;
private Method set;
private String persistenceContext;
private Class[] setArgs;
public SingletonDatabasePropertyEntry( Class definingClass, String entrySetName, Field field, String description, String defaultValue, PropertyTypeParser typeParser,
Boolean readOnly, String displayName, ConfigurableFieldType widgetType, String alias ) {
super( definingClass, entrySetName, field.getName( ), defaultValue, description, typeParser, readOnly, displayName, widgetType, alias );
this.baseMethodName = field.getName( ).substring( 0, 1 ).toUpperCase( ) + field.getName( ).substring( 1 );
this.persistenceContext = ( ( PersistenceContext ) definingClass.getAnnotation( PersistenceContext.class ) ).name( );
this.setArgs = new Class[] { field.getType( ) };
try {
get = definingClass.getDeclaredMethod( "get" + this.baseMethodName );
set = definingClass.getDeclaredMethod( "set" + this.baseMethodName, this.setArgs );
} catch ( Exception e ) {
LOG.debug( e, e );
}
}
private Method getSetter( ) {
if( this.set != null ) {
return this.set;
} else {
synchronized(this) {
if( this.set == null ) {
try {
this.set = this.getDefiningClass( ).getDeclaredMethod( "set" + this.baseMethodName, this.setArgs );
} catch ( Exception e ) {
LOG.debug( "Known methods: " + this.getDefiningClass( ).getDeclaredMethods( ) );
LOG.debug( "Known methods: " + this.getDefiningClass( ).getMethods( ) );
LOG.debug( e, e );
}
}
}
return this.set;
}
}
private Method getGetter( ) {
if ( this.get != null ) {
return this.get;
} else {
synchronized ( this ) {
if ( this.get == null ) {
try {
this.get = this.getDefiningClass( ).getDeclaredMethod( "get" + this.baseMethodName );
} catch ( Exception e ) {
LOG.debug( "Known methods: " + this.getDefiningClass( ).getDeclaredMethods( ) );
LOG.debug( "Known methods: " + this.getDefiningClass( ).getMethods( ) );
LOG.debug( e, e );
}
}
}
return this.get;
}
}
private Object getQueryObject( ) throws Exception {
return super.getDefiningClass( ).newInstance( );
}
@Override
public String getValue( ) {
EntityWrapper db = new EntityWrapper( this.persistenceContext );
try {
Object o = db.getUnique( this.getQueryObject( ) );
Method getter = this.getGetter( );
Object prop = null;
if ( getter != null ) {
prop = getter.invoke( o );
}
String result = prop != null ? prop.toString( ) : "null";
db.commit( );
return result;
} catch ( Exception e ) {
db.rollback( );
return "Error: " + e.getMessage( );
}
}
@Override
public String setValue( String s ) {
EntityWrapper db = new EntityWrapper( this.persistenceContext );
try {
Object o = db.getUnique( this.getQueryObject( ) );
Object prop = this.getTypeParser( ).parse( s );
Method setter = this.getSetter( );
if ( setter != null ) {
setter.invoke( o, prop );
}
db.commit( );
return s;
} catch ( Exception e ) {
db.rollback( );
return "Error: " + e.getMessage( );
}
}
@Override
public void resetValue( ) {}
public static class DatabasePropertyBuilder implements ConfigurablePropertyBuilder {
private static Logger LOG = Logger.getLogger( SingletonDatabasePropertyEntry.DatabasePropertyBuilder.class );
@Override
public ConfigurableProperty buildProperty( Class c, Field f ) throws ConfigurablePropertyException {
if ( c.isAnnotationPresent( Entity.class ) &&
((ConfigurableClass)c.getAnnotation(ConfigurableClass.class)).singleton() &&
f.isAnnotationPresent( ConfigurableField.class ) ) {
LOG.debug( "Checking field: " + c.getName( ) + "." + f.getName( ) );
ConfigurableClass classAnnote = ( ConfigurableClass ) c.getAnnotation( ConfigurableClass.class );
ConfigurableField annote = f.getAnnotation( ConfigurableField.class );
String fqPrefix = classAnnote.root( );
String alias = classAnnote.alias();
String description = annote.description( );
String defaultValue = annote.initial( );
PropertyTypeParser p = PropertyTypeParser.get( f.getType( ) );
try {
if ( !Modifier.isStatic( f.getModifiers( ) ) && !f.isAnnotationPresent( Transient.class ) ) {
ConfigurableProperty prop = new SingletonDatabasePropertyEntry( c, fqPrefix, f, description, defaultValue, p, annote.readonly( ), annote.displayName(), annote.type(), alias );
return prop;
}
} catch ( Throwable e ) {
LOG.debug( e, e );
return null;
}
} else {
return null;
}
return null;
}
}
}