Search in sources :

Example 1 with Thing

use of org.drools.core.factmodel.traits.Thing in project drools by kiegroup.

the class DefaultBeanClassBuilder method buildTraitMap.

/**
 * A traitable class is a special class with support for dynamic properties and types.
 *
 * This method builds the trait map, containing the references to the proxies
 * for each trait carried by an object at a given time.
 *
 * @param cw
 * @param classDef
 */
protected void buildTraitMap(ClassWriter cw, ClassDefinition classDef) {
    FieldVisitor fv = cw.visitField(ACC_PRIVATE, TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class), "Ljava/util/Map<Ljava/lang/String;Lorg/drools/core/factmodel/traits/Thing;>;", null);
    fv.visitEnd();
    MethodVisitor mv;
    mv = cw.visitMethod(ACC_PUBLIC, "_getTraitMap", Type.getMethodDescriptor(Type.getType(Map.class), new Type[] {}), "()Ljava/util/Map<Ljava/lang/String;Lorg/drools/factmodel/traits/Thing;>;", null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, BuildUtils.getInternalType(classDef.getName()), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class));
    mv.visitInsn(ARETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
    mv = cw.visitMethod(ACC_PUBLIC, "_setTraitMap", Type.getMethodDescriptor(Type.getType(void.class), new Type[] { Type.getType(Map.class) }), null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitFieldInsn(PUTFIELD, BuildUtils.getInternalType(classDef.getName()), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class));
    mv.visitInsn(RETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
    mv = cw.visitMethod(ACC_PUBLIC, "addTrait", Type.getMethodDescriptor(Type.getType(void.class), new Type[] { Type.getType(String.class), Type.getType(Thing.class) }), "(Ljava/lang/String;Lorg/drools/core/factmodel/traits/Thing;)V", null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKEVIRTUAL, BuildUtils.getInternalType(classDef.getName()), "_getTraitMap", Type.getMethodDescriptor(Type.getType(Map.class), new Type[] {}));
    mv.visitVarInsn(ALOAD, 1);
    mv.visitVarInsn(ALOAD, 2);
    mv.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Map.class), "put", Type.getMethodDescriptor(Type.getType(Object.class), new Type[] { Type.getType(Object.class), Type.getType(Object.class) }));
    mv.visitInsn(POP);
    mv.visitInsn(RETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
    mv = cw.visitMethod(ACC_PUBLIC, "getTrait", Type.getMethodDescriptor(Type.getType(Thing.class), new Type[] { Type.getType(String.class) }), Type.getMethodDescriptor(Type.getType(Thing.class), new Type[] { Type.getType(String.class) }), null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKEVIRTUAL, BuildUtils.getInternalType(classDef.getName()), "_getTraitMap", Type.getMethodDescriptor(Type.getType(Map.class), new Type[] {}));
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Map.class), "get", Type.getMethodDescriptor(Type.getType(Object.class), new Type[] { Type.getType(Object.class) }));
    mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Thing.class));
    mv.visitInsn(ARETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
    mv = cw.visitMethod(ACC_PUBLIC, "hasTrait", Type.getMethodDescriptor(Type.getType(boolean.class), new Type[] { Type.getType(String.class) }), null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKEVIRTUAL, BuildUtils.getInternalType(classDef.getName()), "_getTraitMap", Type.getMethodDescriptor(Type.getType(Map.class), new Type[] {}));
    Label l0 = new Label();
    mv.visitJumpInsn(IFNONNULL, l0);
    mv.visitInsn(ICONST_0);
    mv.visitInsn(IRETURN);
    mv.visitLabel(l0);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKEVIRTUAL, BuildUtils.getInternalType(classDef.getName()), "_getTraitMap", Type.getMethodDescriptor(Type.getType(Map.class), new Type[] {}));
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Map.class), "containsKey", Type.getMethodDescriptor(Type.getType(boolean.class), new Type[] { Type.getType(Object.class) }));
    mv.visitInsn(IRETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
    mv = cw.visitMethod(ACC_PUBLIC, "hasTraits", Type.getMethodDescriptor(Type.getType(boolean.class), new Type[] {}), null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, BuildUtils.getInternalType(classDef.getName()), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class));
    Label l5 = new Label();
    mv.visitJumpInsn(IFNULL, l5);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, BuildUtils.getInternalType(classDef.getName()), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class));
    mv.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Map.class), "isEmpty", Type.getMethodDescriptor(Type.BOOLEAN_TYPE, new Type[] {}));
    mv.visitJumpInsn(IFNE, l5);
    mv.visitInsn(ICONST_1);
    Label l4 = new Label();
    mv.visitJumpInsn(GOTO, l4);
    mv.visitLabel(l5);
    mv.visitInsn(ICONST_0);
    mv.visitLabel(l4);
    mv.visitInsn(IRETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
    mv = cw.visitMethod(ACC_PUBLIC, "removeTrait", Type.getMethodDescriptor(Type.getType(Collection.class), new Type[] { Type.getType(String.class) }), Type.getMethodDescriptor(Type.getType(Collection.class), new Type[] { Type.getType(String.class) }), null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKEVIRTUAL, BuildUtils.getInternalType(classDef.getName()), "_getTraitMap", Type.getMethodDescriptor(Type.getType(Map.class), new Type[] {}));
    mv.visitTypeInsn(CHECKCAST, Type.getInternalName(TraitTypeMap.class));
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(TraitTypeMap.class), "removeCascade", Type.getMethodDescriptor(Type.getType(Collection.class), new Type[] { Type.getType(String.class) }));
    mv.visitInsn(ARETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
    mv = cw.visitMethod(ACC_PUBLIC, "removeTrait", Type.getMethodDescriptor(Type.getType(Collection.class), new Type[] { Type.getType(BitSet.class) }), Type.getMethodDescriptor(Type.getType(Collection.class), new Type[] { Type.getType(BitSet.class) }), null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKEVIRTUAL, BuildUtils.getInternalType(classDef.getName()), "_getTraitMap", Type.getMethodDescriptor(Type.getType(Map.class), new Type[] {}));
    mv.visitTypeInsn(CHECKCAST, Type.getInternalName(TraitTypeMap.class));
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(TraitTypeMap.class), "removeCascade", Type.getMethodDescriptor(Type.getType(Collection.class), new Type[] { Type.getType(BitSet.class) }));
    mv.visitInsn(ARETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
    mv = cw.visitMethod(ACC_PUBLIC, "getTraits", Type.getMethodDescriptor(Type.getType(Collection.class), new Type[] {}), "()Ljava/util/Collection<Ljava/lang/String;>;", null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKEVIRTUAL, BuildUtils.getInternalType(classDef.getName()), "_getTraitMap", Type.getMethodDescriptor(Type.getType(Map.class), new Type[] {}));
    mv.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Map.class), "keySet", Type.getMethodDescriptor(Type.getType(Set.class), new Type[] {}));
    mv.visitInsn(ARETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
    mv = cw.visitMethod(ACC_PUBLIC, "_setBottomTypeCode", Type.getMethodDescriptor(Type.getType(void.class), new Type[] { Type.getType(BitSet.class) }), null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, BuildUtils.getInternalType(classDef.getName()), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class));
    mv.visitTypeInsn(CHECKCAST, Type.getInternalName(TraitTypeMap.class));
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(TraitTypeMap.class), "setBottomCode", Type.getMethodDescriptor(Type.getType(void.class), new Type[] { Type.getType(BitSet.class) }));
    mv.visitInsn(RETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
    mv = cw.visitMethod(ACC_PUBLIC, "getMostSpecificTraits", Type.getMethodDescriptor(Type.getType(Collection.class), new Type[] {}), "()Ljava/util/Collection<Lorg/drools/core/factmodel/traits/Thing;>;", null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, BuildUtils.getInternalType(classDef.getName()), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class));
    Label l99 = new Label();
    mv.visitJumpInsn(IFNULL, l99);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, BuildUtils.getInternalType(classDef.getName()), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class));
    mv.visitTypeInsn(CHECKCAST, Type.getInternalName(TraitTypeMap.class));
    mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(TraitTypeMap.class), "getMostSpecificTraits", Type.getMethodDescriptor(Type.getType(Collection.class), new Type[] {}));
    mv.visitInsn(ARETURN);
    mv.visitLabel(l99);
    mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Collections.class), "emptySet", Type.getMethodDescriptor(Type.getType(Set.class), new Type[] {}));
    mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(Collections.class), "unmodifiableCollection", Type.getMethodDescriptor(Type.getType(Collection.class), new Type[] { Type.getType(Collection.class) }));
    mv.visitInsn(ARETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
    mv = cw.visitMethod(ACC_PUBLIC, "getCurrentTypeCode", Type.getMethodDescriptor(Type.getType(BitSet.class), new Type[] {}), null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, BuildUtils.getInternalType(classDef.getName()), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class));
    Label l3 = new Label();
    mv.visitJumpInsn(IFNONNULL, l3);
    mv.visitInsn(ACONST_NULL);
    mv.visitInsn(ARETURN);
    mv.visitLabel(l3);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, BuildUtils.getInternalType(classDef.getName()), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class));
    mv.visitTypeInsn(CHECKCAST, Type.getInternalName(TraitTypeMap.class));
    mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(TraitTypeMap.class), "getCurrentTypeCode", Type.getMethodDescriptor(Type.getType(BitSet.class), new Type[] {}));
    mv.visitInsn(ARETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}
