package org.glassfish.pfl.dynamic.copyobject.impl ;
import static java.lang.reflect.Modifier.PRIVATE;
import static java.lang.reflect.Modifier.PUBLIC;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper.DUMP_AFTER_SETUP_VISITOR;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper.TRACE_BYTE_CODE_GENERATION;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper.USE_ASM_VERIFIER;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._Object;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._arg;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._assign;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._body;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._boolean;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._call;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._class;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._clear;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._const;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._constructor;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._data;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._end;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._expr;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._generate;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._if;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._method;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._ne;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._null;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._package;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._super;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._this;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper._void;
import static org.glassfish.pfl.dynamic.codegen.spi.Wrapper.splitClassName;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.Map;
import java.util.Properties;
import org.glassfish.pfl.basic.contain.Pair;
import org.glassfish.pfl.basic.reflection.Bridge;
import org.glassfish.pfl.dynamic.codegen.spi.Expression;
import org.glassfish.pfl.dynamic.codegen.spi.Type;
import org.glassfish.pfl.dynamic.copyobject.spi.ReflectiveCopyException;
public class CodegenCopierGenerator {
private static final String DEBUG = "false" ;
private Class<?> classToCopy ;
private String className ;
private static final Bridge bridge = AccessController.doPrivileged(
(PrivilegedAction<Bridge>) Bridge::get
) ;
CodegenCopierGenerator(String className, Class<?> classToCopy) {
this.className = className ;
this.classToCopy = classToCopy ;
}
public Class<?> create( ProtectionDomain pd, ClassLoader cl ) {
_clear() ;
Pair<String,String> pc = splitClassName( className ) ;
_package( pc.first() ) ;
Type PipelineClassCopierFactory = Type.type(
PipelineClassCopierFactory.class ) ;
Type ReflectiveCopyException = Type.type(
ReflectiveCopyException.class ) ;
Type CodegenCopierBase = Type.type(
CodegenCopierBase.class ) ;
Type ClassFieldCopier = Type.type(
ClassCopierOrdinaryImpl.ClassFieldCopier.class ) ;
Type Map = Type.type(
Map.class ) ;
_class( PUBLIC, pc.second(), CodegenCopierBase ) ;
Expression superCopier = _data( PRIVATE, ClassFieldCopier, "superCopier" ) ;
_constructor( PUBLIC ) ;
Expression factory = _arg( PipelineClassCopierFactory, "factory" ) ;
Expression sc = _arg( ClassFieldCopier, "superCopier" ) ;
_body() ;
_super( factory ) ;
_assign( superCopier, sc ) ;
_end() ;
_method( PUBLIC, _void(), "copy", ReflectiveCopyException ) ;
Expression oldToNew = _arg( Map, "oldToNew" ) ;
Expression src = _arg( _Object(), "src" ) ;
Expression dest = _arg( _Object(), "dest" ) ;
Expression debug = _arg( _boolean(), "debug" ) ;
_body() ;
_if(_ne(superCopier, _null())) ;
_expr(_call( superCopier, "copy", oldToNew, src, dest, debug )) ;
_end() ;
for (Field fld : classToCopy.getDeclaredFields()) {
if (!Modifier.isStatic( fld.getModifiers())) {
long offset = bridge.objectFieldOffset( fld ) ;
String mname = getCopyMethodName( fld.getType() ) ;
if (mname.equals( "copyObject" )) {
_expr(_call( _this(), mname, oldToNew, _const(offset),
src, dest )) ;
} else {
_expr(_call( _this(), mname, _const(offset),
src, dest )) ;
}
}
}
_end() ;
_end() ;
Properties debugProps = new Properties() ;
debugProps.setProperty( DUMP_AFTER_SETUP_VISITOR, DEBUG ) ;
debugProps.setProperty( TRACE_BYTE_CODE_GENERATION, DEBUG ) ;
debugProps.setProperty( USE_ASM_VERIFIER, DEBUG ) ;
Class<?> cls = _generate( cl, pd, debugProps ) ;
return cls ;
}
private String getCopyMethodName( Class<?> fieldType ) {
if (fieldType.equals( Boolean.TYPE )) {
return "copyBoolean";
} else if (fieldType.equals( Byte.TYPE )) {
return "copyByte";
} else if (fieldType.equals( Character.TYPE )) {
return "copyChar";
} else if (fieldType.equals( Integer.TYPE )) {
return "copyInt";
} else if (fieldType.equals( Short.TYPE )) {
return "copyShort";
} else if (fieldType.equals( Long.TYPE )) {
return "copyLong";
} else if (fieldType.equals( Float.TYPE )) {
return "copyFloat";
} else if (fieldType.equals( Double.TYPE )) {
return "copyDouble";
} else {
return "copyObject";
}
}
}