/** * * * <pre> * * * Cheese( price == 5 ) * * * </pre> * * @throws IntrospectionException */ @Test public void testPrimitiveLiteralConstraint() throws IntrospectionException { final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(); final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession(); final ClassFieldReader extractor = store.getReader(Cheese.class, "price", getClass().getClassLoader()); final FieldValue field = FieldFactory.getFieldValue(5); final Evaluator evaluator = equals.getEvaluator(ValueType.PINTEGER_TYPE, Operator.EQUAL); final LiteralConstraint constraint = new LiteralConstraint(extractor, evaluator, field); final ContextEntry context = constraint.createContextEntry(); final Cheese cheddar = new Cheese("cheddar", 5); final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.insert(cheddar); // check constraint assertTrue(constraint.isAllowed(cheddarHandle, workingMemory, context)); final Cheese stilton = new Cheese("stilton", 10); final InternalFactHandle stiltonHandle = (InternalFactHandle) workingMemory.insert(stilton); // check constraint assertFalse(constraint.isAllowed(stiltonHandle, workingMemory, context)); }
/** * * * <pre> * * * ( Cheese (type "cheddar") ) * * * </pre> * * This is currently the same as using a ReturnValueConstraint just that it doesn't need any * requiredDeclarations * * @throws IntrospectionException */ public void testLiteralConstraint() throws IntrospectionException { final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(); final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession(); final ClassFieldExtractor extractor = cache.getExtractor(Cheese.class, "type", getClass().getClassLoader()); final FieldValue field = FieldFactory.getFieldValue("cheddar"); final Evaluator evaluator = ValueType.STRING_TYPE.getEvaluator(Operator.EQUAL); final LiteralConstraint constraint = new LiteralConstraint(extractor, evaluator, field); final ContextEntry context = constraint.createContextEntry(); final Cheese cheddar = new Cheese("cheddar", 5); final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.insert(cheddar); // check constraint assertTrue(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context)); final Cheese stilton = new Cheese("stilton", 5); final InternalFactHandle stiltonHandle = (InternalFactHandle) workingMemory.insert(stilton); // check constraint assertFalse(constraint.isAllowed(stiltonHandle.getObject(), workingMemory, context)); }
/** * * * <pre> * * * type == "cheddar" && price > 10 * * * </pre> * * Test the use of the composite AND constraint. Composite AND constraints are only used when * nested inside other field constraints, as the top level AND is implicit * * @throws IntrospectionException */ public void testCompositeAndConstraint() { final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(); final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession(); final ClassFieldExtractor extractor = cache.getExtractor(Cheese.class, "type", getClass().getClassLoader()); final FieldValue field = FieldFactory.getFieldValue("cheddar"); final Evaluator evaluator = ValueType.STRING_TYPE.getEvaluator(Operator.EQUAL); final LiteralConstraint constraint1 = new LiteralConstraint(extractor, evaluator, field); final ClassFieldExtractor priceExtractor = cache.getExtractor(Cheese.class, "price", getClass().getClassLoader()); final FieldValue priceField = FieldFactory.getFieldValue(10); final Evaluator priceEvaluator = ValueType.INTEGER_TYPE.getEvaluator(Operator.GREATER); final LiteralConstraint constraint2 = new LiteralConstraint(priceExtractor, priceEvaluator, priceField); final Cheese cheddar = new Cheese("cheddar", 15); final AndConstraint constraint = new AndConstraint(); constraint.addAlphaConstraint(constraint1); constraint.addAlphaConstraint(constraint2); final ContextEntry context = constraint.createContextEntry(); final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.insert(cheddar); // check constraint assertTrue(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context)); cheddar.setPrice(5); ((ShadowProxy) cheddarHandle.getObject()).updateProxy(); assertFalse(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context)); cheddar.setType("stilton"); ((ShadowProxy) cheddarHandle.getObject()).updateProxy(); assertFalse(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context)); cheddar.setPrice(15); ((ShadowProxy) cheddarHandle.getObject()).updateProxy(); assertFalse(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context)); }
/** * * * <pre> * * * Cheese( ( type == "cheddar" && price > 10) || ( type == "e;stilton"e; && price < 10 ) ) * * * </pre> * * Test the use of the composite OR constraint. * * @throws IntrospectionException */ public void testNestedCompositeConstraints() { final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(); final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession(); final ClassFieldExtractor typeExtractor = cache.getExtractor(Cheese.class, "type", getClass().getClassLoader()); final FieldValue cheddarField = FieldFactory.getFieldValue("cheddar"); final Evaluator stringEqual = ValueType.STRING_TYPE.getEvaluator(Operator.EQUAL); // type == 'cheddar' final LiteralConstraint constraint1 = new LiteralConstraint(typeExtractor, stringEqual, cheddarField); final ClassFieldExtractor priceExtractor = cache.getExtractor(Cheese.class, "price", getClass().getClassLoader()); final FieldValue field10 = FieldFactory.getFieldValue(10); final Evaluator integerGreater = ValueType.INTEGER_TYPE.getEvaluator(Operator.GREATER); // price > 10 final LiteralConstraint constraint2 = new LiteralConstraint(priceExtractor, integerGreater, field10); // type == 'cheddar' && price > 10 final AndConstraint and1 = new AndConstraint(); and1.addAlphaConstraint(constraint1); and1.addAlphaConstraint(constraint2); final FieldValue stiltonField = FieldFactory.getFieldValue("stilton"); // type == 'stilton' final LiteralConstraint constraint3 = new LiteralConstraint(typeExtractor, stringEqual, stiltonField); final Evaluator integerLess = ValueType.INTEGER_TYPE.getEvaluator(Operator.LESS); // price < 10 final LiteralConstraint constraint4 = new LiteralConstraint(priceExtractor, integerLess, field10); // type == 'stilton' && price < 10 final AndConstraint and2 = new AndConstraint(); and2.addAlphaConstraint(constraint3); and2.addAlphaConstraint(constraint4); // ( type == 'cheddar' && price > 10 ) || ( type == 'stilton' && price < 10 ) final OrConstraint constraint = new OrConstraint(); constraint.addAlphaConstraint(and1); constraint.addAlphaConstraint(and2); final ContextEntry context = constraint.createContextEntry(); final Cheese cheddar = new Cheese("cheddar", 15); final InternalFactHandle cheddarHandle = (InternalFactHandle) workingMemory.insert(cheddar); // check constraint assertTrue(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context)); cheddar.setPrice(5); ((ShadowProxy) cheddarHandle.getObject()).updateProxy(); assertFalse(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context)); cheddar.setType("stilton"); ((ShadowProxy) cheddarHandle.getObject()).updateProxy(); assertTrue(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context)); cheddar.setPrice(15); ((ShadowProxy) cheddarHandle.getObject()).updateProxy(); assertFalse(constraint.isAllowed(cheddarHandle.getObject(), workingMemory, context)); }
/** * * * <pre> * * * (Cheese (price ?price ) * (Cheese (price =(* 2 ?price) ) * (Cheese (price >(* 2 ?price) ) * * * </pre> * * @throws IntrospectionException */ public void testReturnValueConstraint() throws IntrospectionException { final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(); final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession(); final FieldExtractor priceExtractor = cache.getExtractor(Cheese.class, "price", getClass().getClassLoader()); final Pattern pattern = new Pattern(0, new ClassObjectType(Cheese.class)); // Bind the extractor to a decleration // Declarations know the pattern they derive their value form final Declaration priceDeclaration = new Declaration("price1", priceExtractor, pattern); final ReturnValueExpression isDoubleThePrice = new ReturnValueExpression() { /** */ private static final long serialVersionUID = 400L; public FieldValue evaluate( Object object, Tuple tuple, // ?price Declaration[] previousDeclarations, Declaration[] localDeclarations, WorkingMemory workingMemory, Object context) { int price = ((Number) previousDeclarations[0].getValue( (InternalWorkingMemory) workingMemory, workingMemory.getObject(tuple.get(previousDeclarations[0])))) .intValue(); return FieldFactory.getFieldValue(2 * price); } public Object createContext() { return null; } }; final ReturnValueRestriction restriction1 = new ReturnValueRestriction( priceExtractor, isDoubleThePrice, new Declaration[] {priceDeclaration}, new Declaration[0], new String[0], ValueType.INTEGER_TYPE.getEvaluator(Operator.EQUAL)); final ReturnValueConstraint constraint1 = new ReturnValueConstraint(priceExtractor, restriction1); final ReturnValueRestriction restriction2 = new ReturnValueRestriction( priceExtractor, isDoubleThePrice, new Declaration[] {priceDeclaration}, new Declaration[0], new String[0], ValueType.INTEGER_TYPE.getEvaluator(Operator.GREATER)); final ReturnValueConstraint constraint2 = new ReturnValueConstraint(priceExtractor, restriction2); final Cheese cheddar0 = new Cheese("cheddar", 5); final FactHandle f0 = workingMemory.insert(cheddar0); InstrumentedReteTuple tuple = new InstrumentedReteTuple(f0); final Cheese cheddar1 = new Cheese("cheddar", 10); final InternalFactHandle f1 = (InternalFactHandle) workingMemory.insert(cheddar1); tuple = new InstrumentedReteTuple(tuple, f1); final ReturnValueContextEntry context1 = (ReturnValueContextEntry) constraint1.createContextEntry(); context1.updateFromTuple(workingMemory, tuple); assertTrue(constraint1.isAllowedCachedLeft(context1, f1.getObject())); final ReturnValueContextEntry context2 = (ReturnValueContextEntry) constraint2.createContextEntry(); context2.updateFromTuple(workingMemory, tuple); assertFalse(constraint2.isAllowedCachedLeft(context2, f1.getObject())); final Cheese cheddar2 = new Cheese("cheddar", 11); final InternalFactHandle f2 = (InternalFactHandle) workingMemory.insert(cheddar2); assertTrue(constraint2.isAllowedCachedLeft(context2, f2.getObject())); }
/** * * * <pre> * * * (Cheese (price ?price1 ) * (Cheese (price ?price2&:(= ?price2 (* 2 ?price1) ) * * * </pre> * * @throws IntrospectionException */ public void testPredicateConstraint() throws IntrospectionException { final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(); final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession(); final FieldExtractor priceExtractor = cache.getExtractor(Cheese.class, "price", getClass().getClassLoader()); Pattern pattern = new Pattern(0, new ClassObjectType(Cheese.class)); // Bind the extractor to a decleration // Declarations know the pattern they derive their value form final Declaration price1Declaration = new Declaration("price1", priceExtractor, pattern); pattern = new Pattern(1, new ClassObjectType(Cheese.class)); // Bind the extractor to a decleration // Declarations know the pattern they derive their value form final Declaration price2Declaration = new Declaration("price2", priceExtractor, pattern); final PredicateExpression evaluator = new PredicateExpression() { /** */ private static final long serialVersionUID = 400L; public boolean evaluate( Object object, Tuple tuple, Declaration[] previousDeclarations, Declaration[] localDeclarations, WorkingMemory workingMemory, Object context) { int price1 = previousDeclarations[0].getIntValue( (InternalWorkingMemory) workingMemory, workingMemory.getObject(tuple.get(previousDeclarations[0]))); int price2 = localDeclarations[0].getIntValue((InternalWorkingMemory) workingMemory, object); return (price2 == (price1 * 2)); } public Object createContext() { return null; } }; final PredicateConstraint constraint1 = new PredicateConstraint( evaluator, new Declaration[] {price1Declaration}, new Declaration[] {price2Declaration}, new String[] {}); final Cheese cheddar0 = new Cheese("cheddar", 5); final FactHandle f0 = workingMemory.insert(cheddar0); InstrumentedReteTuple tuple = new InstrumentedReteTuple(f0); final Cheese cheddar1 = new Cheese("cheddar", 10); final InternalFactHandle f1 = (InternalFactHandle) workingMemory.insert(cheddar1); tuple = new InstrumentedReteTuple(tuple, f1); final PredicateContextEntry context = (PredicateContextEntry) constraint1.createContextEntry(); context.updateFromTuple(workingMemory, tuple); assertTrue(constraint1.isAllowedCachedLeft(context, f1.getObject())); }
/** * * * <pre> * * * (Cheese (price ?price ) * (Cheese (price =(* 2 ?price) ) * (Cheese (price >(* 2 ?price) ) * * * </pre> * * @throws IntrospectionException */ @Test public void testReturnValueConstraint() throws IntrospectionException { final ReteooRuleBase ruleBase = (ReteooRuleBase) RuleBaseFactory.newRuleBase(); final InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession(); final InternalReadAccessor priceExtractor = store.getReader(Cheese.class, "price", getClass().getClassLoader()); final Pattern pattern = new Pattern(0, new ClassObjectType(Cheese.class)); // Bind the extractor to a decleration // Declarations know the pattern they derive their value form final Declaration priceDeclaration = new Declaration("price1", priceExtractor, pattern); final ReturnValueExpression isDoubleThePrice = new ReturnValueExpression() { private static final long serialVersionUID = 510l; public FieldValue evaluate( Object object, Tuple tuple, // ?price Declaration[] previousDeclarations, Declaration[] localDeclarations, WorkingMemory workingMemory, Object context) { int price = ((Number) previousDeclarations[0].getValue( (InternalWorkingMemory) workingMemory, workingMemory.getObject(tuple.get(previousDeclarations[0])))) .intValue(); return FieldFactory.getFieldValue(2 * price); } public Object createContext() { return null; } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {} public void writeExternal(ObjectOutput out) throws IOException {} public void replaceDeclaration(Declaration declaration, Declaration resolved) {} }; final ReturnValueRestriction restriction1 = new ReturnValueRestriction( priceExtractor, isDoubleThePrice, new Declaration[] {priceDeclaration}, new Declaration[0], new String[0], equals.getEvaluator(ValueType.INTEGER_TYPE, Operator.EQUAL)); final ReturnValueConstraint constraint1 = new ReturnValueConstraint(priceExtractor, restriction1); final ReturnValueRestriction restriction2 = new ReturnValueRestriction( priceExtractor, isDoubleThePrice, new Declaration[] {priceDeclaration}, new Declaration[0], new String[0], comparables.getEvaluator(ValueType.INTEGER_TYPE, Operator.GREATER)); final ReturnValueConstraint constraint2 = new ReturnValueConstraint(priceExtractor, restriction2); final Cheese cheddar0 = new Cheese("cheddar", 5); final InternalFactHandle f0 = (InternalFactHandle) workingMemory.insert(cheddar0); LeftTupleImpl tuple = new LeftTupleImpl(f0, null, true); final Cheese cheddar1 = new Cheese("cheddar", 10); final InternalFactHandle f1 = (InternalFactHandle) workingMemory.insert(cheddar1); tuple = new LeftTupleImpl(tuple, new RightTuple(f1, null), null, true); final ReturnValueContextEntry context1 = (ReturnValueContextEntry) constraint1.createContextEntry(); context1.updateFromTuple(workingMemory, tuple); assertTrue(constraint1.isAllowedCachedLeft(context1, f1)); final ReturnValueContextEntry context2 = (ReturnValueContextEntry) constraint2.createContextEntry(); context2.updateFromTuple(workingMemory, tuple); assertFalse(constraint2.isAllowedCachedLeft(context2, f1)); final Cheese cheddar2 = new Cheese("cheddar", 11); final InternalFactHandle f2 = (InternalFactHandle) workingMemory.insert(cheddar2); assertTrue(constraint2.isAllowedCachedLeft(context2, f2)); }