[jboss-svn-commits] JBL Code SVN: r19693 - in labs/jbossrules/trunk/drools-core/src: main/java/org/drools/factmodel and 2 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Wed Apr 23 00:32:45 EDT 2008
Author: michael.neale at jboss.com
Date: 2008-04-23 00:32:45 -0400 (Wed, 23 Apr 2008)
New Revision: 19693
Added:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassBuilder.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Fact.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Field.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldAccessor.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldAccessorBuilder.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Jenerator.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/ClassBuilderTest.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/FieldAccessorBuilderTest.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/InstancesHashcodedTest.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/JeneratorTest.java
Log:
JBRULES-1573 poor mans ontology
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassBuilder.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassBuilder.java 2008-04-23 04:32:45 UTC (rev 19693)
@@ -0,0 +1,753 @@
+package org.drools.factmodel;
+
+
+import java.beans.IntrospectionException;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+
+import org.drools.asm.ClassWriter;
+import org.drools.asm.FieldVisitor;
+import org.drools.asm.Label;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+import org.drools.asm.Type;
+
+/**
+ * <p><b>Title:</b> ClassBuilder</p>
+ * <p><b>Description:</b> A builder to dinamically build simple Value Object classes</p>
+ * <p><b>Copyright:</b> Copyright (c) 2005</p>
+ * <p><b>Company:</b> Auster Solutions</p>
+ *
+ * @author etirelli
+ * @version $Id: ClassBuilder.java 241 2006-05-11 19:48:25Z framos $
+ */
+public class ClassBuilder {
+ private boolean debug = false;
+
+ public ClassBuilder() {
+ this.debug = "false".equalsIgnoreCase( System.getProperty( "br.com.auster.common.asm.debug" ) );
+ }
+
+ /**
+ * Dinamically builds, defines and loads a class based on the given class definition
+ *
+ * @param classDef the class definition object structure
+ *
+ * @return the Class instance for the given class definition
+ *
+ * @throws IOException
+ * @throws IntrospectionException
+ * @throws InvocationTargetException
+ * @throws IllegalAccessException
+ * @throws NoSuchMethodException
+ * @throws ClassNotFoundException
+ * @throws IllegalArgumentException
+ * @throws SecurityException
+ * @throws NoSuchFieldException
+ * @throws InstantiationException
+ */
+ public Class buildAndLoadClass(ClassDefinition classDef) throws IOException,
+ IntrospectionException,
+ SecurityException,
+ IllegalArgumentException,
+ ClassNotFoundException,
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException,
+ InstantiationException,
+ NoSuchFieldException {
+ try {
+ Class clazz = Class.forName( classDef.getClassName() );
+
+ classDef.setDefinedClass( clazz );
+
+ return clazz;
+
+ } catch ( ClassNotFoundException e ) {
+ // class not loaded, so create and load it
+ byte[] serializedClazz = this.buildClass( classDef );
+
+ Class clazz = this.loadClass( classDef.getClassName(),
+ serializedClazz );
+ classDef.setDefinedClass( clazz );
+
+ return clazz;
+ }
+ }
+
+ /**
+ * Dinamically builds, defines and loads a class based on the given class definition
+ *
+ * @param classDef the class definition object structure
+ *
+ * @return the Class instance for the given class definition
+ *
+ * @throws IOException
+ * @throws IntrospectionException
+ * @throws InvocationTargetException
+ * @throws IllegalAccessException
+ * @throws NoSuchMethodException
+ * @throws ClassNotFoundException
+ * @throws IllegalArgumentException
+ * @throws SecurityException
+ * @throws NoSuchFieldException
+ * @throws InstantiationException
+ */
+ public byte[] buildClass(ClassDefinition classDef) throws IOException,
+ IntrospectionException,
+ SecurityException,
+ IllegalArgumentException,
+ ClassNotFoundException,
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException,
+ InstantiationException,
+ NoSuchFieldException {
+
+ ClassWriter cw = new ClassWriter( true );
+
+ this.buildClassHeader( cw,
+ classDef );
+
+ // Building fields
+ for ( FieldDefinition fieldDef : classDef.getFields() ) {
+ this.buildField( cw,
+ fieldDef );
+ }
+
+ // Building default constructor
+ this.buildDefaultConstructor( cw,
+ classDef );
+
+ // Building methods
+ for ( FieldDefinition fieldDef : classDef.getFields() ) {
+ this.buildGetMethod( cw,
+ classDef,
+ fieldDef );
+ this.buildSetMethod( cw,
+ classDef,
+ fieldDef );
+ }
+
+ this.buildEquals( cw,
+ classDef );
+ this.buildHashCode( cw,
+ classDef );
+
+ this.buildToString( cw,
+ classDef );
+
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+
+ /**
+ * Defines the class header for the given class definition
+ *
+ * @param cw
+ * @param dimDef
+ */
+ private void buildClassHeader(ClassWriter cw,
+ ClassDefinition classDef) {
+ // Building class header
+ cw.visit( Opcodes.V1_4,
+ Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
+ classDef.getClassNameAsInternal(),
+ null,
+ classDef.getSuperClassAsInternal(),
+ classDef.getInterfacesAsInternal() );
+
+ cw.visitSource( classDef.getClassName() + ".java",
+ null );
+ }
+
+ /**
+ * Creates the field defined by the given FieldDefinition
+ *
+ * @param cw
+ * @param fieldDef
+ */
+ private void buildField(ClassWriter cw,
+ FieldDefinition fieldDef) {
+ FieldVisitor fv;
+ fv = cw.visitField( Opcodes.ACC_PRIVATE,
+ fieldDef.getName(),
+ fieldDef.getInternalType(),
+ null,
+ null );
+ fv.visitEnd();
+ }
+
+ /**
+ * Creates a default constructor for the class
+ *
+ * @param cw
+ */
+ private void buildDefaultConstructor(ClassWriter cw,
+ ClassDefinition classDef) {
+ MethodVisitor mv;
+ // Building default constructor
+ {
+ mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+ "<init>",
+ Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[]{} ),
+ null,
+ null );
+ mv.visitCode();
+ Label l0 = null;
+ if ( this.debug ) {
+ l0 = new Label();
+ mv.visitLabel( l0 );
+ }
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitMethodInsn( Opcodes.INVOKESPECIAL,
+ Type.getInternalName( Object.class ),
+ "<init>",
+ Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[]{} ) );
+ mv.visitInsn( Opcodes.RETURN );
+ Label l1 = null;
+ if ( this.debug ) {
+ l1 = new Label();
+ mv.visitLabel( l1 );
+ mv.visitLocalVariable( "this",
+ classDef.getInternalName(),
+ null,
+ l0,
+ l1,
+ 0 );
+ }
+ mv.visitMaxs( 0,
+ 0 );
+ mv.visitEnd();
+ }
+ }
+
+ /**
+ * Creates the set method for the given field definition
+ *
+ * @param cw
+ * @param classDef
+ * @param fieldDef
+ */
+ private void buildSetMethod(ClassWriter cw,
+ ClassDefinition classDef,
+ FieldDefinition fieldDef) {
+ MethodVisitor mv;
+ // set method
+ {
+ mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+ fieldDef.getWriteMethod(),
+ Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[]{Type.getType( fieldDef.getInternalType() )} ),
+ null,
+ null );
+ mv.visitCode();
+ Label l0 = null;
+ if ( this.debug ) {
+ l0 = new Label();
+ mv.visitLabel( l0 );
+ }
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitVarInsn( Type.getType( fieldDef.getInternalType() ).getOpcode( Opcodes.ILOAD ),
+ 1 );
+ mv.visitFieldInsn( Opcodes.PUTFIELD,
+ classDef.getClassNameAsInternal(),
+ fieldDef.getName(),
+ fieldDef.getInternalType() );
+
+ mv.visitInsn( Opcodes.RETURN );
+ Label l1 = null;
+ if ( this.debug ) {
+ l1 = new Label();
+ mv.visitLabel( l1 );
+ mv.visitLocalVariable( "this",
+ classDef.getInternalName(),
+ null,
+ l0,
+ l1,
+ 0 );
+ }
+ mv.visitMaxs( 0,
+ 0 );
+ mv.visitEnd();
+ }
+ }
+
+ /**
+ * Creates the get method for the given field definition
+ *
+ * @param cw
+ * @param classDef
+ * @param fieldDef
+ */
+ private void buildGetMethod(ClassWriter cw,
+ ClassDefinition classDef,
+ FieldDefinition fieldDef) {
+ MethodVisitor mv;
+ // Get method
+ {
+ mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+ fieldDef.getReadMethod(),
+ Type.getMethodDescriptor( Type.getType( fieldDef.getInternalType() ),
+ new Type[]{} ),
+ null,
+ null );
+ mv.visitCode();
+ Label l0 = null;
+ if ( this.debug ) {
+ l0 = new Label();
+ mv.visitLabel( l0 );
+ }
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitFieldInsn( Opcodes.GETFIELD,
+ classDef.getClassNameAsInternal(),
+ fieldDef.getName(),
+ fieldDef.getInternalType() );
+ mv.visitInsn( Type.getType( fieldDef.getInternalType() ).getOpcode( Opcodes.IRETURN ) );
+ Label l1 = null;
+ if ( this.debug ) {
+ l1 = new Label();
+ mv.visitLabel( l1 );
+ mv.visitLocalVariable( "this",
+ classDef.getInternalName(),
+ null,
+ l0,
+ l1,
+ 0 );
+ }
+ mv.visitMaxs( 0,
+ 0 );
+ mv.visitEnd();
+ }
+ }
+
+ private void buildEquals(ClassWriter cw,
+ ClassDefinition classDef) {
+ MethodVisitor mv;
+ // Building equals method
+ {
+ mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+ "equals",
+ "(Ljava/lang/Object;)Z",
+ null,
+ null );
+ mv.visitCode();
+ Label l0 = null;
+ if ( this.debug ) {
+ l0 = new Label();
+ mv.visitLabel( l0 );
+ }
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 1 );
+ Label l1 = new Label();
+ mv.visitJumpInsn( Opcodes.IF_ACMPNE,
+ l1 );
+ mv.visitInsn( Opcodes.ICONST_1 );
+ mv.visitInsn( Opcodes.IRETURN );
+ mv.visitLabel( l1 );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 1 );
+ Label l3 = new Label();
+ mv.visitJumpInsn( Opcodes.IFNULL,
+ l3 );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 1 );
+ mv.visitTypeInsn( Opcodes.INSTANCEOF,
+ classDef.getClassNameAsInternal() );
+ Label l4 = new Label();
+ mv.visitJumpInsn( Opcodes.IFNE,
+ l4 );
+ mv.visitLabel( l3 );
+ mv.visitInsn( Opcodes.ICONST_0 );
+ mv.visitInsn( Opcodes.IRETURN );
+ mv.visitLabel( l4 );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 1 );
+ mv.visitTypeInsn( Opcodes.CHECKCAST,
+ classDef.getClassNameAsInternal() );
+ mv.visitVarInsn( Opcodes.ASTORE,
+ 2 );
+
+ int count = 0;
+ for ( FieldDefinition field : classDef.getFields() ) {
+ if ( field.isKey() ) {
+ count++;
+ Label goNext = new Label();
+ if ( field.isPrimitive() ) {
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitFieldInsn( Opcodes.GETFIELD,
+ classDef.getClassNameAsInternal(),
+ field.getName(),
+ field.getInternalType() );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 2 );
+ mv.visitFieldInsn( Opcodes.GETFIELD,
+ classDef.getClassNameAsInternal(),
+ field.getName(),
+ field.getInternalType() );
+ if ( field.getType().equals( "long" ) ) {
+ mv.visitInsn( Opcodes.LCMP );
+ mv.visitJumpInsn( Opcodes.IFEQ,
+ goNext );
+ } else if ( field.getType().equals( "double" ) ) {
+ mv.visitInsn( Opcodes.DCMPL );
+ mv.visitJumpInsn( Opcodes.IFEQ,
+ goNext );
+ } else if ( field.getType().equals( "float" ) ) {
+ mv.visitInsn( Opcodes.FCMPL );
+ mv.visitJumpInsn( Opcodes.IFEQ,
+ goNext );
+ } else {
+ mv.visitJumpInsn( Opcodes.IF_ICMPEQ,
+ goNext );
+ }
+ mv.visitInsn( Opcodes.ICONST_0 );
+ mv.visitInsn( Opcodes.IRETURN );
+ } else {
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitFieldInsn( Opcodes.GETFIELD,
+ classDef.getClassNameAsInternal(),
+ field.getName(),
+ field.getInternalType() );
+ Label secondIfPart = new Label();
+ mv.visitJumpInsn( Opcodes.IFNONNULL,
+ secondIfPart );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 2 );
+ mv.visitFieldInsn( Opcodes.GETFIELD,
+ classDef.getClassNameAsInternal(),
+ field.getName(),
+ field.getInternalType() );
+ Label returnFalse = new Label();
+ mv.visitJumpInsn( Opcodes.IFNONNULL,
+ returnFalse );
+ mv.visitLabel( secondIfPart );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitFieldInsn( Opcodes.GETFIELD,
+ classDef.getClassNameAsInternal(),
+ field.getName(),
+ field.getInternalType() );
+ mv.visitJumpInsn( Opcodes.IFNULL,
+ goNext );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitFieldInsn( Opcodes.GETFIELD,
+ classDef.getClassNameAsInternal(),
+ field.getName(),
+ field.getInternalType() );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 2 );
+ mv.visitFieldInsn( Opcodes.GETFIELD,
+ classDef.getClassNameAsInternal(),
+ field.getName(),
+ field.getInternalType() );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ field.getBoxTypeName(),
+ "equals",
+ "(Ljava/lang/Object;)Z" );
+ mv.visitJumpInsn( Opcodes.IFNE,
+ goNext );
+ mv.visitLabel( returnFalse );
+ mv.visitInsn( Opcodes.ICONST_0 );
+ mv.visitInsn( Opcodes.IRETURN );
+ }
+ mv.visitLabel( goNext );
+ }
+ }
+ if ( count > 0 ) {
+ mv.visitInsn( Opcodes.ICONST_1 );
+ } else {
+ mv.visitInsn( Opcodes.ICONST_0 );
+ }
+ mv.visitInsn( Opcodes.IRETURN );
+ Label lastLabel = null;
+ if ( this.debug ) {
+ lastLabel = new Label();
+ mv.visitLabel( lastLabel );
+ mv.visitLocalVariable( "this",
+ classDef.getInternalName(),
+ null,
+ l0,
+ lastLabel,
+ 0 );
+ mv.visitLocalVariable( "obj",
+ Type.getDescriptor( Object.class ),
+ null,
+ l0,
+ lastLabel,
+ 1 );
+ mv.visitLocalVariable( "other",
+ classDef.getInternalName(),
+ null,
+ l0,
+ lastLabel,
+ 2 );
+ }
+ mv.visitMaxs( 0,
+ 0 );
+ mv.visitEnd();
+ }
+ }
+
+ private void buildHashCode(ClassWriter cw,
+ ClassDefinition classDef) {
+
+ MethodVisitor mv;
+ // Building hashCode() method
+ {
+ mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+ "hashCode",
+ "()I",
+ null,
+ null );
+ mv.visitCode();
+ Label l0 = null;
+ if ( this.debug ) {
+ l0 = new Label();
+ mv.visitLabel( l0 );
+ }
+ mv.visitInsn( Opcodes.ICONST_0 );
+ mv.visitVarInsn( Opcodes.ISTORE,
+ 1 );
+
+ for ( FieldDefinition field : classDef.getFields() ) {
+ if ( field.isKey() ) {
+ mv.visitVarInsn( Opcodes.ILOAD,
+ 1 );
+ if ( field.isPrimitive() ) {
+ mv.visitTypeInsn( Opcodes.NEW,
+ field.getBoxTypeName() );
+ mv.visitInsn( Opcodes.DUP );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitFieldInsn( Opcodes.GETFIELD,
+ classDef.getClassNameAsInternal(),
+ field.getName(),
+ field.getInternalType() );
+ mv.visitMethodInsn( Opcodes.INVOKESPECIAL,
+ field.getBoxTypeName(),
+ "<init>",
+ Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[]{Type.getType( field.getInternalType() )} ) );
+ } else {
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitFieldInsn( Opcodes.GETFIELD,
+ classDef.getClassNameAsInternal(),
+ field.getName(),
+ field.getInternalType() );
+
+ }
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ field.getBoxTypeName(),
+ "hashCode",
+ "()I" );
+ mv.visitInsn( Opcodes.IADD );
+ mv.visitVarInsn( Opcodes.ISTORE,
+ 1 );
+ }
+ }
+ mv.visitVarInsn( Opcodes.ILOAD,
+ 1 );
+ mv.visitIntInsn( Opcodes.SIPUSH,
+ 9653 );
+ mv.visitInsn( Opcodes.IREM );
+ mv.visitInsn( Opcodes.IRETURN );
+
+ Label lastLabel = null;
+ if ( this.debug ) {
+ lastLabel = new Label();
+ mv.visitLabel( lastLabel );
+ mv.visitLocalVariable( "this",
+ classDef.getInternalName(),
+ null,
+ l0,
+ lastLabel,
+ 0 );
+ mv.visitLocalVariable( "hash",
+ Type.getDescriptor( int.class ),
+ null,
+ l0,
+ lastLabel,
+ 1 );
+ }
+ mv.visitMaxs( 0,
+ 0 );
+ mv.visitEnd();
+ }
+ }
+
+ private void buildToString(ClassWriter cw,
+ ClassDefinition classDef) {
+ MethodVisitor mv;
+ {
+ mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+ "toString",
+ "()Ljava/lang/String;",
+ null,
+ null );
+ mv.visitCode();
+
+ Label l0 = null;
+ if ( this.debug ) {
+ l0 = new Label();
+ mv.visitLabel( l0 );
+ }
+
+ // StringBuffer buf = new StringBuffer();
+ mv.visitTypeInsn( Opcodes.NEW,
+ "java/lang/StringBuffer" );
+ mv.visitInsn( Opcodes.DUP );
+ mv.visitMethodInsn( Opcodes.INVOKESPECIAL,
+ "java/lang/StringBuffer",
+ "<init>",
+ "()V" );
+ mv.visitVarInsn( Opcodes.ASTORE,
+ 1 );
+
+ // buf.append(this.getClass().getSimpleName())
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 1 );
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ classDef.getClassNameAsInternal(),
+ "getClass",
+ "()Ljava/lang/Class;" );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ "java/lang/Class",
+ "getSimpleName",
+ "()Ljava/lang/String;" );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ "java/lang/StringBuffer",
+ "append",
+ "(Ljava/lang/String;)Ljava/lang/StringBuffer;" );
+
+ // buf.append("( ");
+ mv.visitLdcInsn( "( " );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ "java/lang/StringBuffer",
+ "append",
+ "(Ljava/lang/String;)Ljava/lang/StringBuffer;" );
+
+ boolean previous = false;
+ for ( FieldDefinition field : classDef.getFields() ) {
+ if ( previous ) {
+ // buf.append(", ");
+ mv.visitLdcInsn( ", " );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ "java/lang/StringBuffer",
+ "append",
+ "(Ljava/lang/String;)Ljava/lang/StringBuffer;" );
+ }
+ // buf.append(attrName)
+ mv.visitLdcInsn( field.getName() );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ "java/lang/StringBuffer",
+ "append",
+ "(Ljava/lang/String;)Ljava/lang/StringBuffer;" );
+
+ // buf.append("=");
+ mv.visitLdcInsn( "=" );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ "java/lang/StringBuffer",
+ "append",
+ "(Ljava/lang/String;)Ljava/lang/StringBuffer;" );
+
+ // buf.append(attrValue)
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitFieldInsn( Opcodes.GETFIELD,
+ classDef.getClassNameAsInternal(),
+ field.getName(),
+ field.getInternalType() );
+
+ if ( field.isPrimitive() ) {
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ "java/lang/StringBuffer",
+ "append",
+ Type.getMethodDescriptor( Type.getType( StringBuffer.class ),
+ new Type[]{Type.getType( field.getInternalType() )} ) );
+ } else {
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ "java/lang/StringBuffer",
+ "append",
+ Type.getMethodDescriptor( Type.getType( StringBuffer.class ),
+ new Type[]{Type.getType( Object.class )} ) );
+ }
+ previous = true;
+ }
+
+ mv.visitLdcInsn( " )" );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ "java/lang/StringBuffer",
+ "append",
+ "(Ljava/lang/String;)Ljava/lang/StringBuffer;" );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ "java/lang/StringBuffer",
+ "toString",
+ "()Ljava/lang/String;" );
+ mv.visitInsn( Opcodes.ARETURN );
+
+ Label lastLabel = null;
+ if ( this.debug ) {
+ lastLabel = new Label();
+ mv.visitLabel( lastLabel );
+ mv.visitLocalVariable( "this",
+ classDef.getInternalName(),
+ null,
+ l0,
+ lastLabel,
+ 0 );
+ mv.visitLocalVariable( "buf",
+ Type.getDescriptor( StringBuffer.class ),
+ null,
+ l0,
+ lastLabel,
+ 1 );
+ }
+ mv.visitMaxs( 0,
+ 0 );
+ mv.visitEnd();
+ }
+ }
+
+ private Class loadClass(String classname,
+ byte[] b) throws ClassNotFoundException,
+ SecurityException,
+ NoSuchMethodException,
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException {
+ //override classDefine (as it is protected) and define the class.
+ Class clazz = null;
+ ClassLoader loader = ClassBuilder.class.getClassLoader();
+ Class cls = Class.forName( "java.lang.ClassLoader" );
+ java.lang.reflect.Method method = cls.getDeclaredMethod( "defineClass",
+ new Class[]{String.class, byte[].class, int.class, int.class} );
+
+ // protected method invocaton
+ method.setAccessible( true );
+ try {
+ Object[] args = new Object[]{classname, b, new Integer( 0 ), new Integer( b.length )};
+ clazz = (Class) method.invoke( loader,
+ args );
+ } finally {
+ method.setAccessible( false );
+ }
+ return clazz;
+ }
+
+}
Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassBuilder.java
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:eol-style
+ native
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java 2008-04-23 04:32:45 UTC (rev 19693)
@@ -0,0 +1,231 @@
+package org.drools.factmodel;
+
+
+import java.beans.IntrospectionException;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * <p><b>Title:</b> ClassDefinition</p>
+ * <p><b>Description:</b> Declares a class to be dinamically created</p>
+ * <p><b>Copyright:</b> Copyright (c) 2004-2006</p>
+ * <p><b>Company:</b> Auster Solutions</p>
+ *
+ * @author etirelli
+ * @version $Id: ClassDefinition.java 216 2006-03-24 19:16:31Z etirelli $
+ */
+public class ClassDefinition {
+ private String className;
+ private String superClass;
+ private String[] interfaces;
+ private Class definedClass;
+
+ private Map<String, FieldDefinition> fields = new LinkedHashMap<String, FieldDefinition>();
+
+ public ClassDefinition(String className) {
+ this( className,
+ null,
+ null );
+ }
+
+ public ClassDefinition(String className,
+ String superClass) {
+ this( className,
+ superClass,
+ null );
+ }
+
+ public ClassDefinition(String className,
+ String[] interfaces) {
+ this( className,
+ null,
+ interfaces );
+ }
+
+ public ClassDefinition(String className,
+ String superClass,
+ String[] interfaces) {
+ this.setClassName( className );
+ this.setSuperClass( superClass );
+ this.setInterfaces( interfaces );
+ }
+
+ /**
+ * @return Returns the name.
+ */
+ public final String getClassName() {
+ return this.className;
+ }
+
+ /**
+ * @param name The name to set.
+ */
+ public final void setClassName(final String className) {
+ this.className = className;
+ }
+
+ /**
+ * @return the class name replacing '.' by '/'
+ */
+ final String getClassNameAsInternal() {
+ return this.getClassName().replace( '.',
+ '/' );
+ }
+
+ /**
+ * @return Returns the name.
+ */
+ public final String getInternalName() {
+ return "L" + this.getClassNameAsInternal() + ";";
+ }
+
+ /**
+ * @return Returns the className.
+ */
+ public final Class getDefinedClass() {
+ return definedClass;
+ }
+
+ /**
+ * @param className The className to set.
+ * @throws IntrospectionException
+ * @throws NoSuchFieldException
+ * @throws InvocationTargetException
+ * @throws NoSuchMethodException
+ * @throws ClassNotFoundException
+ * @throws IOException
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ * @throws IllegalArgumentException
+ * @throws SecurityException
+ */
+ final void setDefinedClass(final Class definedClass) throws IntrospectionException,
+ SecurityException,
+ IllegalArgumentException,
+ InstantiationException,
+ IllegalAccessException,
+ IOException,
+ ClassNotFoundException,
+ NoSuchMethodException,
+ InvocationTargetException,
+ NoSuchFieldException {
+
+ this.definedClass = definedClass;
+
+ if ( this.definedClass != null ) {
+ this.buildFieldAccessors();
+ }
+ }
+
+ /**
+ * Adds a field definition to this class
+ * @param attr
+ */
+ public final void addField(FieldDefinition attr) {
+ this.fields.put( attr.getName(),
+ attr );
+ }
+
+ /**
+ * @return Returns an unmodifiable collection of field definitions
+ */
+ public final Collection<FieldDefinition> getFields() {
+ return Collections.unmodifiableCollection( this.fields.values() );
+ }
+
+ /**
+ * Returns the field definition object for the given field name
+ *
+ * @param fieldName
+ * @return
+ */
+ public final FieldDefinition getField(final String fieldName) {
+ return this.fields.get( fieldName );
+ }
+
+ /**
+ * @param beanInfo The beanInfo to set.
+ * @throws NoSuchFieldException
+ * @throws InvocationTargetException
+ * @throws NoSuchMethodException
+ * @throws ClassNotFoundException
+ * @throws IntrospectionException
+ * @throws IOException
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ * @throws IllegalArgumentException
+ * @throws SecurityException
+ * @throws IntrospectionException
+ */
+ public final void buildFieldAccessors() throws SecurityException,
+ IllegalArgumentException,
+ InstantiationException,
+ IllegalAccessException,
+ IOException,
+ IntrospectionException,
+ ClassNotFoundException,
+ NoSuchMethodException,
+ InvocationTargetException,
+ NoSuchFieldException {
+ FieldAccessorBuilder builder = new FieldAccessorBuilder();
+
+ for ( FieldDefinition attrDef : this.fields.values() ) {
+ FieldAccessor accessor = (FieldAccessor) builder.buildAndLoadFieldAccessor( this.getDefinedClass(),
+ attrDef.getName() ).newInstance();
+ attrDef.setFieldAccessor( accessor );
+ }
+ }
+
+ /**
+ * @return Returns the interfaces.
+ */
+ public final String[] getInterfaces() {
+ return interfaces;
+ }
+
+ /**
+ * @param interfaces The interfaces to set.
+ */
+ public final void setInterfaces(String[] interfaces) {
+ this.interfaces = (interfaces != null) ? interfaces : new String[0];
+ }
+
+ /**
+ * @return
+ */
+ final String[] getInterfacesAsInternal() {
+ String[] interfaces = new String[this.interfaces.length];
+ for ( int i = 0; i < interfaces.length; i++ ) {
+ interfaces[i] = this.interfaces[i].replace( '.',
+ '/' );
+ }
+ return interfaces;
+ }
+
+ /**
+ * @return Returns the superClass.
+ */
+ public final String getSuperClass() {
+ return superClass;
+ }
+
+ /**
+ * @param superClass The superClass to set.
+ */
+ public final void setSuperClass(final String superClass) {
+ this.superClass = (superClass != null) ? superClass : "java/lang/Object";
+ }
+
+ /**
+ * @return Returns superclass name in the internal String representation
+ */
+ final String getSuperClassAsInternal() {
+ return this.superClass.replace( '.',
+ '/' );
+ }
+
+}
\ No newline at end of file
Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:eol-style
+ native
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Fact.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Fact.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Fact.java 2008-04-23 04:32:45 UTC (rev 19693)
@@ -0,0 +1,17 @@
+package org.drools.factmodel;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A temporary AST.
+ * @author michaelneale
+ *
+ */
+public class Fact {
+
+ public String name;
+ public List fields = new ArrayList();
+
+}
Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Fact.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Field.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Field.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Field.java 2008-04-23 04:32:45 UTC (rev 19693)
@@ -0,0 +1,14 @@
+package org.drools.factmodel;
+
+
+/**
+ * A temporary AST
+ * @author michaelneale
+ *
+ */
+public class Field {
+
+ public String name;
+ public String type;
+
+}
Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Field.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldAccessor.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldAccessor.java 2008-04-23 04:32:45 UTC (rev 19693)
@@ -0,0 +1,19 @@
+package org.drools.factmodel;
+
+
+/**
+ * <p><b>Title:</b> FieldAccessor</p>
+ * <p><b>Description:</b> An interface for dynamic generated FieldAccessor classes </p>
+ * <p><b>Copyright:</b> Copyright (c) 2004-2006</p>
+ * <p><b>Company:</b> Auster Solutions</p>
+ *
+ * @author etirelli
+ * @version $Id: FieldAccessor.java 203 2006-03-20 21:44:48Z etirelli $
+ */
+public interface FieldAccessor {
+
+ public void setValue(Object instance, Object value);
+
+ public Object getValue(Object instance);
+
+}
Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldAccessor.java
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:eol-style
+ native
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldAccessorBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldAccessorBuilder.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldAccessorBuilder.java 2008-04-23 04:32:45 UTC (rev 19693)
@@ -0,0 +1,410 @@
+package org.drools.factmodel;
+
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.asm.ClassWriter;
+import org.drools.asm.Label;
+import org.drools.asm.MethodVisitor;
+import org.drools.asm.Opcodes;
+import org.drools.asm.Type;
+
+/**
+ * <p><b>Title:</b> FieldAccessorBuilder</p>
+ * <p><b>Description:</b> A builder for FieldAccessor instances</p>
+ * <p><b>Copyright:</b> Copyright (c) 2004-2006</p>
+ * <p><b>Company:</b> Auster Solutions</p>
+ *
+ * @author etirelli
+ * @version $Id: FieldAccessorBuilder.java 241 2006-05-11 19:48:25Z framos $
+ */
+public class FieldAccessorBuilder {
+ private Map typeMap = null;
+
+ public FieldAccessorBuilder() {
+ typeMap = new HashMap();
+ typeMap.put( Boolean.TYPE,
+ Boolean.class );
+ typeMap.put( Byte.TYPE,
+ Byte.class );
+ typeMap.put( Character.TYPE,
+ Character.class );
+ typeMap.put( Double.TYPE,
+ Double.class );
+ typeMap.put( Float.TYPE,
+ Float.class );
+ typeMap.put( Integer.TYPE,
+ Integer.class );
+ typeMap.put( Long.TYPE,
+ Long.class );
+ typeMap.put( Short.TYPE,
+ Short.class );
+ typeMap.put( Void.TYPE,
+ Void.class );
+ }
+
+ public Class buildAndLoadFieldAccessor(Class clazz,
+ String fieldName) throws SecurityException,
+ IllegalArgumentException,
+ IOException,
+ IntrospectionException,
+ ClassNotFoundException,
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException,
+ NoSuchFieldException {
+
+ ClassDefinition accClass = new ClassDefinition( clazz.getName() + fieldName.substring( 0,
+ 1 ).toUpperCase() + fieldName.substring( 1 ) + "FA" );
+ try {
+ return Class.forName( accClass.getClassName() );
+ } catch ( ClassNotFoundException e ) {
+ byte[] serializedClazz = this.buildFieldAccessor( clazz,
+ fieldName );
+ Class newClazz = this.loadClass( accClass.getClassName(),
+ serializedClazz );
+ return newClazz;
+ }
+ }
+
+ /**
+ * Dinamically builds, defines and loads a field accessor class for the given field
+ *
+ * @param class the class to build the field accessor for
+ * @param fieldName the name of the field to build the field accessor for
+ *
+ * @return the Class instance for the given class definition
+ *
+ * @throws IOException
+ * @throws IntrospectionException
+ * @throws InvocationTargetException
+ * @throws IllegalAccessException
+ * @throws NoSuchMethodException
+ * @throws ClassNotFoundException
+ * @throws IllegalArgumentException
+ * @throws SecurityException
+ * @throws NoSuchFieldException
+ */
+ public byte[] buildFieldAccessor(Class clazz,
+ String fieldName) throws IOException,
+ IntrospectionException,
+ SecurityException,
+ IllegalArgumentException,
+ ClassNotFoundException,
+ NoSuchMethodException,
+ IllegalAccessException,
+ InvocationTargetException,
+ NoSuchFieldException {
+
+ ClassDefinition accClass = new ClassDefinition( clazz.getName() + fieldName.substring( 0,
+ 1 ).toUpperCase() + fieldName.substring( 1 ) + "FA" );
+ accClass.setInterfaces( new String[]{FieldAccessor.class.getName()} );
+ accClass.setSuperClass( Object.class.getName() );
+
+ PropertyDescriptor field = getPropertyDescriptor( clazz,
+ fieldName );
+
+ ClassWriter cw = new ClassWriter( true );
+
+ this.buildClassHeader( cw,
+ accClass );
+
+ // Building default constructor
+ this.buildDefaultConstructor( cw );
+
+ // Building methods
+ this.buildGetMethod( cw,
+ accClass,
+ clazz,
+ field );
+ this.buildSetMethod( cw,
+ accClass,
+ clazz,
+ field );
+
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+
+ /**
+ * @param clazz
+ * @param fieldName
+ * @param field
+ * @return
+ * @throws IntrospectionException
+ * @throws NoSuchFieldException
+ */
+ private PropertyDescriptor getPropertyDescriptor(Class clazz,
+ String fieldName) throws IntrospectionException,
+ NoSuchFieldException {
+ PropertyDescriptor field = null;
+ PropertyDescriptor[] propDescr = Introspector.getBeanInfo( clazz ).getPropertyDescriptors();
+ for ( int i = 0; i < propDescr.length; i++ ) {
+ if ( fieldName.equals( propDescr[i].getName() ) ) {
+ field = propDescr[i];
+ break;
+ }
+ }
+ if ( field == null ) {
+ throw new NoSuchFieldException( "Field [" + fieldName + "] not found in class [" + clazz.getName() + "]" );
+ }
+ return field;
+ }
+
+ /**
+ * Defines the class header for the given class definition
+ *
+ * @param cw
+ * @param dimDef
+ */
+ private void buildClassHeader(ClassWriter cw,
+ ClassDefinition classDef) {
+ // Building class header
+ cw.visit( Opcodes.V1_4,
+ Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
+ classDef.getClassNameAsInternal(),
+ null,
+ classDef.getSuperClassAsInternal(),
+ classDef.getInterfacesAsInternal() );
+
+ cw.visitSource( classDef.getClassName() + ".java",
+ null );
+ }
+
+ /**
+ * Creates the get method for the given field definition
+ *
+ * @param cw
+ * @param classDef
+ * @param fieldDef
+ */
+ private void buildGetMethod(ClassWriter cw,
+ ClassDefinition classDef,
+ Class clazz,
+ PropertyDescriptor field) {
+ MethodVisitor mv;
+ // Get method
+ {
+ mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+ "getValue",
+ Type.getMethodDescriptor( Type.getType( Object.class ),
+ new Type[]{Type.getType( Object.class )} ),
+ null,
+ null );
+ mv.visitCode();
+ if ( field.getPropertyType().isPrimitive() ) {
+ mv.visitTypeInsn( Opcodes.NEW,
+ Type.getInternalName( (Class) typeMap.get( field.getPropertyType() ) ) );
+ mv.visitInsn( Opcodes.DUP );
+ }
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 1 );
+ mv.visitTypeInsn( Opcodes.CHECKCAST,
+ Type.getInternalName( clazz ) );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ Type.getInternalName( clazz ),
+ field.getReadMethod().getName(),
+ Type.getMethodDescriptor( Type.getType( field.getPropertyType() ),
+ new Type[]{} ) );
+
+ if ( field.getPropertyType().isPrimitive() ) {
+ mv.visitMethodInsn( Opcodes.INVOKESPECIAL,
+ Type.getInternalName( (Class) typeMap.get( field.getPropertyType() ) ),
+ "<init>",
+ Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[]{Type.getType( field.getPropertyType() )} ) );
+ }
+ mv.visitInsn( Opcodes.ARETURN );
+ mv.visitMaxs( 0,
+ 0 ); // automatically calculated
+ mv.visitEnd();
+ }
+ }
+
+ /**
+ * Creates the set method for the given field definition
+ *
+ * @param cw
+ * @param classDef
+ * @param fieldDef
+ */
+ private void buildSetMethod(ClassWriter cw,
+ ClassDefinition classDef,
+ Class clazz,
+ PropertyDescriptor field) {
+ MethodVisitor mv;
+ // set method
+ {
+ mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+ "setValue",
+ Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[]{Type.getType( Object.class ), Type.getType( Object.class )} ),
+ null,
+ null );
+
+ mv.visitCode();
+
+ if ( field.getPropertyType().isPrimitive() ) {
+ // value != null ?
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 2 );
+
+ Label ifnull = new Label();
+ mv.visitJumpInsn( Opcodes.IFNULL,
+ ifnull );
+
+ // ((PrimitiveWrapper)value).xxxValue() :
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 2 );
+ mv.visitTypeInsn( Opcodes.CHECKCAST,
+ Type.getInternalName( (Class) typeMap.get( field.getPropertyType() ) ) );
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ Type.getInternalName( (Class) typeMap.get( field.getPropertyType() ) ),
+ field.getPropertyType().getName() + "Value",
+ Type.getMethodDescriptor( Type.getType( field.getPropertyType() ),
+ new Type[]{} ) );
+
+ Label afterif = new Label();
+ mv.visitJumpInsn( Opcodes.GOTO,
+ afterif );
+
+ // 0
+ mv.visitLabel( ifnull );
+ if ( field.getPropertyType().isAssignableFrom( long.class ) ) {
+ mv.visitInsn( Opcodes.LCONST_0 );
+ } else if ( field.getPropertyType().isAssignableFrom( double.class ) ) {
+ mv.visitInsn( Opcodes.DCONST_0 );
+ } else if ( field.getPropertyType().isAssignableFrom( float.class ) ) {
+ mv.visitInsn( Opcodes.FCONST_0 );
+ } else {
+ mv.visitInsn( Opcodes.ICONST_0 );
+ }
+
+ // localVar = pop()
+ mv.visitLabel( afterif );
+ mv.visitVarInsn( Type.getType( field.getPropertyType() ).getOpcode( Opcodes.ISTORE ),
+ 3 );
+ } else {
+ // localVar = (xxxClass) value
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 2 );
+ mv.visitTypeInsn( Opcodes.CHECKCAST,
+ Type.getInternalName( field.getPropertyType() ) );
+ mv.visitVarInsn( Opcodes.ASTORE,
+ 3 );
+ }
+
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 1 );
+ mv.visitTypeInsn( Opcodes.CHECKCAST,
+ Type.getInternalName( clazz ) );
+ mv.visitVarInsn( Type.getType( field.getPropertyType() ).getOpcode( Opcodes.ILOAD ),
+ 3 );
+
+ mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ Type.getInternalName( clazz ),
+ field.getWriteMethod().getName(),
+ Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[]{Type.getType( field.getPropertyType() )} ) );
+
+ mv.visitInsn( Opcodes.RETURN );
+ mv.visitMaxs( 0,
+ 0 ); // auto calculated
+ mv.visitEnd();
+ }
+ }
+
+ /**
+ * Creates a default constructor for the class
+ *
+ * @param cw
+ */
+ private void buildDefaultConstructor(ClassWriter cw) {
+ MethodVisitor mv;
+ // Building default constructor
+ {
+ mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+ "<init>",
+ Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[]{} ),
+ null,
+ null );
+ mv.visitCode();
+ mv.visitVarInsn( Opcodes.ALOAD,
+ 0 );
+ mv.visitMethodInsn( Opcodes.INVOKESPECIAL,
+ Type.getInternalName( Object.class ),
+ "<init>",
+ Type.getMethodDescriptor( Type.VOID_TYPE,
+ new Type[]{} ) );
+ mv.visitInsn( Opcodes.RETURN );
+ mv.visitMaxs( 0,
+ 0 );
+ mv.visitEnd();
+ }
+ }
+
+ private Class loadClass(String classname,
+ byte[] b) throws ClassNotFoundException,
+ SecurityException,
+ NoSuchMethodException,
+ IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException {
+ //override classDefine (as it is protected) and define the class.
+ Class clazz = null;
+ ClassLoader loader = ClassBuilder.class.getClassLoader();
+ Class cls = Class.forName( "java.lang.ClassLoader" );
+ java.lang.reflect.Method method = cls.getDeclaredMethod( "defineClass",
+ new Class[]{String.class, byte[].class, int.class, int.class} );
+
+ // protected method invocaton
+ method.setAccessible( true );
+ try {
+ Object[] args = new Object[]{classname, b, new Integer( 0 ), new Integer( b.length )};
+ clazz = (Class) method.invoke( loader,
+ args );
+ } finally {
+ method.setAccessible( false );
+ }
+ return clazz;
+ }
+
+ /**
+ * Creates the String name for the get method for a field with the given name and type
+ * @param name
+ * @param type
+ * @return
+ */
+ public String getReadMethod(Field field) {
+ String prefix = null;
+ if ( Boolean.TYPE.equals( field.getType() ) ) {
+ prefix = "is";
+ } else {
+ prefix = "get";
+ }
+ return prefix + field.getName().substring( 0,
+ 1 ).toUpperCase() + field.getName().substring( 1 );
+ }
+
+ /**
+ * Creates the String name for the set method for a field with the given name and type
+ *
+ * @param name
+ * @param type
+ * @return
+ */
+ public String getWriteMethod(Field field) {
+ return "set" + field.getName().substring( 0,
+ 1 ).toUpperCase() + field.getName().substring( 1 );
+ }
+
+}
Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldAccessorBuilder.java
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:eol-style
+ native
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java 2008-04-23 04:32:45 UTC (rev 19693)
@@ -0,0 +1,277 @@
+package org.drools.factmodel;
+
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * <p><b>Title:</b> FieldDefinition</p>
+ * <p><b>Description:</b> Declares a field to be dynamically generated</p>
+ * <p><b>Copyright:</b> Copyright (c) 2004-2006</p>
+ * <p><b>Company:</b> Auster Solutions</p>
+ *
+ * @author etirelli
+ * @version $Id: FieldDefinition.java 205 2006-03-21 18:27:52Z etirelli $
+ */
+public class FieldDefinition {
+ private String name = null;
+ private String type = null;
+ private boolean key = false;
+
+ private String internalType = null;
+ private String boxTypeName = null;
+ private boolean primitive = false;
+ private String unboxMethod = null;
+ private FieldAccessor accessor = null;
+
+ /**
+ * Default constructor
+ *
+ * @param name the field's name
+ * @param type the fully qualified fields type
+ */
+ public FieldDefinition(String name,
+ String type) {
+ this(name, type, false);
+ }
+
+ /**
+ * Default constructor
+ *
+ * @param name the field's name
+ * @param type the fully qualified fields type
+ */
+ public FieldDefinition(String name,
+ String type,
+ boolean key) {
+ this.name = name;
+ this.type = type;
+ this.key = key;
+ this.setInternals();
+ }
+
+ /**
+ * @return Returns the name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name The name to set.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return Returns the fully qualified type.
+ */
+ public String getType() {
+ return this.type;
+ }
+
+ /**
+ * @param type The fully qualified type to set.
+ */
+ public void setType(String type) {
+ this.type = type;
+ this.setInternals();
+ }
+
+ /**
+ * @return Returns the fully qualified internal type representation
+ */
+ String getInternalType() {
+ return this.internalType;
+ }
+
+ String getBoxTypeName() {
+ return this.boxTypeName;
+ }
+
+ /**
+ * @return Returns the primitive.
+ */
+ boolean isPrimitive() {
+ return primitive;
+ }
+
+ /**
+ * @return Returns the unboxMethod.
+ */
+ String getUnboxMethod() {
+ return unboxMethod;
+ }
+
+ /**
+ * @return Returns the key.
+ */
+ public boolean isKey() {
+ return key;
+ }
+
+ /**
+ * @param key The key to set.
+ */
+ public void setKey(boolean key) {
+ this.key = key;
+ }
+
+ /**
+ * Creates the String name for the get method for a field with the given name and type
+ * @param name
+ * @param type
+ * @return
+ */
+ public String getReadMethod() {
+ String prefix = null;
+ if ( "boolean".equals( this.type ) ) {
+ prefix = "is";
+ } else {
+ prefix = "get";
+ }
+ return prefix + this.name.substring( 0,
+ 1 ).toUpperCase() + this.name.substring( 1 );
+ }
+
+ /**
+ * Creates the String name for the set method for a field with the given name and type
+ *
+ * @param name
+ * @param type
+ * @return
+ */
+ public String getWriteMethod() {
+ return "set" + this.name.substring( 0,
+ 1 ).toUpperCase() + this.name.substring( 1 );
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public boolean equals(Object o) {
+ return this.getName().equals( ((FieldDefinition) o).getName() );
+ }
+
+ /**
+ * @return Returns the field accessor
+ */
+ FieldAccessor getFieldAccessor() {
+ return this.accessor;
+ }
+
+ /**
+ * @param property The property descriptor to set.
+ */
+ void setFieldAccessor(FieldAccessor accessor) {
+ this.accessor = accessor;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public int hashCode() {
+ return this.getName().hashCode();
+ }
+
+ /**
+ * Sets the value of this attribute in the target
+ * bean instance
+ *
+ * @param bean the target bean instance where the attribute shall be set
+ * @param value the value to set the attribute to
+ *
+ * @throws IllegalArgumentException
+ * @throws IllegalAccessException
+ * @throws InvocationTargetException
+ */
+ public void setValue(Object bean,
+ Object value) throws IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException {
+ if(this.accessor == null) {
+ System.out.println("ACCESSOR NULL");
+ }
+ this.accessor.setValue( bean, value );
+ }
+
+ /**
+ * Returns the value of this attribute in the target bean instance
+ *
+ * @param bean the target bean instance
+ *
+ * @return target bean instance attribute value
+ *
+ * @throws IllegalArgumentException
+ * @throws IllegalAccessException
+ * @throws InvocationTargetException
+ */
+ public Object getValue(Object bean) throws IllegalArgumentException,
+ IllegalAccessException,
+ InvocationTargetException {
+ return this.accessor.getValue( bean );
+ }
+
+ /**
+ * Creates the internal string representation of this attribute's type
+ *
+ * @param type
+ * @return
+ */
+ private void setInternals() {
+ if ( "byte".equals( this.type ) ) {
+ this.internalType = "B";
+ this.boxTypeName = "java/lang/Byte";
+ this.primitive = true;
+ this.unboxMethod = "byteValue";
+ } else if ( "char".equals( type ) ) {
+ this.internalType = "C";
+ this.boxTypeName = "java/lang/Character";
+ this.primitive = true;
+ this.unboxMethod = "charValue";
+ } else if ( "double".equals( type ) ) {
+ this.internalType = "D";
+ this.boxTypeName = "java/lang/Double";
+ this.primitive = true;
+ this.unboxMethod = "doubleValue";
+ } else if ( "float".equals( type ) ) {
+ this.internalType = "F";
+ this.boxTypeName = "java/lang/Float";
+ this.primitive = true;
+ this.unboxMethod = "floatValue";
+ } else if ( "int".equals( type ) ) {
+ this.internalType = "I";
+ this.boxTypeName = "java/lang/Integer";
+ this.primitive = true;
+ this.unboxMethod = "intValue";
+ } else if ( "long".equals( type ) ) {
+ this.internalType = "J";
+ this.boxTypeName = "java/lang/Long";
+ this.primitive = true;
+ this.unboxMethod = "longValue";
+ } else if ( "short".equals( type ) ) {
+ this.internalType = "S";
+ this.boxTypeName = "java/lang/Short";
+ this.primitive = true;
+ this.unboxMethod = "shortValue";
+ } else if ( "boolean".equals( type ) ) {
+ this.internalType = "Z";
+ this.boxTypeName = "java/lang/Boolean";
+ this.primitive = true;
+ this.unboxMethod = "booleanValue";
+ } else if ( "void".equals( type ) ) {
+ this.internalType = "V";
+ this.boxTypeName = "java/lang/Void";
+ this.primitive = true;
+ this.unboxMethod = null;
+ } else if ( type != null ) {
+ this.internalType = "L" + type.replace( '.',
+ '/' ) + ";";
+ this.boxTypeName = type.replace( '.',
+ '/' );
+ this.primitive = false;
+ this.unboxMethod = null;
+ }
+ }
+
+}
\ No newline at end of file
Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:eol-style
+ native
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Jenerator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Jenerator.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Jenerator.java 2008-04-23 04:32:45 UTC (rev 19693)
@@ -0,0 +1,78 @@
+package org.drools.factmodel;
+
+
+import java.beans.IntrospectionException;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.io.xml.DomDriver;
+
+/**
+ * This will generate a jar from a meta model.
+ * @author Michael Neale
+ *
+ */
+public class Jenerator {
+
+
+
+ public byte[] createJar(Fact[] facts, String packageName) throws SecurityException, IllegalArgumentException, IOException, IntrospectionException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ JarOutputStream jout = new JarOutputStream(result);
+
+ JarEntry metaModel = new JarEntry("factmodel.xml");
+ jout.putNextEntry(metaModel);
+ jout.write(toXML(facts));
+ jout.closeEntry();
+
+ String packagePath = packageName.replace('.', '/');
+
+ for (int i = 0; i < facts.length; i++) {
+ ClassBuilder cb = new ClassBuilder();
+ ClassDefinition classDef = new ClassDefinition( packageName, null, new String[]{"java.io.Serializable"} );
+ for (int j = 0; j < facts[i].fields.size(); j++) {
+ Field fd = (Field) facts[i].fields.get(j);
+ classDef.addField(new FieldDefinition(fd.name, fd.type));
+ }
+ JarEntry je = new JarEntry(packagePath + "/" + facts[i].name + ".class");
+ jout.putNextEntry(je);
+ jout.write(cb.buildClass(classDef));
+ jout.closeEntry();
+ }
+ jout.flush();
+ jout.close();
+
+ return result.toByteArray();
+ }
+
+ private byte[] toXML(Fact[] facts) {
+ XStream x = new XStream(new DomDriver());
+ return x.toXML(facts).getBytes();
+
+ }
+
+ public Fact[] loadMetaModel(JarInputStream jis) throws Exception {
+ JarEntry entry = null;
+ while ( (entry = jis.getNextJarEntry()) != null ) {
+ if (entry.getName().equals("factmodel.xml")) {
+ return fromXML(jis);
+ }
+ }
+
+ throw new IllegalArgumentException("This is not a valid drools model jar - no factmodel.xml found.");
+ }
+
+ private Fact[] fromXML(JarInputStream jis) {
+ XStream x = new XStream(new DomDriver());
+ return (Fact[]) x.fromXML(jis);
+
+ }
+
+
+}
Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/Jenerator.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/ClassBuilderTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/ClassBuilderTest.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/ClassBuilderTest.java 2008-04-23 04:32:45 UTC (rev 19693)
@@ -0,0 +1,312 @@
+package org.drools.factmodel;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Date;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public class ClassBuilderTest extends TestCase {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /*
+ * Test method for 'br.com.auster.common.asm.ClassBuilder.buildClass(ClassDefinition)'
+ */
+ public void testBuildClass() {
+ try {
+ ClassBuilder builder = new ClassBuilder();
+
+ ClassDefinition classDef = new ClassDefinition( "br.com.auster.TestClass1",
+ null,
+ new String[]{"java.io.Serializable"} );
+ FieldDefinition intDef = new FieldDefinition( "intAttr",
+ "int" );
+
+
+ FieldDefinition stringDef = new FieldDefinition( "stringAttr",
+ "java.lang.String");//"java.lang.String" );
+ classDef.addField( intDef );
+ classDef.addField( stringDef );
+
+ Class clazz = builder.buildAndLoadClass( classDef );
+
+
+ byte[] data = builder.buildClass(classDef);
+
+
+
+ Assert.assertSame( "Returned class should be the same",
+ clazz,
+ classDef.getDefinedClass() );
+ Assert.assertEquals( "Class name should be equal",
+ classDef.getClassName(),
+ clazz.getName() );
+
+ Serializable instance = (Serializable) clazz.newInstance();
+
+ String stringValue = "Atributo String ok";
+ stringDef.setValue( instance,
+ stringValue );
+ Assert.assertEquals( "Attribute should have been correctly set",
+ stringValue,
+ stringDef.getValue( instance ) );
+
+ int intValue = 50;
+ intDef.setValue( instance,
+ new Integer( intValue ) );
+ Assert.assertEquals( "Attribute should have been correctly set",
+ intValue,
+ ((Integer) intDef.getValue( instance )).intValue() );
+
+ // testing class rebuilding
+ clazz = builder.buildAndLoadClass( classDef );
+
+ } catch ( Exception e ) {
+ e.printStackTrace();
+ Assert.fail( "Error creating class" );
+ }
+ }
+
+ /**
+ * how to write to a jar.
+ * @param data
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ private void writeJar(byte[] data) throws FileNotFoundException,
+ IOException {
+ FileOutputStream out = new FileOutputStream(new File("/Users/michaelneale/edson.jar"));
+ JarOutputStream jout = new JarOutputStream(out);
+ JarEntry je = new JarEntry("br/com/auster/TestClass1.class");
+ jout.putNextEntry(je);
+ jout.write(data);
+ jout.closeEntry();
+ jout.close();
+ }
+
+ public void testEquals() {
+ try {
+ ClassBuilder builder = new ClassBuilder();
+
+ ClassDefinition classDef = new ClassDefinition( "br.com.auster.TestClass2",
+ null,
+ new String[]{} );
+ FieldDefinition long1Def = new FieldDefinition( "longAttr1",
+ "long",
+ true);
+ FieldDefinition long2Def = new FieldDefinition( "longAttr2",
+ "long",
+ true);
+ FieldDefinition doubleDef = new FieldDefinition( "doubleAttr",
+ "double",
+ true);
+ FieldDefinition intDef = new FieldDefinition( "intAttr",
+ "int",
+ true);
+ FieldDefinition strDef = new FieldDefinition( "stringAttr",
+ "java.lang.String",
+ true);
+ FieldDefinition dateDef = new FieldDefinition( "dateAttr",
+ "java.util.Date",
+ true);
+ FieldDefinition str2Def = new FieldDefinition( "stringAttr2",
+ "java.lang.String" );
+ classDef.addField( long1Def );
+ classDef.addField( long2Def );
+ classDef.addField( doubleDef );
+ classDef.addField( intDef );
+ classDef.addField( strDef );
+ classDef.addField( dateDef );
+ classDef.addField( str2Def );
+
+ Class clazz = builder.buildAndLoadClass( classDef );
+ Object x = clazz.newInstance();
+ Object y = clazz.newInstance();
+
+ long1Def.setValue( x,
+ new Long( 20 ) );
+ long2Def.setValue( x,
+ new Long( 30 ) );
+ doubleDef.setValue( x,
+ new Double( 50.0 ) );
+ intDef.setValue( x,
+ new Integer( 10 ) );
+ strDef.setValue( x,
+ "abc" );
+ dateDef.setValue( x,
+ new Date( 1000 ) );
+ str2Def.setValue( x,
+ "instance1" );
+
+ long1Def.setValue( y,
+ new Long( 20 ) );
+ long2Def.setValue( y,
+ new Long( 30 ) );
+ doubleDef.setValue( y,
+ new Double( 50.0 ) );
+ intDef.setValue( y,
+ new Integer( 10 ) );
+ strDef.setValue( y,
+ "abc" );
+ dateDef.setValue( y,
+ new Date( 1000 ) );
+ str2Def.setValue( y,
+ "instance2" );
+
+ Object o = new Object();
+
+ Assert.assertTrue( x.equals( x ) );
+ Assert.assertFalse( x.equals( null ) );
+ Assert.assertFalse( x.equals( o ) );
+
+ Assert.assertTrue( x.equals( y ) );
+
+ intDef.setValue( y,
+ new Integer( 1 ) );
+ Assert.assertFalse( x.equals( y ) );
+
+ intDef.setValue( y,
+ new Integer( 10 ) );
+ strDef.setValue( y,
+ "xyz" );
+ Assert.assertFalse( x.equals( y ) );
+
+ strDef.setValue( y,
+ null );
+ Assert.assertFalse( x.equals( y ) );
+
+ strDef.setValue( y,
+ "abc" );
+ dateDef.setValue( y,
+ new Date( 1 ) );
+ Assert.assertFalse( x.equals( y ) );
+
+ dateDef.setValue( y,
+ null );
+ Assert.assertFalse( x.equals( y ) );
+
+ } catch ( Exception e ) {
+ e.printStackTrace();
+ Assert.fail("Exception not expected");
+ }
+ }
+
+ public void testHashCode() {
+ try {
+ ClassBuilder builder = new ClassBuilder();
+
+ ClassDefinition classDef = new ClassDefinition( "br.com.auster.TestClass3",
+ null,
+ new String[]{} );
+ FieldDefinition intDef = new FieldDefinition( "intAttr",
+ "int",
+ true);
+ FieldDefinition strDef = new FieldDefinition( "stringAttr",
+ "java.lang.String",
+ false);
+ classDef.addField( intDef );
+ classDef.addField( strDef );
+
+ Class clazz = builder.buildAndLoadClass( classDef );
+ Object x = clazz.newInstance();
+
+ intDef.setValue( x,
+ new Integer( 10 ) );
+ strDef.setValue( x, "abc" );
+
+ Assert.assertEquals("Wrong hashcode calculation", (new Integer(10)).hashCode(), x.hashCode());
+ Assert.assertEquals("Wrong hashcode calculation", x.hashCode(), x.hashCode());
+
+ } catch ( Exception e ) {
+ e.printStackTrace();
+ Assert.fail("Exception not expected");
+ }
+ }
+
+ public void testToString() {
+ try {
+ ClassBuilder builder = new ClassBuilder();
+
+ ClassDefinition classDef = new ClassDefinition( "br.com.auster.TestClass2",
+ null,
+ new String[]{} );
+ FieldDefinition long1Def = new FieldDefinition( "longAttr1",
+ "long",
+ true);
+ FieldDefinition long2Def = new FieldDefinition( "longAttr2",
+ "long",
+ true);
+ FieldDefinition doubleDef = new FieldDefinition( "doubleAttr",
+ "double",
+ true);
+ FieldDefinition intDef = new FieldDefinition( "intAttr",
+ "int",
+ true);
+ FieldDefinition strDef = new FieldDefinition( "stringAttr",
+ "java.lang.String",
+ true);
+ FieldDefinition dateDef = new FieldDefinition( "dateAttr",
+ "java.util.Date",
+ true);
+ FieldDefinition str2Def = new FieldDefinition( "stringAttr2",
+ "java.lang.String" );
+ classDef.addField( long1Def );
+ classDef.addField( long2Def );
+ classDef.addField( doubleDef );
+ classDef.addField( intDef );
+ classDef.addField( strDef );
+ classDef.addField( dateDef );
+ classDef.addField( str2Def );
+
+ Class clazz = builder.buildAndLoadClass( classDef );
+ Object x = clazz.newInstance();
+
+ long1Def.setValue( x,
+ new Long( 20 ) );
+ long2Def.setValue( x,
+ new Long( 30 ) );
+ doubleDef.setValue( x,
+ new Double( 50.0 ) );
+ intDef.setValue( x,
+ new Integer( 10 ) );
+ strDef.setValue( x,
+ "abc" );
+ dateDef.setValue( x,
+ new Date( 1000 ) );
+ str2Def.setValue( x,
+ "instance1" );
+
+ String result = x.toString();
+
+ Assert.assertTrue( result.contains( long1Def.getName() ));
+ Assert.assertTrue( result.contains( long2Def.getName() ));
+ Assert.assertTrue( result.contains( doubleDef.getName() ));
+ Assert.assertTrue( result.contains( intDef.getName() ));
+ Assert.assertTrue( result.contains( strDef.getName() ));
+ Assert.assertTrue( result.contains( dateDef.getName() ));
+ Assert.assertTrue( result.contains( str2Def.getName() ));
+
+ } catch ( Exception e ) {
+ e.printStackTrace();
+ Assert.fail("Exception not expected");
+ }
+
+ }
+
+}
Property changes on: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/ClassBuilderTest.java
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:eol-style
+ native
Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/FieldAccessorBuilderTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/FieldAccessorBuilderTest.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/FieldAccessorBuilderTest.java 2008-04-23 04:32:45 UTC (rev 19693)
@@ -0,0 +1,319 @@
+package org.drools.factmodel;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public class FieldAccessorBuilderTest extends TestCase {
+ FieldAccessorBuilder builder;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.builder = new FieldAccessorBuilder();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /*
+ * Test method for 'br.com.auster.common.asm.FieldAccessorBuilder.buildFieldAccessor(ClassDefinition, FieldDefinition)'
+ */
+ public void testBuildFieldAccessor() {
+ try {
+ FieldAccessor intAccessor = (FieldAccessor) builder.buildAndLoadFieldAccessor( TestClass.class,
+ "intAttr" ).newInstance();
+ FieldAccessor strAccessor = (FieldAccessor) builder.buildAndLoadFieldAccessor( TestClass.class,
+ "strAttr" ).newInstance();
+
+ String testString1 = "TestAttr1";
+ String testString2 = "TestAttr2";
+ TestClass instance = new TestClass();
+ instance.setIntAttr( 10 );
+ instance.setStrAttr( testString1 );
+
+ Assert.assertEquals( "Error reading int attr",
+ 10,
+ ((Integer) intAccessor.getValue( instance )).intValue() );
+ Assert.assertEquals( "Error reading String attr",
+ testString1,
+ strAccessor.getValue( instance ) );
+
+ intAccessor.setValue( instance,
+ new Integer( 50 ) );
+ strAccessor.setValue( instance,
+ testString2 );
+
+ Assert.assertEquals( "Error setting int attr",
+ 50,
+ instance.getIntAttr() );
+ Assert.assertEquals( "Error setting String attr",
+ testString2,
+ instance.getStrAttr() );
+
+ Assert.assertEquals( "Error reading int attr",
+ 50,
+ ((Integer) intAccessor.getValue( instance )).intValue() );
+ Assert.assertEquals( "Error reading String attr",
+ testString2,
+ strAccessor.getValue( instance ) );
+
+ } catch ( Exception e ) {
+ e.printStackTrace();
+ Assert.fail( "No exception is supposed to be generated when creating field accessor: " + e );
+ }
+ }
+
+ public void testNullOnPrimitives() {
+ try {
+ FieldAccessor intAccessor = (FieldAccessor) builder.buildAndLoadFieldAccessor( TestClass.class,
+ "intAttr" ).newInstance();
+ FieldAccessor strAccessor = (FieldAccessor) builder.buildAndLoadFieldAccessor( TestClass.class,
+ "strAttr" ).newInstance();
+ FieldAccessor byteAccessor = (FieldAccessor) builder.buildAndLoadFieldAccessor( TestClass.class,
+ "byteAttr" ).newInstance();
+ FieldAccessor booleanAccessor = (FieldAccessor) builder.buildAndLoadFieldAccessor( TestClass.class,
+ "booleanAttr" ).newInstance();
+ FieldAccessor charAccessor = (FieldAccessor) builder.buildAndLoadFieldAccessor( TestClass.class,
+ "charAttr" ).newInstance();
+ FieldAccessor doubleAccessor = (FieldAccessor) builder.buildAndLoadFieldAccessor( TestClass.class,
+ "doubleAttr" ).newInstance();
+ FieldAccessor floatAccessor = (FieldAccessor) builder.buildAndLoadFieldAccessor( TestClass.class,
+ "floatAttr" ).newInstance();
+ FieldAccessor longAccessor = (FieldAccessor) builder.buildAndLoadFieldAccessor( TestClass.class,
+ "longAttr" ).newInstance();
+ FieldAccessor shortAccessor = (FieldAccessor) builder.buildAndLoadFieldAccessor( TestClass.class,
+ "shortAttr" ).newInstance();
+
+ String testString1 = "TestAttr1";
+ TestClass instance = new TestClass();
+ instance.setIntAttr( 25 );
+ instance.setStrAttr( testString1 );
+ instance.setByteAttr( (byte) 10 );
+ instance.setBooleanAttr( true );
+ instance.setCharAttr( 'x' );
+ instance.setDoubleAttr( 10.5d );
+ instance.setFloatAttr( 40.3f );
+ instance.setLongAttr( 43l );
+ instance.setShortAttr( (short) 20 );
+
+ intAccessor.setValue( instance,
+ null );
+ strAccessor.setValue( instance,
+ null );
+ byteAccessor.setValue( instance,
+ null );
+ booleanAccessor.setValue( instance,
+ null );
+ charAccessor.setValue( instance,
+ null );
+ doubleAccessor.setValue( instance,
+ null );
+ floatAccessor.setValue( instance,
+ null );
+ longAccessor.setValue( instance,
+ null );
+ shortAccessor.setValue( instance,
+ null );
+
+ Assert.assertEquals( "Error setting attr",
+ 0,
+ instance.getIntAttr() );
+ Assert.assertNull( "Error setting attr",
+ instance.getStrAttr() );
+ Assert.assertEquals( "Error setting attr",
+ 0,
+ instance.getByteAttr() );
+ Assert.assertEquals( "Error setting attr",
+ false,
+ instance.isBooleanAttr() );
+ Assert.assertEquals( "Error setting attr",
+ '\0',
+ instance.getCharAttr() );
+ Assert.assertEquals( "Error setting attr",
+ 0.0d,
+ instance.getDoubleAttr(),
+ 0.1d );
+ Assert.assertEquals( "Error setting attr",
+ 0.0f,
+ instance.getFloatAttr(),
+ 0.1f );
+ Assert.assertEquals( "Error setting attr",
+ 0l,
+ instance.getLongAttr() );
+ Assert.assertEquals( "Error setting attr",
+ (short) 0,
+ instance.getShortAttr() );
+
+ Assert.assertEquals( "Error reading int attr",
+ 0,
+ ((Integer) intAccessor.getValue( instance )).intValue() );
+ Assert.assertNull( "Error reading String attr",
+ strAccessor.getValue( instance ) );
+ Assert.assertEquals( "Error reading attr",
+ 0,
+ ((Byte) byteAccessor.getValue( instance )).byteValue() );
+ Assert.assertEquals( "Error reading attr",
+ false,
+ ((Boolean) booleanAccessor.getValue( instance )).booleanValue() );
+ Assert.assertEquals( "Error reading attr",
+ '\0',
+ ((Character) charAccessor.getValue( instance )).charValue() );
+ Assert.assertEquals( "Error reading attr",
+ 0.0d,
+ ((Double) doubleAccessor.getValue( instance )).doubleValue(),
+ 0.1d );
+ Assert.assertEquals( "Error reading attr",
+ 0.0f,
+ ((Float) floatAccessor.getValue( instance )).floatValue(),
+ 0.1f );
+ Assert.assertEquals( "Error reading attr",
+ 0l,
+ ((Long) longAccessor.getValue( instance )).longValue() );
+ Assert.assertEquals( "Error reading attr",
+ (short) 0,
+ ((Short) shortAccessor.getValue( instance )).shortValue() );
+
+ } catch ( Exception e ) {
+ e.printStackTrace();
+ Assert.fail( "No exception is supposed to be generated when creating field accessor: " + e );
+ }
+ }
+
+ public static class TestClass {
+ private int intAttr;
+ private String strAttr;
+ private byte byteAttr;
+ private boolean booleanAttr;
+ private char charAttr;
+ private double doubleAttr;
+ private float floatAttr;
+ private long longAttr;
+ private short shortAttr;
+
+ /**
+ * @return Returns the intAttr.
+ */
+ public int getIntAttr() {
+ return intAttr;
+ }
+
+ /**
+ * @param intAttr The intAttr to set.
+ */
+ public void setIntAttr(int intAttr) {
+ this.intAttr = intAttr;
+ }
+
+ /**
+ * @return Returns the strAttr.
+ */
+ public String getStrAttr() {
+ return strAttr;
+ }
+
+ /**
+ * @param strAttr The strAttr to set.
+ */
+ public void setStrAttr(String strAttr) {
+ this.strAttr = strAttr;
+ }
+
+ /**
+ * @return Returns the booleanAttr.
+ */
+ public boolean isBooleanAttr() {
+ return booleanAttr;
+ }
+
+ /**
+ * @param booleanAttr The booleanAttr to set.
+ */
+ public void setBooleanAttr(boolean booleanAttr) {
+ this.booleanAttr = booleanAttr;
+ }
+
+ /**
+ * @return Returns the byteAttr.
+ */
+ public byte getByteAttr() {
+ return byteAttr;
+ }
+
+ /**
+ * @param byteAttr The byteAttr to set.
+ */
+ public void setByteAttr(byte byteAttr) {
+ this.byteAttr = byteAttr;
+ }
+
+ /**
+ * @return Returns the charAttr.
+ */
+ public char getCharAttr() {
+ return charAttr;
+ }
+
+ /**
+ * @param charAttr The charAttr to set.
+ */
+ public void setCharAttr(char charAttr) {
+ this.charAttr = charAttr;
+ }
+
+ /**
+ * @return Returns the doubleAttr.
+ */
+ public double getDoubleAttr() {
+ return doubleAttr;
+ }
+
+ /**
+ * @param doubleAttr The doubleAttr to set.
+ */
+ public void setDoubleAttr(double doubleAttr) {
+ this.doubleAttr = doubleAttr;
+ }
+
+ /**
+ * @return Returns the floatAttr.
+ */
+ public float getFloatAttr() {
+ return floatAttr;
+ }
+
+ /**
+ * @param floatAttr The floatAttr to set.
+ */
+ public void setFloatAttr(float floatAttr) {
+ this.floatAttr = floatAttr;
+ }
+
+ /**
+ * @return Returns the longAttr.
+ */
+ public long getLongAttr() {
+ return longAttr;
+ }
+
+ /**
+ * @param longAttr The longAttr to set.
+ */
+ public void setLongAttr(long longAttr) {
+ this.longAttr = longAttr;
+ }
+
+ /**
+ * @return Returns the shortAttr.
+ */
+ public short getShortAttr() {
+ return shortAttr;
+ }
+
+ /**
+ * @param shortAttr The shortAttr to set.
+ */
+ public void setShortAttr(short shortAttr) {
+ this.shortAttr = shortAttr;
+ }
+ }
+}
Property changes on: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/FieldAccessorBuilderTest.java
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:eol-style
+ native
Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/InstancesHashcodedTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/InstancesHashcodedTest.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/InstancesHashcodedTest.java 2008-04-23 04:32:45 UTC (rev 19693)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2004-2006 Auster Solutions. All Rights Reserved.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Created on 26/08/2006
+ */
+package org.drools.factmodel;
+
+import java.sql.Types;
+import java.util.Calendar;
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+/**
+ * @author framos
+ * @version $Id$
+ *
+ */
+public class InstancesHashcodedTest extends TestCase {
+
+
+/*
+ <dimension name="bck_cycle_dm" item-expression="cycleDimension"
+ mode="ignore" cache="10" export-to="cycle_id">
+ <id name="objid" type="long" generator-sql="select bck_dimensions_uid.nextval from dual"/>
+ <field name="cut_date" type="java.util.Date" value="cutDate" key="true"/>
+ <field name="due_date" type="java.util.Date" value="dueDate" key="true"/>
+ <field name="cycle_code" type="java.lang.String" value="cycleCode"/>
+ <field name="issue_date" type="java.util.Date" value="issueDate"/>
+ </dimension>
+ */
+
+
+ public void testInstanceHashcodes() {
+
+ ClassDefinition cd = new ClassDefinition( "br.com.auster.TestClass2", null, new String[]{} );
+ cd.addField(new FieldDefinition("cutDate", "java.util.Date", true));
+ cd.addField(new FieldDefinition("dueDate", "java.util.Date", true));
+ cd.addField(new FieldDefinition("issueDate", "java.util.Date", false));
+ cd.addField(new FieldDefinition("cycleCode", "java.lang.String", false));
+
+ ClassBuilder cb = new ClassBuilder();
+
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.YEAR, 2006);
+ cal.set(Calendar.MONTH, Calendar.JUNE);
+ cal.set(Calendar.DAY_OF_MONTH, 01);
+ Date cut = cal.getTime();
+
+ cal.set(Calendar.MONTH, Calendar.JULY);
+ cal.set(Calendar.DAY_OF_MONTH, 13);
+ Date d1 = cal.getTime();
+
+ cal.set(Calendar.DAY_OF_MONTH, 15);
+ Date d2 = cal.getTime();
+
+ try {
+ Class klass = cb.buildAndLoadClass(cd);
+ Object o1 = klass.newInstance();
+ cd.getField("cutDate").getFieldAccessor().setValue(o1, cut);
+ cd.getField("dueDate").getFieldAccessor().setValue(o1, d1);
+
+ Object o2 = klass.newInstance();
+ cd.getField("cutDate").getFieldAccessor().setValue(o2, cut);
+ cd.getField("dueDate").getFieldAccessor().setValue(o2, d2);
+
+ System.out.println(o1);
+ System.out.println(o1.hashCode());
+ System.out.println(o2);
+ System.out.println(o2.hashCode());
+
+ System.out.println(o1.equals(o2));
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
Property changes on: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/InstancesHashcodedTest.java
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:eol-style
+ native
Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/JeneratorTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/JeneratorTest.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/JeneratorTest.java 2008-04-23 04:32:45 UTC (rev 19693)
@@ -0,0 +1,74 @@
+package org.drools.factmodel;
+
+import java.io.ByteArrayInputStream;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+import junit.framework.TestCase;
+
+
+/**
+ * This mostly shows how to go to a jar and back, if needed.
+ * Probably can be partly ignored eventually.
+ *
+ * @author Michael Neale
+ */
+public class JeneratorTest extends TestCase {
+
+
+ public void testRoundTrip() throws Exception {
+ Fact f = new Fact();
+ f.name = "Foobar";
+ Field f1 = new Field();
+ f1.name = "name";
+ f1.type = "java.lang.String";
+ f.fields.add(f1);
+
+ Field f2 = new Field();
+ f2.name = "age";
+ f2.type = "java.lang.Integer";
+ f.fields.add(f2);
+
+ Fact f_ = new Fact();
+ f_.name = "Baz";
+
+ Field f1_ = new Field();
+ f1_.name = "name";
+ f1_.type = "java.lang.String";
+ f_.fields.add(f1_);
+
+
+ Jenerator jen = new Jenerator();
+ byte[] data = jen.createJar(new Fact[] {f, f_}, "whee.waa");
+ JarInputStream jis = new JarInputStream(new ByteArrayInputStream(data));
+ JarEntry je = jis.getNextJarEntry();
+
+ assertNotNull(je);
+ System.err.println(je.getName());
+ assertEquals("factmodel.xml", je.getName());
+
+
+ je = jis.getNextJarEntry();
+
+ assertNotNull(je);
+ System.err.println(je.getName());
+ assertEquals("whee/waa/Foobar.class", je.getName());
+
+
+ je = jis.getNextJarEntry();
+
+ assertNotNull(je);
+ System.err.println(je.getName());
+ assertEquals("whee/waa/Baz.class", je.getName());
+
+
+
+ Fact[] facts = jen.loadMetaModel(new JarInputStream(new ByteArrayInputStream(data)));
+ assertEquals(2, facts.length);
+ assertEquals("Foobar", facts[0].name);
+ assertEquals("Baz", facts[1].name);
+
+
+ }
+
+}
Property changes on: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/factmodel/JeneratorTest.java
___________________________________________________________________
Name: svn:eol-style
+ native
More information about the jboss-svn-commits
mailing list