Commit c08271f5 authored by Vivek Nigam's avatar Vivek Nigam
Browse files

<mira> Safety Aspects



* Corrected Bugs
* Implemented the editor for MooNSolutions

Issue-Ref: 3418
Signed-off-by: Vivek Nigam's avatarVivek Nigam <nigam@fortiss.org>
parent cf95dbba
......@@ -6,6 +6,7 @@ DateToStringConverter.java c969b068ea1dfd77b7153dd8937dca2e4b5630b7 GREEN
DerivedRequirementEditor.java b63b7200096998268b777f6060076073cb018a89 GREEN
FormalSpecificationTreeContentProvider.java 469e589d7911316da6a52b4cbd97a59fcc720a97 GREEN
FunctionalRequirementEditor.java 386dd8b065aea7e155a60823cdd73b35100185cc GREEN
HazardRequirementEditor.java 0985139682ed38747b10ed0a9b39d936ce68a12e YELLOW
InterfaceBehaviourAspectEditor.java ca70f1f82fca7f92e95ff83bf049c9383d5a781e GREEN
InterfaceBehaviourEditor.java be0a51fa8116f1c47b5d706935dfb17a19c775e5 GREEN
InterfaceBehaviourSectionExtension.java ead6ef67dd9aeafb070db4bd1fc9a0e8829af418 GREEN
......
......@@ -76,10 +76,8 @@ public class HazardRequirementEditor<T extends Requirement> extends AspectEditor
bind(dbc, inputName.getTextWidget(), spec, INAMED_ELEMENT__NAME);
ComboViewer standardInput =
createSingleLineFixedInputRequirementField(hazardSection, "Hazard Impact",
HazardImpact.values(), spec,
HAZARD_REQUIREMENT_SPECIFICATION__HAZARD_IMPACT);
createSingleLineFixedInputRequirementField(hazardSection, "Hazard Impact",
HazardImpact.values(), spec, HAZARD_REQUIREMENT_SPECIFICATION__HAZARD_IMPACT);
}
/** {@inheritDoc} */
......
/*-------------------------------------------------------------------------+
| Copyright 2018 fortiss GmbH |
| Copyright 2011 fortiss GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
......@@ -15,30 +15,275 @@
+--------------------------------------------------------------------------*/
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.model.safety.SafetyPackage.Literals.MOO_NSOLUTION_REQUIREMENT_SPECIFICATION__VOTER_THRESHOLD;
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.Shell;
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.MooNSolutionRequirementSpecification;
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;
/**
* Editor for MooN Solution Aspects.
* Editor for the functional specification aspect of a {@link Requirement}.
*
* @author vivek
* @author abid
*/
public class MooNSolutionRequirementEditor<T extends Requirement> extends AspectEditorBase<T> {
/** The edited functional specification. */
private MooNSolutionRequirementSpecification spec;
/** The default shell - for component dialog. */
private Shell shell;
/** 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 functional component table. */
private static final String CLICK_TO_ADD_A_NEW_SIGNAL = "Click to add a new signal";
/**
* The tree viewer displaying the functional component. 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() {
// TODO Auto-generated method stub
localRegisteredSourceViewers = new ArrayList<SourceViewer>();
EList<IModelElementSpecification> specs = editedObject.getSpecifications();
spec = pickFirstInstanceOf(MooNSolutionRequirementSpecification.class, specs);
addMooNHeaderSection(spec);
addSignalSection(spec);
}
/**
* Definition of the Hazard section
*/
private void addMooNHeaderSection(MooNSolutionRequirementSpecification spec) {
Composite headerSection =
createNewSection("MooN Solution Requirement",
"This requirement defines Voter parameters:");
headerSection.setLayout(new GridLayout(2, false));
Label nameLabel = toolkit.createLabel(headerSection, "Voter 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);
Label thresholdLabel =
toolkit.createLabel(headerSection, "Voter Threshold (M): ", SWT.READ_ONLY);
singleLineLabelFactory.applyTo(thresholdLabel);
SourceViewer thredsholdVal = createSourceViewer(form, headerSection, SWT.BORDER, analysis);
registeredSourceViewers.add(thredsholdVal);
singleLineInputFactory.applyTo(thredsholdVal.getControl());
bind(dbc, thredsholdVal.getTextWidget(), spec,
MOO_NSOLUTION_REQUIREMENT_SPECIFICATION__VOTER_THRESHOLD);
}
/** Section for functional component. */
private Composite addSignalSection(MooNSolutionRequirementSpecification ms) {
Composite moonSection =
createNewSection("Input Signals",
"This requirement defines the following M out of N Voter Solution:");
moonSection.setLayout(new GridLayout(1, false));
viewer = new TreeViewer(moonSection, 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 signal component";
}
return spec.getInputSignals().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.getInputSignals().size() - 1).boxed()
.collect(Collectors.toList()));
return range.toArray();
}
return new Object[0];
}
});
viewer.getControl().addKeyListener(new ViewerKeyAdapter());
viewer.setInput(spec.getInputSignals());
return moonSection;
}
/** 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.getInputSignals().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.getInputSignals().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.getInputSignals().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();
}
}
}
/** {@inheritDoc} */
@Override
protected List<IModelElementSpecification> getElementsToDelete() {
// TODO Auto-generated method stub
return null;
ArrayList<IModelElementSpecification> res = new ArrayList<>();
res.addAll(pickInstanceOf(MooNSolutionRequirementSpecification.class,
editedObject.getSpecifications()));
return res;
}
}
This diff is collapsed.
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