/******************************************************************************* * Copyright (c) 2006-2012 * Software Technology Group, Dresden University of Technology * DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026 * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Software Technology Group - TU Dresden, Germany; * DevBoost GmbH - Berlin, Germany * - initial API and implementation ******************************************************************************/ package org.reuseware.coconut.reuseextension.resource.rex.analysis; import java.util.Map; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.util.EcoreUtil; import org.reuseware.coconut.reuseextension.ReuseExtension; import org.reuseware.coconut.reuseextension.RuleContext; import org.reuseware.coconut.reuseextension.resource.rex.IRexReferenceResolveResult; import org.reuseware.coconut.reuseextension.resource.rex.IRexReferenceResolver; /** * Finds the EClass for a rule context in the EPackages referenced by the reuse extension. */ public class RuleContextEBoundClassReferenceResolver implements IRexReferenceResolver<RuleContext, EClass> { /** * Looks for an EClass identified by the given identifier. All packages referenced * in the containing reuse extension are considered. Subpackages are also supported * via '::' notation. * * @param identifier The identifier for the reference. * @param container The object that contains the reference. * @param reference The reference that points to the target of the reference. * @param position The index of the reference (if it has an upper bound greater than 1). * @param resolveFuzzy return objects that do not match exactly * @param result an object that can be sued to store the result of the resolve operation. */ public void resolve(String identifier, RuleContext container, EReference reference, int position, boolean resolveFuzzy, IRexReferenceResolveResult<EClass> result) { EPackage ePackage = null; String eClassName = identifier; EObject eo = container; while (eo != null && !(eo instanceof ReuseExtension)) { eo = eo.eContainer(); } if (eo == null) { return; } ReuseExtension rex = (ReuseExtension) eo; if (eClassName.contains("::")) { //class resides in another package String[] namespaces = eClassName.split("::"); eClassName = namespaces[namespaces.length - 1]; String rootNsPrefix = namespaces[0]; for (EPackage ePackageCand : rex.getEPackages()) { if (ePackageCand.getNsPrefix() != null) { if (ePackageCand.getNsPrefix().equals(rootNsPrefix)) { ePackage = (EPackage) ePackageCand; break; } //try name as alternative to nsPrefix if (ePackageCand.getName().equals(rootNsPrefix)) { ePackage = (EPackage) ePackageCand; } } } if (ePackage == null) { result.setErrorMessage("EPackage '" + rootNsPrefix + "' not found"); return; } //subpackages outer : for (int i = 1; i < namespaces.length - 1; i++) { for (EPackage subPackage : ePackage.getESubpackages()) { if (namespaces[i].equals(subPackage.getNsPrefix())) { ePackage = subPackage; continue outer; } } for (EPackage subPackage : ePackage.getESubpackages()) { //try name as alternative to nsPrefix if (namespaces[i].equals(subPackage.getName())) { ePackage = subPackage; continue outer; } } result.setErrorMessage("Nested EPackage '" + namespaces[i] + "' not found"); return; } } else { EObject rExtension = container; while (!(rExtension instanceof ReuseExtension)) { rExtension = rExtension.eContainer(); } ePackage = ((ReuseExtension) rExtension).getEPackages().get(0); } if (ePackage != null && !ePackage.eIsProxy()) { if (resolveFuzzy) { for (EPackage subPackage : rex.getEPackages()) { collectClassesOfPackage("", subPackage, result); } for (EClassifier eClassifier : ePackage.getEClassifiers()) { if (eClassifier instanceof EClass) { result.addMapping(eClassifier.getName(), (EClass) eClassifier); } } } else { EClassifier eClassifier = ePackage.getEClassifier(eClassName); if (eClassifier instanceof EClass) { result.addMapping(identifier, (EClass) eClassifier); } } } else { result.setErrorMessage("EClass '" + eClassName + "' not declared"); } } private void collectClassesOfPackage(String oldBase, EPackage ePackage, IRexReferenceResolveResult<EClass> result) { String base = oldBase + ePackage.getNsPrefix() + "::"; for (EClassifier eClassifier : ePackage.getEClassifiers()) { if (eClassifier instanceof EClass) { result.addMapping(base + eClassifier.getName(), (EClass) eClassifier); } } for (EPackage subPackage : ePackage.getESubpackages()) { collectClassesOfPackage(base, subPackage, result); } } /** * Returns the full qualified name of the EClass. * * @param element The referenced model element. * @param container The object referencing the element. * @param reference The reference that holds the element. * * @return The identification string for the reference */ public String deResolve(EClass element, RuleContext container, EReference reference) { EObject root = EcoreUtil.getRootContainer(container); if (element.getEPackage() == null || !(root instanceof ReuseExtension)) { return element.getName(); } ReuseExtension reuseExtension = (ReuseExtension) root; String fullPackageName = fullPackageName(element.getEPackage(), reuseExtension); return fullPackageName + element.getName(); } private String fullPackageName(EPackage ePackage, ReuseExtension reuseExtension) { String name = ""; if (ePackage.getESuperPackage() != null) { if (!reuseExtension.getEPackages().contains(ePackage)) { name = fullPackageName(ePackage.getESuperPackage(), reuseExtension); } } name = name + ePackage.getName() + "::"; return name; } /** * @param options not supported */ public void setOptions(Map<?, ?> options) { } }