Also used : Type(org.mvel2.asm.Type) Label(org.mvel2.asm.Label) BitSet(java.util.BitSet) Collection(java.util.Collection) TraitTypeMap(org.drools.core.factmodel.traits.TraitTypeMap) Collections(java.util.Collections) FieldVisitor(org.mvel2.asm.FieldVisitor) Map(java.util.Map) TraitTypeMap(org.drools.core.factmodel.traits.TraitTypeMap) Thing(org.drools.core.factmodel.traits.Thing) MethodVisitor(org.mvel2.asm.MethodVisitor)

Example 2 with Thing

use of org.drools.core.factmodel.traits.Thing in project drools by kiegroup.

the class TraitHelper method shed.

public <T, K, X extends TraitableBean> Thing<K> shed(TraitableBean<K, X> core, Class<T> trait, Activation activation) {
    if (trait.isAssignableFrom(core.getClass())) {
        Collection<Thing<K>> removedTypes = core.removeTrait(trait.getName());
        if (!removedTypes.isEmpty()) {
            reassignNodes(core, removedTypes);
            update(getFactHandle(core), onlyTraitBitSetMask(), core.getClass(), activation);
        // updateTraits( core, Long.MIN_VALUE, null, core.getClass(), null, ((TraitableBean) core).getMostSpecificTraits()  );
        }
        if (core instanceof Thing) {
            return (Thing<K>) core;
        } else {
            return null;
        }
    } else {
        Collection<Thing<K>> removedTypes;
        Thing<K> thing = core.getTrait(Thing.class.getName());
        if (trait == Thing.class) {
            removedTypes = new ArrayList<Thing<K>>(core._getTraitMap().values());
            for (Thing t : removedTypes) {
                if (!((TraitType) t)._isVirtual()) {
                    delete(getFactHandle(t), activation);
                }
            }
            core._getTraitMap().clear();
            core._setTraitMap(null);
            return thing;
        } else if (core.hasTrait(trait.getName())) {
            removedTypes = core.removeTrait(trait.getName());
        } else {
            HierarchyEncoder hier = this.workingMemory.getKnowledgeBase().getConfiguration().getComponentFactory().getTraitRegistry().getHierarchy();
            BitSet code = hier.getCode(trait.getName());
            removedTypes = core.removeTrait(code);
        }
        removedTypes = new ArrayList<Thing<K>>(removedTypes);
        reassignNodes(core, removedTypes);
        for (Thing t : removedTypes) {
            if (!((TraitType) t)._isVirtual()) {
                InternalFactHandle handle = (InternalFactHandle) getFactHandle(t);
                if (handle.getEqualityKey() != null && handle.getEqualityKey().getLogicalFactHandle() == handle) {
                    entryPoint.getTruthMaintenanceSystem().delete(handle);
                } else {
                    delete(getFactHandle(t), activation);
                }
            }
        }
        if (!core.hasTraits()) {
            don(activation, core, Thing.class, false);
        } else if (!removedTypes.isEmpty()) {
            update(getFactHandle(core), onlyTraitBitSetMask(), core.getClass(), activation);
        // updateTraits( core, Long.MIN_VALUE, null, core.getClass(), null, ((TraitableBean) core).getMostSpecificTraits()  );
        }
        return thing;
    }
}
Also used : HierarchyEncoder(org.drools.core.util.HierarchyEncoder) BitSet(java.util.BitSet) InternalFactHandle(org.drools.core.common.InternalFactHandle) Thing(org.drools.core.factmodel.traits.Thing)

