/*****************************************************************************
* Copyright (c) 2010 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:
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.common.service.palette;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.emf.common.util.EList;
import org.eclipse.papyrus.uml.diagram.common.Activator;
import org.eclipse.papyrus.uml.diagram.common.part.PaletteUtil;
import org.eclipse.papyrus.uml.diagram.common.service.IPapyrusPaletteConstant;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Stereotype;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
*
* This class provides methods to store the palette configuration concerning the
* stereotypes application
*
*/
public class Configuration {
/** name of the property node */
public static final String PROPERTY = "property"; //$NON-NLS-1$
/** name of the property name attribute */
public static final String PROPERTY_NAME = "propertyName"; //$NON-NLS-1$
/** name of the runtimeProperty attribute */
public static final String RUNTIME_PROPERTY = "runtimeProperty"; //$NON-NLS-1$
/** name of the stereotype node */
public static final String STEREOTYPE = "stereotype"; //$NON-NLS-1$
/** name of the stereotypes to apply node */
public static final String STEREOTYPE_TO_APPLY = "stereotypesToApply"; //$NON-NLS-1$
/** name of the property name */
public static final String STEREOTYPE_NAME = "stereotypeName"; //$NON-NLS-1$
/** name of the value node */
public static final String VALUE = "value"; //$NON-NLS-1$
/** the stereotypes representation list */
private ArrayList<StereotypeRepresentation> myStereotypesList = new ArrayList<StereotypeRepresentation>();
/** the configuration node */
private Node configurationNode;
/**
* the applied profile
*/
private List<Profile> appliedProfiles;
/**
*
* Constructor.
*
* @param configurationNode
*/
public Configuration(Node configurationNode) {
this.configurationNode = configurationNode;
this.buildConfiguration();
}
/**
* builds the configuration with the configurationNode contents That's to
* say create :
* <ul>
* <li> {@link StereotypeRepresentation}</li>
* <li> {@link PropertyRepresentation}</li>
* <li> {@link Value}</li>
* </ul>
* corresponding to the configuration node contents to populate the
* configuration
*/
public void buildConfiguration() {
if(configurationNode == null) {
return;
}
NamedNodeMap nodeAttributes = configurationNode.getAttributes();
// transform old version in new version!
if(null != nodeAttributes.getNamedItem(IPapyrusPaletteConstant.STEREOTYPES_TO_APPLY)) {// old
// version
String stereotypesToApplyQN = configurationNode.getAttributes().getNamedItem(IPapyrusPaletteConstant.STEREOTYPES_TO_APPLY).getNodeValue();
if(stereotypesToApplyQN != null && !"".equals(stereotypesToApplyQN)) { //$NON-NLS-1$
List<String> stereotypesToApply = PaletteUtil.getStereotypeListFromString(stereotypesToApplyQN);
for(String qualifiedName : stereotypesToApply) {
myStereotypesList.add(new StereotypeRepresentation(qualifiedName));
}
}
} else {// new version
NodeList configurationChildren = configurationNode.getChildNodes();// stereotypesToApply
// Node
Node stereotypesToApplyNode = null;
for(int i = 0; i < configurationChildren.getLength(); i++) {
Node configurationChild = configurationChildren.item(i);
if(IPapyrusPaletteConstant.STEREOTYPES_TO_APPLY.equals(configurationChild.getLocalName())) {
stereotypesToApplyNode = configurationChild;
}
}
if(stereotypesToApplyNode != null && stereotypesToApplyNode.hasChildNodes()) {
NodeList childNodes = stereotypesToApplyNode.getChildNodes();
for(int iter = 0; iter < childNodes.getLength(); iter++) {
Node steNode = childNodes.item(iter);
if(STEREOTYPE.equals(steNode.getLocalName())) {// this node
// is really
// a
// stereotype?
String stereotypeName = steNode.getAttributes().getNamedItem(STEREOTYPE_NAME).getNodeValue();
StereotypeRepresentation mySte = null;
// does this stereotype exist?
if(getStereotypeRepresentation(stereotypeName) == null) {
mySte = new StereotypeRepresentation(stereotypeName);
} else {
mySte = getStereotypeRepresentation(stereotypeName);
}
// we store the stereotype
if(steNode.hasChildNodes()) {// there are associated
// properties and values
NodeList properties = steNode.getChildNodes();
for(int i = 0; i < properties.getLength(); i++) {// we
// iterate
// on
// the
// properties
Node propertyNode = properties.item(i);
if(PROPERTY.equals(propertyNode.getLocalName())) {// ist'
// a
// property
// node?
String propertyName = propertyNode.getAttributes().getNamedItem(PROPERTY_NAME).getNodeValue();
PropertyRepresentation proper = null;
if(mySte.getPropertyRepresentation(stereotypeName, propertyName) != null) {
proper = mySte.getPropertyRepresentation(stereotypeName, propertyName);
} else {
proper = new PropertyRepresentation(stereotypeName, propertyName);
mySte.addProperty(proper);
}
NodeList valuesList = propertyNode.getChildNodes();
for(int ii = 0; ii < valuesList.getLength(); ii++) {// we iterate
// on the
// values
Node valueNode = valuesList.item(ii);
if(VALUE.equals(valueNode.getLocalName())) {// this node
// is really
// a value?
Value myValue = new Value(valueNode.getTextContent());
proper.addValue(myValue);
}
}
} else if(RUNTIME_PROPERTY.equals(propertyNode.getLocalName())) {// it's a runtime
// property
String propertyName = propertyNode.getAttributes().getNamedItem(PROPERTY_NAME).getNodeValue();
propertyName = propertyNode.getAttributes().getNamedItem(PROPERTY_NAME).getNodeValue();
PropertyRepresentation prop = null;
if(mySte.getPropertyRepresentation(stereotypeName, propertyName) != null) {
prop = mySte.getPropertyRepresentation(stereotypeName, propertyName);
} else {
prop = new PropertyRepresentation(stereotypeName, propertyName);
mySte.addProperty(prop);
}
prop.setRuntime(true);
}
}
}
myStereotypesList.add(mySte);
}
}
}
}
}
/**
* This method completes the {@link Configuration} object with the
* properties owned by each stereotype. It completes the contents obtained
* with the {@link #buildConfiguration()} method. This method is called by :
* <ul>
* <li>{@link #setAppliedProfiles(List)}</li>
* <li>{@link #setStereotypesRepresentations(ArrayList)}</li>
* </ul>
*
*/
protected void completeData() {
List<Stereotype> stereotypeList = retrieveAllStereotypesOwnedByTheProfiles();
if(!stereotypeList.isEmpty()) {
for(Stereotype ste : stereotypeList) {
if(ste != null) {
StereotypeRepresentation currentSte = null;
// does this stereotype exist?
if(getStereotypeRepresentation(ste.getQualifiedName()) == null) {
currentSte = new StereotypeRepresentation(ste.getQualifiedName());
myStereotypesList.add(currentSte);
} else {
currentSte = getStereotypeRepresentation(ste.getQualifiedName());
}
currentSte.setUMLStereotype(ste);
EList<Property> attributs = ste.getAllAttributes();
for(Property prop : attributs) {
if(prop != null) {
if((prop.getAssociation() == null && !prop.isDerived()) || ((prop.getAssociation() != null) && (!prop.getName().startsWith("base_")) && !prop.isDerived())) { //$NON-NLS-1$
if(currentSte.getPropertyRepresentation(ste.getQualifiedName(), prop.getQualifiedName()) == null) {
PropertyRepresentation myProp = new PropertyRepresentation(ste.getQualifiedName(), prop.getQualifiedName());
myProp.setUMLProperty(prop);
currentSte.addProperty(myProp);
} else {
currentSte.getPropertyRepresentation(ste.getQualifiedName(), prop.getQualifiedName()).setUMLProperty(prop);
}
}
}
}
}
}
}
}
/**
* Saves the configuration in the parentNode}
*
* @param parentNode
* the node that contains the configuration
*/
public void save(Node parentNode) {
ListIterator<StereotypeRepresentation> it = getStereotypesRepresentations().listIterator();
Element appliedStereotypeNode = ((Element)parentNode).getOwnerDocument().createElement(STEREOTYPE_TO_APPLY);
while(it.hasNext()) {// iteration on stereotypes
StereotypeRepresentation currentStereotype = it.next();
Element stereotypeNode = ((Element)parentNode).getOwnerDocument().createElement(STEREOTYPE);
stereotypeNode.setAttribute(STEREOTYPE_NAME, currentStereotype.getStereotypeQualifiedName());
// the properties with value
for(PropertyRepresentation prop : currentStereotype.getPropertiesWithValues()) {
Element propertyNode = ((Element)parentNode).getOwnerDocument().createElement(PROPERTY);
propertyNode.setAttribute(PROPERTY_NAME, prop.getQualifiedName());
ArrayList<Value> values = prop.getValues();
for(int i = 0; i < ((ArrayList<?>)values).size(); i++) {// iteration
// on
// values
Element valueNode = ((Element)parentNode).getOwnerDocument().createElement(VALUE);
valueNode.setTextContent(((ArrayList<?>)values).get(i).toString());
propertyNode.appendChild(valueNode);
}
stereotypeNode.appendChild(propertyNode);
}
// the runtime properties
for(PropertyRepresentation prop : currentStereotype.getRuntimeProperties()) {
Element propertyNode = ((Element)parentNode).getOwnerDocument().createElement(RUNTIME_PROPERTY);
propertyNode.setAttribute(PROPERTY_NAME, prop.getQualifiedName());
stereotypeNode.appendChild(propertyNode);
}
appliedStereotypeNode.appendChild(stereotypeNode);
}// end of iteration on stereotype
parentNode.appendChild(appliedStereotypeNode);
}
/**
* Adds new stereotypes to the {@link Configuration}
*
* @param stereotypesQNList
* the list of stereotypes to add, identified by the qualified
* name
*/
public void setStereotypesRepresentations(ArrayList<String> stereotypesQNList) {
// 1. remove unused stereotype
for(String oldSte : getStereotypesToApplyQN()) {
if(!stereotypesQNList.contains(oldSte)) {
myStereotypesList.remove(getStereotypeRepresentation(oldSte));
}
}
// 2. add new stereotypes
for(String ste : stereotypesQNList) {
this.myStereotypesList.add(new StereotypeRepresentation(ste));
}
// 3. complete datas
completeData();
}
/**
*
* @param stereotypeQN
* the stereotype to find in the configuration, identified by its
* qualified name
* @return <ul>
* <li> {@link StereotypeRepresentation} if it exits
* <li> {@code null} if not</li>
* </ul>
*/
public StereotypeRepresentation getStereotypeRepresentation(String stereotypeQN) {
for(StereotypeRepresentation ste : myStereotypesList) {
if(ste.getStereotypeQualifiedName().equals(stereotypeQN)) {
return ste;
}
}
return null;
}
/**
* Returns the list of stereotypes contained by the {@link Configuration}
*
* @return all the {@link StereotypeRepresentation} owned by the {@link Configuration}
*/
public ArrayList<StereotypeRepresentation> getStereotypesRepresentations() {
return myStereotypesList;
}
/**
* Returns the list of applied stereotypes contained by the {@link Configuration}
*
* @return the list of applied stereotypes identified by its qualified name
*/
public ArrayList<String> getStereotypesToApplyQN() {
ArrayList<String> stereotypesList = new ArrayList<String>();
for(StereotypeRepresentation ste : getStereotypesRepresentations()) {
stereotypesList.add(ste.getStereotypeQualifiedName());
}
return stereotypesList;
}
/**
*
* @param stereotype
* the stereotype to remove from the {@link Configuration}
*/
public void removeStereotype(StereotypeRepresentation stereotype) {
myStereotypesList.remove(stereotype);
}
/**
* setter for {@link #appliedProfiles} moreover call {@link #completeData()} to complete the {@link Configuration}
*
* @param appliedProfiles
* the profiles to apply
*/
public void setAppliedProfiles(List<Profile> appliedProfiles) {
this.appliedProfiles = appliedProfiles;
this.completeData();
}
/**
* Returns the list of the applied {@link Profile}
*
* @return the applied profiles
*/
public List<Profile> getAppliedProfiles() {
return this.appliedProfiles;
}
/**
* Retrieves the list of stereotypes owned by {@link #appliedProfiles}
*
* @return the list of stereotypes owned by the profiles
*
*/
protected List<Stereotype> retrieveAllStereotypesOwnedByTheProfiles() {
List<Stereotype> stereotypes = new ArrayList<Stereotype>();
for(String qualifiedName : getStereotypesToApplyQN()) {
Stereotype stereotype = null;
Iterator<Profile> it = getAppliedProfiles().iterator();
while(stereotype == null && it.hasNext()) {
stereotype = retrieveStereotypeFromQualifiedName(qualifiedName, it.next());
}
if(stereotype == null) {
Activator.log.error("impossible to retrieve stereotype " + qualifiedName, null); //$NON-NLS-1$
}
stereotypes.add(stereotype);
}
return stereotypes;
}
/**
* Retrieves a Stereotype in a profile, given its qualified name.
*
* @param qualifiedName
* the qualified name of the stereotype to find
* @param profile
* the profile to look in
* @return <code>null</code> or the found stereotype
*/
protected Stereotype retrieveStereotypeFromQualifiedName(String qualifiedName, Profile profile) {
for(Stereotype stereotype : profile.getOwnedStereotypes()) {
if(qualifiedName.equals(stereotype.getQualifiedName())) {
return stereotype;
}
}
return null;
}
/**
* Returns all the stereotypes
*
* @return all the stereotypes
*/
public List<Stereotype> getUMLStereotypes() {
ArrayList<Stereotype> list = new ArrayList<Stereotype>();
for(StereotypeRepresentation ste : myStereotypesList) {
list.add(ste.getUMLStereotype());
}
return list;
}
/**
*
* @return <ul>
* <li> {@code true} if there is runtime properties
* <li> {@code false} if not</li>
* </ul>
*/
public boolean hasRuntimeProperties() {
for(StereotypeRepresentation ste : myStereotypesList) {
if(ste.hasRuntimeProperties()) {
return true;
}
}
return false;
}
/**
* Returns the configuration node
*
* @return the configuration node
*/
public Node getConfigurationNode() {
return configurationNode;
}
}