/*****************************************************************************
* Copyright (c) 2011 Atos Origin.
*
*
* 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:
* Atos Origin - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.controlmode.profile.helpers;
import java.util.Iterator;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.ProfileApplication;
/**
* This helper provides methods to manipulate profile applications on packages.
*
* @author vhemery
*/
public class ProfileApplicationHelper {
/** EAnnotation for duplicated profiles on controlled packages */
public static final String DUPLICATED_PROFILE = "duplicatedProfile";
/**
* Duplicate a profile application on a child package.
*
* @param _package
* package to duplicate profile application on
* @param profile
* profile to apply
*/
public static void duplicateProfileApplication(Package _package, Profile profile) {
if(profile != null && profile.getDefinition() != null) {
if(!isSameProfileApplied(_package, profile)) {
_package.applyProfile(profile);
ProfileApplication profileAppl = _package.getProfileApplication(profile);
if(profileAppl != null) {
markAsDuplicate(profileAppl);
}
}
}
}
/**
* Remove a profile application duplicate on a child package
*
* @param _package
* package to remove duplicated profile application from
* @param profile
* profile to unapply
* @param force
* true when package is no longer controlled for forcing profile application removal
*/
public static void removeProfileApplicationDuplication(Package _package, Profile profile, boolean force) {
if(profile != null && profile.getDefinition() != null) {
if(isSameProfileApplied(_package, profile)) {
ProfileApplication profileAppl = _package.getProfileApplication(profile);
// remove only duplicated profile applications with eannotation
if(isDuplicatedProfileApplication(profileAppl)) {
if(force || getParentPackageWithProfile(_package, profile, false) == null) {
// first remove eannotation to ensure it will not added again by checker
profileAppl.getEAnnotations().remove(profileAppl.getEAnnotation(DUPLICATED_PROFILE));
_package.unapplyProfile(profile);
}
// else, there is another parent profile which justifies the duplication
}
}
}
}
/**
* Check if the profile is applied on a package, or one similar
*
* @param _package
* package to test on
* @param profile
* profile to check
* @return true if a similar profile is applied
*/
private static boolean isSameProfileApplied(Package _package, Profile profile) {
for(Profile prof : _package.getAppliedProfiles()) {
if(prof == null) {
break;
}
if(prof.equals(profile)) {
return true;
}
if(profile.getQualifiedName() != null && profile.getQualifiedName().equals(prof.getQualifiedName())) {
return true;
}
}
return false;
}
/**
* Relocate stereotype applications for the nested elements of the selection in the controlled resource
*
* @param root
* the root element for which stereotype applications must be relocated
* @param target
* the target controlled resource
*/
public static void relocateStereotypeApplications(Element root, Resource target) {
// Relocate stereotype applications of the root element itself.
for(EObject stereotypeApplication : root.getStereotypeApplications()) {
relocateStereotypeApplication(root, stereotypeApplication);
}
// Relocate stereotype applications of the root's child elements.
for(Iterator<EObject> i = EcoreUtil.getAllProperContents(root, false); i.hasNext();) {
EObject current = i.next();
if(current instanceof Element) {
Element element = (Element)current;
for(EObject stereotypeApplication : element.getStereotypeApplications()) {
relocateStereotypeApplication(element, stereotypeApplication);
}
}
}
}
/**
* Relocate one stereotype application of the given element.
*
* @param element
* the element holding the stereotype application to be relocated
* @param stereotypeApplication
* the stereotype application to be relocated
*/
public static void relocateStereotypeApplication(Element element, EObject stereotypeApplication) {
// Too bad that StereotypeApplicationHelper.getContainmentList is not public, it would have allowed a completely generic heuristic.
EList<EObject> containmentList; // = StereotypeApplicationHelper.INSTANCE.getContainmentList(element, stereotypeApplication.eClass());
Resource resource = element.eResource();
containmentList = resource != null ? resource.getContents() : null; // Default heuristic of StereotypeApplicationHelper.
if (containmentList != null) {
containmentList.add(stereotypeApplication);
}
}
/**
* Check if the profile application is a duplicated one
*
* @param profileAppl
* profile application to check
* @return true if it is a duplicated copy
*/
public static boolean isDuplicatedProfileApplication(ProfileApplication profileAppl) {
return profileAppl.getEAnnotation(DUPLICATED_PROFILE) != null;
}
/**
* Get the nearest parent package which has the profile applied.
*
* @param packageElement
* child package
* @param profile
* applied profile
* @param notControlledOnly
* true to return only a not controlled package
* @return the parent package with profile application
*/
public static Package getParentPackageWithProfile(Package packageElement, Profile profile, boolean notControlledOnly) {
if(profile != null && profile.getDefinition() != null) {
Element parent = packageElement.getOwner();
while(parent != null) {
if(parent instanceof Package) {
Package parentPackage = (Package)parent;
if(isSameProfileApplied(parentPackage, profile)) {
if(!notControlledOnly || !AdapterFactoryEditingDomain.isControlled(parentPackage)) {
return parentPackage;
}
}
}
parent = parent.getOwner();
}
}
return null;
}
/**
* Mark this profile application as the duplication of a parent profile
*
* @param profileAppl
* profile application to mark
*/
public static void markAsDuplicate(ProfileApplication profileAppl) {
// add eannotation for duplicated profile applications
profileAppl.createEAnnotation(DUPLICATED_PROFILE);
}
}