NamedElementImpl.java
/**
* Copyright (c) 2004-2025 Carnegie Mellon University and others. (see Contributors file).
* All Rights Reserved.
*
* NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
* KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE
* OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
* MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
*
* This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
* SPDX-License-Identifier: EPL-2.0
*
* Created, in part, with funding and support from the United States Government. (see Acknowledgments file).
*
* This program includes and/or can make use of certain third party source code, object code, documentation and other
* files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system
* configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and
* conditions contained in any such Third Party Software or separate license file distributed with such Third Party
* Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici-
* aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li-
* censes only apply to the Third Party Software and not any other portion of this program or this program as a whole.
*/
package org.osate.aadl2.impl;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.util.EObjectContainmentEList;
import org.eclipse.emf.ecore.util.InternalEList;
import org.osate.aadl2.Aadl2Factory;
import org.osate.aadl2.Aadl2Package;
import org.osate.aadl2.ClassifierValue;
import org.osate.aadl2.ContainedNamedElement;
import org.osate.aadl2.ListValue;
import org.osate.aadl2.MetaclassReference;
import org.osate.aadl2.ModalPropertyValue;
import org.osate.aadl2.Mode;
import org.osate.aadl2.NamedElement;
import org.osate.aadl2.Namespace;
import org.osate.aadl2.Property;
import org.osate.aadl2.PropertyAssociation;
import org.osate.aadl2.PropertyExpression;
import org.osate.aadl2.PropertyOwner;
import org.osate.aadl2.PropertyType;
import org.osate.aadl2.PropertyValue;
import org.osate.aadl2.instance.InstanceObject;
import org.osate.aadl2.instance.SystemInstance;
import org.osate.aadl2.instance.SystemOperationMode;
import org.osate.aadl2.operations.NamedElementOperations;
import org.osate.aadl2.properties.InvalidModelException;
import org.osate.aadl2.properties.PropertyAcc;
import org.osate.aadl2.properties.PropertyDoesNotApplyToHolderException;
import org.osate.aadl2.properties.PropertyIsListException;
import org.osate.aadl2.properties.PropertyIsModalException;
import org.osate.aadl2.properties.PropertyNotPresentException;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Named Element</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* </p>
* <ul>
* <li>{@link org.osate.aadl2.impl.NamedElementImpl#getName <em>Name</em>}</li>
* <li>{@link org.osate.aadl2.impl.NamedElementImpl#getQualifiedName <em>Qualified Name</em>}</li>
* <li>{@link org.osate.aadl2.impl.NamedElementImpl#getOwnedPropertyAssociations <em>Owned Property Association</em>}</li>
* </ul>
*
* @generated
*/
public abstract class NamedElementImpl extends ElementImpl implements NamedElement {
/**
* The default value of the '{@link #getName() <em>Name</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getName()
* @generated
* @ordered
*/
protected static final String NAME_EDEFAULT = null;
/**
* The cached value of the '{@link #getName() <em>Name</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getName()
* @generated
* @ordered
*/
protected String name = NAME_EDEFAULT;
/**
* The default value of the '{@link #getQualifiedName() <em>Qualified Name</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getQualifiedName()
* @generated
* @ordered
*/
protected static final String QUALIFIED_NAME_EDEFAULT = null;
/**
* The cached value of the '{@link #getOwnedPropertyAssociations() <em>Owned Property Association</em>}' containment reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getOwnedPropertyAssociations()
* @generated
* @ordered
*/
protected EList<PropertyAssociation> ownedPropertyAssociations;
/**
* Stack of property definitions that are in the process of being looked
* up by the current thread. This is used to check for circular
* dependencies in the values of properties. The value of this
* thread local is a {@link LinkedList} whose items are
* {@link Property} objects.
*/
private static ThreadLocal<LinkedList<Property>> lookupStack = new ThreadLocal<>() {
protected LinkedList<Property> initialValue() {
return new LinkedList<>();
}
};
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected NamedElementImpl() {
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass() {
return Aadl2Package.eINSTANCE.getNamedElement();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public String getName() {
return name;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void setName(String newName) {
String oldName = name;
name = newName;
if (eNotificationRequired()) {
eNotify(new ENotificationImpl(this, Notification.SET, Aadl2Package.NAMED_ELEMENT__NAME, oldName, name));
}
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public String getQualifiedName() {
// DONE: implement this method to return the 'Qualified Name' attribute
return qualifiedName();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public EList<PropertyAssociation> getOwnedPropertyAssociations() {
if (ownedPropertyAssociations == null) {
ownedPropertyAssociations = new EObjectContainmentEList<>(PropertyAssociation.class,
this, Aadl2Package.NAMED_ELEMENT__OWNED_PROPERTY_ASSOCIATION);
}
return ownedPropertyAssociations;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public PropertyAssociation createOwnedPropertyAssociation() {
PropertyAssociation newOwnedPropertyAssociation = (PropertyAssociation) create(
Aadl2Package.eINSTANCE.getPropertyAssociation());
getOwnedPropertyAssociations().add(newOwnedPropertyAssociation);
return newOwnedPropertyAssociation;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public Namespace getNamespace() {
return NamedElementOperations.getNamespace(this);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public String qualifiedName() {
return NamedElementOperations.qualifiedName(this);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public EList<PropertyExpression> getPropertyValues(String propertySetName, String propertyName) {
return NamedElementOperations.getPropertyValues(this, propertySetName, propertyName);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
switch (featureID) {
case Aadl2Package.NAMED_ELEMENT__OWNED_PROPERTY_ASSOCIATION:
return ((InternalEList<?>) getOwnedPropertyAssociations()).basicRemove(otherEnd, msgs);
}
return super.eInverseRemove(otherEnd, featureID, msgs);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case Aadl2Package.NAMED_ELEMENT__NAME:
return getName();
case Aadl2Package.NAMED_ELEMENT__QUALIFIED_NAME:
return getQualifiedName();
case Aadl2Package.NAMED_ELEMENT__OWNED_PROPERTY_ASSOCIATION:
return getOwnedPropertyAssociations();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@SuppressWarnings("unchecked")
@Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case Aadl2Package.NAMED_ELEMENT__NAME:
setName((String) newValue);
return;
case Aadl2Package.NAMED_ELEMENT__OWNED_PROPERTY_ASSOCIATION:
getOwnedPropertyAssociations().clear();
getOwnedPropertyAssociations().addAll((Collection<? extends PropertyAssociation>) newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID) {
switch (featureID) {
case Aadl2Package.NAMED_ELEMENT__NAME:
setName(NAME_EDEFAULT);
return;
case Aadl2Package.NAMED_ELEMENT__OWNED_PROPERTY_ASSOCIATION:
getOwnedPropertyAssociations().clear();
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case Aadl2Package.NAMED_ELEMENT__NAME:
return NAME_EDEFAULT == null ? name != null : !NAME_EDEFAULT.equals(name);
case Aadl2Package.NAMED_ELEMENT__QUALIFIED_NAME:
return QUALIFIED_NAME_EDEFAULT == null ? getQualifiedName() != null
: !QUALIFIED_NAME_EDEFAULT.equals(getQualifiedName());
case Aadl2Package.NAMED_ELEMENT__OWNED_PROPERTY_ASSOCIATION:
return ownedPropertyAssociations != null && !ownedPropertyAssociations.isEmpty();
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public String toString() {
if (eIsProxy()) {
return super.toString();
}
StringBuilder result = new StringBuilder(super.toString());
result.append(" (name: ");
result.append(name);
result.append(')');
return result.toString();
}
public boolean hasName() {
String name = getName();
return name != null && name.length() > 0;
}
public String getFullName() {
return getName();
}
/**
* Retrieves the property value of a non-modal, single-valued property. Use
* this method if you know the property can only have a single value and is
* not modal
*
* @param property
* Property
* @return PropertyValue, does not return null.
* @exception InvalidModelException Thrown if the property value cannot
* be retrieved because the model is incomplete or otherwise invalid.
* @throws PropertyNotPresentException
* @throws PropertyIsModalException
* @throws IllegalStateException
* @throws IllegalArgumentException
* @throws PropertyDoesNotApplyToHolderException
* @throws PropertyIsListException
*/
public PropertyExpression getSimplePropertyValue(Property property)
throws InvalidModelException, PropertyNotPresentException, PropertyIsModalException, IllegalStateException,
IllegalArgumentException, PropertyDoesNotApplyToHolderException, PropertyIsListException {
return getNonModalPropertyValue(property);
}
/**
* Retrieves the property value (single or list) of a non-modal property. Throws an exception
* if its a modal value or undefined.
* @param property Property
* @return The property expression or null if the property has no value.
*/
public PropertyExpression getNonModalPropertyValue(final Property property)
throws InvalidModelException, PropertyNotPresentException, PropertyIsModalException, IllegalStateException,
IllegalArgumentException, PropertyDoesNotApplyToHolderException {
PropertyAssociation pa = getPropertyValue(property, false).first();
if (pa == null) {
if (property.getDefaultValue() == null) {
throw new PropertyNotPresentException(this, property, "No property association was found");
}
return property.getDefaultValue();
} else {
if (!pa.isModal()) {
// should always exist because it's not modal
if (pa.getOwnedValues().isEmpty()) {
throw new PropertyNotPresentException(this, property, "Property association has no value (yet)");
}
return pa.getOwnedValues().get(0).getOwnedValue();
} else {
// If we are an InstanceObject, get the value in the current SOM
if (this instanceof InstanceObject) {
final SystemInstance si = ((InstanceObject) this).getSystemInstance();
final SystemOperationMode som = si.getCurrentSystemOperationMode();
if (som != null) {
PropertyExpression defaultPE = null;
// find value in SOM
for (ModalPropertyValue mpv : pa.getOwnedValues()) {
if (mpv.getInModes() == null || mpv.getInModes().size() == 0) {
defaultPE = mpv.getOwnedValue();
} else if (mpv.getInModes().contains(som)) {
return mpv.getOwnedValue();
}
}
// default
if (defaultPE != null) {
return defaultPE;
}
// use global default
return property.getDefaultValue();
} else {
throw new PropertyIsModalException(this, property,
"Cannot use simple property lookup because the instance model has not been projected into a System Operation Mode."
+ " This occurred when looking up Property " + property.getName()
+ " on NamedElement " + getName() + ".");
}
} else {
throw new PropertyIsModalException(this, property,
"A non-modal property lookup method was called for a modal property."
+ " This occurred when looking up Property " + property.getName()
+ " on NamedElement " + getName() + ".");
}
}
}
}
/**
* Returns the property value for the property specified by property
*
* @param property
* The property to lookup
* @return AadlModalPropertyValue
* @exception IllegalStateException
* Thrown if the lookup encounters a cycle of property
* reference dependencies.
*/
public PropertyAcc getPropertyValue(final Property property, final boolean all) throws IllegalStateException,
InvalidModelException, PropertyDoesNotApplyToHolderException, IllegalArgumentException {
// Error if the property is not acceptable
if (property == null) {
throw new IllegalArgumentException("Property property cannot be null.");
}
if (!acceptsProperty(property)) {
throw new PropertyDoesNotApplyToHolderException(this, property,
"Property " + property.getName() + " does not apply to " + getClass().getName());
}
// Check that we aren't already looking up this property
final LinkedList<Property> stack = lookupStack.get();
if (stack.contains(property)) {
throw new IllegalStateException(
"Encountered circular dependency on property \"" + property.getName() + "\"");
}
try {
stack.addFirst(property);
PropertyAcc pas = new PropertyAcc(property);
getPropertyValueInternal(property, pas, false, all);
return pas;
} finally {
stack.removeFirst();
}
}
public PropertyAcc getPropertyValue(Property property) throws IllegalStateException, InvalidModelException,
PropertyDoesNotApplyToHolderException, IllegalArgumentException {
return getPropertyValue(property, false);
};
public boolean acceptsProperty(Property property) {
for (PropertyOwner appliesTo : property.getAppliesTos()) {
if (Aadl2Package.eINSTANCE.getAbstract().isSuperTypeOf(eClass())) {
return true;
}
if (appliesTo instanceof MetaclassReference) {
MetaclassReference metaRef = (MetaclassReference) appliesTo;
if (metaRef.getMetaclass() != null && metaRef.getMetaclass().isSuperTypeOf(eClass())) {
return true;
}
}
if (appliesTo instanceof ClassifierValue) {
return true;
}
}
return false;
}
/*
* TODO-lw: check if fromInstanceSlaveCall is still needed and if it's correctly implemented
* See https://github.com/osate/osate2/issues/875
*/
public void getPropertyValueInternal(final Property pn, final PropertyAcc pas, final boolean fromInstanceSlaveCall,
final boolean all) throws InvalidModelException {
if (!fromInstanceSlaveCall && getContainingClassifier() != null
&& pas.addLocalContained(this, getContainingClassifier())) {
if (!all) {
return;
}
}
pas.addLocal(this);
}
public void getPropertyValueInternal(Property property, PropertyAcc pas, boolean fromInstanceSlaveCall)
throws InvalidModelException {
getPropertyValueInternal(property, pas, fromInstanceSlaveCall, false);
}
public final PropertyAssociation setPropertyValue(final Property pd, final List<? extends PropertyExpression> pes) {
checkPropertyAssociation(pd, pes);
PropertyAssociation pa = Aadl2Factory.eINSTANCE.createPropertyAssociation();
pa.setProperty(pd);
ModalPropertyValue mpv = pa.createOwnedValue();
ListValue lv = (ListValue) mpv.createOwnedValue(Aadl2Package.eINSTANCE.getListValue());
lv.getOwnedListElements().addAll(pes);
if (this instanceof InstanceObject) {
final SystemInstance si = ((InstanceObject) this).getSystemInstance();
final SystemOperationMode som = si.getCurrentSystemOperationMode();
if (som == null) {
// non-modal instance model
removePropertyAssociations(pd);
} else {
mpv.getInModes().add(som);
removePropertyAssociations(pd, Collections.singletonList(som));
}
} else {
removePropertyAssociations(pd);
}
getOwnedPropertyAssociations().add(pa);
return pa;
}
/**
* Check that the proposed association is legal.
*/
public void checkPropertyAssociation(final Property pd, final Collection<? extends PropertyExpression> vals) {
// Check that the property applies to this element
if (!acceptsProperty(pd)) {
throw new IllegalArgumentException("Property " + pd.getName() + " does not apply to " + getName());
}
final boolean isList = pd.isList();
if (!isList) {
if (vals.size() == 0) {
throw new IllegalArgumentException(
"Cannot assign an empty list to the non-list property " + pd.getName());
} else if (vals.size() > 1) {
throw new IllegalArgumentException(
"Cannot assign a list of values to the non-list property " + pd.getName());
}
}
final PropertyType pt = (PropertyType) pd.getType();
if (pt == null) {
return;
// for (final Iterator<? extends PropertyExpression> i =
// vals.iterator(); i.hasNext();) {
// final PropertyExpression pv = i.next();
// final String msg = pt.containsValue(isList, pv);
// if (msg != PropertyType.VALUE_OKAY) {
// throw new IllegalArgumentException("Type mismatch: " + msg);
// }
// }
}
}
public final void removePropertyAssociations(final Property pd) {
final EList<PropertyAssociation> pal = getOwnedPropertyAssociations();
for (final Iterator<PropertyAssociation> it = pal.iterator(); it.hasNext();) {
final PropertyAssociation pa = it.next();
if (pa.getProperty() == pd) {
final EList<ContainedNamedElement> appliesTo = pa.getAppliesTos();
// ignore contained property associations
if (appliesTo == null || appliesTo.isEmpty()) {
it.remove();
}
}
}
}
public final void removePropertyAssociations(final Property pd, final List<? extends Mode> modes) {
final EList<PropertyAssociation> pal = getOwnedPropertyAssociations();
for (final Iterator<PropertyAssociation> it = pal.iterator(); it.hasNext();) {
final PropertyAssociation pa = it.next();
if (pa.getProperty() == pd) {
final EList<ContainedNamedElement> appliesTo = pa.getAppliesTos();
// ignore contained property associations
if (appliesTo == null || appliesTo.isEmpty()) {
for (Iterator<ModalPropertyValue> mpvi = pa.getOwnedValues().iterator(); mpvi.hasNext();) {
final ModalPropertyValue mpv = mpvi.next();
final EList<Mode> inModes = mpv.getInModes();
if (inModes != null && !inModes.isEmpty()) {
// Remove the given modes from the in modes clause
for (final Iterator<Mode> mi = inModes.iterator(); mi.hasNext();) {
final Mode mode = mi.next();
if (modes.contains(mode)) {
mi.remove();
}
}
// Remove the whole pa if we wiped out its in modes
// clause
if (inModes.isEmpty()) {
mpvi.remove();
}
}
}
if (pa.getOwnedValues().isEmpty()) {
it.remove();
}
}
}
}
}
public final PropertyAssociation setPropertyValue(final Property pd, final List<? extends PropertyExpression> pvl,
final List<? extends Mode> modes) {
checkPropertyAssociation(pd, pvl);
removePropertyAssociations(pd, modes);
final PropertyAssociation pa = Aadl2Factory.eINSTANCE.createPropertyAssociation();
pa.setProperty(pd);
final ModalPropertyValue mpv = pa.createOwnedValue();
// mpv.setOwnedValue(pvl);
mpv.getInModes().addAll(modes);
getOwnedPropertyAssociations().add(pa);
return pa;
}
/**
* Retrieves a non-modal property value as a list. Use this method if you
* know that the property is defined as a LIST OF. While this method can be used
* on scalar properties, getSimplePropertyValue should be used if you know that it is
* scalar. If the property is scalar, a list of length 1 is returned.
*
* @param property PropertyDefinition
* @return A list of PropertyValues. This does not return null.
*/
public final List<PropertyExpression> getPropertyValueList(final Property property)
throws InvalidModelException, IllegalArgumentException, PropertyNotPresentException,
PropertyIsModalException, IllegalStateException, PropertyDoesNotApplyToHolderException {
try {
PropertyExpression pe = getNonModalPropertyValue(property);
if (pe instanceof ListValue) {
return ((ListValue) pe).getOwnedListElements();
} else {
List<PropertyExpression> pes = new BasicEList<>();
pes.add(pe);
return pes;
}
} catch (Exception e) {
return Collections.emptyList();
}
}
public final PropertyAssociation setPropertyValue(final Property pd, final PropertyValue pv) {
checkPropertyAssociation(pd, Collections.singletonList(pv));
PropertyAssociation pa = Aadl2Factory.eINSTANCE.createPropertyAssociation();
ModalPropertyValue mpv = Aadl2Factory.eINSTANCE.createModalPropertyValue();
mpv.setOwnedValue(pv);
pa.setProperty(pd);
pa.getOwnedValues().add(mpv);
if (this instanceof InstanceObject) {
final SystemInstance si = ((InstanceObject) this).getSystemInstance();
final SystemOperationMode som = si.getCurrentSystemOperationMode();
if (som != null) {
mpv.getInModes().add(som);
}
this.removePropertyAssociations(pd, Collections.singletonList(som));
} else {
this.removePropertyAssociations(pd);
}
getOwnedPropertyAssociations().add(pa);
return pa;
}
public boolean equals(Object arg0) {
/*
* if (arg0 instanceof DataPortImpl)
* {
* System.out.println ("equals on " + arg0);
* }
*/
return (this == arg0);
}
} // NamedElementImpl