/*
* Initial version copyright 2008 Lockheed Martin Corporation, except
* as stated in the file entitled Licensing-Information.
*
* All modifications copyright 2009-2012 Data Access Technologies, Inc.
*
* Licensed under the Academic Free License version 3.0
* (http://www.opensource.org/licenses/afl-3.0.php), except as stated
* in the file entitled Licensing-Information.
*/
package fUML.Semantics.Classes.Kernel;
import fUML.Debug;
import UMLPrimitiveTypes.*;
import fUML.Syntax.*;
import fUML.Syntax.Classes.Kernel.*;
import fUML.Semantics.*;
import fUML.Semantics.Loci.*;
public class Link extends fUML.Semantics.Classes.Kernel.ExtensionalValue {
public fUML.Syntax.Classes.Kernel.Association type = null;
public void destroy() {
// Remove the type of this link and destroy it.
// Shift the positions of the feature values of any remaining links in
// the extent of the same association, for ends that are ordered.
Debug.println("[destroy] link = " + this.identifier);
PropertyList ends = this.type.memberEnd;
ExtensionalValueList extent = this.locus.getExtent(this.type);
for (int i = 0; i < extent.size(); i++) {
ExtensionalValue otherLink = extent.getValue(i);
for (int j = 0; j < ends.size(); j++) {
Property end = ends.getValue(j);
if (end.multiplicityElement.isOrdered) {
FeatureValue featureValue = otherLink.getFeatureValue(end);
if (this.getFeatureValue(end).position < featureValue.position) {
featureValue.position = featureValue.position - 1;
}
}
}
}
this.type = null;
super.destroy();
} // destroy
public fUML.Semantics.Classes.Kernel.Value copy() {
// Create a new link with the same type, locus and feature values as
// this link.
Link newValue = (Link) (super.copy());
newValue.type = this.type;
return newValue;
} // copy
protected fUML.Semantics.Classes.Kernel.Value new_() {
// Create a new link with no type or properies.
return new Link();
} // new_
public fUML.Syntax.Classes.Kernel.ClassifierList getTypes() {
// Return the single type of this link (if any).
ClassifierList types = null;
if (this.type == null) {
types = new ClassifierList();
} else {
types = new ClassifierList();
types.addValue(this.type);
}
return types;
} // getTypes
public boolean isMatchingLink(
fUML.Semantics.Classes.Kernel.ExtensionalValue link,
fUML.Syntax.Classes.Kernel.Property end) {
// Test whether the given link matches the values of this link on all
// ends other than the given end.
PropertyList ends = this.type.memberEnd;
boolean matches = true;
int i = 1;
while (matches & i <= ends.size()) {
Property otherEnd = ends.getValue(i - 1);
if (otherEnd != end
& !this.getFeatureValue(otherEnd).values.getValue(0)
.equals(
link.getFeatureValue(otherEnd).values
.getValue(0))) {
matches = false;
}
i = i + 1;
}
return matches;
} // isMatchingLink
public fUML.Semantics.Classes.Kernel.FeatureValueList getOtherFeatureValues(
fUML.Semantics.Classes.Kernel.ExtensionalValueList extent,
fUML.Syntax.Classes.Kernel.Property end) {
// Return all feature values for the given end of links in the given
// extent whose other ends match this link.
FeatureValueList featureValues = new FeatureValueList();
for (int i = 0; i < extent.size(); i++) {
ExtensionalValue link = extent.getValue(i);
if (link != this) {
if (isMatchingLink(link, end)) {
featureValues.addValue(link.getFeatureValue(end));
}
}
}
return featureValues;
} // getOtherFeatureValues
public void addTo(fUML.Semantics.Loci.LociL1.Locus locus) {
// Add this link to the extent of its association at the given locus.
// Shift the positions of ends of other links, as appropriate, for ends
// that are ordered.
Debug.println("[addTo] link = " + this.identifier);
PropertyList ends = this.type.memberEnd;
ExtensionalValueList extent = locus.getExtent(this.type);
for (int i = 0; i < ends.size(); i++) {
Property end = ends.getValue(i);
if (end.multiplicityElement.isOrdered) {
FeatureValue featureValue = this.getFeatureValue(end);
FeatureValueList otherFeatureValues = this
.getOtherFeatureValues(extent, end);
int n = otherFeatureValues.size();
if (featureValue.position < 0 | featureValue.position > n) {
featureValue.position = n + 1;
} else {
if (featureValue.position == 0) {
featureValue.position = 1;
}
for (int j = 0; j < otherFeatureValues.size(); j++) {
FeatureValue otherFeatureValue = otherFeatureValues
.getValue(j);
if (featureValue.position <= otherFeatureValue.position) {
otherFeatureValue.position = otherFeatureValue.position + 1;
}
}
}
}
}
locus.add(this);
} // addTo
} // Link