Example 3 with Thing

use of org.drools.core.factmodel.traits.Thing in project drools by kiegroup.

the class TraitTest method testHasTypes.

@Test(timeout = 10000)
public void testHasTypes() {
    String source = "org/drools/compiler/factmodel/traits/testTraitDon.drl";
    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    Resource res = ResourceFactory.newClassPathResource(source);
    assertNotNull(res);
    kbuilder.add(res, ResourceType.DRL);
    if (kbuilder.hasErrors()) {
        fail(kbuilder.getErrors().toString());
    }
    InternalKnowledgeBase kb = KnowledgeBaseFactory.newKnowledgeBase();
    kb.addPackages(kbuilder.getKnowledgePackages());
    TraitFactory traitBuilder = ((KnowledgeBaseImpl) kb).getConfiguration().getComponentFactory().getTraitFactory();
    TraitFactory.setMode(mode, kb);
    try {
        FactType impClass = kb.getFactType("org.drools.compiler.trait.test", "Imp");
        TraitableBean imp = (TraitableBean) impClass.newInstance();
        impClass.set(imp, "name", "aaabcd");
        Class trait = kb.getFactType("org.drools.compiler.trait.test", "Student").getFactClass();
        Class trait2 = kb.getFactType("org.drools.compiler.trait.test", "Role").getFactClass();
        assertNotNull(trait);
        TraitProxy proxy = (TraitProxy) traitBuilder.getProxy(imp, trait);
        Thing thing = traitBuilder.getProxy(imp, Thing.class);
        TraitableBean core = (TraitableBean) proxy.getObject();
        TraitProxy proxy2 = (TraitProxy) traitBuilder.getProxy(imp, trait);
        Thing thing2 = traitBuilder.getProxy(imp, Thing.class);
        assertSame(proxy, proxy2);
        assertSame(thing, thing2);
        assertEquals(2, core.getTraits().size());
    } catch (Exception e) {
        e.printStackTrace();
        fail(e.getMessage());
    }
}
Also used : TraitProxy(org.drools.core.factmodel.traits.TraitProxy) KnowledgeBuilder(org.kie.internal.builder.KnowledgeBuilder) Resource(org.kie.api.io.Resource) ByteArrayResource(org.drools.core.io.impl.ByteArrayResource) ClassPathResource(org.drools.core.io.impl.ClassPathResource) KnowledgeBaseImpl(org.drools.core.impl.KnowledgeBaseImpl) TraitableBean(org.drools.core.factmodel.traits.TraitableBean) InternalKnowledgeBase(org.drools.core.impl.InternalKnowledgeBase) Thing(org.drools.core.factmodel.traits.Thing) LogicalTypeInconsistencyException(org.drools.core.factmodel.traits.LogicalTypeInconsistencyException) TraitFactory(org.drools.core.factmodel.traits.TraitFactory) FactType(org.kie.api.definition.type.FactType) Test(org.junit.Test)

