| /* |
| ----------------------------------------------------------------------- |
| -- CHESS core plugin -- |
| -- -- |
| -- Copyright (C) 2011-2012 -- |
| -- University of Padova, ITALY -- |
| -- -- |
| -- Author: Alessandro Zovi azovi@math.unipd.it -- |
| -- -- |
| -- 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-v20.html -- |
| ----------------------------------------------------------------------- |
| */ |
| |
| package org.polarsys.chess.core.internal.views.permissions; |
| |
| import java.util.ArrayList; |
| |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.ecore.EAttribute; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.impl.DynamicEObjectImpl; |
| import org.eclipse.uml2.uml.Classifier; |
| import org.eclipse.uml2.uml.Comment; |
| import org.eclipse.uml2.uml.Element; |
| import org.eclipse.uml2.uml.Feature; |
| import org.eclipse.uml2.uml.InstanceSpecification; |
| import org.eclipse.uml2.uml.Package; |
| import org.eclipse.uml2.uml.ProfileApplication; |
| import org.eclipse.uml2.uml.Region; |
| import org.eclipse.uml2.uml.Relationship; |
| import org.eclipse.uml2.uml.Stereotype; |
| import org.eclipse.uml2.uml.util.UMLUtil; |
| |
| /** |
| * This class implements an identifier for a permission entry. The identifier |
| * represent a way to identify a type of a model element. In this sense the |
| * identifier is static, it cannot represent an actual artifact of the model |
| * since it works at metamodel level (i.e. it can identify a "Class" but not the |
| * "Person" class, however it can identify a class with a stereotype "Person"). |
| * |
| * An identifier is defined by a triple whose first two values define a TYPE |
| * either by a combination of both or by each one on its own. The first value is |
| * the UML element type name, the second one is the stereotype name. A TYPE |
| * therefore represents an UML element or a Profile element. In the first case |
| * the first value must be a metaclass name representing an UML element and |
| * optionally the second value is the stereotype name associated with that UML |
| * element. In the second case the first value is not set while the second one |
| * is the stereotype name. The third value of the triple is the owned feature |
| * which is either a UML feature owned by the UML element or a stereotype |
| * attribute defined in the stereotype depending on the former two cases. |
| * |
| * Examples: |
| * <ul> |
| * <li>An UML Component without a stereotype [Component, -, -]</li> |
| * <li>An UML Class with any associated stereotype and an owned feature type (an |
| * Operation): [Class, *, Operation])</li> |
| * <li>A stereotype and one of its owned attributes [*, Person, age]</li> |
| * </ul> |
| * |
| * |
| * |
| */ |
| public class EntryId { |
| |
| /** The none. */ |
| public static String ANY = "*", NONE = "-"; |
| |
| /** The any entry. */ |
| public static EntryId anyEntry = new EntryId(ANY, ANY, ANY); |
| |
| /** The feature. */ |
| String feature; // eClass().getName(); |
| |
| /** The stereotype. */ |
| String stereotype; // Stereotype.getName(); |
| |
| /** The type. */ |
| String type; // eClass().getName(); |
| |
| /** The type atr. */ |
| public static String FEATURE_ATR = "ft", STEREOTYPE_ATR = "st", |
| TYPE_ATR = "el"; |
| |
| /** |
| * Instantiates a new entry id. |
| * |
| * @param type the type |
| * @param stereotype the stereotype |
| * @param feature the feature |
| */ |
| public EntryId(String type, String stereotype, String feature) { |
| this.type = type == null ? NONE : type; |
| this.stereotype = stereotype == null ? NONE : stereotype; |
| this.feature = feature == null ? NONE : feature; |
| } |
| |
| /** |
| * Gets the feature. |
| * |
| * @return the feature |
| */ |
| public String getFeature() { |
| return feature; |
| } |
| |
| /** |
| * Gets the stereotype. |
| * |
| * @return the stereotype |
| */ |
| public String getStereotype() { |
| return stereotype; |
| } |
| |
| /** |
| * Gets the type. |
| * |
| * @return the type |
| */ |
| public String getType() { |
| return type; |
| } |
| |
| /** |
| * Match. |
| * |
| * @param id the id |
| * @return true, if successful |
| */ |
| public boolean match(EntryId id) { |
| return match(id.getType(), id.getStereotype(), id.getFeature()); |
| } |
| |
| /** |
| * Match. |
| * |
| * @param type the type |
| * @param stereotype the stereotype |
| * @param feature the feature |
| * @return true, if successful |
| */ |
| public boolean match(String type, String stereotype, String feature) { |
| return matcher(this.type, type) && matcher(this.stereotype, stereotype) |
| && matcher(this.feature, feature); |
| } |
| |
| /** |
| * Matcher. |
| * |
| * @param a the a |
| * @param b the b |
| * @return true, if successful |
| */ |
| private boolean matcher(String a, String b) { |
| if (a.equals(ANY) || b.equals(ANY)) |
| return true; |
| return a.equalsIgnoreCase(b); |
| } |
| |
| /* (non-Javadoc) |
| * @see java.lang.Object#toString() |
| */ |
| @Override |
| public String toString() { |
| StringBuffer s = new StringBuffer(30); |
| s.append('['); |
| s.append(type == null ? NONE : type); |
| s.append(','); |
| s.append(stereotype == null ? NONE : stereotype); |
| s.append(','); |
| s.append(feature == null ? NONE : feature); |
| s.append(']'); |
| return s.toString(); |
| } |
| |
| /** |
| * Generate entry id. |
| * |
| * @param el the el |
| * @param str the str |
| * @param feature the feature |
| * @return the entry id |
| */ |
| public static EntryId generateEntryId(Element el, Stereotype str, |
| Feature feature) { |
| String name = (el == null) ? null : el.eClass().getName(); |
| String strName = (str == null) ? null : str.getName(); |
| String ftName = (feature == null) ? null : feature.getName(); |
| return new EntryId(name, strName, ftName); |
| } |
| |
| /** |
| * Compute stereotype entry ids. |
| * |
| * @param el the el |
| * @param ft the ft |
| * @param st the st |
| * @return the array list |
| */ |
| public static ArrayList<EntryId> computeStereotypeEntryIds(Object el, |
| Object ft, Object st) { |
| ArrayList<EntryId> ids = new ArrayList<EntryId>(); |
| String name = NONE, strName = NONE, ftName = NONE; |
| |
| if (st instanceof EObject) { |
| strName = ((EObject) st).eClass().getName(); |
| // Element baseEl = UMLUtil.getBaseElement((EObject) st); |
| // name = (baseEl == null)? null: baseEl.eClass().getName(); |
| ftName = getFeatureName(ft); |
| ids.add(new EntryId(name, strName, ftName)); |
| } |
| return ids; |
| } |
| |
| /** |
| * Given an element and a feature compute a list of ids to match permission |
| * entries. |
| * |
| * @param el the el |
| * @param ft the ft |
| * @return the array list |
| */ |
| public static ArrayList<EntryId> computeEntryIds(Object el, Object ft) { |
| ArrayList<EntryId> ids = new ArrayList<EntryId>(); |
| String name = NONE, strName = NONE, ftName = NONE; |
| // it's a Stereotype |
| if (el instanceof DynamicEObjectImpl) { |
| |
| strName = UMLUtil.getStereotype((DynamicEObjectImpl) el).getName(); |
| Element baseEl = UMLUtil.getBaseElement((DynamicEObjectImpl) el); |
| // TODO investigate why baseEl is null when a model element is |
| // removed. Perhaps we should check the oldValue?? |
| name = (baseEl == null) ? null : baseEl.eClass().getName(); |
| if (ft instanceof EAttribute) { |
| ftName = ((EAttribute) ft).getName(); |
| } |
| ids.add(new EntryId(name, strName, ftName)); |
| } else |
| // if its a Component, Interface or Class |
| if (el instanceof Classifier) { |
| // (1) |
| name = ((Classifier) el).eClass().getName(); |
| // Is it pointless to generate all the stereotype entries? No. It is |
| // not the |
| // same as put the ANY value |
| // in the stereotype field. We cannot discern between the |
| // stereotypes of a classifier upon its modification, but we can |
| // create |
| // a specific entry in the permission list to forbid the |
| // modification of a specific stereotyped classifier |
| // Instead when we modify a property of a stereotype, the |
| // modification is |
| // checked when the notification element (el) is a stereotype |
| // itself. |
| ftName = getFeatureName(ft); |
| |
| // EList<Stereotype> ss = ((Element) el).getAppliedStereotypes(); |
| // if (ss.isEmpty()){ |
| // Do not add stereotypes on the id |
| ids.add(new EntryId(name, NONE, ftName)); |
| // } |
| // else{ |
| // //if there are stereotypes generate the corresponding entries |
| // for (Stereotype str : ((Element) el).getAppliedStereotypes()) { |
| // ids.add(new EntryId(name, str.getName(), ftName)); |
| // } |
| // } |
| |
| // (2) |
| // name = ((Classifier) el).eClass().getName(); |
| // if (ft instanceof Feature) { |
| // ftName = ((EAttribute) ft).getName(); |
| // } |
| // ids.add(new EntryId(name, ANY, ftName)); |
| |
| } else |
| // it's a Package |
| if (el instanceof Package) { |
| name = ((Package) el).eClass().getName(); |
| // if (ft instanceof Feature) { |
| // ftName = ((EAttribute) ft).getName(); |
| // } |
| ids.add(new EntryId(name, NONE, getFeatureName(ft))); |
| } else |
| // it's a Feature |
| if (el instanceof Feature) { |
| EObject cont = ((Feature) el).eContainer(); |
| // TODO investigate why cont is null when a model element is |
| // removed. Perhaps we should check the oldValue?? |
| name = null; |
| // We need the feature type (i.e. Property, Operation), not the |
| // name!!! |
| // ftName = ((Feature) el).getName(); |
| ftName = ((Feature) el).eClass().getName(); |
| if (cont != null && cont instanceof Element) { |
| name = cont.eClass().getName(); |
| } |
| ids.add(new EntryId(name, NONE, ftName)); |
| } |
| // TODO it there any other type elements of interest? |
| else if (el instanceof Comment) { |
| name = ((Comment) el).eClass().getName(); |
| ids.add(new EntryId(name, NONE, NONE)); |
| } else if (el instanceof Relationship) { |
| name = ((Relationship) el).eClass().getName(); |
| ids.add(new EntryId(name, NONE, NONE)); |
| } else if (el instanceof InstanceSpecification) { |
| name = ((InstanceSpecification) el).eClass().getName(); |
| ids.add(new EntryId(name, NONE, NONE)); |
| } else if (el instanceof Region) { |
| name = ((Region) el).eClass().getName(); |
| ids.add(new EntryId(name, NONE, NONE)); |
| } else if (el instanceof Element) { |
| name = ((Element) el).eClass().getName(); |
| ids.add(new EntryId(name, NONE, NONE)); |
| } |
| // else if (el instanceof TypedElement) { |
| // try { |
| // name = ((Parameter) el).eContainer().eClass().getName(); |
| // } catch (Exception e) { |
| // } |
| // ftName = ((TypedElement) el).eClass().getName(); |
| // ids.add(new EntryId(NONE, NONE, ftName)); |
| // } |
| // else { |
| // // create a generic entry |
| // ids.add(anyEntry); |
| // } |
| return ids; |
| } |
| |
| /** |
| * Gets the feature name. |
| * |
| * @param ft the ft |
| * @return the feature name |
| */ |
| private static String getFeatureName(Object ft) { |
| // UML stuff |
| if (ft instanceof Element) { |
| return ((Feature) ft).getName(); |
| } |
| // ECore stuff |
| if (ft instanceof EStructuralFeature) { |
| return ((EStructuralFeature) ft).getName(); |
| } |
| return NONE; |
| } |
| |
| /** |
| * Compute entry ids. |
| * |
| * @param el the el |
| * @param ft the ft |
| * @return the array list |
| */ |
| public static ArrayList<EntryId> computeEntryIds_(Object el, Object ft) { |
| ArrayList<EntryId> ids = new ArrayList<EntryId>(); |
| String name = NONE, strName = NONE, ftName = NONE; |
| // it's a Stereotype |
| if (el instanceof DynamicEObjectImpl) { |
| strName = UMLUtil.getStereotype((DynamicEObjectImpl) el).getName(); |
| Element baseEl = UMLUtil.getBaseElement((DynamicEObjectImpl) el); |
| // TODO investigate why baseEl is null when a model element is |
| // removed. Perhaps we should check the oldValue?? |
| name = (baseEl == null) ? null : baseEl.eClass().getName(); |
| if (ft instanceof EAttribute) { |
| ftName = ((EAttribute) ft).getName(); |
| } |
| ids.add(new EntryId(name, strName, ftName)); |
| } else |
| // if its a Component, Interface or Class |
| if (el instanceof Classifier) { |
| name = ((Classifier) el).eClass().getName(); |
| ftName = getFeatureName(ft); |
| EList<Stereotype> ss = ((Element) el).getAppliedStereotypes(); |
| if (ss.isEmpty()) { |
| ids.add(new EntryId(name, NONE, ftName)); |
| } else { |
| // if there are stereotypes generate the corresponding entries |
| for (Stereotype str : ((Element) el).getAppliedStereotypes()) { |
| ids.add(new EntryId(name, str.getName(), ftName)); |
| } |
| } |
| } |
| // // it's a Feature |
| // else if (el instanceof Feature || el instanceof Parameter || el |
| // instanceof InstanceValue) { |
| // EObject cont = ((EObject) el).eContainer(); |
| // name = null; |
| // if (cont!= null && cont instanceof Feature){ |
| // cont = (cont).eContainer(); |
| // } |
| // // We need the feature type (i.e. Property, Operation), not the |
| // name!!! |
| // ftName = ((EObject) el).eClass().getName(); |
| // if(cont != null && cont instanceof Element){ |
| // name = cont.eClass().getName(); |
| // } |
| // ids.add(new EntryId(name, NONE, ftName)); |
| // //ids.add(new EntryId(NONE, NONE, getFeatureName(ft))); |
| // } |
| else if (el instanceof Element && !(el instanceof ProfileApplication)) { |
| name = ((Element) el).eClass().getName(); |
| ftName = getFeatureName(ft); |
| EList<Stereotype> ss = ((Element) el).getAppliedStereotypes(); |
| if (ss.isEmpty()) { |
| ids.add(new EntryId(name, NONE, ftName)); |
| } else { |
| // if there are stereotypes generate the corresponding entries |
| for (Stereotype str : ((Element) el).getAppliedStereotypes()) { |
| ids.add(new EntryId(name, str.getName(), ftName)); |
| } |
| } |
| } |
| |
| else if (el instanceof EObject && isInSupportedProfiles((EObject) el)) { |
| EObject e = (EObject) el; |
| ids.add(new EntryId(NONE, e.eClass().getName(), getFeatureName(ft))); |
| } |
| return ids; |
| } |
| |
| /** |
| * Checks if is any. |
| * |
| * @return true, if is any |
| */ |
| public boolean isANY() { |
| return type.equals(ANY) && stereotype.equals(ANY) |
| && feature.equals(ANY); |
| } |
| |
| /** |
| * Checks if is in supported profiles. |
| * |
| * @param el the el |
| * @return true, if is in supported profiles |
| */ |
| private static boolean isInSupportedProfiles(EObject el) { |
| for (int i = 0; i < availableProfiles.length; i++) { |
| if (el.getClass().getPackage().getName() |
| .startsWith(availableProfiles[i])) |
| return true; |
| } |
| return false; |
| } |
| |
| /** The available profiles. */ |
| private static String[] availableProfiles = { "org.polarsys.chess" }; |
| |
| /* (non-Javadoc) |
| * @see java.lang.Object#equals(java.lang.Object) |
| */ |
| @Override |
| public boolean equals(Object arg0) { |
| if (arg0 instanceof EntryId) { |
| EntryId ei = (EntryId) arg0; |
| return ei.getType().equals(this.getType()) |
| && ei.getFeature().equals(this.getFeature()) |
| && ei.getStereotype().equals(this.getStereotype()); |
| } |
| return false; |
| } |
| } |