Example #1
0
  /**
   * Analyse an expression.
   *
   * @param availDecls Total set of declarations available.
   * @param ast The AST for the expression.
   * @return The <code>Set</code> of declarations used by the expression.
   * @throws RecognitionException If an error occurs in the parser.
   */
  @SuppressWarnings("unchecked")
  private MVELAnalysisResult analyze(
      final Set<String> identifiers, final BoundIdentifiers availableIdentifiers) {

    MVELAnalysisResult result = new MVELAnalysisResult();
    result.setIdentifiers(identifiers);

    final Set<String> notBound = new HashSet<String>(identifiers);
    notBound.remove("this");
    Map<String, Class<?>> usedDecls = new HashMap<String, Class<?>>();
    Map<String, Class<?>> usedGlobals = new HashMap<String, Class<?>>();

    for (Entry<String, Class<?>> entry : availableIdentifiers.getDeclarations().entrySet()) {
      if (identifiers.contains(entry.getKey())) {
        usedDecls.put(entry.getKey(), entry.getValue());
        notBound.remove(entry.getKey());
      }
    }

    for (Entry<String, Class<?>> entry : availableIdentifiers.getGlobals().entrySet()) {
      if (identifiers.contains(entry.getKey())) {
        usedGlobals.put(entry.getKey(), entry.getValue());
        notBound.remove(entry.getKey());
      }
    }

    result.setBoundIdentifiers(
        new BoundIdentifiers(usedDecls, usedGlobals, availableIdentifiers.getThisClass()));
    result.setNotBoundedIdentifiers(notBound);

    return result;
  }
  private Declaration[] getUsedDeclarations(
      Map<String, Declaration> decls, AnalysisResult analysis) {
    final BoundIdentifiers usedIdentifiers = analysis.getBoundIdentifiers();
    List<Declaration> usedDeclarations = new ArrayList<Declaration>();
    for (String id : usedIdentifiers.getDeclrClasses().keySet()) {
      if (decls.containsKey(id)) {
        usedDeclarations.add(decls.get(id));
      }
    }

    if (!usedDeclarations.isEmpty()) {
      Collections.sort(usedDeclarations, SortDeclarations.instance);
    }

    return usedDeclarations.toArray(new Declaration[usedDeclarations.size()]);
  }
Example #3
0
  /**
   * Builds and returns an Eval Conditional Element
   *
   * @param context The current build context
   * @param utils The current build utils instance
   * @param patternBuilder not used by EvalBuilder
   * @param descr The Eval Descriptor to build the eval conditional element from
   * @return the Eval Conditional Element
   */
  public RuleConditionElement build(
      final RuleBuildContext context, final BaseDescr descr, final Pattern prefixPattern) {
    // it must be an EvalDescr
    final EvalDescr evalDescr = (EvalDescr) descr;

    final String className = "eval" + context.getNextId();

    evalDescr.setClassMethodName(className);

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

    AnalysisResult analysis =
        context
            .getDialect()
            .analyzeExpression(
                context,
                evalDescr,
                evalDescr.getContent(),
                new BoundIdentifiers(
                    context.getDeclarationResolver().getDeclarationClasses(decls),
                    context.getPackageBuilder().getGlobals()));
    final BoundIdentifiers usedIdentifiers = analysis.getBoundIdentifiers();

    final Declaration[] declarations = decls.values().toArray(new Declaration[decls.size()]);
    Arrays.sort(declarations, SortDeclarations.instance);

    final EvalCondition eval = new EvalCondition(declarations);

    final Map map =
        createVariableContext(
            className,
            (String) evalDescr.getContent(),
            context,
            declarations,
            null,
            usedIdentifiers.getGlobals(),
            null);

    generatTemplates("evalMethod", "evalInvoker", context, className, map, eval, descr);

    return eval;
  }