Example 4 with Thing

use of org.drools.core.factmodel.traits.Thing in project drools by kiegroup.

the class TraitObjectTypeNode method sameAndNotCoveredByDescendants.

/**
 *  Edge case: due to the way traits are encoded, consider this hierarchy:
 *  A    B
 *    C
 *    D
 *  On don/insertion of C, C may be vetoed by its parents, but might have been
 *  already covered by one of its descendants (D)
 */
private boolean sameAndNotCoveredByDescendants(TraitProxy proxy, BitSet typeMask) {
    boolean isSameType = typeMask.equals(proxy._getTypeCode());
    if (isSameType) {
        TraitTypeMap<String, Thing<?>, ?> ttm = (TraitTypeMap<String, Thing<?>, ?>) proxy.getObject()._getTraitMap();
        Collection<Thing<?>> descs = ttm.lowerDescendants(typeMask);
        // we have to exclude the "mock" bottom proxy
        if (descs == null || descs.isEmpty()) {
            return true;
        } else {
            for (Thing sub : descs) {
                TraitType tt = (TraitType) sub;
                if (tt != proxy && tt._hasTypeCode(typeMask)) {
                    return false;
                }
            }
            return true;
        }
    } else {
        return false;
    }
}
Also used : TraitType(org.drools.core.factmodel.traits.TraitType) TraitTypeMap(org.drools.core.factmodel.traits.TraitTypeMap) Thing(org.drools.core.factmodel.traits.Thing)

