예제 #1
0
 public List<String> getDeclarationIds() {
   List<String> decls = new ArrayList<String>();
   for (Declaration decl : this.declarations) {
     decls.add(decl.getIdentifier());
   }
   return Collections.unmodifiableList(decls);
 }
예제 #2
0
  private void initDeclarations() {
    Map<String, Declaration> declMap = subrule.getOuterDeclarations();
    this.allDeclarations = declMap.values().toArray(new Declaration[declMap.size()]);

    this.requiredDeclarations = new Declaration[query.getParameters().length];
    int i = 0;
    for (Declaration declr : query.getParameters()) {
      this.requiredDeclarations[i++] = declMap.get(declr.getIdentifier());
    }
  }
예제 #3
0
 @Override
 public XpathConstraint clone() {
   XpathConstraint clone = new XpathConstraint(this.chunks);
   if (declaration != null) {
     clone.setDeclaration(declaration.clone());
   }
   if (xpathStartDeclaration != null) {
     clone.setXpathStartDeclaration(xpathStartDeclaration.clone());
   }
   return clone;
 }
예제 #4
0
 private boolean checkProcessInstance(Activation activation, long processInstanceId) {
   final Map<String, Declaration> declarations = activation.getSubRule().getOuterDeclarations();
   for (Declaration declaration : declarations.values()) {
     if ("processInstance".equals(declaration.getIdentifier())) {
       Object value =
           declaration.getValue(workingMemory, activation.getTuple().get(declaration).getObject());
       if (value instanceof ProcessInstance) {
         return ((ProcessInstance) value).getId() == processInstanceId;
       }
     }
   }
   return true;
 }
예제 #5
0
  public String[] getIdentifiers() {
    if (identifiers != null) {
      return identifiers;
    }
    Declaration[] parameters = this.results.getParameters();

    Set<String> set = new HashSet<String>();
    for (Declaration declr : parameters) {
      set.add(declr.getIdentifier());
    }

    Collection<Declaration> declrCollection = new ArrayList(results.getDeclarations(0).values());

    for (Iterator<Declaration> it = declrCollection.iterator(); it.hasNext(); ) {
      Declaration declr = it.next();
      if (set.contains(declr.getIdentifier())) {
        it.remove();
      }
    }

    String[] declrs = new String[parameters.length + declrCollection.size()];
    int i = 0;
    for (Declaration declr : parameters) {
      declrs[i++] = declr.getIdentifier();
    }
    for (Declaration declr : declrCollection) {
      declrs[i++] = declr.getIdentifier();
    }
    identifiers = declrs;
    return identifiers;
  }
예제 #6
0
 protected boolean checkProcessInstance(Activation activation) {
   final Map<?, ?> declarations = activation.getSubRule().getOuterDeclarations();
   for (Iterator<?> it = declarations.values().iterator(); it.hasNext(); ) {
     Declaration declaration = (Declaration) it.next();
     if ("processInstance".equals(declaration.getIdentifier())
         || "org.kie.api.runtime.process.WorkflowProcessInstance"
             .equals(declaration.getTypeName())) {
       Object value =
           declaration.getValue(
               ((StatefulKnowledgeSessionImpl) getProcessInstance().getKnowledgeRuntime())
                   .getInternalWorkingMemory(),
               ((InternalFactHandle) activation.getTuple().get(declaration)).getObject());
       if (value instanceof ProcessInstance) {
         return ((ProcessInstance) value).getId() == getProcessInstance().getId();
       }
     }
   }
   return true;
 }
예제 #7
0
  public BetaNodeFieldConstraint getBoundVariableConstraint(
      final Class clazz,
      final String fieldName,
      final Declaration declaration,
      final String evaluatorString)
      throws IntrospectionException {

    final InternalReadAccessor extractor =
        store.getReader(clazz, fieldName, getClass().getClassLoader());
    String expression = fieldName + " " + evaluatorString + " " + declaration.getIdentifier();
    return new MvelConstraintTestUtil(expression, declaration, extractor);
  }
예제 #8
0
    @Override
    public Iterator getResults(
        Tuple leftTuple, InternalWorkingMemory wm, PropagationContext ctx, Object providerContext) {
      InternalFactHandle fh = leftTuple.getFactHandle();
      Object obj = fh.getObject();

      if (obj instanceof DroolsQuery) {
        obj = ((DroolsQuery) obj).getElements()[declaration.getPattern().getOffset()];
      }

      return xpathEvaluator.evaluate(wm, leftTuple, obj).iterator();
    }
