/**
   * Just like MVEL command line, we can allow expressions to span lines, with optional ";"
   * seperating expressions. If its needed a ";" can be thrown in, but if not, a new line is fine.
   *
   * <p>However, when in the middle of unbalanced brackets, a new line means nothing.
   *
   * @throws Exception
   */
  @Test
  public void testLineSpanOptionalSemis() throws Exception {

    String simpleEx = "foo\nbar\nbaz";
    MVELConsequenceBuilder cons = new MVELConsequenceBuilder();
    assertEquals("foo;\nbar;\nbaz", MVELConsequenceBuilder.delimitExpressions(simpleEx));

    String ex = "foo (\n bar \n)\nbar;\nyeah;\nman\nbaby";
    assertEquals(
        "foo ( bar );\n\n\nbar;\nyeah;\nman;\nbaby", MVELConsequenceBuilder.delimitExpressions(ex));

    ex = "foo {\n bar \n}\nbar;   \nyeah;\nman\nbaby";
    assertEquals(
        "foo { bar };\n\n\nbar;   \nyeah;\nman;\nbaby",
        MVELConsequenceBuilder.delimitExpressions(ex));

    ex = "foo [\n bar \n]\nbar;  x\nyeah();\nman[42]\nbaby;ca chiga;\nend";
    assertEquals(
        "foo [ bar ];\n\n\nbar;  x;\nyeah();\nman[42];\nbaby;ca chiga;\nend",
        MVELConsequenceBuilder.delimitExpressions(ex));

    ex = "   \n\nfoo [\n bar \n]\n\n\nbar;  x\n  \nyeah();\nman[42]\nbaby;ca chiga;\nend";
    assertEquals(
        "   \n\nfoo [ bar ];\n\n\n\n\nbar;  x;\n  \nyeah();\nman[42];\nbaby;ca chiga;\nend",
        MVELConsequenceBuilder.delimitExpressions(ex));

    ex = "   retract(f1) // some comment\n   retract(f2)\nend";
    assertEquals(
        "   retract(f1) ;// some comment\n   retract(f2);\nend",
        MVELConsequenceBuilder.delimitExpressions(ex));

    ex = "   retract(f1 /* inline comment */) /* some\n comment\n*/   retract(f2)\nend";
    assertEquals(
        "   retract(f1 /* inline comment */) ;/* some\n comment\n*/   retract(f2);\nend",
        MVELConsequenceBuilder.delimitExpressions(ex));
  }
  @Test
  public void testSimpleExpression() throws Exception {
    PackageDescr pkgDescr = new PackageDescr("pkg1");
    KnowledgeBuilderImpl pkgBuilder = new KnowledgeBuilderImpl();
    pkgBuilder.addPackage(pkgDescr);

    InternalKnowledgePackage pkg = pkgBuilder.getPackageRegistry("pkg1").getPackage();
    final RuleDescr ruleDescr = new RuleDescr("rule 1");
    ruleDescr.setNamespace("pkg1");
    ruleDescr.setConsequence("modify (cheese) {price = 5 };\nretract (cheese)");

    DialectCompiletimeRegistry dialectRegistry =
        pkgBuilder.getPackageRegistry(pkg.getName()).getDialectCompiletimeRegistry();

    MVELDialect mvelDialect = (MVELDialect) dialectRegistry.getDialect("mvel");

    final InstrumentedBuildContent context =
        new InstrumentedBuildContent(pkgBuilder, ruleDescr, dialectRegistry, pkg, mvelDialect);

    final InstrumentedDeclarationScopeResolver declarationResolver =
        new InstrumentedDeclarationScopeResolver();

    final ObjectType cheeseObjeectType = new ClassObjectType(Cheese.class);

    final Pattern pattern = new Pattern(0, cheeseObjeectType, "cheese");

    final GroupElement subrule = new GroupElement(GroupElement.AND);
    subrule.addChild(pattern);
    final Map<String, Declaration> map = new HashMap<String, Declaration>();
    map.put("cheese", pattern.getDeclaration());
    declarationResolver.setDeclarations(map);
    context.setDeclarationResolver(declarationResolver);

    final MVELConsequenceBuilder builder = new MVELConsequenceBuilder();
    builder.build(context, RuleImpl.DEFAULT_CONSEQUENCE_NAME);

    InternalKnowledgeBase kBase = (InternalKnowledgeBase) KnowledgeBaseFactory.newKnowledgeBase();

    PropagationContextFactory pctxFactory =
        kBase.getConfiguration().getComponentFactory().getPropagationContextFactory();
    kBase.addPackage(pkg);

    StatefulKnowledgeSessionImpl ksession =
        (StatefulKnowledgeSessionImpl) kBase.newStatefulKnowledgeSession();

    final Cheese cheddar = new Cheese("cheddar", 10);
    final InternalFactHandle f0 = (InternalFactHandle) ksession.insert(cheddar);
    final LeftTupleImpl tuple = new LeftTupleImpl(f0, null, true);
    f0.removeLeftTuple(tuple);

    final AgendaItem item =
        new AgendaItemImpl(
            0,
            tuple,
            10,
            pctxFactory.createPropagationContext(1, 1, null, tuple, null),
            new RuleTerminalNode(
                0,
                new CompositeObjectSinkAdapterTest.MockBetaNode(),
                context.getRule(),
                subrule,
                0,
                new BuildContext(kBase, null)),
            null);
    final DefaultKnowledgeHelper kbHelper = new DefaultKnowledgeHelper(ksession);
    kbHelper.setActivation(item);
    ((MVELConsequence) context.getRule().getConsequence())
        .compile(
            (MVELDialectRuntimeData)
                pkgBuilder
                    .getPackageRegistry(pkg.getName())
                    .getDialectRuntimeRegistry()
                    .getDialectData("mvel"));
    context.getRule().getConsequence().evaluate(kbHelper, ksession);

    assertEquals(5, cheddar.getPrice());
  }
  @Test
  public void testImperativeCodeError() throws Exception {
    InternalKnowledgePackage pkg = new KnowledgePackageImpl("pkg1");
    final RuleDescr ruleDescr = new RuleDescr("rule 1");
    ruleDescr.setConsequence("if (cheese.price == 10) { cheese.price = 5; }");

    Properties properties = new Properties();
    properties.setProperty("drools.dialect.default", "mvel");
    KnowledgeBuilderConfigurationImpl cfg1 = new KnowledgeBuilderConfigurationImpl(properties);

    KnowledgeBuilderImpl pkgBuilder = new KnowledgeBuilderImpl(pkg, cfg1);
    final KnowledgeBuilderConfigurationImpl conf = pkgBuilder.getBuilderConfiguration();
    PackageRegistry pkgRegistry = pkgBuilder.getPackageRegistry(pkg.getName());
    DialectCompiletimeRegistry dialectRegistry =
        pkgBuilder.getPackageRegistry(pkg.getName()).getDialectCompiletimeRegistry();
    MVELDialect mvelDialect = (MVELDialect) dialectRegistry.getDialect(pkgRegistry.getDialect());

    final InstrumentedBuildContent context =
        new InstrumentedBuildContent(pkgBuilder, ruleDescr, dialectRegistry, pkg, mvelDialect);

    final InstrumentedDeclarationScopeResolver declarationResolver =
        new InstrumentedDeclarationScopeResolver();

    final ObjectType cheeseObjeectType = new ClassObjectType(Cheese.class);

    final Pattern pattern = new Pattern(0, cheeseObjeectType);

    final PatternExtractor extractor = new PatternExtractor(cheeseObjeectType);

    final Declaration declaration = new Declaration("cheese", extractor, pattern);
    final Map<String, Declaration> map = new HashMap<String, Declaration>();
    map.put("cheese", declaration);
    declarationResolver.setDeclarations(map);
    context.setDeclarationResolver(declarationResolver);

    final MVELConsequenceBuilder builder = new MVELConsequenceBuilder();
    builder.build(context, RuleImpl.DEFAULT_CONSEQUENCE_NAME);

    InternalKnowledgeBase kBase = (InternalKnowledgeBase) KnowledgeBaseFactory.newKnowledgeBase();
    StatefulKnowledgeSessionImpl ksession =
        (StatefulKnowledgeSessionImpl) kBase.newStatefulKnowledgeSession();

    final Cheese cheddar = new Cheese("cheddar", 10);
    final InternalFactHandle f0 = (InternalFactHandle) ksession.insert(cheddar);
    final LeftTupleImpl tuple = new LeftTupleImpl(f0, null, true);

    final AgendaItem item = new AgendaItemImpl(0, tuple, 10, null, null, null);
    final DefaultKnowledgeHelper kbHelper = new DefaultKnowledgeHelper(ksession);
    kbHelper.setActivation(item);
    try {
      ((MVELConsequence) context.getRule().getConsequence())
          .compile(
              (MVELDialectRuntimeData)
                  pkgBuilder
                      .getPackageRegistry(pkg.getName())
                      .getDialectRuntimeRegistry()
                      .getDialectData("mvel"));
      context.getRule().getConsequence().evaluate(kbHelper, ksession);
      fail("should throw an exception, as 'if' is not allowed");
    } catch (Exception e) {
    }

    assertEquals(10, cheddar.getPrice());
  }