Example 5 with Thing

use of org.drools.core.factmodel.traits.Thing in project drools by kiegroup.

the class TraitHelperImpl method applyTrait.

protected <T, K> T applyTrait(Activation activation, K core, Class<T> trait, Object value, boolean logical, Mode... modes) throws LogicalTypeInconsistencyException {
    TraitFactoryImpl builder = TraitFactoryImpl.getTraitBuilderForKnowledgeBase(entryPoint.getKnowledgeBase());
    TraitableBean inner = makeTraitable(core, builder, logical, activation);
    boolean needsProxy = trait.isAssignableFrom(inner.getClass());
    boolean hasTrait = inner.hasTrait(trait.getName());
    boolean needsUpdate = needsProxy || core != inner;
    checkStaticTypeCode(inner);
    Collection<Thing> mostSpecificTraits = getTraitBoundary(inner, needsProxy, hasTrait, trait);
    T thing = asTrait(core, inner, trait, needsProxy, hasTrait, needsUpdate, builder, logical, activation);
    configureTrait(thing, value);
    thing = doInsertTrait(activation, thing, core, logical, modes);
    refresh(thing, core, inner, trait, mostSpecificTraits, logical, activation);
    if (trait != Thing.class && inner._getFieldTMS() != null) {
        inner._getFieldTMS().resetModificationMask();
    }
    return thing;
}
Also used : TraitFactoryImpl(org.drools.traits.core.factmodel.TraitFactoryImpl) TraitableBean(org.drools.core.factmodel.traits.TraitableBean) Thing(org.drools.core.factmodel.traits.Thing)

Aggregations

Thing (org.drools.core.factmodel.traits.Thing)23 BitSet (java.util.BitSet)7 ArrayList (java.util.ArrayList)6 TraitableBean (org.drools.core.factmodel.traits.TraitableBean)6 Test (org.junit.Test)6 InternalFactHandle (org.drools.core.common.InternalFactHandle)4 Collection (java.util.Collection)3 Map (java.util.Map)3 TraitFactory (org.drools.core.factmodel.traits.TraitFactory)3 TraitProxy (org.drools.core.factmodel.traits.TraitProxy)3 TraitTypeMap (org.drools.core.factmodel.traits.TraitTypeMap)3 TraitFactoryImpl (org.drools.traits.core.factmodel.TraitFactoryImpl)3 TraitProxyImpl (org.drools.traits.core.factmodel.TraitProxyImpl)3 FieldVisitor (org.mvel2.asm.FieldVisitor)3 Label (org.mvel2.asm.Label)3 MethodVisitor (org.mvel2.asm.MethodVisitor)3 Type (org.mvel2.asm.Type)3 Collections (java.util.Collections)2 List (java.util.List)2 TraitType (org.drools.core.factmodel.traits.TraitType)2