/**
  * Sets the delayed reference.
  *
  * @param reference the reference
  * @param modelAdapter the model handler
  * @param contextByElement the context by element
  * @return <code>true</code> if the reference was resolved successfully, <code>false</code> else.
  * @throws ModelAdapterException the model handler exception
  * @throws ModelElementCreationException
  */
 @Override
 public boolean setDelayedReference(
     DelayedReference reference,
     IModelAdapter modelAdapter,
     ContextManager contextManager,
     ObservableInjectingParser parser)
     throws ModelAdapterException, ModelElementCreationException {
   Object contextElement = reference.getContextElement();
   if (contextElement instanceof IModelElementProxy) {
     IModelElementProxy proxyContext = (IModelElementProxy) contextElement;
     contextElement = proxyContext.getRealObject();
   }
   return setDelayedReferenceWithPredicate(
       reference, modelAdapter, contextManager, contextElement, parser);
 }
  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);
    }
  }