Esempio n. 1
0
  private void replaceDeclarations(
      DeclarationScopeResolver resolver, Pattern pattern, Constraint constraint) {
    Declaration[] decl = constraint.getRequiredDeclarations();
    for (Declaration aDecl : decl) {
      Declaration resolved = resolver.getDeclaration(null, aDecl.getIdentifier());

      if (constraint instanceof MvelConstraint && ((MvelConstraint) constraint).isUnification()) {
        if (ClassObjectType.DroolsQuery_ObjectType.isAssignableFrom(
            resolved.getPattern().getObjectType())) {
          Declaration redeclaredDeclr =
              new Declaration(
                  resolved.getIdentifier(),
                  ((MvelConstraint) constraint).getFieldExtractor(),
                  pattern,
                  false);
          pattern.addDeclaration(redeclaredDeclr);
        } else if (resolved.getPattern() != pattern) {
          ((MvelConstraint) constraint).unsetUnification();
        }
      }

      if (resolved != null && resolved != aDecl && resolved.getPattern() != pattern) {
        constraint.replaceDeclaration(aDecl, resolved);
      } else if (resolved == null) {
        // it is probably an implicit declaration, so find the corresponding pattern
        Pattern old = aDecl.getPattern();
        Pattern current = resolver.findPatternByIndex(old.getIndex());
        if (current != null && old != current) {
          resolved = new Declaration(aDecl.getIdentifier(), aDecl.getExtractor(), current);
          constraint.replaceDeclaration(aDecl, resolved);
        }
      }
    }
  }
Esempio n. 2
0
 private void processEvalCondition(DeclarationScopeResolver resolver, EvalCondition element) {
   Declaration[] decl = element.getRequiredDeclarations();
   for (Declaration aDecl : decl) {
     Declaration resolved = resolver.getDeclaration(null, aDecl.getIdentifier());
     if (resolved != null && resolved != aDecl) {
       element.replaceDeclaration(aDecl, resolved);
     }
   }
 }
Esempio n. 3
0
  private void replaceDeclarations(DeclarationScopeResolver resolver, Accumulate accumulate) {
    Declaration[] decl = accumulate.getRequiredDeclarations();
    for (Declaration aDecl : decl) {
      Declaration resolved = resolver.getDeclaration(null, aDecl.getIdentifier());

      if (resolved != null && resolved != aDecl) {
        accumulate.replaceDeclaration(aDecl, resolved);
      } else if (resolved == null) {
        // it is probably an implicit declaration, so find the corresponding pattern
        Pattern old = aDecl.getPattern();
        Pattern current = resolver.findPatternByIndex(old.getIndex());
        if (current != null && old != current) {
          resolved = new Declaration(aDecl.getIdentifier(), aDecl.getExtractor(), current);
          accumulate.replaceDeclaration(aDecl, resolved);
        }
      }
    }
  }