예제 #9
0
  private void processPositional(
      RuleBuildContext context,
      Query query,
      Declaration[] params,
      List<Integer> declrIndexes,
      List<Integer> varIndexes,
      List<Object> arguments,
      List<Declaration> requiredDeclarations,
      InternalReadAccessor arrayReader,
      Pattern pattern,
      BaseDescr base,
      String expression,
      ConstraintConnectiveDescr result) {
    int position = ((ExprConstraintDescr) base).getPosition();
    if (position >= arguments.size()) {
      context.addError(
          new DescrBuildError(
              context.getParentDescr(),
              base,
              null,
              "Unable to parse query '"
                  + query.getName()
                  + "', as postion "
                  + (position - 1)
                  + " for expression '"
                  + expression
                  + "' does not exist on query size "
                  + arguments.size()));
      return;
    }
    if (isVariable(expression)) {
      // is this already bound?
      Declaration declr = context.getDeclarationResolver().getDeclaration(query, expression);
      if (declr != null) {
        // it exists, so it's an input
        arguments.set(position, declr);
        declrIndexes.add(position);
        requiredDeclarations.add(declr);
      } else {
        // it doesn't exist, so it's an output
        arguments.set(position, Variable.v);

        varIndexes.add(position);

        declr = pattern.addDeclaration(expression);

        // this bit is different, notice its the ArrayElementReader that we wire up to, not the
        // declaration.
        ArrayElementReader reader =
            new ArrayElementReader(
                arrayReader, position, params[position].getExtractor().getExtractToClass());

        declr.setReadAccessor(reader);
      }
    } else {
      // it's an expression and thus an input
      MVELDumper.MVELDumperContext mvelCtx = new MVELDumper.MVELDumperContext();
      String rewrittenExpr =
          context.getCompilerFactory().getExpressionProcessor().dump(result, mvelCtx);
      arguments.set(position, MVEL.eval(rewrittenExpr)); // for now we just work with literals
    }
  }
예제 #10
0
  @SuppressWarnings("unchecked")
  private void processBinding(
      RuleBuildContext context,
      BaseDescr descr,
      Declaration[] params,
      List<Integer> declrIndexes,
      List<Integer> varIndexes,
      List<Object> arguments,
      List<Declaration> requiredDeclarations,
      InternalReadAccessor arrayReader,
      Pattern pattern,
      BindingDescr bind,
      ConstraintConnectiveDescr result) {
    Declaration declr =
        context.getDeclarationResolver().getDeclaration(context.getRule(), bind.getVariable());
    if (declr != null) {
      // check right maps to a slot, otherwise we can't reverse this and should error
      int pos = getPos(bind.getExpression(), params);
      if (pos >= 0) {
        // slot exist, reverse and continue
        String slot = bind.getExpression();
        String var = bind.getVariable();
        bind.setVariable(slot);
        bind.setExpression(var);
      } else {
        // else error, we cannot find the slot to unify against
      }
    }

    // left does not already exist, is it a slot?
    int pos = getPos(bind.getVariable(), params);
    if (pos >= 0) {
      // it's an input on a slot, is the input using bindings?
      declr =
          context.getDeclarationResolver().getDeclaration(context.getRule(), bind.getExpression());
      if (declr != null) {
        arguments.set(pos, declr);
        declrIndexes.add(pos);
        requiredDeclarations.add(declr);
      } else {
        // it must be a literal/expression
        // it's an expression and thus an input
        DrlExprParser parser = new DrlExprParser(context.getConfiguration().getLanguageLevel());
        ConstraintConnectiveDescr bresult = parser.parse(bind.getExpression());
        if (parser.hasErrors()) {
          for (DroolsParserException error : parser.getErrors()) {
            context.addError(
                new DescrBuildError(
                    context.getParentDescr(),
                    descr,
                    null,
                    "Unable to parser pattern expression:\n" + error.getMessage()));
          }
          return;
        }

        MVELDumper.MVELDumperContext mvelCtx = new MVELDumper.MVELDumperContext();
        String expr = context.getCompilerFactory().getExpressionProcessor().dump(bresult, mvelCtx);
        try {
          Object o = MVEL.eval(expr);
          arguments.set(pos, o); // for now we just work with literals
        } catch (Exception e) {
          context.addError(
              new DescrBuildError(
                  context.getParentDescr(), descr, null, "Unable to compile expression:\n" + expr));
        }
      }
    } else {
      // this is creating a new output binding
      // we know it doesn't exist, as we already checked for left == var
      declr = pattern.addDeclaration(bind.getVariable());

      pos = getPos(bind.getExpression(), params);
      if (pos < 0) {
        // error this must be a binding on a slot
        context.addError(
            new DescrBuildError(
                context.getParentDescr(),
                descr,
                null,
                "named argument does not exist:\n" + bind.getExpression()));
        return;
      }

      // this bit is different, notice its the ArrayElementReader that we wire up to, not the
      // declaration.
      ArrayElementReader reader =
          new ArrayElementReader(arrayReader, pos, params[pos].getExtractor().getExtractToClass());

      // Should the reader be registered like the others? Probably yes...
      // PatternBuilder.registerReadAccessor(  );

      declr.setReadAccessor(reader);

      varIndexes.add(pos);
      arguments.set(pos, Variable.v);
    }
  }
