/** * Walks up the containment hierarchy to find an EObject that is able to hold (contain) the given * object. */ protected EObject findHookParent( EObject container, EClass startClass, org.emftext.language.xpath3.resource.xpath3.mopp.Xpath3ContainedFeature currentLink, EObject object) { EClass containerClass = currentLink.getContainerClass(); while (container != null) { if (containerClass.isInstance(object)) { if (startClass.equals(container.eClass())) { return container; } } container = container.eContainer(); } return null; }
protected EObject findCorrectContainer( org.emftext.language.xpath3.resource.xpath3.mopp.Xpath3ExpectedTerminal expectedTerminal) { EObject container = expectedTerminal.getContainer(); EClass ruleMetaclass = expectedTerminal.getTerminal().getRuleMetaclass(); if (ruleMetaclass.isInstance(container)) { // container is correct for expected terminal return container; } // the container is wrong EObject parent = null; EObject previousParent = null; EObject correctContainer = null; EObject hookableParent = null; org.emftext.language.xpath3.resource.xpath3.grammar.Xpath3ContainmentTrace containmentTrace = expectedTerminal.getContainmentTrace(); EClass startClass = containmentTrace.getStartClass(); org.emftext.language.xpath3.resource.xpath3.mopp.Xpath3ContainedFeature currentLink = null; org.emftext.language.xpath3.resource.xpath3.mopp.Xpath3ContainedFeature previousLink = null; org.emftext.language.xpath3.resource.xpath3.mopp.Xpath3ContainedFeature[] containedFeatures = containmentTrace.getPath(); for (int i = 0; i < containedFeatures.length; i++) { currentLink = containedFeatures[i]; if (i > 0) { previousLink = containedFeatures[i - 1]; } EClass containerClass = currentLink.getContainerClass(); hookableParent = findHookParent(container, startClass, currentLink, parent); if (hookableParent != null) { // we found the correct parent break; } else { previousParent = parent; parent = containerClass.getEPackage().getEFactoryInstance().create(containerClass); if (parent != null) { if (previousParent == null) { // replace container for expectedTerminal with correctContainer correctContainer = parent; } else { // This assignment is only performed to get rid of a warning about a potential // null pointer access. Variable 'previousLink' cannot be null here, because it is // initialized for all loop iterations where 'i' is greather than 0 and for the // case where 'i' equals zero, this path is never executed, because // 'previousParent' is null in this case. org.emftext.language.xpath3.resource.xpath3.mopp.Xpath3ContainedFeature link = previousLink; org.emftext.language.xpath3.resource.xpath3.util.Xpath3EObjectUtil.setFeature( parent, link.getFeature(), previousParent, false); } } } } if (correctContainer == null) { correctContainer = container; } if (currentLink == null) { return correctContainer; } hookableParent = findHookParent(container, startClass, currentLink, parent); final EObject finalHookableParent = hookableParent; final EStructuralFeature finalFeature = currentLink.getFeature(); final EObject finalParent = parent; if (parent != null && hookableParent != null) { expectedTerminal.setAttachmentCode( new Runnable() { public void run() { org.emftext.language.xpath3.resource.xpath3.util.Xpath3EObjectUtil.setFeature( finalHookableParent, finalFeature, finalParent, false); } }); } return correctContainer; }