Esempio n. 4
0
  /** recurse through the rule condition elements updating the declaration objecs */
  private void processElement(
      final DeclarationScopeResolver resolver,
      final Stack<RuleConditionElement> contextStack,
      final RuleConditionElement element) {
    if (element instanceof Pattern) {
      Pattern pattern = (Pattern) element;
      for (RuleConditionElement ruleConditionElement : pattern.getNestedElements()) {
        processElement(resolver, contextStack, ruleConditionElement);
      }
      for (Constraint constraint : pattern.getConstraints()) {
        if (constraint instanceof Declaration) {
          continue;
        }
        replaceDeclarations(resolver, pattern, constraint);
      }

    } else if (element instanceof EvalCondition) {
      processEvalCondition(resolver, (EvalCondition) element);

    } else if (element instanceof Accumulate) {
      for (RuleConditionElement rce : element.getNestedElements()) {
        processElement(resolver, contextStack, rce);
      }
      Accumulate accumulate = (Accumulate) element;
      replaceDeclarations(resolver, accumulate);
      accumulate.resetInnerDeclarationCache();

    } else if (element instanceof From) {
      DataProvider provider = ((From) element).getDataProvider();
      Declaration[] decl = provider.getRequiredDeclarations();
      for (Declaration aDecl : decl) {
        Declaration resolved = resolver.getDeclaration(null, aDecl.getIdentifier());
        if (resolved != null && resolved != aDecl) {
          provider.replaceDeclaration(aDecl, resolved);
        } else if (resolved == null) {
          // it is probably an implicit declaration, so find the corresponding pattern
          Pattern old = aDecl.getPattern();
          Pattern current = resolver.findPatternByIndex(old.getIndex());
          if (current != null && old != current) {
            resolved = new Declaration(aDecl.getIdentifier(), aDecl.getExtractor(), current);
            provider.replaceDeclaration(aDecl, resolved);
          }
        }
      }

    } else if (element instanceof QueryElement) {
      QueryElement qe = (QueryElement) element;
      Pattern pattern = qe.getResultPattern();

      for (Entry<String, Declaration> entry : pattern.getInnerDeclarations().entrySet()) {
        Declaration resolved = resolver.getDeclaration(null, entry.getValue().getIdentifier());
        if (resolved != null && resolved != entry.getValue() && resolved.getPattern() != pattern) {
          entry.setValue(resolved);
        }
      }

      List<Integer> varIndexes = asList(qe.getVariableIndexes());
      for (int i = 0; i < qe.getArguments().length; i++) {
        if (!(qe.getArguments()[i] instanceof QueryArgument.Declr)) {
          continue;
        }
        Declaration declr = ((QueryArgument.Declr) qe.getArguments()[i]).getDeclaration();
        Declaration resolved = resolver.getDeclaration(null, declr.getIdentifier());
        if (resolved != declr && resolved.getPattern() != pattern) {
          qe.getArguments()[i] = new QueryArgument.Declr(resolved);
        }

        if (ClassObjectType.DroolsQuery_ObjectType.isAssignableFrom(
            resolved.getPattern().getObjectType())) {
          // if the resolved still points to DroolsQuery, we know this is the first unification
          // pattern, so redeclare it as the visible Declaration
          declr = pattern.addDeclaration(declr.getIdentifier());

          // this bit is different, notice its the ArrayElementReader that we wire up to, not the
          // declaration.
          ArrayElementReader reader =
              new ArrayElementReader(
                  new SelfReferenceClassFieldReader(Object[].class),
                  i,
                  resolved.getDeclarationClass());
          declr.setReadAccessor(reader);

          varIndexes.add(i);
        }
      }
      qe.setVariableIndexes(toIntArray(varIndexes));

    } else if (element instanceof ConditionalBranch) {
      processBranch(resolver, (ConditionalBranch) element);

    } else {
      contextStack.push(element);
      for (RuleConditionElement ruleConditionElement : element.getNestedElements()) {
        processElement(resolver, contextStack, ruleConditionElement);
      }
      contextStack.pop();
    }
  }
  @SuppressWarnings("unchecked")
  public RuleConditionElement build(
      final RuleBuildContext context, final BaseDescr descr, final Pattern prefixPattern) {
    boolean typesafe = context.isTypesafe();
    try {
      final AccumulateDescr accumDescr = (AccumulateDescr) descr;

      if (!accumDescr.hasValidInput()) {
        return null;
      }

      final RuleConditionBuilder builder =
          (RuleConditionBuilder) context.getDialect().getBuilder(accumDescr.getInput().getClass());

      // create source CE
      final RuleConditionElement source = builder.build(context, accumDescr.getInput());

      if (source == null) {
        return null;
      }

      MVELDialect dialect = (MVELDialect) context.getDialect();

      Map<String, Declaration> decls =
          context.getDeclarationResolver().getDeclarations(context.getRule());
      Map<String, Declaration> sourceOuterDeclr = source.getOuterDeclarations();

      Map<String, Declaration> mergedDecl = new HashMap(decls);
      mergedDecl.putAll(sourceOuterDeclr);

      Map<String, Class<?>> declarationClasses =
          DeclarationScopeResolver.getDeclarationClasses(decls);
      declarationClasses.putAll(DeclarationScopeResolver.getDeclarationClasses(sourceOuterDeclr));

      BoundIdentifiers boundIds =
          new BoundIdentifiers(declarationClasses, context.getKnowledgeBuilder().getGlobals());
      boundIds.setDeclarations(mergedDecl);

      Accumulator[] accumulators;

      final boolean readLocalsFromTuple =
          PackageBuilderUtil.isReadLocalsFromTuple(context, accumDescr, source);

      if (accumDescr.isExternalFunction()) {
        // uses accumulate functions
        accumulators =
            buildExternalFunctions(
                context,
                accumDescr,
                dialect,
                decls,
                sourceOuterDeclr,
                boundIds,
                readLocalsFromTuple);
      } else {
        // it is a custom accumulate
        accumulators =
            buildCustomAccumulate(
                context,
                accumDescr,
                dialect,
                decls,
                sourceOuterDeclr,
                boundIds,
                readLocalsFromTuple);
      }

      List<Declaration> requiredDeclarations = new ArrayList<Declaration>();
      for (Accumulator acc : accumulators) {
        MvelAccumulator mvelAcc = (MvelAccumulator) acc;
        Collections.addAll(requiredDeclarations, mvelAcc.getRequiredDeclarations());
      }

      MVELDialectRuntimeData data =
          (MVELDialectRuntimeData)
              context.getPkg().getDialectRuntimeRegistry().getDialectData("mvel");

      Accumulate accumulate;
      if (accumDescr.isMultiFunction()) {
        accumulate =
            new MultiAccumulate(
                source,
                requiredDeclarations.toArray(new Declaration[requiredDeclarations.size()]),
                accumulators);
        int index = 0;
        for (Accumulator accumulator : accumulators) {
          data.addCompileable(
              ((MultiAccumulate) accumulate).new Wirer(index++), (MVELCompileable) accumulator);
          ((MVELCompileable) accumulator).compile(data, context.getRule());
        }
      } else {
        accumulate =
            new SingleAccumulate(
                source,
                requiredDeclarations.toArray(new Declaration[requiredDeclarations.size()]),
                accumulators[0]);
        data.addCompileable(
            ((SingleAccumulate) accumulate).new Wirer(), (MVELCompileable) accumulators[0]);
        ((MVELCompileable) accumulators[0]).compile(data, context.getRule());
      }

      return accumulate;
    } catch (Exception e) {
      DialectUtil.copyErrorLocation(e, descr);
      context.addError(
          new DescrBuildError(
              context.getParentDescr(),
              descr,
              e,
              "Unable to build expression for 'accumulate' : " + e.getMessage()));
      return null;
    } finally {
      context.setTypesafe(typesafe);
    }
  }
  public void build(final RuleBuildContext context, String consequenceName) {

    // pushing consequence LHS into the stack for variable resolution
    context.getBuildStack().push(context.getRule().getLhs());

    try {
      MVELDialect dialect = (MVELDialect) context.getDialect(context.getDialect().getId());

      final RuleDescr ruleDescr = context.getRuleDescr();

      String text =
          (Rule.DEFAULT_CONSEQUENCE_NAME.equals(consequenceName))
              ? (String) ruleDescr.getConsequence()
              : (String) ruleDescr.getNamedConsequences().get(consequenceName);

      text = processMacros(text);

      Map<String, Declaration> decls =
          context.getDeclarationResolver().getDeclarations(context.getRule());

      AnalysisResult analysis =
          dialect.analyzeBlock(
              context,
              context.getRuleDescr(),
              dialect.getInterceptors(),
              text,
              new BoundIdentifiers(
                  DeclarationScopeResolver.getDeclarationClasses(decls),
                  context.getPackageBuilder().getGlobals(),
                  null,
                  KnowledgeHelper.class),
              null,
              "drools",
              KnowledgeHelper.class);

      if (analysis == null) {
        // something bad happened, issue already logged in errors
        return;
      }

      final BoundIdentifiers usedIdentifiers = analysis.getBoundIdentifiers();

      final Declaration[] declarations = new Declaration[usedIdentifiers.getDeclrClasses().size()];
      String[] declrStr = new String[declarations.length];
      int j = 0;
      for (String str : usedIdentifiers.getDeclrClasses().keySet()) {
        declrStr[j] = str;
        declarations[j++] = decls.get(str);
      }
      Arrays.sort(declarations, SortDeclarations.instance);
      for (int i = 0; i < declrStr.length; i++) {
        declrStr[i] = declarations[i].getIdentifier();
      }
      context.getRule().setRequiredDeclarationsForConsequence(consequenceName, declrStr);
      MVELCompilationUnit unit =
          dialect.getMVELCompilationUnit(
              text,
              analysis,
              declarations,
              null,
              null,
              context,
              "drools",
              KnowledgeHelper.class,
              false);

      MVELConsequence expr = new MVELConsequence(unit, dialect.getId());

      if (Rule.DEFAULT_CONSEQUENCE_NAME.equals(consequenceName)) {
        context.getRule().setConsequence(expr);
      } else {
        context.getRule().addNamedConsequence(consequenceName, expr);
      }

      MVELDialectRuntimeData data =
          (MVELDialectRuntimeData)
              context.getPkg().getDialectRuntimeRegistry().getDialectData("mvel");
      data.addCompileable(context.getRule(), expr);

      expr.compile(data);
    } catch (final Exception e) {
      copyErrorLocation(e, context.getRuleDescr());
      context.addError(
          new DescrBuildError(
              context.getParentDescr(),
              context.getRuleDescr(),
              null,
              "Unable to build expression for 'consequence': "
                  + e.getMessage()
                  + " '"
                  + context.getRuleDescr().getConsequence()
                  + "'"));
    }
  }