blob: 7341414334b44ee37269f8250e473bcf72c42e15 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2012 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.fuml.actions;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.papyrus.moka.fuml.loci.ChoiceStrategy;
import org.eclipse.papyrus.moka.fuml.structuredclassifiers.ILink;
import org.eclipse.papyrus.moka.fuml.structuredclassifiers.IReference;
import org.eclipse.papyrus.moka.fuml.structuredclassifiers.Link;
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.simpleclassifiers.UnlimitedNaturalValue;
import org.eclipse.uml2.uml.AddStructuralFeatureValueAction;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.StructuralFeature;
public class AddStructuralFeatureValueActionActivation extends WriteStructuralFeatureActionActivation {
@Override
public void doAction() {
// Get the values of the object and value input pins.
// If the given feature is an association end, then create a link
// between the object and value inputs.
// Otherwise, if the object input is a structural value, then add a
// value to the values for the feature.
// If isReplaceAll is true, first remove all current matching links or
// feature values.
// If isReplaceAll is false and there is an insertAt pin, insert the
// value at the appropriate position.
AddStructuralFeatureValueAction action = (AddStructuralFeatureValueAction) (this.node);
StructuralFeature feature = action.getStructuralFeature();
Association association = this.getAssociation(feature);
IValue value = this.takeTokens(action.getObject()).get(0);
List<IValue> inputValues = this.takeTokens(action.getValue());
// NOTE: Multiplicity of the value input pin is required to be 1..1.
IValue inputValue = inputValues.get(0);
int insertAt = 0;
if (action.getInsertAt() != null) {
insertAt = ((UnlimitedNaturalValue) this.takeTokens(action.getInsertAt()).get(0)).value;
}
if (association != null) {
List<ILink> links = this.getMatchingLinks(association, feature, value);
Property oppositeEnd = this.getOppositeEnd(association, feature);
int position = 0;
if (oppositeEnd.isOrdered()) {
position = this.getMatchingLinks(association, oppositeEnd, inputValue).size() + 1;
}
if (action.isReplaceAll()) {
for (int i = 0; i < links.size(); i++) {
ILink link = links.get(i);
link.destroy();
}
} else if (feature.isUnique()) {
int i = 1;
boolean destroyed = false;
while (!destroyed & i <= links.size()) {
ILink link = links.get(i - 1);
IFeatureValue featureValue = link.getFeatureValue(feature);
if (featureValue.getValues().get(0).equals(inputValue)) {
position = link.getFeatureValue(oppositeEnd).getPosition();
link.destroy();
destroyed = true;
}
i = i + 1;
}
}
ILink newLink = new Link();
newLink.setType(association);
newLink.setFeatureValue(feature, inputValues, insertAt);
List<IValue> oppositeValues = new ArrayList<IValue>();
oppositeValues.add(value);
newLink.setFeatureValue(oppositeEnd, oppositeValues, position);
newLink.addTo(this.getExecutionLocus());
} 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();
}
IStructuredValue structuredValue = (IStructuredValue) value;
if (action.isReplaceAll()) {
structuredValue.setFeatureValue(feature, inputValues, 0);
} else {
IFeatureValue featureValue = structuredValue.getFeatureValue(feature);
if (featureValue.getValues().size() > 0 & insertAt == 0) {
// *** If there is no insertAt pin, then the structural
// feature must be unordered, and the insertion position is
// immaterial. ***
insertAt = ((ChoiceStrategy) this.getExecutionLocus().getFactory().getStrategy("choice")).choose(featureValue.getValues().size());
}
if (feature.isUnique()) {
// Remove any existing value that duplicates the input value
int j = position(inputValue, featureValue.getValues(), 1);
if (j > 0) {
featureValue.getValues().remove(j - 1);
}
}
if (insertAt <= 0) { // Note: insertAt = -1 indicates an
// unlimited value of "*"
featureValue.getValues().add(inputValue);
} else {
featureValue.getValues().add(insertAt - 1, inputValue);
}
}
}
if (action.getResult() != null) {
this.putToken(action.getResult(), value);
}
}
}