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();
}
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;
}
}
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());
}
}
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;
}
}
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;
}
Aggregations