/**
   *
   *
   * <pre>
   *
   *
   *                type == &quot;cheddar&quot &amp;&amp; price &gt; 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));
  }
  public void testSimpleExpression() {
    final Package pkg = new Package("pkg1");
    final RuleDescr ruleDescr = new RuleDescr("rule 1");

    PackageBuilder pkgBuilder = new PackageBuilder(pkg);
    final PackageBuilderConfiguration conf = pkgBuilder.getPackageBuilderConfiguration();
    MVELDialect mvelDialect = (MVELDialect) pkgBuilder.getDialectRegistry().getDialect("mvel");

    final InstrumentedBuildContent context =
        new InstrumentedBuildContent(
            conf, pkg, ruleDescr, pkgBuilder.getDialectRegistry(), mvelDialect);

    final InstrumentedDeclarationScopeResolver declarationResolver =
        new InstrumentedDeclarationScopeResolver();

    final FieldExtractor extractor =
        cache.getExtractor(Cheese.class, "price", getClass().getClassLoader());

    final Pattern pattern = new Pattern(0, new ClassObjectType(int.class));
    final Declaration declaration = new Declaration("a", extractor, pattern);
    final Map map = new HashMap();
    map.put("a", declaration);
    declarationResolver.setDeclarations(map);
    context.setDeclarationResolver(declarationResolver);

    final EvalDescr evalDescr = new EvalDescr();
    evalDescr.setContent("a == 10");

    final MVELEvalBuilder builder = new MVELEvalBuilder();
    final EvalCondition eval = (EvalCondition) builder.build(context, evalDescr);

    final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
    final WorkingMemory wm = ruleBase.newStatefulSession();

    final Cheese cheddar = new Cheese("cheddar", 10);
    final InternalFactHandle f0 = (InternalFactHandle) wm.insert(cheddar);
    final ReteTuple tuple = new ReteTuple(f0);

    Object evalContext = eval.createContext();

    assertTrue(eval.isAllowed(tuple, wm, evalContext));

    cheddar.setPrice(9);
    wm.update(f0, cheddar);
    assertFalse(eval.isAllowed(tuple, wm, evalContext));
  }
  /**
   *
   *
   * <pre>
   *
   *
   *                Cheese( ( type == &quot;cheddar&quot &amp;&amp; price &gt; 10) || ( type == &quote;stilton&quote; && price &lt; 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));
  }
  @Test
  public void testLogicalInsertionsDynamicRule() throws Exception {
    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    kbuilder.add(
        ResourceFactory.newClassPathResource("test_LogicalInsertionsDynamicRule.drl", getClass()),
        ResourceType.DRL);

    if (kbuilder.hasErrors()) {
      fail(kbuilder.getErrors().toString());
    }

    Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
    KnowledgeBase kbase = getKnowledgeBase();
    kbase.addKnowledgePackages(kpkgs);
    StatefulKnowledgeSession ksession = createKnowledgeSession(kbase);

    final Cheese c1 = new Cheese("a", 1);
    final Cheese c2 = new Cheese("b", 2);
    final Cheese c3 = new Cheese("c", 3);
    List list;

    ksession.insert(c1);
    FactHandle h = ksession.insert(c2);
    ksession.insert(c3);
    ksession.fireAllRules();

    ksession = getSerialisedStatefulKnowledgeSession(ksession, true);

    // Check logical Insertions where made for c2 and c3
    list = new ArrayList(ksession.getObjects(new ClassObjectFilter(Person.class)));
    assertEquals(2, list.size());
    assertFalse(list.contains(new Person(c1.getType())));
    assertTrue(list.contains(new Person(c2.getType())));
    assertTrue(list.contains(new Person(c3.getType())));

    // this rule will make a logical assertion for c1 too
    kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    kbuilder.add(
        ResourceFactory.newClassPathResource("test_LogicalInsertionsDynamicRule2.drl", getClass()),
        ResourceType.DRL);
    if (kbuilder.hasErrors()) {
      fail(kbuilder.getErrors().toString());
    }
    Collection<KnowledgePackage> kpkgs2 = kbuilder.getKnowledgePackages();
    kbase.addKnowledgePackages(kpkgs2);
    kbase = SerializationHelper.serializeObject(kbase);

    ksession.fireAllRules();

    ksession = getSerialisedStatefulKnowledgeSession(ksession, true);

    kbase = ksession.getKnowledgeBase();

    // check all now have just one logical assertion each
    list = new ArrayList(ksession.getObjects(new ClassObjectFilter(Person.class)));
    assertEquals(3, list.size());
    assertTrue(list.contains(new Person(c1.getType())));
    assertTrue(list.contains(new Person(c2.getType())));
    assertTrue(list.contains(new Person(c3.getType())));

    ksession = getSerialisedStatefulKnowledgeSession(ksession, true);

    // check the packages are correctly populated
    assertEquals(2, kbase.getKnowledgePackages().size());
    KnowledgePackage test = null, test2 = null;
    // different JVMs return the package list in different order
    for (KnowledgePackage kpkg : kbase.getKnowledgePackages()) {
      if (kpkg.getName().equals("org.drools.test")) {
        test = kpkg;
      } else if (kpkg.getName().equals("org.drools.test2")) {
        test2 = kpkg;
      }
    }

    assertNotNull(test);
    assertNotNull(test2);
    assertEquals("rule1", test.getRules().iterator().next().getName());
    assertEquals("rule2", test2.getRules().iterator().next().getName());

    // now remove the first rule
    kbase.removeRule(test.getName(), test.getRules().iterator().next().getName());
    // different JVMs return the package list in different order
    for (KnowledgePackage kpkg : kbase.getKnowledgePackages()) {
      if (kpkg.getName().equals("org.drools.test")) {
        test = kpkg;
      } else if (kpkg.getName().equals("org.drools.test2")) {
        test2 = kpkg;
      }
    }
    assertNotNull(test);
    assertNotNull(test2);

    // Check the rule was correctly remove
    assertEquals(0, test.getRules().size());
    assertEquals(1, test2.getRules().size());
    assertEquals("rule2", test2.getRules().iterator().next().getName());

    list = new ArrayList(ksession.getObjects(new ClassObjectFilter(Person.class)));
    assertEquals(
        "removal of the rule should result in retraction of c3's logical assertion",
        2,
        list.size());
    assertTrue(
        "c1's logical assertion should not be retracted", list.contains(new Person(c1.getType())));
    assertTrue(
        "c2's logical assertion should  not be retracted", list.contains(new Person(c2.getType())));
    assertFalse(
        "c3's logical assertion should be  retracted", list.contains(new Person(c3.getType())));

    c2.setPrice(3);
    h = getFactHandle(h, ksession);
    ksession.update(h, c2);
    ksession = getSerialisedStatefulKnowledgeSession(ksession, true);
    list = new ArrayList(ksession.getObjects(new ClassObjectFilter(Person.class)));
    assertEquals(
        "c2 now has a higher price, its logical assertion should  be cancelled", 1, list.size());
    assertFalse(
        "The logical assertion cor c2 should have been retracted",
        list.contains(new Person(c2.getType())));
    assertTrue(
        "The logical assertion  for c1 should exist", list.contains(new Person(c1.getType())));

    // different JVMs return the package list in different order
    for (KnowledgePackage kpkg : kbase.getKnowledgePackages()) {
      if (kpkg.getName().equals("org.drools.test")) {
        test = kpkg;
      } else if (kpkg.getName().equals("org.drools.test2")) {
        test2 = kpkg;
      }
    }
    assertNotNull(test);
    assertNotNull(test2);

    kbase.removeRule(test2.getName(), test2.getRules().iterator().next().getName());
    kbase = SerializationHelper.serializeObject(kbase);

    // different JVMs return the package list in different order
    for (KnowledgePackage kpkg : kbase.getKnowledgePackages()) {
      if (kpkg.getName().equals("org.drools.test")) {
        test = kpkg;
      } else if (kpkg.getName().equals("org.drools.test2")) {
        test2 = kpkg;
      }
    }
    assertNotNull(test);
    assertNotNull(test2);

    assertEquals(0, test.getRules().size());
    assertEquals(0, test2.getRules().size());
    list = new ArrayList(ksession.getObjects(new ClassObjectFilter(Person.class)));
    assertEquals(0, list.size());
  }