Example #4
0
  /**
   * Analyze an expression.
   *
   * @param expr The expression to analyze.
   * @param availDecls Total set of declarations available.
   * @return The <code>Set</code> of declarations used by the expression.
   * @throws RecognitionException If an error occurs in the parser.
   */
  public MVELAnalysisResult analyzeExpression(
      final PackageBuildContext context,
      final String expr,
      final BoundIdentifiers availableIdentifiers,
      final Map<String, Class<?>> localTypes) {
    MVELAnalysisResult result = null;
    if (expr.trim().length() > 0) {
      MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL = true;
      MVELDialect dialect = (MVELDialect) context.getDialect("mvel");

      // creating a reusable parser configuration
      ParserConfiguration conf = new ParserConfiguration();
      conf.setImports(dialect.getImports());
      conf.setPackageImports((HashSet) dialect.getPackgeImports());

      conf.setClassLoader(context.getPackageBuilder().getRootClassLoader());

      // first compilation is for verification only
      // @todo proper source file name
      final ParserContext parserContext1 = new ParserContext(conf);
      if (localTypes != null) {
        for (Entry entry : localTypes.entrySet()) {
          parserContext1.addInput((String) entry.getKey(), (Class) entry.getValue());
        }
      }
      if (availableIdentifiers.getThisClass() != null) {
        parserContext1.addInput("this", availableIdentifiers.getThisClass());
      }

      parserContext1.setStrictTypeEnforcement(false);
      parserContext1.setStrongTyping(false);
      parserContext1.setInterceptors(dialect.getInterceptors());
      Class returnType = null;

      try {
        returnType = MVEL.analyze(expr, parserContext1);
      } catch (Exception e) {
        context
            .getErrors()
            .add(
                new DescrBuildError(
                    context.getParentDescr(),
                    null,
                    null,
                    "Unable to Analyse Expression " + expr + ":\n" + e.getMessage()));
        return null;
      }

      Set<String> requiredInputs = new HashSet();
      requiredInputs.addAll(parserContext1.getInputs().keySet());
      HashMap<String, Class<?>> variables =
          (HashMap<String, Class<?>>) ((Map) parserContext1.getVariables());

      // MVEL includes direct fields of context object in non-strict mode. so we need to strip those
      if (availableIdentifiers.getThisClass() != null) {
        for (Iterator<String> it = requiredInputs.iterator(); it.hasNext(); ) {
          if (PropertyTools.getFieldOrAccessor(availableIdentifiers.getThisClass(), it.next())
              != null) {
            it.remove();
          }
        }
      }

      // now, set the required input types and compile again
      final ParserContext parserContext2 = new ParserContext(conf);
      parserContext2.setStrictTypeEnforcement(true);
      parserContext2.setStrongTyping(true);
      parserContext2.setInterceptors(dialect.getInterceptors());

      if (context.isTypesafe()) {
        if (localTypes != null) {
          for (Entry<String, Class<?>> entry : localTypes.entrySet()) {
            parserContext2.addInput(entry.getKey(), entry.getValue());
          }
        }

        for (String str : requiredInputs) {
          Class cls = availableIdentifiers.getDeclarations().get(str);
          if (cls != null) {
            parserContext2.addInput(str, cls);
            continue;
          }

          if (cls == null) {
            cls = availableIdentifiers.getGlobals().get(str);
            if (cls != null) {
              parserContext2.addInput(str, cls);
              continue;
            }
          }

          if (cls == null) {
            if (str.equals("drools")) {
              parserContext2.addInput("drools", KnowledgeHelper.class);
            } else if (str.equals("kcontext")) {
              parserContext2.addInput("kcontext", RuleContext.class);
            }
            if (str.equals("rule")) {
              parserContext2.addInput("rule", Rule.class);
            }
          }
        }

        if (availableIdentifiers.getThisClass() != null) {
          parserContext2.addInput("this", availableIdentifiers.getThisClass());
        }

        try {
          returnType = MVEL.analyze(expr, parserContext2);
        } catch (Exception e) {
          context
              .getErrors()
              .add(
                  new DescrBuildError(
                      context.getParentDescr(),
                      null,
                      null,
                      "Unable to Analyse Expression " + expr + ":\n" + e.getMessage()));
          return null;
        }

        requiredInputs = new HashSet();
        requiredInputs.addAll(parserContext2.getInputs().keySet());
        requiredInputs.addAll(variables.keySet());
        variables = (HashMap<String, Class<?>>) ((Map) parserContext2.getVariables());
      }

      result = analyze(requiredInputs, availableIdentifiers);

      result.setReturnType(returnType);

      result.setMvelVariables(variables);
    } else {
      result = analyze((Set<String>) Collections.EMPTY_SET, availableIdentifiers);
      result.setMvelVariables(new HashMap<String, Class<?>>());
    }
    return result;
  }