예제 #11
0
  public void execute(Map<String, Object> context, List<String[]> args) {
    BuildContext buildContext = (BuildContext) context.get("BuildContext");

    if (args.size() >= 1) {

      // The first argument list is the node parameters
      String[] a = args.get(0);
      String name = a[0];
      String leftInput = a[1];
      String rightInput = a[2];
      String sourceType = a[3];
      String expr = a[4];

      Class cls = null;

      LeftTupleSource leftTupleSource;
      if (leftInput.startsWith("mock")) {
        leftTupleSource = new MockTupleSource(buildContext.getNextId());
      } else {
        leftTupleSource = (LeftTupleSource) context.get(leftInput);
      }

      ObjectSource rightObjectSource;
      if (rightInput.startsWith("mock")) {
        String type = rightInput.substring(5, rightInput.length() - 1);
        try {
          cls = reteTesterHelper.getTypeResolver().resolveType(type);
        } catch (ClassNotFoundException e) {
          throw new RuntimeException(e);
        }
        rightObjectSource = new MockObjectSource(buildContext.getNextId());
      } else {
        rightObjectSource = (ObjectSource) context.get(rightInput);
        ObjectSource source = rightObjectSource;
        while (!(source instanceof ObjectTypeNode)) {
          source = source.getParentObjectSource();
        }
        cls = ((ClassObjectType) ((ObjectTypeNode) source).getObjectType()).getClassType();
      }

      Pattern sourcePattern;
      Pattern resultPattern;
      try {
        sourcePattern = reteTesterHelper.getPattern(0, sourceType);

        // we always use the accumulate function "sum", so return type is always Number
        resultPattern =
            reteTesterHelper.getPattern(buildContext.getNextId(), Number.class.getName());
      } catch (Exception e) {
        throw new IllegalArgumentException(
            "Not possible to process arguments: " + Arrays.toString(a));
      }

      List<BetaNodeFieldConstraint> list = new ArrayList<BetaNodeFieldConstraint>();

      AlphaNodeFieldConstraint[] alphaResultConstraint = new AlphaNodeFieldConstraint[0];
      // the following arguments are constraints
      for (int i = 1; i < args.size(); i++) {
        a = args.get(i);
        String type = a[0];
        String fieldName = a[1];
        String operator = a[2];
        String val = a[3];

        if ("source".equals(type)) {
          Declaration declr = (Declaration) context.get(val);
          try {
            BetaNodeFieldConstraint sourceBetaConstraint =
                this.reteTesterHelper.getBoundVariableConstraint(cls, fieldName, declr, operator);
            list.add(sourceBetaConstraint);
          } catch (IntrospectionException e) {
            throw new IllegalArgumentException();
          }
        } else if ("result".equals(type)) {
          alphaResultConstraint = new AlphaNodeFieldConstraint[1];
          try {
            alphaResultConstraint[0] =
                this.reteTesterHelper.getLiteralConstraint(resultPattern, fieldName, operator, val);
          } catch (IntrospectionException e) {
            throw new IllegalArgumentException(
                "Unable to configure alpha constraint: " + Arrays.toString(a), e);
          }
        }
      }

      BetaConstraints betaSourceConstraints;
      switch (list.size()) {
        case 0:
          betaSourceConstraints = new EmptyBetaConstraints();
          break;
        case 1:
          betaSourceConstraints =
              new SingleBetaConstraints(
                  list.get(0), buildContext.getKnowledgeBase().getConfiguration());
          break;
        case 2:
          betaSourceConstraints =
              new DoubleBetaConstraints(
                  list.toArray(new BetaNodeFieldConstraint[2]),
                  buildContext.getKnowledgeBase().getConfiguration());
          break;
        case 3:
          betaSourceConstraints =
              new TripleBetaConstraints(
                  list.toArray(new BetaNodeFieldConstraint[2]),
                  buildContext.getKnowledgeBase().getConfiguration());
          break;
        case 4:
          betaSourceConstraints =
              new QuadroupleBetaConstraints(
                  list.toArray(new BetaNodeFieldConstraint[2]),
                  buildContext.getKnowledgeBase().getConfiguration());
          break;
        default:
          betaSourceConstraints =
              new DefaultBetaConstraints(
                  list.toArray(new BetaNodeFieldConstraint[2]),
                  buildContext.getKnowledgeBase().getConfiguration());
          break;
      }

      MVELDialectRuntimeData data =
          (MVELDialectRuntimeData)
              buildContext
                  .getKnowledgeBase()
                  .getPackage(buildContext.getRule().getPackageName())
                  .getDialectRuntimeRegistry()
                  .getDialectData("mvel");
      data.onAdd(null, buildContext.getKnowledgeBase().getRootClassLoader());
      // MvelD data = (MVELDialectRuntimeData) buildContext.getRuleBase().getPackage(
      // buildContext.getRule().getName() ).getDialectRuntimeRegistry().getDialectData( "mvel" );

      NodeTestCase testCase = (NodeTestCase) context.get("TestCase");

      try {
        for (String imp : testCase.getImports()) {
          if (imp.endsWith(".*")) {
            data.addPackageImport(imp.substring(0, imp.lastIndexOf('.')));
          } else {
            // classImports.add( imp );
            cls = data.getRootClassLoader().loadClass(imp);
            data.addImport(cls.getSimpleName(), cls);
          }
        }
      } catch (Exception e) {
        throw new RuntimeException("Unable to load class", e);
      }

      Declaration decl = (Declaration) context.get(expr);
      // build an external function executor
      MVELCompilationUnit compilationUnit =
          new MVELCompilationUnit(
              name,
              expr,
              new String[] {}, // global identifiers
              new EvaluatorWrapper[] {}, // operator identifiers
              new Declaration[] {}, // previous declarations
              new Declaration[] {decl}, // local declarations
              new String[] {}, // other identifiers
              new String[] {
                "this", "drools", "kcontext", "rule", decl.getIdentifier()
              }, // input identifiers
              new String[] {
                Object.class.getName(),
                KnowledgeHelper.class.getName(),
                KnowledgeHelper.class.getName(),
                Rule.class.getName(),
                decl.getValueType().getClassType().getName()
              }, // input types
              4,
              false,
              false);

      AccumulateFunction accFunction = new SumAccumulateFunction();

      Accumulator accumulator = new MVELAccumulatorFunctionExecutor(compilationUnit, accFunction);
      ((MVELCompileable) accumulator).compile(data);

      Accumulate accumulate =
          new SingleAccumulate(
              sourcePattern,
              new Declaration[] {}, // required declaration
              accumulator);
      AccumulateNode accNode =
          new AccumulateNode(
              buildContext.getNextId(),
              leftTupleSource,
              rightObjectSource,
              alphaResultConstraint,
              betaSourceConstraints,
              new EmptyBetaConstraints(),
              accumulate,
              false,
              buildContext);

      accNode.attach(buildContext);
      context.put(name, accNode);

    } else {
      StringBuilder msgBuilder = new StringBuilder();
      msgBuilder.append("Can not parse AccumulateNode step arguments: \n");
      for (String[] arg : args) {
        msgBuilder.append("    ");
        msgBuilder.append(Arrays.toString(arg));
        msgBuilder.append("\n");
      }
      throw new IllegalArgumentException(msgBuilder.toString());
    }
  }
  private Accumulator[] buildExternalFunctions(
      final RuleBuildContext context,
      final AccumulateDescr accumDescr,
      MVELDialect dialect,
      Map<String, Declaration> decls,
      Map<String, Declaration> sourceOuterDeclr,
      BoundIdentifiers boundIds,
      boolean readLocalsFromTuple) {
    Accumulator[] accumulators;
    List<AccumulateFunctionCallDescr> functions = accumDescr.getFunctions();

    accumulators = new Accumulator[functions.size()];
    // creating the custom array reader
    InternalReadAccessor arrayReader = new SelfReferenceClassFieldReader(Object[].class, "this");

    int index = 0;
    Pattern pattern = (Pattern) context.getDeclarationResolver().peekBuildStack();
    for (AccumulateFunctionCallDescr func : functions) {
      // build an external function executor
      AccumulateFunction function =
          context.getConfiguration().getAccumulateFunction(func.getFunction());
      if (function == null) {
        // might have been imported in the package
        function =
            context
                .getKnowledgeBuilder()
                .getPackage()
                .getAccumulateFunctions()
                .get(func.getFunction());
      }
      if (function == null) {
        context.addError(
            new DescrBuildError(
                accumDescr,
                context.getRuleDescr(),
                null,
                "Unknown accumulate function: '"
                    + func.getFunction()
                    + "' on rule '"
                    + context.getRuleDescr().getName()
                    + "'. All accumulate functions must be registered before building a resource."));
        return null;
      }

      final AnalysisResult analysis =
          dialect.analyzeExpression(
              context,
              accumDescr,
              func.getParams().length > 0 ? func.getParams()[0] : "\"\"",
              boundIds);

      MVELCompilationUnit unit =
          dialect.getMVELCompilationUnit(
              func.getParams().length > 0 ? func.getParams()[0] : "\"\"",
              analysis,
              getUsedDeclarations(decls, analysis),
              getUsedDeclarations(sourceOuterDeclr, analysis),
              null,
              context,
              "drools",
              KnowledgeHelper.class,
              readLocalsFromTuple,
              MVELCompilationUnit.Scope.CONSTRAINT);

      accumulators[index] = new MVELAccumulatorFunctionExecutor(unit, function);
      // if there is a binding, create the binding
      if (func.getBind() != null) {
        if (context
            .getDeclarationResolver()
            .isDuplicated(context.getRule(), func.getBind(), function.getResultType().getName())) {
          if (!func.isUnification()) {
            context.addError(
                new DescrBuildError(
                    context.getParentDescr(),
                    accumDescr,
                    null,
                    "Duplicate declaration for variable '"
                        + func.getBind()
                        + "' in the rule '"
                        + context.getRule().getName()
                        + "'"));
          } else {
            Declaration inner =
                context.getDeclarationResolver().getDeclaration(context.getRule(), func.getBind());
            Constraint c =
                new MvelConstraint(
                    Collections.singletonList(context.getPkg().getName()),
                    accumDescr.isMultiFunction()
                        ? "this[ " + index + " ] == " + func.getBind()
                        : "this == " + func.getBind(),
                    new Declaration[] {inner},
                    null,
                    IndexUtil.ConstraintType.EQUAL,
                    context
                        .getDeclarationResolver()
                        .getDeclaration(context.getRule(), func.getBind()),
                    accumDescr.isMultiFunction()
                        ? new ArrayElementReader(arrayReader, index, function.getResultType())
                        : new SelfReferenceClassFieldReader(function.getResultType(), "this"),
                    true);
            ((MutableTypeConstraint) c).setType(Constraint.ConstraintType.BETA);
            pattern.addConstraint(c);
            index++;
          }
        } else {
          Declaration declr = pattern.addDeclaration(func.getBind());
          if (accumDescr.isMultiFunction()) {
            declr.setReadAccessor(
                new ArrayElementReader(arrayReader, index, function.getResultType()));
          } else {
            declr.setReadAccessor(
                new SelfReferenceClassFieldReader(function.getResultType(), "this"));
          }
        }
      }
      index++;
    }
    return accumulators;
  }
예제 #13
0
 public Object getDeclarationValue(String variableName) {
   Declaration decl = ((RuleImpl) this.rule).getDeclaration(variableName);
   return decl.getValue(
       null, ((InternalFactHandle) factHandles.get(decl.getPattern().getOffset())).getObject());
 }
예제 #14
0
 public void setDeclaration(Declaration declaration) {
   declaration.setReadAccessor(getReadAccessor());
   this.declaration = declaration;
 }