/* * Copyright 2011 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.chance.factmodel; import org.drools.chance.common.ImperfectField; import org.drools.chance.degree.ChanceDegreeTypeRegistry; import org.drools.chance.degree.DegreeType; import org.drools.chance.distribution.ImpKind; import org.drools.chance.distribution.ImpType; import org.drools.factmodel.AnnotationDefinition; import org.drools.factmodel.BuildUtils; import org.drools.factmodel.ClassDefinition; import org.drools.factmodel.FieldDefinition; import org.drools.factmodel.traits.TraitFactory; import org.drools.factmodel.traits.TraitRegistry; import org.drools.factmodel.traits.TraitTripleProxyClassBuilderImpl; import org.mvel2.asm.*; import java.lang.reflect.Method; import java.util.BitSet; import java.util.List; import java.util.Map; public class ChanceTripleProxyBuilderImpl extends TraitTripleProxyClassBuilderImpl { protected int buildConstructorCore( ClassWriter cw, MethodVisitor mv, String internalProxy, String internalWrapper, String internalCore, String descrCore, String mixin, Class mixinClass ) { int size = super.buildConstructorCore( cw, mv, internalProxy, internalWrapper, internalCore, descrCore, mixin, mixinClass ); List<AnnotationDefinition> annotations = getTrait().getAnnotations(); if ( annotations != null ) { for ( AnnotationDefinition adef : annotations ) { if ( adef.getName().equals( Imperfect.class.getName() ) ) { String kind = adef.getValues().containsKey( ImpKind.name ) ? adef.getValues().get( ImpKind.name ).getValue().toString() : ImpKind.PROBABILITY.toString(); String type = adef.getValues().containsKey( ImpType.name ) ? adef.getValues().get( ImpType.name ).getValue().toString() : ImpType.BASIC.toString(); String degree = adef.getValues().containsKey( DegreeType.name ) ? adef.getValues().get( DegreeType.name ).getValue().toString() : ChanceDegreeTypeRegistry.getDefaultDegree().toString(); mv.visitVarInsn( ALOAD, 0 ); mv.visitTypeInsn( NEW, "org/drools/chance/common/ImperfectFieldImpl" ); mv.visitInsn( DUP ); mv.visitFieldInsn( GETSTATIC, "org/drools/chance/distribution/ImpKind", kind, "Lorg/drools/chance/distribution/ImpKind;" ); mv.visitFieldInsn( GETSTATIC, "org/drools/chance/distribution/ImpType", type, "Lorg/drools/chance/distribution/ImpType;" ); mv.visitFieldInsn( GETSTATIC, "org/drools/chance/degree/DegreeType", degree, "Lorg/drools/chance/degree/DegreeType;" ); mv.visitLdcInsn( Type.getType( "Ljava/lang/Boolean;" ) ); mv.visitMethodInsn( INVOKESTATIC, "org/drools/chance/common/ChanceStrategyFactory", "buildStrategies", "(Lorg/drools/chance/distribution/ImpKind;Lorg/drools/chance/distribution/ImpType;Lorg/drools/chance/degree/DegreeType;Ljava/lang/Class;)Lorg/drools/chance/distribution/DistributionStrategies;" ); mv.visitMethodInsn( INVOKESPECIAL, "org/drools/chance/common/ImperfectFieldImpl", "<init>", "(Lorg/drools/chance/distribution/DistributionStrategies;)V" ); mv.visitFieldInsn( PUTFIELD, "org/drools/chance/factmodel/ImperfectTraitProxy", "holds", "Lorg/drools/chance/common/ImperfectField;" ); } } } return size + 2; } protected void buildProxyAccessor(BitSet mask, ClassWriter cw, String masterName, ClassDefinition core, Map<String, Method> mixinGetSet, FieldDefinition field, boolean isSoftField ) { if ( field instanceof VirtualFieldDefinition) return; if ( ! ( field instanceof ImperfectFieldDefinition) ) { if ( field instanceof DirectAccessFieldDefinition) { DirectAccessFieldDefinition dfld = (DirectAccessFieldDefinition) field; int j = 0; for ( FieldDefinition x : getTrait().getFieldsDefinitions() ) { if ( x.equals( dfld.getTarget() ) ) { break; } j++; } buildDirectProxyAccessor( mask, cw, masterName, core, mixinGetSet, dfld, TraitRegistry.isSoftField( dfld.getTarget(), j, mask) ); } else if ( ! isSupport( field ) ) { super.buildProxyAccessor( mask, cw, masterName, core, mixinGetSet, field, isSoftField ); } } else { buildImperfectGetter( cw, field, masterName, core, isSoftField ); buildImperfectSetter( cw, field, masterName, core, isSoftField ); if ( ! isSoftField ) { FieldVisitor fv; { fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, field.getName()+"_reader", "Lorg/drools/spi/InternalReadAccessor;", null, null); fv.visitEnd(); } { fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, field.getName()+"_writer", "Lorg/drools/spi/WriteAccessor;", null, null); fv.visitEnd(); } } if ( ImperfectFieldDefinition.isLinguistic( field ) ) { ImperfectFieldDefinition ifld = (ImperfectFieldDefinition) field; int j = 0; for ( FieldDefinition testField : getTrait().getFieldsDefinitions() ) { if ( testField.equals( ifld.getSupportFieldDef() ) ) { break; } else { j++; } } buildSupportFieldAccessors( mask, cw, masterName, core, mixinGetSet, ifld.getSupportFieldDef(), TraitRegistry.isSoftField( ifld, j , mask ) ); } } } private void buildSupportFieldAccessors( BitSet mask, ClassWriter cw, String masterName, ClassDefinition core, Map<String, Method> mixinGetSet, FieldDefinition supportField, boolean isSoftField ) { ImperfectFieldDefinition lingField = findSupportingField( getTrait(), supportField ); MethodVisitor mv; { mv = cw.visitMethod( ACC_PUBLIC, BuildUtils.getterName( supportField.getName(), supportField.getTypeName() ), "()" + BuildUtils.getTypeDescriptor( supportField.getTypeName() ), null, null); mv.visitCode(); mv.visitVarInsn( ALOAD, 0 ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( masterName ), BuildUtils.getterName( supportField.getName(), supportField.getTypeName() ) + "Core", "()" + BuildUtils.getTypeDescriptor( supportField.getTypeName() ) ); mv.visitInsn(ARETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, BuildUtils.setterName( supportField.getName(), supportField.getTypeName() ), "(" + BuildUtils.getTypeDescriptor( supportField.getTypeName() )+ ")V", null, null); mv.visitCode(); mv.visitVarInsn( ALOAD, 0 ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( masterName ), BuildUtils.getterName( lingField.getName(), lingField.getTypeName() ), "()Lorg/drools/chance/common/ImperfectField;" ); mv.visitTypeInsn( CHECKCAST, "org/drools/chance/distribution/fuzzy/linguistic/LinguisticImperfectField" ); mv.visitVarInsn( ASTORE, 2 ); mv.visitVarInsn( ALOAD, 2 ); mv.visitVarInsn( ALOAD, 2 ); mv.visitVarInsn( ALOAD, 1 ); mv.visitMethodInsn( INVOKEVIRTUAL, "org/drools/chance/distribution/fuzzy/linguistic/LinguisticImperfectField", "fuzzify", "(Ljava/lang/Number;)Lorg/drools/chance/distribution/Distribution;" ); mv.visitInsn( ICONST_0 ); mv.visitMethodInsn( INVOKEVIRTUAL, "org/drools/chance/distribution/fuzzy/linguistic/LinguisticImperfectField", "setValue", "(Lorg/drools/chance/distribution/Distribution;Z)V" ); mv.visitVarInsn( ALOAD, 0 ); mv.visitVarInsn( ALOAD, 2 ); mv.visitMethodInsn( INVOKEVIRTUAL, "org/drools/chance/distribution/fuzzy/linguistic/LinguisticImperfectField", "getCrisp", "()Lorg/drools/chance/distribution/fuzzy/linguistic/Linguistic;" ); mv.visitTypeInsn( CHECKCAST, BuildUtils.getInternalType( lingField.getTypeName() ) ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( masterName ), BuildUtils.setterName( lingField.getName(), lingField.getTypeName() ) + "Core", "(" + BuildUtils.getTypeDescriptor(lingField.getTypeName()) + ")V" ); mv.visitVarInsn( ALOAD, 0 ); mv.visitVarInsn( ALOAD, 1 ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( masterName ), BuildUtils.setterName(supportField.getName(), supportField.getTypeName()) + "Core", "(" + BuildUtils.getTypeDescriptor( supportField.getTypeName() )+ ")V" ); mv.visitInsn( RETURN ); mv.visitMaxs( 3, 3 ); mv.visitEnd(); } if ( ! isSoftField ) { FieldVisitor fv; { fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, supportField.getName()+"_reader", "Lorg/drools/spi/InternalReadAccessor;", null, null); fv.visitEnd(); } { fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, supportField.getName()+"_writer", "Lorg/drools/spi/WriteAccessor;", null, null); fv.visitEnd(); } } } protected void buildDirectProxyAccessor( BitSet mask, ClassWriter cw, String masterName, ClassDefinition core, Map<String,Method> mixinGetSet, DirectAccessFieldDefinition field, boolean isSoftField ) { FieldVisitor fv; String getterName = BuildUtils.getterName( field.getName(), field.getTypeName() ); String setterName = BuildUtils.setterName( field.getName(), field.getTypeName() ); if ( isSoftField ) { if ( ! mixinGetSet.containsKey( BuildUtils.getterName( field.getName(), field.getTypeName() ) ) ) { buildSoftGetter( cw, field.getTarget(), masterName, getTrait(), core, getterName, false ); buildSoftSetter( cw, field.getTarget(), masterName, getTrait(), core, setterName, false ); } else { // } } else { { fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, field.getName()+"_reader", "Lorg/drools/spi/InternalReadAccessor;", null, null); fv.visitEnd(); } { fv = cw.visitField(ACC_PUBLIC + ACC_STATIC, field.getName()+"_writer", "Lorg/drools/spi/WriteAccessor;", null, null); fv.visitEnd(); } buildHardGetter( cw, field.getTarget(), masterName, getTrait(), core, getterName, false ); buildHardSetter( cw, field.getTarget(), masterName, getTrait(), core, setterName, false ); } } /******************************************************************************************************************* * * Synch * *******************************************************************************************************************/ protected void buildExtendedMethods(ClassWriter cw, ClassDefinition trait, ClassDefinition core, BitSet mask ) { buildSynchFields( cw, TraitFactory.getProxyName(trait, core), core.getName(), getTrait() ); } protected void buildSynchFields( ClassWriter cw, String proxyName, String coreName, ClassDefinition def ) { { MethodVisitor mv = cw.visitMethod(ACC_PRIVATE, "synchFields", Type.getMethodDescriptor( Type.VOID_TYPE, new Type[] { Type.BOOLEAN_TYPE } ), null, null); mv.visitCode(); boolean hasLinguistic = false; for ( FieldDefinition fld : def.getFieldsDefinitions() ) { if ( fld instanceof VirtualFieldDefinition ) continue; if ( fld instanceof ImperfectFieldDefinition ) { ImperfectFieldDefinition ifld = (ImperfectFieldDefinition) fld; if ( ImperfectFieldDefinition.isLinguistic(ifld) ) { FieldDefinition tfld = ifld.getSupportFieldDef(); synchLinguisticField(mv, ifld, tfld, proxyName, coreName); hasLinguistic = true; } else { synchField(mv, ifld, proxyName); } } } mv.visitInsn( RETURN ); mv.visitMaxs( 3, hasLinguistic ? 4 : 3 ); mv.visitEnd(); } } private void synchField( MethodVisitor mv, ImperfectFieldDefinition ifld, String proxyName ) { // core field simple value mv.visitVarInsn( ALOAD, 0 ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( proxyName ), BuildUtils.getterName( ifld.getName(), ifld.getTypeName() )+ "Core", "()" + BuildUtils.getTypeDescriptor( ifld.getTypeName() ) ); mv.visitVarInsn( ASTORE, 1 ); // imp. field value mv.visitVarInsn( ALOAD, 0 ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( proxyName ), BuildUtils.getterName( ifld.getName(), ifld.getTypeName() ), "()Lorg/drools/chance/common/ImperfectField;"); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 1); Label l0 = new Label(); mv.visitJumpInsn(IFNULL, l0); mv.visitVarInsn( ALOAD, 2 ); mv.visitVarInsn( ALOAD, 1 ); mv.visitInsn( ICONST_0 ); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "setValue", "(Ljava/lang/Object;Z)V" ); mv.visitLabel(l0); // mv.visitFieldInsn( GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;" ); // mv.visitVarInsn( ALOAD, 2 ); // mv.visitMethodInsn( INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/Object;)V" ); mv.visitVarInsn( ALOAD, 0 ); mv.visitVarInsn( ALOAD, 2 ); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "getCrisp", "()Ljava/lang/Object;" ); mv.visitTypeInsn( CHECKCAST, BuildUtils.getInternalType( ifld.getTypeName() ) ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( proxyName ), BuildUtils.setterName( ifld.getName(), ifld.getTypeName())+"Core", "(" + BuildUtils.getTypeDescriptor( ifld.getTypeName() ) + ")V" ); } protected void synchLinguisticField( MethodVisitor mv, FieldDefinition fld, FieldDefinition tfld, String proxyName, String coreName ) { mv.visitVarInsn( ALOAD, 0 ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( proxyName ), BuildUtils.getterName( fld.getName(), fld.getTypeName() ), "()Lorg/drools/chance/common/ImperfectField;"); mv.visitTypeInsn( CHECKCAST, "org/drools/chance/distribution/fuzzy/linguistic/LinguisticImperfectField" ); mv.visitVarInsn( ASTORE, 1 ); mv.visitVarInsn( ALOAD, 0 ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( proxyName ), BuildUtils.getterName( tfld.getName(), tfld.getTypeName() ), "()" + BuildUtils.getTypeDescriptor( tfld.getTypeName() ) ); mv.visitVarInsn( ASTORE, 2 ); mv.visitVarInsn( ALOAD, 2 ); Label l0 = new Label(); mv.visitJumpInsn( IFNULL, l0 ); mv.visitVarInsn( ALOAD, 1 ); mv.visitVarInsn( ALOAD, 2 ); mv.visitMethodInsn( INVOKEVIRTUAL, "org/drools/chance/distribution/fuzzy/linguistic/LinguisticImperfectField", "fuzzify", "(Ljava/lang/Number;)Lorg/drools/chance/distribution/Distribution;"); mv.visitVarInsn( ASTORE, 3 ); mv.visitVarInsn( ALOAD, 1 ); mv.visitVarInsn( ALOAD, 3 ); mv.visitInsn( ICONST_0 ); mv.visitMethodInsn( INVOKEVIRTUAL, "org/drools/chance/distribution/fuzzy/linguistic/LinguisticImperfectField", "setValue", "(Lorg/drools/chance/distribution/Distribution;Z)V" ); mv.visitVarInsn( ALOAD, 0 ); mv.visitVarInsn( ALOAD, 1 ); mv.visitMethodInsn( INVOKEVIRTUAL, "org/drools/chance/distribution/fuzzy/linguistic/LinguisticImperfectField", "getCrisp", "()Lorg/drools/chance/distribution/fuzzy/linguistic/Linguistic;" ); mv.visitTypeInsn( CHECKCAST, BuildUtils.getInternalType( fld.getTypeName() ) ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( proxyName ), BuildUtils.setterName( fld.getName(), fld.getTypeName() ) + "Core", "(" + BuildUtils.getTypeDescriptor( fld.getTypeName() ) + ")V" ); Label l1 = new Label(); mv.visitJumpInsn( GOTO, l1 ); mv.visitLabel( l0 ); mv.visitVarInsn( ALOAD, 0 ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( proxyName ), BuildUtils.getterName( fld.getName(), fld.getTypeName() ) + "Value", "()" + BuildUtils.getTypeDescriptor( fld.getTypeName() ) + "" ); mv.visitVarInsn( ASTORE, 3 ); mv.visitVarInsn( ALOAD, 3 ); Label l2 = new Label(); mv.visitJumpInsn( IFNULL, l2 ); mv.visitVarInsn( ALOAD, 1 ); mv.visitVarInsn( ALOAD, 3 ); mv.visitMethodInsn( INVOKEVIRTUAL, "org/drools/chance/distribution/fuzzy/linguistic/LinguisticImperfectField", "setValue", "(Lorg/drools/chance/distribution/fuzzy/linguistic/Linguistic;)V" ); mv.visitLabel( l2 ); mv.visitVarInsn( ALOAD, 1 ); mv.visitJumpInsn( IFNULL, l1 ); mv.visitVarInsn( ALOAD, 0 ); mv.visitVarInsn( ALOAD, 1 ); mv.visitMethodInsn( INVOKEVIRTUAL, "org/drools/chance/distribution/fuzzy/linguistic/LinguisticImperfectField", "getCrisp", "()Lorg/drools/chance/distribution/fuzzy/linguistic/Linguistic;" ); mv.visitTypeInsn( CHECKCAST, BuildUtils.getInternalType( fld.getTypeName() ) ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( proxyName ), BuildUtils.setterName( fld.getName(), fld.getTypeName() ) + "Core", "(" + BuildUtils.getTypeDescriptor( fld.getTypeName() ) + ")V" ); mv.visitVarInsn( ALOAD, 0 ); mv.visitVarInsn( ALOAD, 1 ); defuzzifyOnTargetField( mv, proxyName, tfld ); mv.visitLabel( l1 ); } /******************************************************************************************************************* * * Accessors * *******************************************************************************************************************/ protected void buildImperfectGetter(ClassVisitor cw, FieldDefinition ifld, String wrapperName, ClassDefinition core, boolean softField) { MethodVisitor mv; String getter = BuildUtils.getterName( ifld.getName(), ifld.getTypeName() ); { mv = cw.visitMethod( ACC_PUBLIC, getter, "()Lorg/drools/chance/common/ImperfectField;", "()Lorg/drools/chance/common/ImperfectField<" + BuildUtils.getTypeDescriptor( ifld.getTypeName() )+ ">;", null); mv.visitCode(); int stack = getTargetDistField(mv, ifld, wrapperName, core.getName(), softField); mv.visitInsn(ARETURN); mv.visitMaxs( 1 + stack, 1); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, getter+"Distr", "()Lorg/drools/chance/distribution/Distribution;", "()Lorg/drools/chance/distribution/Distribution<" + BuildUtils.getTypeDescriptor( ifld.getTypeName() )+ ">;", null); mv.visitCode(); int stack = getTargetDistField(mv, ifld, wrapperName, core.getName(), softField); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "getCurrent", "()Lorg/drools/chance/distribution/Distribution;"); mv.visitInsn(ARETURN); mv.visitMaxs( 1 + stack, 1); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, getter+"Value", "()"+BuildUtils.getTypeDescriptor( ifld.getTypeName() ), null, null); mv.visitCode(); int stack = getTargetCrispValue( mv, ifld, wrapperName, core.getName(), softField ); mv.visitInsn(ARETURN); mv.visitMaxs(1 + stack, 1); mv.visitEnd(); } if ( softField ) { buildSoftGetter( cw, ifld, wrapperName, getTrait(), core, BuildUtils.getterName( ifld.getName(), ifld.getTypeName() ) + "Core", true); } else { buildHardGetter(cw, ifld, wrapperName, getTrait(), core, BuildUtils.getterName(ifld.getName(), ifld.getTypeName()) + "Core", true); } } protected void buildImperfectSetter(ClassVisitor cw, FieldDefinition field, String wrapperName, ClassDefinition core, boolean softField) { MethodVisitor mv; String setter = BuildUtils.setterName( field.getName(), field.getTypeName() ); FieldDefinition lingTarget = null; ImperfectFieldDefinition ifld = (ImperfectFieldDefinition) field; if ( ImperfectFieldDefinition.isLinguistic(ifld) ) { lingTarget = ifld.getSupportFieldDef(); } { mv = cw.visitMethod( ACC_PUBLIC, setter, "(Lorg/drools/chance/common/ImperfectField;)V", "(Lorg/drools/chance/common/ImperfectField<" + BuildUtils.getTypeDescriptor( ifld.getTypeName() ) + ">;)V", null); int stack = 2; mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, BuildUtils.getInternalType( wrapperName ), "store", "Lorg/drools/core/util/TripleStore;"); mv.visitVarInsn(ALOAD, 0); mv.visitLdcInsn( ifld.getName() + "_$$Imp" ); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, BuildUtils.getInternalType( wrapperName ), "property", "(Ljava/lang/String;Ljava/lang/Object;)Lorg/drools/core/util/Triple;"); mv.visitMethodInsn(INVOKEVIRTUAL, "org/drools/core/util/TripleStore", "put", "(Lorg/drools/core/util/Triple;)Z"); mv.visitInsn(POP); mv.visitVarInsn(ALOAD, 0); prepareSetTargetValue( mv, wrapperName, core.getName(), ifld, softField); getTargetDistField( mv, ifld, wrapperName, core.getName(), softField ); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "getCrisp", "()Ljava/lang/Object;"); stack += setTargetValue( mv, wrapperName, core.getName(), ifld, softField ); if ( ImperfectFieldDefinition.isLinguistic(ifld) ) { updateSupportField( mv, ifld, wrapperName, lingTarget ); } mv.visitInsn(RETURN); mv.visitMaxs( 2 + stack, 2); mv.visitEnd(); } // { mv = cw.visitMethod( ACC_PUBLIC, setter.replace( "set", "update" ), "(Lorg/drools/chance/common/ImperfectField;)V", "(Lorg/drools/chance/common/ImperfectField<" + BuildUtils.getTypeDescriptor( ifld.getTypeName() ) + ">;)V", null); int stack = 2; mv.visitCode(); getTargetDistField( mv, ifld, wrapperName, core.getName(), softField ); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 2); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "getCurrent", "()Lorg/drools/chance/distribution/Distribution;"); mv.visitMethodInsn(INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "update", "(Lorg/drools/chance/distribution/Distribution;)V"); mv.visitVarInsn(ALOAD, 0); prepareSetTargetValue( mv, wrapperName, core.getName(), ifld, softField); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "getCrisp", "()Ljava/lang/Object;"); stack += setTargetValue( mv, wrapperName, core.getName(), ifld, softField ); if ( ImperfectFieldDefinition.isLinguistic(ifld) ) { updateSupportField( mv, ifld, wrapperName, lingTarget ); } mv.visitInsn(RETURN); mv.visitMaxs( 2 + stack, 3 ); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, setter + "Value", "(" + BuildUtils.getTypeDescriptor( ifld.getTypeName() ) + ")V", null, null); mv.visitCode(); int stack = getTargetDistField( mv, ifld, wrapperName, core.getName(), softField ); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 2); mv.visitVarInsn(ALOAD, 1); mv.visitInsn(ICONST_0); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "setValue", "(Ljava/lang/Object;Z)V"); mv.visitVarInsn(ALOAD, 0); prepareSetTargetValue( mv, wrapperName, core.getName(), ifld, softField); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "getCrisp", "()Ljava/lang/Object;"); int stack2 = setTargetValue( mv, wrapperName, core.getName(), ifld, softField ); if ( ImperfectFieldDefinition.isLinguistic(ifld) ) { updateSupportField( mv, ifld, wrapperName, lingTarget ); } mv.visitInsn(RETURN); mv.visitMaxs( 2 + stack + stack2, 3); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, setter.replace("set","update")+"Value", "(" + BuildUtils.getTypeDescriptor( ifld.getTypeName() ) + ")V", null, null); mv.visitCode(); getTargetDistField( mv, ifld, wrapperName, core.getName(), softField ); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 2); // int stack = getTargetDistField( mv, ifld, wrapperName, core.getName(), softField ); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "update", "(Ljava/lang/Object;)V"); mv.visitVarInsn(ALOAD, 0); prepareSetTargetValue( mv, wrapperName, core.getName(), ifld, softField ); // getTargetDistField( mv, ifld, wrapperName, core.getName(), softField ); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "getCrisp", "()Ljava/lang/Object;"); int stack2 = setTargetValue( mv, wrapperName, core.getName(), ifld, softField ); if ( ImperfectFieldDefinition.isLinguistic(ifld) ) { updateSupportField( mv, ifld, wrapperName, lingTarget ); } mv.visitInsn(RETURN); mv.visitMaxs( 3 + stack2, 3); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, setter+"Distr", "(Lorg/drools/chance/distribution/Distribution;)V", "(Lorg/drools/chance/distribution/Distribution<" +BuildUtils.getTypeDescriptor( ifld.getTypeName() ) +">;)V", null); mv.visitCode(); int stack = getTargetDistField( mv, ifld, wrapperName, core.getName(), softField); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 2); mv.visitVarInsn(ALOAD, 1); mv.visitInsn(ICONST_0); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "setValue", "(Lorg/drools/chance/distribution/Distribution;Z)V"); mv.visitVarInsn(ALOAD, 0); prepareSetTargetValue(mv, wrapperName, core.getName(), ifld, softField); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "getCrisp", "()Ljava/lang/Object;"); int stack2 = setTargetValue( mv, wrapperName, core.getName(), ifld, softField ); if ( ImperfectFieldDefinition.isLinguistic(ifld) ) { updateSupportField( mv, ifld, wrapperName, lingTarget ); } mv.visitInsn(RETURN); mv.visitMaxs(2 + stack + stack2, 3); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, setter.replace("set","update") + "Distr", "(Lorg/drools/chance/distribution/Distribution;)V", "(Lorg/drools/chance/distribution/Distribution<" + BuildUtils.getTypeDescriptor( ifld.getTypeName() ) + ">;)V", null); mv.visitCode(); getTargetDistField( mv, ifld, wrapperName, core.getName(), softField ); mv.visitVarInsn(ASTORE, 2); mv.visitVarInsn(ALOAD, 2); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "update", "(Lorg/drools/chance/distribution/Distribution;)V"); mv.visitVarInsn(ALOAD, 0); prepareSetTargetValue( mv, wrapperName, core.getName(), ifld, softField ); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn( INVOKEINTERFACE, "org/drools/chance/common/ImperfectField", "getCrisp", "()Ljava/lang/Object;"); int stack2 = setTargetValue( mv, wrapperName, core.getName(), ifld, softField ); if ( ImperfectFieldDefinition.isLinguistic(ifld) ) { updateSupportField( mv, ifld, wrapperName, lingTarget ); } mv.visitInsn(RETURN); mv.visitMaxs( stack2 + 3, 3 ); mv.visitEnd(); } if ( softField ) { buildSoftSetter( cw, ifld, wrapperName, getTrait(), core, BuildUtils.setterName( ifld.getName(), ifld.getTypeName() ) + "Core", true); } else { buildHardSetter( cw, ifld, wrapperName, getTrait(), core, BuildUtils.setterName( ifld.getName(), ifld.getTypeName() ) + "Core", true); } } /******************************************************************************************************************* * * Utilities * *******************************************************************************************************************/ protected ImperfectFieldDefinition findSupportingField( ClassDefinition cdef, FieldDefinition ifld ) { for ( FieldDefinition fld : getTrait().getFieldsDefinitions() ) { if ( fld instanceof ImperfectFieldDefinition && ImperfectFieldDefinition.isLinguistic( fld ) && ((ImperfectFieldDefinition) fld).getSupportFieldDef().equals( ifld ) ) { return (ImperfectFieldDefinition) fld; } } return null; } private boolean isSupport( FieldDefinition field ) { return findSupportingField( getTrait(), field) != null; } private void updateSupportField( MethodVisitor mv, ImperfectFieldDefinition ifld, String proxyName, FieldDefinition target ) { mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( proxyName ), BuildUtils.getterName( ifld.getName(), ifld.getTypeName() ), "()Lorg/drools/chance/common/ImperfectField;" ); mv.visitTypeInsn( CHECKCAST, "org/drools/chance/distribution/fuzzy/linguistic/LinguisticImperfectField" ); defuzzifyOnTargetField( mv, proxyName, target ); } protected void defuzzifyOnTargetField( MethodVisitor mv, String proxyName, FieldDefinition target ) { mv.visitMethodInsn(INVOKEVIRTUAL, "org/drools/chance/distribution/fuzzy/linguistic/LinguisticImperfectField", "defuzzify", "()Ljava/lang/Number;"); mv.visitTypeInsn(CHECKCAST, "java/lang/Number" ); mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Number", BuildUtils.numericMorph( target.getTypeName() ), "()" + BuildUtils.unBox( target.getTypeName() ) ); if ( ! BuildUtils.isPrimitive( target.getTypeName() ) ) { mv.visitMethodInsn(INVOKESTATIC, BuildUtils.getInternalType( target.getTypeName() ), "valueOf", "(" + BuildUtils.unBox( target.getTypeName() )+ ")" + BuildUtils.getTypeDescriptor( target.getTypeName() ) ); } mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( proxyName ), BuildUtils.setterName( target.getName(), target.getTypeName() ) + "Core", "(" + BuildUtils.getTypeDescriptor( target.getTypeName() ) + ")V"); } protected int setTargetValue(MethodVisitor mv, String wrapperName, String coreName, FieldDefinition field, boolean isSoftField ) { if ( isSoftField ) { mv.visitMethodInsn(INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "property", "(Ljava/lang/String;Ljava/lang/Object;)Lorg/drools/core/util/Triple;"); mv.visitMethodInsn(INVOKEVIRTUAL, "org/drools/core/util/TripleStore", "put", "(Lorg/drools/core/util/Triple;)Z"); mv.visitInsn(POP); return 2; } else { mv.visitTypeInsn(CHECKCAST, BuildUtils.getInternalType( field.getTypeName() ) ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( coreName ), BuildUtils.setterName( field.getName(), field.getTypeName() ), "(" + BuildUtils.getTypeDescriptor( field.getTypeName() ) + ")V" ); return 0; } } protected void prepareSetTargetValue(MethodVisitor mv, String wrapperName, String coreName, FieldDefinition ifld, boolean softField) { if ( softField ) { mv.visitFieldInsn(GETFIELD, BuildUtils.getInternalType( wrapperName ), "store", "Lorg/drools/core/util/TripleStore;"); mv.visitVarInsn(ALOAD, 0); mv.visitLdcInsn( ifld.getName() ); } else { mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( wrapperName ), "getCore", "()" + BuildUtils.getTypeDescriptor( coreName ) ); } } protected int getTargetDistField( MethodVisitor mv, FieldDefinition field, String wrapperName, String coreName, boolean isSoftField ) { mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, BuildUtils.getInternalType(wrapperName), "store", "Lorg/drools/core/util/TripleStore;"); mv.visitVarInsn(ALOAD, 0); mv.visitLdcInsn(field.getName() + "_$$Imp"); //TODO : how can this work?? mv.visitMethodInsn(INVOKEVIRTUAL, BuildUtils.getInternalType( wrapperName ), "propertyKey", "(Ljava/lang/String;)Lorg/drools/core/util/Triple;"); mv.visitMethodInsn(INVOKEVIRTUAL, "org/drools/core/util/TripleStore", "get", "(Lorg/drools/core/util/Triple;)Lorg/drools/core/util/Triple;"); mv.visitMethodInsn(INVOKEINTERFACE, "org/drools/core/util/Triple", "getValue", "()Ljava/lang/Object;"); mv.visitTypeInsn(CHECKCAST, BuildUtils.getInternalType( ImperfectField.class.getName() ) ); return 2; } protected int getTargetCrispValue( MethodVisitor mv, FieldDefinition field, String wrapperName, String coreName, boolean isSoftField ) { if ( isSoftField ) { mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, BuildUtils.getInternalType( wrapperName ), "store", "Lorg/drools/core/util/TripleStore;"); mv.visitVarInsn(ALOAD, 0); mv.visitLdcInsn( field.getName() ); mv.visitMethodInsn(INVOKEVIRTUAL, BuildUtils.getInternalType( wrapperName ), "propertyKey", "(Ljava/lang/String;)Lorg/drools/core/util/Triple;"); mv.visitMethodInsn(INVOKEVIRTUAL, "org/drools/core/util/TripleStore", "get", "(Lorg/drools/core/util/Triple;)Lorg/drools/core/util/Triple;"); mv.visitMethodInsn(INVOKEINTERFACE, "org/drools/core/util/Triple", "getValue", "()Ljava/lang/Object;"); mv.visitTypeInsn(CHECKCAST, BuildUtils.getInternalType( field.getTypeName() ) ); return 2; } else { mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( wrapperName ), "getCore", "()" + BuildUtils.getTypeDescriptor( coreName ) ); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType( coreName ), BuildUtils.getterName( field.getName(), field.getTypeName() ), "()" + BuildUtils.getTypeDescriptor( field.getTypeName() ) ); return 0; } } }