package com.sap.furcas.runtime.parser.textblocks; import java.util.Stack; import org.eclipse.emf.ecore.EObject; import com.sap.furcas.metamodel.FURCAS.TCS.ContextTags; import com.sap.furcas.metamodel.FURCAS.TCS.ContextTemplate; import com.sap.furcas.metamodel.FURCAS.TCS.Template; import com.sap.furcas.metamodel.FURCAS.textblocks.DocumentNode; import com.sap.furcas.metamodel.FURCAS.textblocks.TextBlock; import com.sap.furcas.runtime.common.implementation.ResolvedModelElementProxy; import com.sap.furcas.runtime.parser.impl.ContextBuilder; public class TbParsingUtil { /** * Starting at the text block <tt>fromHereOutwards</tt> constructs a context stack using the <tt>contextBuilder</tt> * . Ascends the text block structure, and each block that was created by a "context" template will add a context * using the <tt>contextBuilder</tt>. The context contents created by <tt>addToContext</tt> templates will * <em>not</em> be added to these contexts here. * * @param fromHereOutwards * the first block checked for belonging to a {@link ContextTemplate} with * <code>{@link ContextTemplate#isIsContext()}==true</code>. It is permissible * to pass <code>null</code> turning the call into a no-op. * @param contextBuilder * the contexts discovered starting from <code>fromHereOutwards</code> (inclusive) are * {@link ContextBuilder#addContext(com.sap.furcas.runtime.common.interfaces.IModelElementProxy, String...) * added} to this context builder. All elements <em>in</em> those contexts (see * {@link TextBlock#getElementsInContext()}) are {@link ContextBuilder#addToCurrentContext(Object) added} * to their respective contexts on this context builder. */ public static void constructContext(DocumentNode fromHereOutwards, ContextBuilder contextBuilder) { TextBlock parentBlock = fromHereOutwards == null ? null : fromHereOutwards instanceof TextBlock ? (TextBlock) fromHereOutwards : fromHereOutwards.getParent(); Stack<TextBlock> contextStack = new Stack<TextBlock>(); while (parentBlock != null) { if (parentBlock.getType() != null) { Template template = parentBlock.getType(); if ((template instanceof ContextTemplate && ((ContextTemplate) template).isIsContext())) { contextStack.push(parentBlock); } } parentBlock = parentBlock.getParent(); } while (!contextStack.isEmpty()) { TextBlock t = contextStack.pop(); ContextTags tags = null; Template template = t.getType(); if (template instanceof ContextTemplate) { tags = ((ContextTemplate) template).getContextTags(); } if (tags != null) { for (EObject element : t.getCorrespondingModelElements()) { contextBuilder.addContext(new ResolvedModelElementProxy(element), tags.getTags() .toArray(new String[0])); } } else { // The correspondingModelElements not only contain the element produced by t's // parseRule but also those produced by other templates and foreach property inits // TODO When there is more than one element in the correspondingModelElements, decide whether additionalTemplate or template used by foreach-propinit hasContext if (!t.getCorrespondingModelElements().isEmpty()) { // FIXME I saw a case where the iterator did not produce any elements! // FIXME ...and I saw a case where additional correspondingModelElements were produced by additionalTemplates or foreach propinits that are not context // currently, only the first correspondingModelElement is used because only it was created by the parseRule contextBuilder.addContext(new ResolvedModelElementProxy(t.getCorrespondingModelElements().iterator().next())); } } for (EObject elementInContext : t.getElementsInContext()) { contextBuilder.addToCurrentContext(new ResolvedModelElementProxy(elementInContext)); } } } }