blob: cdeaac572687b04f56a76cfec7785d090e377886 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2013 CEA LIST.
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* CEA LIST - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.moka.pscs.actions;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.papyrus.moka.fuml.actions.ClearStructuralFeatureActionActivation;
import org.eclipse.papyrus.moka.fuml.simpleclassifiers.IFeatureValue;
import org.eclipse.papyrus.moka.fuml.simpleclassifiers.IStructuredValue;
import org.eclipse.papyrus.moka.fuml.simpleclassifiers.IValue;
import org.eclipse.papyrus.moka.fuml.structuredclassifiers.IExtensionalValue;
import org.eclipse.papyrus.moka.fuml.structuredclassifiers.ILink;
import org.eclipse.papyrus.moka.fuml.structuredclassifiers.IReference;
import org.eclipse.papyrus.moka.pscs.structuredclassifiers.CS_Link;
import org.eclipse.papyrus.moka.pscs.structuredclassifiers.CS_Reference;
import org.eclipse.papyrus.moka.pscs.structuredclassifiers.ICS_InteractionPoint;
import org.eclipse.papyrus.moka.pscs.structuredclassifiers.ICS_Link;
import org.eclipse.papyrus.moka.pscs.structuredclassifiers.ICS_Reference;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.ClearStructuralFeatureAction;
import org.eclipse.uml2.uml.Port;
import org.eclipse.uml2.uml.StructuralFeature;
public class CS_ClearStructuralFeatureValueActionActivation extends ClearStructuralFeatureActionActivation
implements ICS_ClearStructuralFeatureValueActionActivation {
@Override
public void doAction() {
// Get the value of the object input pin.
// If the given feature is an association end, then
// destroy all links that have the object input on the opposite end.
// Otherwise, if the object input is a structured value, then
// set the appropriate feature of the input value to be empty.
ClearStructuralFeatureAction action = (ClearStructuralFeatureAction) (this.node);
StructuralFeature feature = action.getStructuralFeature();
Association association = this.getAssociation(feature);
IValue value = this.takeTokens(action.getObject()).get(0);
if (association != null) {
List<ILink> links = this.getMatchingLinks(association, feature, value);
for (int i = 0; i < links.size(); i++) {
ILink link = links.get(i);
link.destroy();
}
} else if (value instanceof IStructuredValue) {
// If the value is a data value, then it must be copied before
// any change is made.
if (!(value instanceof IReference)) {
value = value.copy();
} else {
// extension to fUML
List<ICS_Link> linksToDestroy = this.getLinksToDestroy((IStructuredValue) value, feature);
for (int i = 0; i < linksToDestroy.size(); i++) {
linksToDestroy.get(i).destroy();
}
//
}
((IStructuredValue) value).setFeatureValue(action.getStructuralFeature(), new ArrayList<IValue>(), 0);
}
if (action.getResult() != null) {
this.putToken(action.getResult(), value);
}
}
public List<ICS_Link> getLinksToDestroy(IStructuredValue value, StructuralFeature feature) {
List<ICS_Link> linksToDestroy = new ArrayList<ICS_Link>();
if (value instanceof CS_Reference) {
ICS_Reference context = (CS_Reference) value;
// Retrieves the feature values for the structural feature associated with this
// action,
// in the context of this reference
IFeatureValue featureValue = context.getFeatureValue(feature);
if (feature instanceof Port) {
// all values are interaction points
// any link targeting this interaction point must be destroyed
for (int i = 0; i < featureValue.getValues().size(); i++) {
ICS_InteractionPoint interactionPoint = (ICS_InteractionPoint) featureValue.getValues().get(i);
List<ICS_Link> connectorInstances = context.getCompositeReferent().getLinks(interactionPoint);
for (int j = 0; j < connectorInstances.size(); j++) {
ICS_Link link = connectorInstances.get(j);
linksToDestroy.add(link);
}
}
} else { // feature is an attribute
// Retrieve all potential link ends,
// separating potential link ends corresponding to the given feature,
// and potential link ends corresponding to other features.
// By "potential link ends", we refer to the values of a given feature,
// as well as interaction points associated with this value, if any.
List<IValue> allValuesForFeature = new ArrayList<IValue>();
List<IValue> allOtherValues = new ArrayList<IValue>();
for (int i = 0; i < context.getReferent().getFeatureValues().size(); i++) {
StructuralFeature currentFeature = context.getReferent().getFeatureValues().get(i).getFeature();
List<IValue> values = this.getPotentialLinkEnds(context, currentFeature);
for (int j = 0; j < values.size(); j++) {
IValue v = values.get(j);
if (currentFeature != feature) {
allOtherValues.add(v);
} else {
allValuesForFeature.add(v);
}
}
}
// Retrieves all links available at the locus
List<IExtensionalValue> extensionalValues = this.getExecutionLocus().getExtensionalValues();
List<CS_Link> allLinks = new ArrayList<CS_Link>();
for (int i = 0; i < extensionalValues.size(); i++) {
IExtensionalValue extensionalValue = extensionalValues.get(i);
if (extensionalValue instanceof CS_Link) {
allLinks.add((CS_Link) extensionalValue);
}
}
// Retrieves links representing connector instances in the context object
for (int i = 0; i < allLinks.size(); i++) {
ICS_Link link = allLinks.get(i);
boolean linkHasToBeDestroyed = false;
for (int j = 0; j < allValuesForFeature.size() && !linkHasToBeDestroyed; j++) {
IValue v = allValuesForFeature.get(j);
StructuralFeature featureForV = link.getFeature(v);
if (featureForV != null) {
// Check if feature values of this link for other features
// contains elements identified in allOtherValue
for (int k = 0; k < link.getFeatureValues().size() && !linkHasToBeDestroyed; k++) {
IFeatureValue otherFeatureValue = link.getFeatureValues().get(k);
if (otherFeatureValue.getFeature() != featureForV) {
for (int l = 0; l < otherFeatureValue.getValues().size()
&& !linkHasToBeDestroyed; l++) {
for (int m = 0; m < allOtherValues.size() && !linkHasToBeDestroyed; m++) {
if (otherFeatureValue.getValues().get(l) == allOtherValues.get(m)) {
linkHasToBeDestroyed = true;
}
}
}
}
}
}
}
if (linkHasToBeDestroyed) {
linksToDestroy.add(link);
}
}
}
}
return linksToDestroy;
}
public List<IValue> getPotentialLinkEnds(ICS_Reference context, StructuralFeature feature) {
// Retrieves all feature values for the context object for the given feature,
// as well as all interaction point for these values
List<IValue> potentialLinkEnds = new ArrayList<IValue>();
IFeatureValue featureValue = context.getFeatureValue(feature);
for (int i = 0; i < featureValue.getValues().size(); i++) {
IValue v = featureValue.getValues().get(i);
potentialLinkEnds.add(v);
if (v instanceof ICS_Reference) {
// add all interaction points associated with v
for (int j = 0; j < ((CS_Reference) v).getReferent().getFeatureValues().size(); j++) {
if (((ICS_Reference) v).getReferent().getFeatureValues().get(j).getFeature() instanceof Port) {
List<IValue> interactionPoints = (((ICS_Reference) v).getReferent().getFeatureValues().get(j))
.getValues();
for (int k = 0; k < interactionPoints.size(); k++) {
potentialLinkEnds.add(interactionPoints.get(k));
}
}
}
}
}
return potentialLinkEnds;
}
}