private String computeRuleName(
      ObservableInjectingParser parser,
      Object singleForeachResult,
      PredicateSemantic activePredicateSemantic,
      String mode,
      IRuleName ruleNameFinder)
      throws SyntaxElementException {
    String ruleName = null;
    if (activePredicateSemantic == null) {
      // no matching when/as combination; perform default handling:
      if (singleForeachResult instanceof EObject) {
        EClass foreachElementType = ((EObject) singleForeachResult).eClass();
        // get the template

        Template tmpl =
            TcsUtil.findTemplate(
                foreachElementType,
                mode,
                Collections.singletonList(URI.createURI(parser.getSyntaxUUID())));
        // get the rule name from the template
        ruleName = ruleNameFinder.getRuleName(tmpl, mode);
      } else {
        // handle the base types
        if (!(singleForeachResult instanceof String) || !(singleForeachResult instanceof Number)) {
          throw new IllegalArgumentException(
              "The OCL element "
                  + singleForeachResult
                  + " cannot be used, as it is neither of type String nor a Number");
        }
      }
    } else {
      ruleName = activePredicateSemantic.getAs();
    }
    return ruleName;
  }
  private ModelElementProxy produceSingleForeachUsingParserRule(
      ObservableInjectingParser parser, DelayedReference reference, Object next, String ruleName)
      throws NoSuchMethodException, UnknownProductionRuleException, IllegalAccessException,
          InvocationTargetException, ModelElementCreationException {
    // invoke the parser to execute the template
    Method methodToCall = parser.getClass().getMethod(ruleName);
    // parser.reset();
    if (!Modifier.isFinal(methodToCall.getModifiers())) {
      throw new UnknownProductionRuleException(
          ruleName + " is not a production rule in generated Parser.");
    }
    boolean originalResolveProxiesValue = parser.isResolveProxies();
    parser.setResolveProxies(false);
    DelegationParsingObserver delegator = new DelegationParsingObserver();
    IParsingObserver originalObserver = parser.getObserver();
    if (originalObserver != null) {
      delegator.addParsingObserver(originalObserver);
    }
    delegator.addParsingObserver(new ForeachParsingObserver((TextBlock) reference.getTextBlock()));
    parser.setObserver(delegator);

    IModelElementProxy proxyForContextElement = null;
    if (reference.getContextElement() instanceof IModelElementProxy) {
      proxyForContextElement = (IModelElementProxy) reference.getContextElement();
    } else {
      proxyForContextElement = new ResolvedModelElementProxy(reference.getContextElement());
    }
    parser.setCurrentForeachElement(next);
    if (parser.getContextManager().getContextForElement(reference.getContextElement()) == null) {
      parser.addContext(proxyForContextElement);
      if (proxyForContextElement.getRealObject() != null
          && reference.getContextElement() instanceof EObject) {
        parser
            .getContextManager()
            .notifyProxyResolvedWith(
                proxyForContextElement,
                reference.getContextElement(),
                /*
                 * no creation context element needs to be provided here because the proxy has just been created and has not been
                 * added to any other context
                 */
                null);
      }
    } else {
      parser
          .getCurrentContextStack()
          .push(proxyForContextElement); // the Context object was already created elsewhere
    }
    try {
      ModelElementProxy parseReturn = (ModelElementProxy) methodToCall.invoke(parser);
      if (parseReturn == null) {
        throw new ModelElementCreationException(
            "Unable to create model element using parse rule "
                + ruleName
                + ". Parse errors: "
                + parser.getInjector().getErrorList());
      }
      return parseReturn;
    } finally {
      parser.getCurrentContextStack().pop();
      parser.setObserver(originalObserver);
      parser.setResolveProxies(originalResolveProxiesValue);
    }
  }
  private boolean setDelayedReferenceWithPredicate(
      DelayedReference reference,
      IModelAdapter modelAdapter,
      ContextManager contextManager,
      Object contextElement,
      ObservableInjectingParser parser)
      throws ModelAdapterException {
    try {
      contextElement =
          DelayedReferencesHelper.getNavigatedContextElementFromReference(
              reference, modelAdapter, contextManager, contextElement);

      // when the element is a Proxy resolve it first
      resolveModelElementProxy(reference, modelAdapter);
      if (reference.getOclQuery() == null) {
        parser
            .getInjector()
            .addError(new ParsingError("You must specify an OCL query.", reference.getToken()));
        return false;
      }
      Collection<?> result =
          DelayedReferencesHelper.evaluateForeachOcl(
              (EObject) reference.getModelElement(), reference, modelAdapter, contextElement);
      List<ForeachProductionResult> producedResults = new ArrayList<ForeachProductionResult>();
      // loop over the results to handle them one by one,
      // delete all elements that were created by this foreach but are
      // not valid anymore
      String mode = reference.getMode();
      IRuleName ruleNameFinder = reference.getRuleNameFinder();
      for (Object singleForeachResult : result) {
        if (!(singleForeachResult instanceof Boolean)
            || ((Boolean) singleForeachResult).booleanValue()) {
          // look if there are possible when/as constructs
          PredicateSemantic activePredicateSemantic =
              getActivePredicateFromWhenAsClauses(
                  reference, modelAdapter, contextElement, singleForeachResult);
          Template templateUsedForProduction =
              getTemplateFromPredicateSemantic(activePredicateSemantic, reference);
          // TODO it would be nice to compute the rule name from the template; however, if no
          // textblocks are being produced, the reference doesn't have the link to the
          // ForeachPropertyInit set, so the template can't be determined and isn't passed in by the
          // parser run; only the rule name is passed
          String parserRuleNameToUseForProduction =
              computeRuleName(
                  parser, singleForeachResult, activePredicateSemantic, mode, ruleNameFinder);
          if (parserRuleNameToUseForProduction == null) {
            throw new UnknownProductionRuleException(
                "At least one as parameter is needed in that case.");
          }
          ModelElementProxy foreachTargetElement =
              produceForOneForeachResult(
                  reference,
                  modelAdapter,
                  contextElement,
                  parser,
                  singleForeachResult,
                  activePredicateSemantic,
                  parserRuleNameToUseForProduction);
          ForeachProductionResult resultObject =
              new ForeachProductionResult(
                  foreachTargetElement, templateUsedForProduction, singleForeachResult);
          producedResults.add(resultObject);
        }
      }
      setReferenceAndUpdateForeachContexts(
          reference, modelAdapter, parser.getInjector(), producedResults);
    } catch (Exception e) {
      parser.getInjector().addError(new ParsingError(e.getMessage(), reference.getToken()));
      return false;
    }
    return true;
  }