/**
* Copyright 2010 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.guvnor.server.util;
/*
* Copyright 2005 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.drools.guvnor.client.rpc.MetaData;
import org.drools.repository.RulesRepositoryException;
/**
* This utility uses reflection to map from the MetaData DTO to
* the AssetItem back end class, to adhere to the DRY principle.
*
* AssetItem is not a remotable instance, but MetaData is.
*
* @author Michael Neale
*/
public class MetaDataMapper {
private Map writeMappingsForClass = new HashMap();
private Map readMappipngsForClass = new HashMap();
public void copyFromMetaData(MetaData data, Object target) {
Map writeMappings = getWriteMappings( data,
target );
for ( Iterator iter = writeMappings.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry e = (Map.Entry) iter.next();
Field f = (Field) e.getKey();
Method m = (Method) e.getValue();
try {
m.invoke( target, new Object[] {f.get( data )} ) ;
} catch ( IllegalArgumentException e1 ) {
throw new RulesRepositoryException(e1);
} catch ( IllegalAccessException e1 ) {
throw new RulesRepositoryException(e1);
} catch ( InvocationTargetException e1 ) {
throw new RulesRepositoryException(e1);
}
}
}
private Map getWriteMappings(MetaData data,
Object target) {
if (!this.writeMappingsForClass.containsKey( target.getClass() )) {
Map writeMappings = loadWriteMappings( data,
target.getClass() );
writeMappingsForClass.put( target.getClass(), writeMappings );
}
return (Map) writeMappingsForClass.get( target.getClass() );
}
private Map loadWriteMappings(MetaData data,
Class bean) {
Map mappings = new HashMap();
Field fields[] = data.getClass().getFields();
for ( int i = 0; i < fields.length; i++ ) {
Field f = fields[i];
String old = f.getName();
String name = Character.toUpperCase( old.charAt( 0 ) ) + old.substring( 1 );
name = "update" + name;
Method m;
try {
m = bean.getMethod( name, new Class[] {f.getType()} );
mappings.put( f,
m );
} catch ( SecurityException e ) {
throw new RulesRepositoryException( "Unable to map meta data",
e );
} catch ( NoSuchMethodException e ) {
//ignore
}
}
return mappings;
}
public void copyToMetaData(MetaData data,
Object source) {
Map readMappings = getReadMappings( data,
source );
for ( Iterator iter = readMappings.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry e = (Map.Entry) iter.next();
Field f = (Field) e.getKey();
Method m = (Method) e.getValue();
try {
f.set( data, m.invoke( source, null ) );
} catch ( IllegalArgumentException e1 ) {
throw new RulesRepositoryException(e1);
} catch ( IllegalAccessException e1 ) {
throw new RulesRepositoryException(e1);
} catch ( InvocationTargetException e1 ) {
throw new RulesRepositoryException(e1);
}
}
}
private Map getReadMappings(MetaData data,
Object source) {
if (!this.readMappipngsForClass.containsKey( source.getClass() )) {
this.readMappipngsForClass.put( source.getClass(), loadReadMappings( data,
source.getClass() ) );
}
return (Map) this.readMappipngsForClass.get( source.getClass() );
}
private Map loadReadMappings(MetaData data,
Class bean) {
Map mappings = new HashMap();
Field fields[] = data.getClass().getFields();
for ( int i = 0; i < fields.length; i++ ) {
Field f = fields[i];
String old = f.getName();
String name = Character.toUpperCase( old.charAt( 0 ) ) + old.substring( 1 );
if ( f.getType() == Boolean.class ) {
name = "is" + name;
} else {
name = "get" + name;
}
Method m;
try {
m = bean.getMethod( name, null );
if (f.getType() == m.getReturnType())
{
mappings.put( f,
m );
}
} catch ( SecurityException e ) {
throw new RulesRepositoryException( "Unable to map meta data",
e );
} catch ( NoSuchMethodException e ) {
//ignore
}
}
return mappings;
}
}