Commit 55c25626 authored by Ashmi Banerjee's avatar Ashmi Banerjee
Browse files

Issue# 3462: FTA Aspect implementation



* Implemented the FTA aspect (WIP)
* Aspect binding for the FTA aspect (WIP)
Signed-off-by: default avatarAshmi Banerjee <ashmi.banerjee@tum.de>
parent 5f1be414
......@@ -124,6 +124,12 @@
<modelElementClass
modelElementClass="org.fortiss.af3.mira.model.safety.MooNSolutionRequirementSpecification">
</modelElementClass>
</modelElementHandler>
<modelElementHandler
handler="org.fortiss.af3.mira.ui.handler.AspectHandlers$FTASolutionHandler">
<modelElementClass
modelElementClass="org.fortiss.af3.mira.model.safety.FTASolutionRequirementSpecification">
</modelElementClass>
</modelElementHandler>
<modelElementHandler
handler="org.fortiss.af3.mira.ui.handler.AspectHandlers$AssetsHandler">
......@@ -349,7 +355,13 @@
<modelElementClass
modelElementClass="org.fortiss.af3.mira.model.Requirement">
</modelElementClass>
</modelEditorBinding>
</modelEditorBinding>
<modelEditorBinding
binding="org.fortiss.af3.mira.ui.editorbinding.AspectBindings$FTASolutionAspectBinding">
<modelElementClass
modelElementClass="org.fortiss.af3.mira.model.Requirement">
</modelElementClass>
</modelEditorBinding>
<modelEditorBinding
binding="org.fortiss.af3.mira.ui.editorbinding.AspectBindings$AssetsBinding">
<modelElementClass
......
......@@ -4,12 +4,10 @@ AssetsEditor.java 165885aba6ff43f5b59e690bb11f2c33805af90b GREEN
CounterMeasuresEditor.java 94b90214d707dcb4739f308b981e608492a8690e GREEN
DateToStringConverter.java c969b068ea1dfd77b7153dd8937dca2e4b5630b7 GREEN
DerivedRequirementEditor.java b63b7200096998268b777f6060076073cb018a89 GREEN
FTASolutionRequirementEditor.java e7ffbd4190b6f1ba5c5537eb3987501c7233be5f RED
FormalSpecificationTreeContentProvider.java 469e589d7911316da6a52b4cbd97a59fcc720a97 GREEN
FunctionalRequirementEditor.java 386dd8b065aea7e155a60823cdd73b35100185cc GREEN
HazardRequirementEditor.java 0985139682ed38747b10ed0a9b39d936ce68a12e GREEN
InterfaceBehaviourAspectEditor.java ca70f1f82fca7f92e95ff83bf049c9383d5a781e GREEN
InterfaceBehaviourEditor.java be0a51fa8116f1c47b5d706935dfb17a19c775e5 GREEN
InterfaceBehaviourSectionExtension.java ead6ef67dd9aeafb070db4bd1fc9a0e8829af418 GREEN
InterfaceEditor.java 0e9f292c180ee06f6972a484e050252653df6178 GREEN
ModeDefinitionEditor.java 2ea1404961c2f75156d1214339b0c9b53058d4bc GREEN
MooNSolutionRequirementEditor.java 032f39665ed9682b20274ea8517c681a87ea2d85 YELLOW
......
/*-------------------------------------------------------------------------+
| Copyright 2018 fortiss GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
+--------------------------------------------------------------------------*/
package org.fortiss.af3.mira.ui.editor;
import static org.eclipse.core.runtime.IStatus.ERROR;
import static org.eclipse.jface.dialogs.ErrorDialog.openError;
import static org.fortiss.af3.mira.ui.utils.HighlightUtils.createSourceViewer;
import static org.fortiss.af3.mira.ui.utils.MiraLayoutUtils.singleLineInputFactory;
import static org.fortiss.af3.mira.ui.utils.MiraLayoutUtils.singleLineLabelFactory;
import static org.fortiss.tooling.kernel.model.FortissToolingKernelPackage.Literals.INAMED_ELEMENT__NAME;
import static org.fortiss.tooling.kernel.ui.util.DataBindingUtils.bind;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.pickFirstInstanceOf;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.pickInstanceOf;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.conqat.ide.commons.ui.jface.TreeContentProviderBase;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.fortiss.af3.mira.model.Requirement;
import org.fortiss.af3.mira.model.functional.FunctionalFactory;
import org.fortiss.af3.mira.model.functional.Signal;
import org.fortiss.af3.mira.model.safety.FTASolutionRequirementSpecification;
import org.fortiss.tooling.base.model.element.IModelElementSpecification;
import org.fortiss.tooling.base.ui.ToolingBaseUIActivator;
import org.fortiss.tooling.base.ui.editor.StyledTextCellEditor;
import org.fortiss.tooling.base.ui.utils.TreeViewerUtils;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.service.IPersistencyService;
import org.fortiss.tooling.kernel.ui.service.IActionService;
import org.fortiss.tooling.kernel.ui.util.SelectionUtils;
/**
*
* @author ashmi
*/
public class FTASolutionRequirementEditor<T extends Requirement> extends AspectEditorBase<T> {
/** The edited solution specification. */
private FTASolutionRequirementSpecification spec;
/** Label width. */
public static final int PROPERTIES_LABEL_WIDTH = 150;
/** List of the registered source viewers. We store this in a field because.... */
protected List<SourceViewer> localRegisteredSourceViewers;
/** Default text displayed in the input signals table. */
private static final String CLICK_TO_ADD_A_NEW_SIGNAL = "Click to add a new signal";
/**
* The tree viewer displaying the signals table. Only used as a table, but we use trees
* because it does
* not cost anything.
*/
private TreeViewer viewer;
/** Top level element for the edited object. */
private ITopLevelElement top;
/** {@inheritDoc} */
@Override
protected void createAspectSection() {
localRegisteredSourceViewers = new ArrayList<SourceViewer>();
EList<IModelElementSpecification> specs = editedObject.getSpecifications();
spec = pickFirstInstanceOf(FTASolutionRequirementSpecification.class, specs);
addFTAHeaderSection(spec);
addSignalSection(spec);
}
/**
* Definition of the Hazard section
*/
private void addFTAHeaderSection(FTASolutionRequirementSpecification spec) {
Composite headerSection =
createNewSection("FTA Solution Requirement",
"This requirement defines FTA parameters:");
headerSection.setLayout(new GridLayout(2, false));
Label nameLabel = toolkit.createLabel(headerSection, "Name: ", SWT.READ_ONLY);
singleLineLabelFactory.applyTo(nameLabel);
SourceViewer inputName = createSourceViewer(form, headerSection, SWT.BORDER, analysis);
registeredSourceViewers.add(inputName);
singleLineInputFactory.applyTo(inputName.getControl());
bind(dbc, inputName.getTextWidget(), spec, INAMED_ELEMENT__NAME);
}
/** {@inheritDoc} */
@Override
protected List<IModelElementSpecification> getElementsToDelete() {
ArrayList<IModelElementSpecification> res = new ArrayList<>();
res.addAll(pickInstanceOf(FTASolutionRequirementSpecification.class,
editedObject.getSpecifications()));
return res;
}
/** Section for signal component. */
private Composite addSignalSection(FTASolutionRequirementSpecification ms) {
Composite ftaSection =
createNewSection("Table of minimum cut sets",
"This requirement defines the table of minimum cut sets ");
ftaSection.setLayout(new GridLayout(1, false));
viewer = new TreeViewer(ftaSection, SWT.BORDER | SWT.FULL_SELECTION);
Tree tree = viewer.getTree();
GridDataFactory.swtDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).minSize(300, 300)
.applyTo(tree);
tree.setLinesVisible(true);
tree.setHeaderVisible(true);
TreeViewerUtils.allowTabing(viewer);
TreeViewerColumn nameColumn = new TreeViewerColumn(viewer, SWT.NONE);
TreeColumn trclmnMode = nameColumn.getColumn();
trclmnMode.setWidth(300);
trclmnMode.setText("Name");
nameColumn.setLabelProvider(new ColumnLabelProvider() {
/** {@inheritDoc} */
@Override
public String getText(Object element) {
if(element instanceof FakeChild) {
return "Click to add a cut set component";
}
return spec.getMinCutSet().get((Integer)element).getName();
}
});
nameColumn.setEditingSupport(createNameEditingSupport(viewer, nameColumn));
viewer.setContentProvider(new TreeContentProviderBase() {
@Override
public Object[] getChildren(Object parentElement) {
if(parentElement instanceof List<?>) {
List<Object> range = new ArrayList<Object>();
range.add(new FakeChild());
range.addAll(IntStream.rangeClosed(0, ms.getMinCutSet().size() - 1).boxed()
.collect(Collectors.toList()));
return range.toArray();
}
return new Object[0];
}
});
viewer.getControl().addKeyListener(new ViewerKeyAdapter());
viewer.setInput(spec.getMinCutSet());
return ftaSection;
}
/** Fake child used to add new elements. */
private static class FakeChild {
// Nothing to implement: just a marker class
}
/**
* Checks if the name is empty or already exists among current signals, if so displays an error
* message and return true, otherwise returns false.
*/
private boolean emptyOrAlreadyExists(String name) {
if(name.equals("") || name.equals(CLICK_TO_ADD_A_NEW_SIGNAL)) {
Status status =
new Status(ERROR, ToolingBaseUIActivator.PLUGIN_ID, 0,
"Signal name is not valid.", null);
openError(Display.getCurrent().getActiveShell(), "Error", null, status);
return true;
}
List<String> signalNames =
spec.getMinCutSet().stream().map(c -> c.getName().toLowerCase())
.collect(Collectors.toList());
if(signalNames.contains(name.toLowerCase()) ||
name.toLowerCase().equals(CLICK_TO_ADD_A_NEW_SIGNAL)) {
Status status =
new Status(ERROR, ToolingBaseUIActivator.PLUGIN_ID, 0,
"A Signal with this name already exists.", null);
openError(Display.getCurrent().getActiveShell(), "Error", null, status);
return true;
}
return false;
}
/** {@link EditingSupport} for the name column. */
private EditingSupport createNameEditingSupport(TreeViewer viewer,
TreeViewerColumn funcCompColumn) {
top = IPersistencyService.getInstance().getTopLevelElementFor(getEditedObject());
return new EditingSupport(funcCompColumn.getViewer()) {
@Override
protected void setValue(Object element, Object value) {
if(element instanceof FakeChild) {
if(!emptyOrAlreadyExists((String)value)) {
top.runAsCommand(() -> {
Signal newSig = FunctionalFactory.eINSTANCE.createSignal();
newSig.setName((String)value);
spec.getMinCutSet().add(newSig);
viewer.refresh();
});
}
}
}
@Override
protected Object getValue(Object element) {
return element instanceof Signal ? ((Signal)element).getName() : "";
}
@Override
protected CellEditor getCellEditor(Object element) {
return new StyledTextCellEditor(getTextStyledTextActionHandler(),
(Composite)getViewer().getControl());
}
@Override
protected boolean canEdit(Object element) {
return true;
}
};
}
/** Key adapter to deal with copy/paste/delete/... done through the keyboard. */
public class ViewerKeyAdapter extends KeyAdapter {
/** Constructor. */
public ViewerKeyAdapter() {
}
/** {@inheritDoc} */
@Override
public void keyReleased(KeyEvent e) {
if(e.keyCode == SWT.DEL) {
Integer modeIdx =
SelectionUtils.checkAndPickFirst(viewer.getSelection(), Integer.class);
if(modeIdx != null) {
top.runAsCommand(() -> {
spec.getMinCutSet().remove(modeIdx.intValue());
});
viewer.refresh();
}
} else if((e.stateMask & SWT.CTRL) != 0 && e.keyCode == 0x7A) {
IActionService.getInstance().runGlobalUndoAction();
} else if((e.stateMask & SWT.CTRL) != 0 && e.keyCode == 0x79) {
IActionService.getInstance().runGlobalRedoAction();
}
}
}
}
......@@ -26,6 +26,7 @@ import org.fortiss.af3.mira.model.SafetyLevelRequirementSpecification;
import org.fortiss.af3.mira.model.functional.FormalSpecification;
import org.fortiss.af3.mira.model.functional.FunctionalSpecification;
import org.fortiss.af3.mira.model.functional.SignalContainerSpecification;
import org.fortiss.af3.mira.model.safety.FTASolutionRequirementSpecification;
import org.fortiss.af3.mira.model.safety.HazardRequirementSpecification;
import org.fortiss.af3.mira.model.safety.MooNSolutionRequirementSpecification;
import org.fortiss.af3.mira.model.security.Assets;
......@@ -36,6 +37,7 @@ import org.fortiss.af3.mira.model.timing.TimingRequirement;
import org.fortiss.af3.mira.ui.editor.AssetsEditor;
import org.fortiss.af3.mira.ui.editor.CounterMeasuresEditor;
import org.fortiss.af3.mira.ui.editor.DerivedRequirementEditor;
import org.fortiss.af3.mira.ui.editor.FTASolutionRequirementEditor;
import org.fortiss.af3.mira.ui.editor.FunctionalRequirementEditor;
import org.fortiss.af3.mira.ui.editor.HazardRequirementEditor;
import org.fortiss.af3.mira.ui.editor.InterfaceEditor;
......@@ -185,6 +187,32 @@ public class AspectBindings {
}
}
/** Binding for FTA aspect. */
public static class FTASolutionAspectBinding extends ModelEditorBindingBase<Requirement> {
/** {@inheritDoc} */
@Override
public Class<? extends IEditorPart> getEditorClass(Requirement obj) {
if(pickFirstInstanceOf(FTASolutionRequirementSpecification.class,
obj.getSpecifications()) == null) {
return null;
}
return FTASolutionRequirementEditor.class;
}
/** {@inheritDoc} */
@Override
public String getLabel() {
return "FTA Solution definition";
}
/** {@inheritDoc} */
@Override
public int getPriority() {
return SECONDEDITORPRIORITY;
}
}
/** Binding for Assets aspect. */
public static class AssetsBinding extends ModelEditorBindingBase<Requirement> {
......
......@@ -30,6 +30,7 @@ import org.fortiss.af3.mira.model.SafetyLevelRequirementSpecification;
import org.fortiss.af3.mira.model.functional.FormalSpecification;
import org.fortiss.af3.mira.model.functional.FunctionalSpecification;
import org.fortiss.af3.mira.model.functional.SignalContainerSpecification;
import org.fortiss.af3.mira.model.safety.FTASolutionRequirementSpecification;
import org.fortiss.af3.mira.model.safety.HazardRequirementSpecification;
import org.fortiss.af3.mira.model.safety.MooNSolutionRequirementSpecification;
import org.fortiss.af3.mira.model.security.Assets;
......@@ -126,6 +127,17 @@ public class AspectHandlers {
}
}
/** Handler for {@link FTASolutionRequirementSpecification}s. */
public static class FTASolutionHandler extends
SpecificationHandlerBase<FTASolutionRequirementSpecification> {
/** {@inheritDoc} */
@Override
public String getName(FTASolutionRequirementSpecification element) {
return "FTA aspect";
}
}
/** Handler for {@link Assets}'s. */
public static class AssetsHandler extends SpecificationHandlerBase<Assets> {
......
......@@ -32,6 +32,7 @@ import org.fortiss.af3.mira.model.SafetyLevelRequirementSpecification;
import org.fortiss.af3.mira.model.functional.FormalSpecification;
import org.fortiss.af3.mira.model.functional.FunctionalSpecification;
import org.fortiss.af3.mira.model.functional.SignalContainerSpecification;
import org.fortiss.af3.mira.model.safety.FTASolutionRequirementSpecification;
import org.fortiss.af3.mira.model.safety.HazardRequirementSpecification;
import org.fortiss.af3.mira.model.safety.MooNSolutionRequirementSpecification;
import org.fortiss.af3.mira.model.timing.TimingRequirement;
......@@ -85,6 +86,7 @@ public class RequirementHandler extends NamedCommentedModelElementHandlerBase<Re
boolean temporalAspect = false;
boolean moonSolutionAspect = false;
boolean hazardAspect = false;
boolean ftaAspect = false;
for(IModelElementSpecification spec : element.getSpecifications()) {
if(spec instanceof TimingRequirement) {
......@@ -128,6 +130,10 @@ public class RequirementHandler extends NamedCommentedModelElementHandlerBase<Re
aspectCounter++;
hazardAspect = true;
}
if(spec instanceof FTASolutionRequirementSpecification) {
aspectCounter++;
ftaAspect = true;
}
}
if(aspectCounter == 1 && signalAspect == true) {
......@@ -143,7 +149,7 @@ public class RequirementHandler extends NamedCommentedModelElementHandlerBase<Re
(paramdefCounter > 1 && parameterdefAspect == true)) {
return imageDescriptorFromPlugin(PLUGIN_ID, "icons/Icon_ReqwithParameterDef.png");
}
if(aspectCounter == 1 && (safetyAspect || moonSolutionAspect || hazardAspect)) {
if(aspectCounter == 1 && (safetyAspect || moonSolutionAspect || hazardAspect || ftaAspect)) {
return imageDescriptorFromPlugin(PLUGIN_ID, "icons/Icon_ReqwithSafety.png");
}
if(aspectCounter == 1 && formalspecAspect == true) {
......
......@@ -838,5 +838,10 @@
<eLiterals name="Hazardous" value="4"/>
<eLiterals name="Catastrophic" value="5"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="FTASolutionRequirementSpecification"
eSuperTypes="platform:/resource/org.fortiss.tooling.base/model/base.ecore#//element/IModelElementSpecification #//INonFunctionalRequirement platform:/resource/org.fortiss.tooling.kernel/model/kernel.ecore#//INamedElement">
<eStructuralFeatures xsi:type="ecore:EReference" name="minCutSet" upperBound="-1"
eType="#//functional/Signal" containment="true"/>
</eClassifiers>
</eSubpackages>
</ecore:EPackage>
......@@ -429,6 +429,9 @@
<genFeatures notify="false" createChild="false" propertySortChoices="true"
ecoreFeature="ecore:EReference mira.ecore#//safety/MooNSolutionRequirementSpecification/inputSignals"/>
</genClasses>
<genClasses ecoreClass="mira.ecore#//safety/FTASolutionRequirementSpecification">
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference mira.ecore#//safety/FTASolutionRequirementSpecification/minCutSet"/>
</genClasses>
</nestedGenPackages>
</genPackages>
</genmodel:GenModel>
......@@ -27,6 +27,7 @@ import org.fortiss.af3.mira.model.SafetyLevelRequirementSpecification;
import org.fortiss.af3.mira.model.functional.FormalSpecification;
import org.fortiss.af3.mira.model.functional.FunctionalSpecification;
import org.fortiss.af3.mira.model.functional.SignalContainerSpecification;
import org.fortiss.af3.mira.model.safety.FTASolutionRequirementSpecification;
import org.fortiss.af3.mira.model.safety.HazardRequirementSpecification;
import org.fortiss.af3.mira.model.safety.MooNSolutionRequirementSpecification;
import org.fortiss.af3.mira.model.security.Assets;
......@@ -113,6 +114,11 @@ public class RequirementCompositor extends HierarchicElementCompositorBase<Requi
if(moonsol == null && contained instanceof MooNSolutionRequirementSpecification) {
return true;
}
FTASolutionRequirementSpecification ftasol =
pickFirstInstanceOf(FTASolutionRequirementSpecification.class, specs);
if(ftasol == null && contained instanceof FTASolutionRequirementSpecification) {
return true;
}
if(contained instanceof ParameterDefinition || contained instanceof TimingRequirement) {
return true;
......
......@@ -45,6 +45,7 @@ import org.fortiss.af3.mira.model.functional.FunctionalSpecification;
import org.fortiss.af3.mira.model.functional.SignalContainerSpecification;
import org.fortiss.af3.mira.model.glossary.Glossary;
import org.fortiss.af3.mira.model.requirementSource.RequirementSource;
import org.fortiss.af3.mira.model.safety.FTASolutionRequirementSpecification;
import org.fortiss.af3.mira.model.safety.HazardRequirementSpecification;
import org.fortiss.af3.mira.model.safety.MooNSolutionRequirementSpecification;
import org.fortiss.af3.mira.model.safety.SafetyFactory;
......@@ -127,6 +128,10 @@ public class PrototypeProvider extends PrototypeProviderBase {
SafetyFactory.eINSTANCE.createMooNSolutionRequirementSpecification();
registerPrimaryPrototype("Safety - MooN Solution aspect", moonsol, CATEGORY_NAME);
FTASolutionRequirementSpecification ftasol =
SafetyFactory.eINSTANCE.createFTASolutionRequirementSpecification();
registerPrimaryPrototype("Safety - FTA Solution aspect", ftasol, CATEGORY_NAME);
Assets a = MiraModelElementFactory.createAssets();
registerPrimaryPrototype("Assets", a, CATEGORY_NAME);
......
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