Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/DependencyAnalysisHelper.java')
-rw-r--r--extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/DependencyAnalysisHelper.java392
1 files changed, 392 insertions, 0 deletions
diff --git a/extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/DependencyAnalysisHelper.java b/extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/DependencyAnalysisHelper.java
new file mode 100644
index 00000000000..a6638c6e7a5
--- /dev/null
+++ b/extraplugins/migration/org.eclipse.papyrus.migration.rsa/src/org/eclipse/papyrus/migration/rsa/transformation/DependencyAnalysisHelper.java
@@ -0,0 +1,392 @@
+/*****************************************************************************
+ * Copyright (c) 2015 CEA LIST.
+ *
+ * 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:
+ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
+ *****************************************************************************/
+package org.eclipse.papyrus.migration.rsa.transformation;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.eclipse.emf.ecore.xml.type.AnyType;
+import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
+import org.eclipse.papyrus.migration.rsa.RSAToPapyrusParameters.Config;
+import org.eclipse.papyrus.migration.rsa.RSAToPapyrusParameters.RSAToPapyrusParametersFactory;
+import org.eclipse.papyrus.migration.rsa.RSAToPapyrusParameters.URIMapping;
+import org.eclipse.papyrus.uml.extensionpoints.library.IRegisteredLibrary;
+import org.eclipse.papyrus.uml.extensionpoints.library.RegisteredLibrary;
+import org.eclipse.papyrus.uml.extensionpoints.profile.IRegisteredProfile;
+import org.eclipse.papyrus.uml.extensionpoints.profile.RegisteredProfile;
+import org.eclipse.uml2.uml.Element;
+
+import com.google.common.collect.Sets;
+
+public class DependencyAnalysisHelper {
+
+ protected final Config config;
+
+ protected final static Set<String> rsaExtensions = Sets.newHashSet("emx", "efx"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ protected final static String rsaProfileExtension = "epx"; //$NON-NLS-1$
+
+ // ResourceSet used to load and explore Static Libraries
+ protected final ResourceSet localResourceSet = new ResourceSetImpl();
+
+ // Store the broken URIs without trying to resolve them. We don't have enough information to resolve them during the first phase of the model import
+ // The Key is the resource URI, the value is the Set of each individual EObject Fragment (We need the EObject fragments to find potential matches)
+ protected final Map<URI, Set<String>> brokenUris = new HashMap<URI, Set<String>>();
+
+ protected final Set<URI> brokenProfiles = new HashSet<URI>();
+
+ public DependencyAnalysisHelper(Config config) {
+ this.config = config;
+
+ configureResourceSet();
+ }
+
+ protected void configureResourceSet() {
+ localResourceSet.getLoadOptions().put(XMLResource.OPTION_DEFER_ATTACHMENT, true);
+ localResourceSet.getLoadOptions().put(XMLResource.OPTION_DEFER_IDREF_RESOLUTION, true);
+ localResourceSet.getLoadOptions().put(XMLResource.OPTION_RECORD_UNKNOWN_FEATURE, Boolean.TRUE);
+ localResourceSet.getLoadOptions().put(XMLResource.OPTION_USE_PACKAGE_NS_URI_AS_LOCATION, Boolean.FALSE);
+ }
+
+ protected void unloadResourceSet() {
+ EMFHelper.unload(localResourceSet);
+ }
+
+ public void computeURIMappings(Collection<Resource> sourceModels) {
+ for (Resource sourceModel : sourceModels) {
+ doComputeURIMappings(sourceModel);
+ }
+ }
+
+ public synchronized void resolveAllMappings(Map<URI, URI> urisToReplace, Map<URI, URI> profileUrisToReplace) {
+ if (config.getMappingParameters() == null) {
+ config.setMappingParameters(RSAToPapyrusParametersFactory.eINSTANCE.createMappingParameters());
+ }
+
+ try {
+ for (Entry<URI, Set<String>> resourceToRepair : brokenUris.entrySet()) {
+
+ // Already known mapping
+ if (urisToReplace.containsKey(resourceToRepair.getKey())) {
+ continue;
+ }
+ findMatch(resourceToRepair.getKey(), resourceToRepair.getValue());
+ }
+
+ for (URI profileDefinition : brokenProfiles) {
+
+ // Already known mapping
+ if (profileUrisToReplace.containsKey(profileDefinition.trimFragment().trimQuery())) {
+ continue;
+ }
+ findMatch(profileDefinition);
+ }
+ } finally {
+ unloadResourceSet();
+ brokenUris.clear();
+ brokenProfiles.clear();
+ }
+ }
+
+ protected void findMatch(URI resourceURI, Set<String> fragments) {
+ URIMapping mapping = null;
+
+ for (String fragment : fragments) {
+ URI eObjectURI = resourceURI.appendFragment(fragment);
+ mapping = findExistingMapping(eObjectURI, localResourceSet);
+
+ if (mapping != null) {
+ break;
+ }
+ }
+
+ if (mapping == null) {
+ mapping = RSAToPapyrusParametersFactory.eINSTANCE.createURIMapping();
+ mapping.setSourceURI(resourceURI.toString());
+ mapping.setTargetURI(mapping.getSourceURI());
+ }
+
+ config.getMappingParameters().getUriMappings().add(mapping);
+ }
+
+ protected void findMatch(URI profileDefinitionURI) {
+ URIMapping match = findExistingProfileMapping(profileDefinitionURI, localResourceSet);
+
+ if (match == null) {
+ match = RSAToPapyrusParametersFactory.eINSTANCE.createURIMapping();
+ match.setSourceURI(profileDefinitionURI.trimFragment().trimQuery().toString());
+ match.setTargetURI(match.getSourceURI());
+ }
+
+ config.getMappingParameters().getProfileUriMappings().add(match);
+ }
+
+ protected void doComputeURIMappings(Resource sourceModel) {
+ doComputeProfileURIMappings(sourceModel);
+
+ TreeIterator<EObject> resourceContents = sourceModel.getAllContents();
+ ResourceSet resourceSet = sourceModel.getResourceSet();
+
+ while (resourceContents.hasNext()) {
+ EObject next = resourceContents.next();
+ for (EReference reference : next.eClass().getEAllReferences()) {
+ if (reference.isContainer() || reference.isContainment() || reference.isDerived() || reference.isTransient()) {
+ continue;
+ }
+
+ Object value = next.eGet(reference);
+ if (value instanceof EObject) {
+ handleURIMapping((EObject) value, resourceSet);
+ } else if (value instanceof Collection<?>) {
+ for (Object element : (Collection<?>) value) {
+ if (element instanceof EObject) {
+ handleURIMapping((EObject) element, resourceSet);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ protected void doComputeProfileURIMappings(Resource sourceModel) {
+ ResourceSet resourceSet = sourceModel.getResourceSet();
+
+ for (EObject rootObject : sourceModel.getContents()) {
+ if (isInvalidStereotypeApplication(rootObject)) {
+ handleProfileURIMapping(rootObject, resourceSet);
+ }
+ }
+ }
+
+ protected boolean isInvalidStereotypeApplication(EObject eObject) {
+ if (eObject instanceof Element) {
+ return false;
+ }
+
+ // The package is not resolved: probably a missing profile
+ if (eObject instanceof AnyType) {
+ return true;
+ }
+
+ // If the package is resolved but is contained in an EPX resource, it needs to be mapped to the Papyrus equivalent
+ EPackage ePackage = eObject.eClass().getEPackage();
+ if ("epx".equals(ePackage.eResource().getURI().fileExtension())) {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected boolean isRSAModelElement(EObject eObject) {
+ return isRSAModelElement(EcoreUtil.getURI(eObject));
+ }
+
+ protected boolean isRSAModelElement(URI objectURI) {
+ String fileExtension = objectURI.fileExtension();
+ return rsaExtensions.contains(fileExtension) || rsaProfileExtension.equals(fileExtension);
+ }
+
+ protected synchronized Set<String> getFragments(URI resourceURI) {
+ if (!brokenUris.containsKey(resourceURI)) {
+ brokenUris.put(resourceURI, new HashSet<String>());
+ }
+
+ return brokenUris.get(resourceURI);
+ }
+
+ protected synchronized void handleBrokenReference(EObject proxy) {
+ URI proxyURI = EcoreUtil.getURI(proxy);
+ URI resourceURI = proxyURI.trimFragment().trimQuery();
+
+ String fragment = proxyURI.fragment();
+ Set<String> fragments = getFragments(resourceURI);
+ fragments.add(fragment);
+ }
+
+ protected synchronized void addBrokenProfileDefinition(URI packageURI) {
+ brokenProfiles.add(packageURI);
+ }
+
+
+ protected void handleProfileURIMapping(EObject stereotypeApplication, ResourceSet resourceSet) {
+
+ EPackage profileDefinition = stereotypeApplication.eClass().getEPackage();
+ URI packageURI = EcoreUtil.getURI(profileDefinition);
+ if (packageURI.trimFragment().isEmpty()) {
+ packageURI = URI.createURI(profileDefinition.getNsURI());
+ }
+ addBrokenProfileDefinition(packageURI);
+
+ }
+
+ protected void handleURIMapping(EObject eObject, ResourceSet resourceSet) {
+
+ if (isRSAModelElement(eObject)) {
+ handleBrokenReference(eObject);
+ return;
+ }
+
+ if (eObject.eIsProxy()) {
+ eObject = EcoreUtil.resolve(eObject, resourceSet);
+ if (eObject.eIsProxy()) {
+ handleBrokenReference(eObject);
+ return;
+ }
+ }
+
+ }
+
+ protected URIMapping findExistingProfileMapping(URI profileDefinitionURI, ResourceSet resourceSet) {
+
+ String fileExtension = profileDefinitionURI.fileExtension();
+
+ URIMapping mapping = RSAToPapyrusParametersFactory.eINSTANCE.createURIMapping();
+ URI sourceURI = profileDefinitionURI.trimFragment().trimQuery();
+ mapping.setSourceURI(sourceURI.toString());
+
+ URI targetURI = null;
+
+ if ("epx".equals(fileExtension)) {
+ targetURI = sourceURI.trimFileExtension().appendFileExtension("profile").appendFileExtension("uml");
+ try {
+ Resource resource = resourceSet.getResource(targetURI, true);
+ if (resource != null && !resource.getContents().isEmpty()) {
+ mapping.setTargetURI(targetURI.toString());
+ return mapping;
+ }
+ } catch (Exception ex) {
+ // Ignore: we can't find the target resource
+ }
+ }
+
+ return findExistingMapping(profileDefinitionURI, resourceSet);
+ }
+
+ protected URIMapping findExistingMapping(URI proxyURI, ResourceSet resourceSet) {
+ String fileExtension = proxyURI.fileExtension();
+
+ URIMapping mapping = RSAToPapyrusParametersFactory.eINSTANCE.createURIMapping();
+ mapping.setSourceURI(proxyURI.trimFragment().trimQuery().toString());
+
+ URI targetURI = null;
+ // Maybe the element has been migrated locally
+ if (rsaExtensions.contains(fileExtension)) {
+ targetURI = proxyURI.trimFileExtension().appendFileExtension("uml");
+ } else if (rsaProfileExtension.equals(fileExtension)) {
+ targetURI = proxyURI.trimFileExtension().appendFileExtension("profile.uml");
+ }
+
+ if (targetURI != null) {
+ try {
+ EObject targetElement = resourceSet.getEObject(targetURI, true);
+ if (targetElement != null) {
+
+ targetURI = EcoreUtil.getURI(targetElement);
+
+ mapping.setTargetURI(targetURI.trimFragment().trimQuery().toString());
+
+ return mapping;
+ }
+ } catch (Exception ex) {
+ // Ignore: we can't find a target element for the given proxy
+ }
+ }
+
+
+ if (!isRSAModelElement(proxyURI)) {
+ // Maybe the resource exists, but doesn't contain this specific element
+ URI resourceURI = proxyURI.trimFragment().trimQuery();
+ try {
+ Resource resource = resourceSet.getResource(resourceURI, true);
+ if (resource != null && !resource.getContents().isEmpty()) {
+
+ mapping.setTargetURI(resourceURI.toString());
+
+ return mapping;
+ }
+ } catch (Exception ex) {
+ // Ignore: we can't find the target resource
+ }
+ }
+
+ // If the URI fragment is a path, don't explore registered libraries/profiles: almost all libraries will
+ // have a matching element, although there is no specific correspondence
+ if (isPathFragment(proxyURI)) {
+ return null;
+ }
+
+ // Otherwise, we have an ID fragment
+
+ // Maybe the resource has already been migrated, then deployed as a static library. Browse all registered libraries and try to find a matching XMI ID
+ for (IRegisteredLibrary library : RegisteredLibrary.getRegisteredLibraries()) {
+ URI libraryURI = library.getUri();
+ try {
+ Resource libraryResource = localResourceSet.getResource(libraryURI, true);
+ if (libraryResource != null) {
+ EObject resolvedElement = libraryResource.getEObject(proxyURI.fragment());
+ if (resolvedElement != null && !resolvedElement.eIsProxy()) {
+ mapping.setTargetURI(libraryURI.toString());
+
+ return mapping;
+ }
+ }
+ } catch (Exception ex) {
+ // Ignore
+ }
+ }
+
+ // Maybe the object is a Profile, so let's browse registered profiles as well
+ for (IRegisteredProfile profile : RegisteredProfile.getRegisteredProfiles()) {
+ URI profileURI = profile.getUri();
+ try {
+ Resource profileResource = localResourceSet.getResource(profileURI, true);
+ if (profileResource != null) {
+ EObject resolvedElement = profileResource.getEObject(proxyURI.fragment());
+ if (resolvedElement != null && !resolvedElement.eIsProxy()) {
+ mapping.setTargetURI(profileURI.toString());
+
+ return mapping;
+ }
+ }
+ } catch (Exception ex) {
+ // Ignore
+ }
+ }
+
+ return null;
+ }
+
+ protected boolean isPathFragment(URI proxyURI) {
+ String uriFragment = proxyURI.fragment();
+
+ return uriFragment != null && uriFragment.charAt(0) == '/';
+ }
+
+ protected URIMapping findExistingMapping(EObject proxy, ResourceSet resourceSet) {
+ URI proxyURI = EcoreUtil.getURI(proxy);
+ return findExistingMapping(proxyURI, resourceSet);
+ }
+}

Back to the top