Example #5
0
  /**
   * Builds and returns an Eval Conditional Element
   *
   * @param context The current build context
   * @param utils The current build utils instance
   * @param patternBuilder not used by EvalBuilder
   * @param descr The Eval Descriptor to build the eval conditional element from
   * @return the Eval Conditional Element
   */
  public RuleConditionElement build(
      final RuleBuildContext context, final BaseDescr descr, final Pattern prefixPattern) {
    boolean typesafe = context.isTypesafe();
    // it must be an EvalDescr
    final EvalDescr evalDescr = (EvalDescr) descr;

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

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

      AnalysisResult analysis =
          context
              .getDialect()
              .analyzeExpression(
                  context,
                  evalDescr,
                  evalDescr.getContent(),
                  new BoundIdentifiers(
                      context.getDeclarationResolver().getDeclarationClasses(decls),
                      context.getPackageBuilder().getGlobals()));

      final BoundIdentifiers usedIdentifiers = analysis.getBoundIdentifiers();
      int i = usedIdentifiers.getDeclrClasses().keySet().size();
      Declaration[] previousDeclarations = new Declaration[i];
      i = 0;
      for (String id : usedIdentifiers.getDeclrClasses().keySet()) {
        previousDeclarations[i++] = decls.get(id);
      }
      Arrays.sort(previousDeclarations, SortDeclarations.instance);

      MVELCompilationUnit unit =
          dialect.getMVELCompilationUnit(
              (String) evalDescr.getContent(),
              analysis,
              previousDeclarations,
              null,
              null,
              context,
              "drools",
              KnowledgeHelper.class,
              false);
      final EvalCondition eval = new EvalCondition(previousDeclarations);

      MVELEvalExpression expr = new MVELEvalExpression(unit, dialect.getId());
      eval.setEvalExpression(expr);

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

      expr.compile(data);
      return eval;
    } catch (final Exception e) {
      copyErrorLocation(e, evalDescr);
      context.addError(
          new DescrBuildError(
              context.getParentDescr(),
              evalDescr,
              e,
              "Unable to build expression for 'eval':"
                  + e.getMessage()
                  + " '"
                  + evalDescr.getContent()
                  + "'"));
      return null;
    } finally {
      context.setTypesafe(typesafe);
    }
  }
  @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 =
          context.getDeclarationResolver().getDeclarationClasses(decls);
      declarationClasses.putAll(
          context.getDeclarationResolver().getDeclarationClasses(sourceOuterDeclr));

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

      Accumulator[] accumulators = null;

      final boolean readLocalsFromTuple =
          PackageBuilderUtil.isReadLocalsFromTuple(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,
                source,
                dialect,
                decls,
                sourceOuterDeclr,
                boundIds,
                readLocalsFromTuple);
      }

      final Accumulate accumulate =
          new Accumulate(source, null, accumulators, accumDescr.isMultiFunction());

      MVELDialectRuntimeData data =
          (MVELDialectRuntimeData)
              context.getPkg().getDialectRuntimeRegistry().getDialectData("mvel");
      int index = 0;
      for (Accumulator accumulator : accumulators) {
        data.addCompileable(accumulate.new Wirer(index++), (MVELCompileable) accumulator);
        ((MVELCompileable) accumulator).compile(data);
      }

      return accumulate;
    } catch (Exception e) {
      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);
    }
  }