/*****************************************************************************
* Copyright (c) 2008 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:
* Chokri Mraidha (CEA LIST) Chokri.Mraidha@cea.fr - Initial API and implementation
* Patrick Tessier (CEA LIST) Patrick.Tessier@cea.fr - modification
*
*****************************************************************************/
package org.eclipse.papyrus.uml.profile.tree.objects;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.papyrus.infra.core.utils.EditorUtils;
import org.eclipse.papyrus.uml.profile.utils.Util;
import org.eclipse.uml2.uml.DataType;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.PrimitiveType;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.Type;
/**
* The Class AppliedStereotypePropertyTreeObject. References a stereotype attribute
* (property)
*/
public class AppliedStereotypePropertyTreeObject extends ParentTreeObject {
/**
* The property.
*/
private Property property;
/**
* The Constructor.
*
* @param property
* the property
* @param parent
* the parent
*/
public AppliedStereotypePropertyTreeObject(AppliedStereotypeTreeObject parent, Property property) {
super(parent);
this.property = property;
}
public Stereotype getParentStereotype() {
return ((AppliedStereotypeTreeObject) getParent()).getStereotype();
}
/**
* Gets the property.
*
* @return the property
*/
public Property getProperty() {
return property;
}
/**
* Reinitialize the children from model, useful to reflect model changes in
* the value tree.
*/
public void reInitChilds () {
children.clear ();
createChildren ();
}
/**
* Creates the children.
*/
@Override
protected void createChildren() {
// Retrieve value which is normally either a list of objects or a single object
Object value = getValue();
if(value == null) {
return;
}
if (value instanceof EList) {
@SuppressWarnings("unchecked")
EList<Object> values = (EList<Object>) value;
Iterator<Object> it = values.iterator();
while(it.hasNext()) {
final Object currentValue = it.next();
ValueTreeObject vTO = createValueTreeObject(currentValue);
addChild(vTO);
}
}
else {
ValueTreeObject vTO = createValueTreeObject(value);
addChild(vTO);
}
}
/**
* Returns the value of the stereotype attribute
*
* @return the value
*/
public Object getValue() {
AppliedStereotypeTreeObject sTO = (AppliedStereotypeTreeObject) getParent();
StereotypedElementTreeObject rTO = (StereotypedElementTreeObject) sTO.getParent();
Stereotype st = sTO.getStereotype();
Element elt = rTO.getElement();
return elt.getValue(st, property.getName());
}
public Element getElement() {
AppliedStereotypeTreeObject sTO = (AppliedStereotypeTreeObject) getParent();
StereotypedElementTreeObject rTO = (StereotypedElementTreeObject) sTO.getParent();
return rTO.getElement();
}
public EStructuralFeature getFeature() {
return getStereotypeApplication().eClass().getEStructuralFeature(property.getName());
}
public EObject getStereotypeApplication() {
return getElement().getStereotypeApplication(getStereotype());
}
public Stereotype getStereotype() {
AppliedStereotypeTreeObject sTO = (AppliedStereotypeTreeObject) getParent();
return sTO.getStereotype();
}
/**
* Creates the value tree object.
*
* @param value
* the value
*
* @return the value tree object
*/
private ValueTreeObject createValueTreeObject(Object value) {
Type type = property.getType();
// Select correct class based on its type
ValueTreeObject vTO = null;
/** Property type is a PrimitiveType */
if(type instanceof PrimitiveType) {
vTO = PrimitiveTypeValueTreeObject.createInstance(this, value);
/** Property type is a metaclass */
} else if(Util.isMetaclass(type)) {
vTO = new MetaclassValueTreeObject(this, value);
/** Property type is an Enumeration */
} else if(type instanceof Enumeration) {
vTO = new EnumerationValueTreeObject(this, value);
/** Property is a dataType */
} else if(type instanceof DataType) {
vTO = new DataTypeValueTreeObject(this, value);
/** Property is a stereotype */
} else if(type instanceof Stereotype) {
vTO = new StereotypeValueTreeObject(this, value);
/** property is a composite class */
} else if((type instanceof org.eclipse.uml2.uml.Class) && !(type instanceof Stereotype) && property.isComposite()) {
vTO = new CompositeValueTreeObject(this, value);
}
return vTO;
}
/**
* This function is used prior to updating the model. It will add the new value to the
* list of existing values, in case of a multi-valued property. editMe methods should call
* this method before calling update.
* @param newValue a new value for the property (must not be a list itself)
* @return a new list which the existing stereotype value and the newValue in case of
* a multi-value property or the newValue, if not multi-valued
*/
public Object appendMV (Object newValue) {
Stereotype stereotype = ((AppliedStereotypeTreeObject) getParent()).getStereotype();
Element element = ((StereotypedElementTreeObject) getParent().getParent()).getElement();
if (property.isMultivalued ()) {
// add to existing contents
Object existingValue = element.getValue(stereotype, property.getName());
if (existingValue instanceof EList) {
@SuppressWarnings("unchecked")
EList<Object> existingValueList = (EList<Object>) existingValue;
EList<Object> valueList = new BasicEList<Object>();
valueList.addAll(existingValueList);
valueList.add(newValue);
return valueList;
}
}
return newValue;
}
/**
* Remove elements from the list of proposed stereotype values that have already
* selected - except the currently selected element.
* @param proposalList the list of possible stereotype values
* @param oldValue the currently selected value
*/
protected <T extends Object> void removeSelected (List<T> proposalList, T oldValue) {
if (property.isMultivalued()) {
@SuppressWarnings("unchecked")
EList<EObject> values = (EList<EObject>) getValue();
if (values != null) {
proposalList.removeAll(values);
}
if (oldValue != null) {
proposalList.add (oldValue);
}
}
}
/**
* Update value by means of a command that is executed within the Papyrus
* editing domain.
*
* @param newValue
* the new value
*/
public void updateValue(final Object newValue) {
// use domain to update the value
TransactionalEditingDomain domain = EditorUtils.getTransactionalEditingDomain();
RecordingCommand command = new RecordingCommand(domain, "Edit Stereotype Property Value") {
/**
* {@inheritDoc}
*/
@Override
protected void doExecute() {
Stereotype stereotype = ((AppliedStereotypeTreeObject) getParent()).getStereotype();
Element element = ((StereotypedElementTreeObject) getParent().getParent()).getElement();
Property property = getProperty();
// Affect newValue in UML model
element.setValue(stereotype, property.getName(), newValue);
}
};
domain.getCommandStack().execute(command);
}
}