Commit b4fcc597 authored by Alexander Diewald's avatar Alexander Diewald
Browse files

SIL-Annotation: Move most logic to static impl

* Move the platform-logic to the static impl.
* Use more infrastructure logic from the annotation framework.
* Move common methods to the SafetyUtils.

Issue-Ref: 3859
Issue-Url: https://af3-developer.fortiss.org/issues/3859

Signed-off-by: Alexander Diewald's avatarAlexander Diewald <diewald@fortiss.org>
parent d1394e8d
safety.ecore 36e011a7da1a4d0704004b80bea0963415a53981 RED
safety.ecore 6394bb80e33ae0d0720bbd0ecea7164ab5c5d275 RED
......@@ -83,6 +83,12 @@
</eAnnotations>
<eParameters name="value" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EEnumerator"/>
</eOperations>
<eOperations name="isUserAnnotatedValuePreferred" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="{@inheritDoc}"/>
<details key="body" value="return true;"/>
</eAnnotations>
</eOperations>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="safetyStandard" eType="#//SafetyStandard">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Safety standard (if selected for this particular annotation). Value might also be derived from other model elements (see {@link #getValue()})."/>
......
......@@ -75,6 +75,8 @@
body="return SafetyIntegrityLevelStaticImpl.setValue(this, value);">
<genParameters ecoreParameter="safety.ecore#//annotation/SafetyIntegrityLevel/setValue/value"/>
</genOperations>
<genOperations ecoreOperation="safety.ecore#//annotation/SafetyIntegrityLevel/isUserAnnotatedValuePreferred"
body="return true;"/>
</genClasses>
<genClasses ecoreClass="safety.ecore#//annotation/ProbabilisticMetricHardwareFailure">
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute safety.ecore#//annotation/ProbabilisticMetricHardwareFailure/pmhfValue"/>
......
HwComplexityValueProvider.java 23583ed930bbd942485e317ecf485323c7152a4f GREEN
SafetyIntegrityLevelValueProvider.java a697fe1d502102755ddb109c77ba64a0f2ea05e9 RED
SafetyIntegrityLevelValueProvider.java d4c0e644e3186f9fee86f2946fae14e02110f0b0 RED
......@@ -15,27 +15,18 @@
+--------------------------------------------------------------------------*/
package org.fortiss.af3.safety.annotation.valueprovider;
import static java.util.stream.Collectors.toList;
import static org.fortiss.af3.safety.utils.SafetyUtils.getLowestChildSafetyLevelValue;
import static org.fortiss.af3.safety.utils.SafetyUtils.getSafetyIntegrityLevelEnumOf;
import static org.fortiss.tooling.common.util.LambdaUtils.filterByType;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.pickFirstInstanceOf;
import java.util.Collection;
import java.util.List;
import static org.fortiss.af3.safety.utils.SafetyUtils.haveDirectChildsSpecifiedSIL;
import static org.fortiss.af3.safety.utils.SafetyUtils.isElementTopElement;
import org.eclipse.emf.common.util.Enumerator;
import org.fortiss.af3.platform.hierarchic.model.node.INodeDomain;
import org.fortiss.af3.platform.hierarchic.model.processor.IProcessorDomain;
import org.fortiss.af3.platform.hierarchic.model.tile.ITileDomain;
import org.fortiss.af3.platform.model.ExecutionUnit;
import org.fortiss.af3.safety.model.annotation.SafetyAnnotationPackage;
import org.fortiss.af3.safety.model.annotation.SafetyIntegrityLevel;
import org.fortiss.tooling.base.annotation.valueprovider.DerivedAnnotationValueProviderBase;
import org.fortiss.tooling.base.model.element.IHierarchicElement;
import org.fortiss.tooling.base.model.element.IHierarchicElementContainer;
import org.fortiss.tooling.base.model.element.IModelElement;
import org.fortiss.tooling.base.utils.AnnotationUtils;
/**
* Value provider for the {@link SafetyIntegrityLevel} annotation. Most logic is implemented in the
......@@ -56,10 +47,16 @@ public class SafetyIntegrityLevelValueProvider
@Override
public boolean canEdit(SafetyIntegrityLevel specification) {
IModelElement modelElement = specification.getSpecificationOf();
if(isElementTopElement(modelElement)) {
return true;
}
if(modelElement instanceof INodeDomain) {
if(modelElement instanceof IHierarchicElementContainer) {
return !haveDirectChildsSpecifiedSIL(modelElement);
}
} else if(modelElement instanceof ITileDomain) {
return true;
} else if(modelElement instanceof IProcessorDomain) {
return false;
}
......@@ -77,34 +74,6 @@ public class SafetyIntegrityLevelValueProvider
@SuppressWarnings("unchecked")
@Override
public <U> U getAnnotationValue(SafetyIntegrityLevel specification) {
IModelElement modelElement = specification.getSpecificationOf();
if(modelElement instanceof INodeDomain) {
if(modelElement instanceof IHierarchicElementContainer) {
if(haveDirectChildsSpecifiedSIL(modelElement)) {
Integer lowestChildSIL = getLowestChildSafetyLevelValue(specification, false);
return (U)getSafetyIntegrityLevelEnumOf(specification)[lowestChildSIL];
}
return (U)specification.getValue();
}
} else if(modelElement instanceof ITileDomain) {
// Return the parent SIL, if unspecified. Here, only the user annotated value is
// considered --> otherwise, there is a pingpong play between tiles and nodes.
Enumerator value = specification.getUserAnnotatedValue();
if(value == null && modelElement instanceof IHierarchicElement) {
IModelElement parent =
(IModelElement)((IHierarchicElement)modelElement).getContainer();
return (U)pickFirstInstanceOf(SafetyIntegrityLevel.class,
parent.getSpecifications()).getUserAnnotatedValue();
}
} else if(modelElement instanceof IProcessorDomain) {
if(modelElement instanceof IHierarchicElement) {
IModelElement parent =
(IModelElement)((IHierarchicElement)modelElement).getContainer();
return (U)AnnotationUtils.getAnnotationValue(parent, SafetyIntegrityLevel.class,
Enumerator.class);
}
}
return super.getAnnotationValue(specification);
}
......@@ -114,19 +83,4 @@ public class SafetyIntegrityLevelValueProvider
throws Exception {
super.setAnnotationValue((Enumerator)value, specification);
}
/** Determines whether any of the direct hierarchical child elements */
private boolean haveDirectChildsSpecifiedSIL(IModelElement modelElement) {
Collection<ExecutionUnit> directChildExUs =
filterByType(((IHierarchicElementContainer)modelElement).getContainedElements(),
ExecutionUnit.class);
List<Enumerator> safetyEnums = directChildExUs.stream().map(e -> AnnotationUtils
.getAnnotation(e, SafetyIntegrityLevel.class).getUserAnnotatedValue())
.collect(toList());
// get(0): safe due to size check.
boolean childrenAnnNotSet = (safetyEnums.size() == 1 && safetyEnums.get(0) == null);
return !safetyEnums.isEmpty() && !childrenAnnNotSet;
}
}
HwComplexityStaticImpl.java c2831359544871abc99c4b64d671090c5adb01cb GREEN
SafetyIntegrityLevelStaticImpl.java 082a8b5bff2f94a5a0500a04d36adc52faca0ca4 RED
SafetyIntegrityLevelStaticImpl.java 47b5ec543370f5eca1697e266d46a959c191a408 RED
......@@ -15,9 +15,13 @@
+--------------------------------------------------------------------------*/
package org.fortiss.af3.safety.model.annotation.impl;
import static org.fortiss.af3.safety.utils.SafetyUtils.getLowestChildSafetyLevelValue;
import static org.fortiss.af3.safety.utils.SafetyUtils.getSafetyEnumeratorOf;
import static org.fortiss.af3.safety.utils.SafetyUtils.getSafetyIntegrityLevelEnumOf;
import static org.fortiss.af3.safety.utils.SafetyUtils.getSafetyStandardOf;
import static org.fortiss.af3.safety.utils.SafetyUtils.isElementTopElement;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.getChildrenWithType;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.pickFirstInstanceOf;
import static org.fortiss.tooling.kernel.utils.KernelModelElementUtils.getParentElement;
import java.util.Collections;
......@@ -29,15 +33,20 @@ import org.eclipse.emf.common.util.Enumerator;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.fortiss.af3.component.model.Component;
import org.fortiss.af3.component.model.ComponentArchitecture;
import org.fortiss.af3.platform.hierarchic.model.node.INodeDomain;
import org.fortiss.af3.platform.hierarchic.model.processor.IProcessorDomain;
import org.fortiss.af3.platform.hierarchic.model.tile.ITileDomain;
import org.fortiss.af3.safety.model.ASIL;
import org.fortiss.af3.safety.model.DAL;
import org.fortiss.af3.safety.model.SIL;
import org.fortiss.af3.safety.model.SafetyStandard;
import org.fortiss.af3.safety.model.annotation.SafetyAnnotationPackage;
import org.fortiss.af3.safety.model.annotation.SafetyIntegrityLevel;
import org.fortiss.af3.safety.utils.SafetyUtils;
import org.fortiss.tooling.base.model.element.IHierarchicElement;
import org.fortiss.tooling.base.model.element.IHierarchicElementContainer;
import org.fortiss.tooling.base.model.element.IModelElement;
import org.fortiss.tooling.base.utils.AnnotationUtils;
import org.fortiss.tooling.kernel.model.IProjectRootElement;
/**
......@@ -137,59 +146,41 @@ public class SafetyIntegrityLevelStaticImpl {
}
});
/**
* Returns the safety level that is compatible with the domain in for which
* the architecture is defined.
*/
public static Enumerator getDerivedValue(SafetyIntegrityLevel specification) {
IModelElement modelElement = specification.getSpecificationOf();
IProjectRootElement rootElement =
getParentElement(modelElement, IProjectRootElement.class, false);
SafetyStandard safetyStandard = getSafetyStandardOf(specification);
boolean isRootStandardUndefined =
safetyStandard == SafetyStandard.UNDEFINED && modelElement == rootElement;
if(isRootStandardUndefined || isElementTopComponent(modelElement)) {
return safetyStandard;
}
return (Enumerator)specification.eGet(getSafetyEnumeratorOf(safetyStandard));
}
/**
* Returns whether the given {@link IModelElement} is the top {@link Component} of a
* {@link ComponentArchitecture}.
*/
private static boolean isElementTopComponent(IModelElement element) {
if(element instanceof IProjectRootElement) {
return true;
}
IProjectRootElement rootElement =
getParentElement(element, IProjectRootElement.class, false);
if(rootElement instanceof ComponentArchitecture) {
if(((ComponentArchitecture)rootElement).getTopComponent() == element) {
return true;
if(modelElement instanceof INodeDomain) {
if(modelElement instanceof IHierarchicElementContainer) {
if(SafetyUtils.haveDirectChildsSpecifiedSIL(modelElement)) {
Integer lowestChildSIL = getLowestChildSafetyLevelValue(specification, false);
return (Enumerator)getSafetyIntegrityLevelEnumOf(specification)[lowestChildSIL];
}
return specification.getUserAnnotatedValue();
}
} else if(modelElement instanceof ITileDomain) {
// Return the parent SIL, if unspecified. Here, only the user annotated value is
// considered --> otherwise, there is a pingpong play between tiles and nodes.
Enumerator value = specification.getUserAnnotatedValue();
if(value == null && modelElement instanceof IHierarchicElement) {
IModelElement parent =
(IModelElement)((IHierarchicElement)modelElement).getContainer();
return pickFirstInstanceOf(SafetyIntegrityLevel.class, parent.getSpecifications())
.getUserAnnotatedValue();
}
} else if(modelElement instanceof IProcessorDomain) {
if(modelElement instanceof IHierarchicElement) {
IModelElement parent =
(IModelElement)((IHierarchicElement)modelElement).getContainer();
return AnnotationUtils.getAnnotationValue(parent, SafetyIntegrityLevel.class,
Enumerator.class);
}
}
return false;
return specification.getUserAnnotatedValue();
}
/** Returns the user annotated value based on the root {@link SafetyStandard}. */
public static Enumerator getUserAnnotatedValue(SafetyIntegrityLevelImpl specification) {
IModelElement modelElement = specification.getSpecificationOf();
IProjectRootElement rootElement =
getParentElement(modelElement, IProjectRootElement.class, false);
SafetyStandard safetyStandard = getSafetyStandardOf(specification);
boolean isRootStandardUndefined =
safetyStandard == SafetyStandard.UNDEFINED && modelElement == rootElement;
if(isRootStandardUndefined || isElementTopComponent(modelElement)) {
return safetyStandard;
}
return (Enumerator)specification.eGet(getSafetyEnumeratorOf(safetyStandard));
return SafetyUtils.getStandardSpecificValue(specification);
}
/**
......@@ -213,7 +204,7 @@ public class SafetyIntegrityLevelStaticImpl {
SafetyStandard safetyStandard = getSafetyStandardOf(specification);
if(modelElement == rootElement || isElementTopComponent(modelElement)) {
if(modelElement == rootElement || isElementTopElement(modelElement)) {
return SafetyAnnotationPackage.Literals.SAFETY_INTEGRITY_LEVEL__SAFETY_STANDARD;
}
return getSafetyEnumeratorOf(safetyStandard);
......
SafetyUtils.java 14cfa83ff061f6dd3fb25c8c9af9fb5d726bb44d RED
SafetyUtils.java f2d5401ba9b5de84d9a6e861c551bbc29695165f RED
package org.fortiss.af3.safety.utils;
import static java.lang.Math.max;
import static java.util.stream.Collectors.toList;
import static org.fortiss.tooling.base.utils.AnnotationUtils.getAnnotation;
import static org.fortiss.tooling.base.utils.AnnotationUtils.getAnnotationValue;
import static org.fortiss.tooling.base.utils.AnnotationUtils.getParentAnnotationsWithType;
import static org.fortiss.tooling.common.util.LambdaUtils.filterByType;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.getChildrenWithType;
import static org.fortiss.tooling.kernel.utils.KernelModelElementUtils.getParentElement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
......@@ -18,6 +22,9 @@ import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.Enumerator;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.fortiss.af3.component.model.Component;
import org.fortiss.af3.component.model.ComponentArchitecture;
import org.fortiss.af3.platform.model.ExecutionUnit;
import org.fortiss.af3.platform.model.generic.GenericExecutionUnit;
import org.fortiss.af3.platform.model.generic.GenericTransmissionUnit;
import org.fortiss.af3.safety.model.ASIL;
......@@ -26,7 +33,10 @@ import org.fortiss.af3.safety.model.SIL;
import org.fortiss.af3.safety.model.SafetyStandard;
import org.fortiss.af3.safety.model.annotation.SafetyAnnotationPackage;
import org.fortiss.af3.safety.model.annotation.SafetyIntegrityLevel;
import org.fortiss.tooling.base.model.element.IHierarchicElementContainer;
import org.fortiss.tooling.base.model.element.IModelElement;
import org.fortiss.tooling.base.utils.AnnotationUtils;
import org.fortiss.tooling.kernel.model.IProjectRootElement;
/**
* Utility methods for dealing with safety-related parts of the model.
......@@ -196,4 +206,57 @@ public class SafetyUtils {
public static EAttribute getSafetyEnumeratorOf(SafetyStandard domain) {
return standardToSpecificSIL.get(domain);
}
/** Determines whether any of the direct hierarchical child elements */
public static boolean haveDirectChildsSpecifiedSIL(IModelElement modelElement) {
Collection<ExecutionUnit> directChildExUs =
filterByType(((IHierarchicElementContainer)modelElement).getContainedElements(),
ExecutionUnit.class);
List<Enumerator> safetyEnums = directChildExUs.stream().map(e -> AnnotationUtils
.getAnnotation(e, SafetyIntegrityLevel.class).getUserAnnotatedValue())
.collect(toList());
// get(0): safe due to size check.
boolean childrenAnnNotSet = (safetyEnums.size() == 1 && safetyEnums.get(0) == null);
return !safetyEnums.isEmpty() && !childrenAnnNotSet;
}
/**
* Returns the safety level that is compatible with the domain in for which
* the architecture is defined.
*/
public static Enumerator getStandardSpecificValue(SafetyIntegrityLevel specification) {
IModelElement modelElement = specification.getSpecificationOf();
IProjectRootElement rootElement =
getParentElement(modelElement, IProjectRootElement.class, false);
SafetyStandard safetyStandard = getSafetyStandardOf(specification);
boolean isRootStandardUndefined =
safetyStandard == SafetyStandard.UNDEFINED && modelElement == rootElement;
if(isRootStandardUndefined || isElementTopElement(modelElement)) {
return safetyStandard;
}
return (Enumerator)specification.eGet(getSafetyEnumeratorOf(safetyStandard));
}
/**
* Returns whether the given {@link IModelElement} is the top {@link Component} of a
* {@link ComponentArchitecture}.
*/
public static boolean isElementTopElement(IModelElement element) {
if(element instanceof IProjectRootElement) {
return true;
}
IProjectRootElement rootElement =
getParentElement(element, IProjectRootElement.class, false);
if(rootElement instanceof ComponentArchitecture) {
if(((ComponentArchitecture)rootElement).getTopComponent() == element) {
return true;
}
}
return false;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment