blob: 6c8eecb033cf6137a882bc0fecd2f975097b3dfd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 Christian W. Damus and others.
* 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:
* Christian W. Damus - initial API and implementation
*
*******************************************************************************/
package org.eclipse.mdht.uml.validation.internal.provider;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.mdht.uml.validation.ConstraintProvider;
import org.eclipse.mdht.uml.validation.Diagnostic;
import org.eclipse.mdht.uml.validation.internal.ValidationPlugin;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Namespace;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.UMLPlugin;
import org.eclipse.uml2.uml.util.UMLUtil;
import org.osgi.framework.Bundle;
/**
* Utilities for working with the validation profile.
*/
public class ValidationProfileUtil {
private static final String ECORE_EPACKAGE_STEREOTYPE = UMLUtil.PROFILE__ECORE + NamedElement.SEPARATOR +
UMLUtil.STEREOTYPE__E_PACKAGE;
private static final String ECORE_EPACKAGE_NSURI = UMLUtil.TAG_DEFINITION__NS_URI;
private static final Pattern BUNDLE_ID_PATTERN = Pattern.compile("^\\d+");
private ValidationProfileUtil() {
super();
}
public static Diagnostic getDiagnostic(Constraint constraint) {
return getApplication(constraint, Diagnostic.class);
}
public static ConstraintProvider getConstraintProvider(Namespace namespace) {
return getApplication(namespace, ConstraintProvider.class);
}
static <T extends EObject> T getApplication(Element element, java.lang.Class<? extends T> stereotype) {
T result = null;
for (EObject next : element.getStereotypeApplications()) {
if (stereotype.isInstance(next)) {
result = stereotype.cast(next);
break;
}
}
return result;
}
/**
* Finds the profiles applied to a package that are, themselves, profiled by the <tt>Validation</tt> profile.
*
* @param context
* a package
*
* @return its validating profiles, if any
*/
public static Iterable<Profile> getValidatingProfiles(Package context) {
List<Profile> result = new java.util.ArrayList<Profile>(context.getAppliedProfiles().size());
for (Profile next : context.getAppliedProfiles()) {
if (getConstraintProvider(next) != null) {
result.add(next);
}
}
return Collections.unmodifiableCollection(result);
}
/**
* Gets the most appropriate URI converter for the specified {@code context} object.
*
* @param context
* an object
* @return the resource set's URI converter, if the {@code context} is in a resource set; the global converter, otherwise
*/
public static URIConverter getURIConverter(EObject context) {
URIConverter result = URIConverter.INSTANCE;
Resource res = context.eResource();
ResourceSet rset = (res == null)
? null
: res.getResourceSet();
if (rset != null) {
result = rset.getURIConverter();
}
return result;
}
/**
* Finds the Eclipse bundle that registers the specified {@code profile}. It may be registered as a statically-generated profile, or as a dynamic
* profile, but it must be registered.
*
* @param profile
* a profile
*
* @return the bundle ID that registers it, or {@code null} if none
*/
public static String getBundleName(Profile profile) {
// first try the <<constraintProvider>> stereotype to see whether it names a bundle
ConstraintProvider constraintProvider = getConstraintProvider(profile);
String result = (constraintProvider == null)
? null
: constraintProvider.getBundleName();
if (result == null) {
// find the bundle that registers the profile
String nsURI = (String) UMLUtil.getTaggedValue(profile, ECORE_EPACKAGE_STEREOTYPE, ECORE_EPACKAGE_NSURI);
if (nsURI != null) {
URI locationURI = UMLPlugin.getEPackageNsURIToProfileLocationMap().get(nsURI);
if (locationURI != null) {
locationURI = getURIConverter(profile).normalize(locationURI);
if (locationURI.isPlatformPlugin()) {
result = locationURI.segment(1); // segment 0 is "plugin"
} else if ("bundleentry".equals(locationURI.scheme())) {
String bundleID = locationURI.authority();
Matcher m = BUNDLE_ID_PATTERN.matcher(bundleID);
if (m.find()) {
bundleID = m.group();
}
Bundle bundle = ValidationPlugin.getPlugin().getBundle().getBundleContext().getBundle(
Long.parseLong(bundleID));
result = (bundle == null)
? null
: bundle.getSymbolicName();
}
}
}
}
// clean the result
return nullSafeTrim(result, true);
}
public static String nullSafeTrim(String s) {
String result = (s == null)
? s
: s.trim();
return result;
}
public static String nullSafeTrim(String s, boolean preferNull) {
String result = nullSafeTrim(s);
return (preferNull && ((result == null) || (result.length() == 0)))
? null
: result;
}
/**
* Gets all packages transitively imported into some package.
*
* @param package_
* a UML package
*
* @return all of the packages that it imports and that are imported (transitively) by its imports
*/
public static Iterable<Package> getAllImportedPackages(final Package package_) {
final List<Package> result = new java.util.ArrayList<Package>();
Queue<Package> queue = new java.util.LinkedList<Package>(package_.getImportedPackages());
Set<Package> seen = new java.util.HashSet<Package>();
seen.add(package_);
for (Package next = queue.poll(); next != null; next = queue.poll()) {
Package poll = queue.poll();
if (poll == null) {
break; // we're done
} else if (seen.add(poll)) {
// enqueue its imports
queue.addAll(poll.getImportedPackages());
// and add it
result.add(poll);
}
}
;
return Collections.unmodifiableCollection(result);
}
}