blob: 5a2d9d61c9d65533b5821cfe643ea6ec7e8df660 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 Honeywell, Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Vit Koksa <Vit.Koksa@honeywell.com>
* Initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.opencert.vavmanager;
import java.lang.reflect.Array;
//import org.polarsys.chess.contracts.profile.chesscontract.impl.ContractImpl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
//import java.util.stream.Stream;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.Type;
import org.polarsys.chess.contracts.profile.chesscontract.Contract;
import org.polarsys.chess.contracts.profile.chesscontract.ContractProperty;
import org.polarsys.chess.contracts.profile.chesscontract.FormalProperty;
import org.eclipse.uml2.uml.internal.impl.PortImpl;
//import org.polarsys.chess.utils;
import org.eclipse.uml2.uml.internal.impl.PropertyImpl;
import org.eclipse.xtext.util.Pair;
//import org.eclipse.uml2.uml.internal.impl.ClassifierImpl;
//import org.eclipse.emf.common.util.EList;
//import org.eclipse.uml2.uml.Property;
//import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.Class;
//import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Element;
//import org.eclipse.uml2.uml.Port;
//import org.eclipse.uml2.uml.Constraint;
//import org.eclipse.uml2.uml.Namespace;
import org.polarsys.chess.contracts.profile.chesscontract.util.Constants;
import org.polarsys.chess.contracts.profile.chesscontract.util.ContractEntityUtil;
import org.polarsys.chess.contracts.profile.chesscontract.util.EntityUtil;
public class RequestWriter {
private static final String CONTRACTPROP = "CHESSContract::ContractProperty";
private static final String FORMPROP = "CHESSContract::FormalProperty";
private static ContractEntityUtil contractEntityUtil = ContractEntityUtil.getInstance();
private static EntityUtil entityUtil = EntityUtil.getInstance();
/* Has the element a given stereotype? */
public static Boolean hasStereotype(Element elt, String stereotype) { // "Contract", "Block"
return elementHasType(elt, stereotype);
}
/* Is the input really a Component? */
public static Boolean isComponent(Element elt) {
return elementHasType(elt, "Block");
}
/* Has the element a given stereotype? */
public static Boolean elementHasType(Element elt, String type) {
boolean hasType = false;
EList<Stereotype> stList = ((Element) elt).getAppliedStereotypes();
String stName;
stereotypes:
for (Stereotype st : stList) {
stName = st.getName();
if (stName.equals(type)) {
hasType = true;
break stereotypes;
}
}
return hasType;
}
public static String mergeInputs(String inOuts) { // inOuts = ".inputs i1, i2\n.outputs o1\n.inputs i1, i3, i4\n.outputs o2"
String[] lines;
lines = inOuts.split("\n"); // lines = [".inputs i1, i2", ".outputs o1", ".inputs i1, i3, i4", ".outputs o2"]
String[] ins = Arrays.stream(lines).filter(x -> x.startsWith(".inputs")).toArray(String[]::new); // ins = [".inputs i1, i2", ".inputs i1, i3, i4"]
String[] outs = Arrays.stream(lines).filter(x -> x.startsWith(".outputs")).toArray(String[]::new); // outs = [".outputs o1", ".outputs o2"]
List<String> listOfInputs = new ArrayList<String>(); // listOfInputs = ["i1", "i2", "i3", "i4"]
for (String insStr : ins) {
lines = insStr.replaceFirst("^.inputs", "").split(","); // lines variable is recycled
for (String inStr : lines) {
listOfInputs.add(inStr.trim());
}
}
Set<String> set = new HashSet<String>(listOfInputs); // remove duplicates
lines = set.toArray(new String[set.size()]); // lines variable is recycled
listOfInputs = Arrays.asList(lines);
List<String> listOfOutputs = new ArrayList<String>(); // listOfOutputs = ["o1", "o2"]
for (String outsStr : outs) {
lines = outsStr.replaceFirst("^.outputs", "").split(","); // lines variable is recycled
for (String outStr : lines) {
listOfOutputs.add(outStr.trim());
}
}
set = new HashSet<String>(listOfOutputs); // remove duplicates
lines = set.toArray(new String[set.size()]); // lines variable is recycled
listOfOutputs = Arrays.asList(lines);
String stringOfInputs = String.join(" ", listOfInputs); // stringOfInputs = "i1 i2 i3 i4"
String stringOfOutputs = String.join(" ", listOfOutputs); // stringOfOutputs = "o1 o2"
String result = ".inputs " + stringOfInputs + "\n.outputs " + stringOfOutputs;
return result; // result = ".inputs i1 i2 i3 i4\n.outputs o1 o2"
}
public static String extractAssume(Element elt) {
String assume = ""; // the variable whose content will be returned by the function
/* Get the assumption of the contract. */
if (hasStereotype(elt, "Contract")) {
if (elt instanceof Class) {
return ""; // Currently selected Contract is not supported. Classification of signals to either input or output is not realised.
//assume = contractEntityUtil.getAssumeStrFromUmlContract((Class) elt);
} else {
throw new RuntimeException("elt has the <Contract> stereotype, but is not of type Class.");
}
} else {
/* Get the assumes of the component. */
if (hasStereotype(elt, "Block")) {
EList<ContractProperty> contrProp = contractEntityUtil.getContractProperties((Class) elt);
Class contractBaseClass = null;
Contract contract = null;
FormalProperty assumptionFP = null;
StringBuffer sBuf = new StringBuffer();
for (ContractProperty prop : contrProp){
contractBaseClass = (Class) prop.getBase_Property().getType();
contract = (Contract) contractBaseClass.getStereotypeApplication(contractBaseClass.getAppliedStereotype(Constants.CONTRACT));
assumptionFP = contract.getAssume();
sBuf.append("\n" + assumptionFP.getBase_Constraint().getSpecification().stringValue());
}
assume = sBuf.toString();
assume = mergeInputs(assume);
}
}
return assume;
}
/**
* get the contents of the element
*
* @param selectedElement
* @return the root element
*/
/* private static TreeIterator<EObject> getAllContents(EObject selectedElement) {
TreeIterator<EObject> selectedContents = selectedElement.eAllContents();
return selectedContents;
}
*/
public static String extractGuaranteeFromComponent(Element elt) {
String guarantee = ""; // the variable whose content will be returned by the function
if (elt instanceof Class) {
EList<ContractProperty> contrProp = contractEntityUtil.getContractProperties((Class) elt);
Class contractBaseClass = null;
Contract contract = null;
FormalProperty guaranteeFP = null;
StringBuffer sBuf = new StringBuffer();
for (ContractProperty prop : contrProp){
contractBaseClass = (Class) prop.getBase_Property().getType();
contract = (Contract) contractBaseClass.getStereotypeApplication(contractBaseClass.getAppliedStereotype(Constants.CONTRACT));
guaranteeFP = contract.getGuarantee();
sBuf.append("\n" + guaranteeFP.getBase_Constraint().getSpecification().stringValue());
}
guarantee = sBuf.toString();
return guarantee.trim();
} else {
MessageDialog.openInformation(VAndVManagerCommand.shell, "Selected element can have no related guarantee.",
"Please, change your selection.");
return "";
}
}
public static String extractGuarantee(Element elt) {
String guarantee = ""; // the variable whose content will be returned by the function
/* Get the guarantee of the contract. */
if (hasStereotype(elt, "Contract")) {
if (elt instanceof Class) {
MessageDialog.openInformation(VAndVManagerCommand.shell, "The V&V Manager currently does not check contracts.",
"The needed classification of signals as either inputs or outputs is not realised for contracts."
+ "\nPlease, do not select contracts for V&V Manager.");
return "";
//guarantee = contractEntityUtil.getGuaranteeStrFromUmlContract((Class) elt);
} else {
throw new RuntimeException("elt has the <Contract> stereotype, but is not of type Class.");
}
} else {
/* Get the guarantees of the component (and optionally also of the subcomponents). */
if (hasStereotype(elt, "Block")) {
boolean alsoSub;
// EList<Element> listObjs = elt.getOwnedElements(); // eContents();
TreeIterator<EObject> titer = elt.eAllContents(); //getAllContents(elt);
int nodeCount = 0;
EObject eobj;
PropertyImpl property;
boolean isProperty;
boolean isBlock;
treeIteration:
while (titer.hasNext()) {
eobj = titer.next();
String str = eobj.getClass().getName();
isProperty = str.endsWith("PropertyImpl");
if (isProperty) { // && hasStereotype((Element)eobj, "part")) {
property = (PropertyImpl) eobj;
Type type = property.getType();
EList<Stereotype> stereotypes = type.getAppliedStereotypes();
for (Stereotype stype : stereotypes) {
isBlock = stype.getName().equals("Block");
if (isBlock) {
nodeCount++;
if (nodeCount == 1) { // Validated element has at least one subcomponent.
alsoSub = MessageDialog.openQuestion(VAndVManagerCommand.shell, "Include contracts of subcomponents?",
"The selected block has subblock(s). Should their formal properties be included in the validation/verification?");
if (!alsoSub) {
guarantee = extractGuaranteeFromComponent(elt); // Process just the selected component.
break treeIteration; // while (titer.hasNext())
}
}
guarantee += "\n" + extractGuaranteeFromComponent((Element) type);
}
}
}
}
if (nodeCount == 0) { // selected component has no subcomponents.
guarantee = extractGuaranteeFromComponent(elt);
}
}
}
return guarantee.trim();
}
public static String extractLtl(Element contract) {
//Class cl = contract.getClass();
String ltl = "No LTL.";
EList<Stereotype> stList = ((Element) contract).getAppliedStereotypes();
boolean isContract = false;
String stName;
stereotypes:
for (Stereotype st : stList) {
stName = st.getName();
if (stName.equals("Contract")) {
isContract = true;
if (contract instanceof Class) {
//String str = contractEntityUtil.getAssumeStrFromUmlContract((Class) contract);
ltl = contractEntityUtil.getGuaranteeStrFromUmlContract((Class) contract);
break stereotypes;
} else {
throw new RuntimeException("elt has the <Contract> stereotype, but is not of type Class.");
}
}
}
/*
List<Constraint> allFormalProps = new ArrayList<Constraint>();
List<Property> allContractProperties = new ArrayList<Property>();
if (contract instanceof Property){
if (contract.getAppliedStereotype(CONTRACTPROP) != null){
allContractProperties.add((Property) contract);
}
}
if (contract instanceof Constraint && contract.getAppliedStereotype(FORMPROP) != null){
allFormalProps.add((Constraint)contract);
}
if (isContract) {
for (Element elt : contract.allOwnedElements()) {
if (elt instanceof Constraint) {
System.out.println("asdf");
}
}
//Property pr = ((Classifier) contract).get //getOwnedAttribute("Assume", null);
List<Property> props = ((Classifier) contract).getAttributes();
for (Property prop : props) {
String propName = prop.getName();
if (propName.equals("Assume")) {
ltl = "aaa";
}
}
}
if (contract != null) {
//ContractImpl cntrct = (ContractImpl) contract;
//ltl = cntrct.getAssume().getBase_Constraint().getSpecification().toString();
return ltl;
}
*/
return ltl;
}
public static String[] getInputPortsNames(Element elt) {
String[] inputPortsNames = entityUtil.getInputPortsNames(elt,false);
return inputPortsNames;
}
public static String[] getOutputPortsNames(Element elt) {
String[] outputPortsNames = entityUtil.getOutputPortsNames(elt,false);
return outputPortsNames;
}
public static String[] getInputOutputPortsNames(Element elt) {
String[] inputOutputPortsNames = entityUtil.getInputOutputPortsNames(elt,false);
return inputOutputPortsNames;
}
/* public static EList<PortImpl> getPorts(Element elt) {
EList<PortImpl> portList = new BasicEList<PortImpl>();
String[] inputPortNames, outputPortNames, inputOutputPortNames;
// Get the guarantees of the component (and optionally also of the subcomponents).
if (hasStereotype(elt, "Block")) {
inputPortNames = entityUtil.getInputPortsNames(elt);
outputPortNames = entityUtil.getOutputPortsNames(elt);
inputOutputPortNames = entityUtil.getInputOutputPortsNames(elt);
boolean alsoSub;
//EList<Element> listObjs = elt.getOwnedElements(); // eContents();
TreeIterator<EObject> titer = elt.eAllContents(); //getAllContents(elt);
int nodeCount = 0;
EObject eobj;
PortImpl port;
boolean isPort;
boolean isBlock;
int direction;
treeIteration:
while (titer.hasNext()) {
eobj = titer.next();
//String str = eobj.getClass().getName();
//isPort = str.endsWith("PortImpl");
isPort = entityUtil.isPort((Element) eobj);
if (isPort) { // && hasStereotype((Element)eobj, "part")) {
direction = entityUtil.getPortDirection((Element) eobj);
port = (PortImpl) eobj;
portList.add(port);
//Type type = port.getType();
}
}
}
return portList;
}
*/
static Set<String> extractSignalsFromLtl(String ltl) {
String[] signals = null;
Set<String> sigs = new HashSet<String>(); // signals and filtered signals
signals = ltl.split("[()\n &|!]+");
for (String sig : signals) {
if (!sig.equals("G") && !sig.equals("X") && !sig.equals("F") && !sig.equals("U") && !sig.equals("->") && !sig.equals("<->")) {
sigs.add(sig);
}
}
return sigs;
}
/*
* result[0] .. inputs
* result[1] .. outputs
*/
static String extractInputsAndOutputs(Set<String> signalsFromLtl,
String[] inputPortNames, String[] outputPortsNames, String[] inputOutputPortsNames) {
String inputs = "";
String outputs = "";
for (String sig : signalsFromLtl) {
boolean isInput = false;
boolean isOutput = false;
for (String inp : inputPortNames) {
if (sig.startsWith(inp) || sig.endsWith(inp)) {
isInput = true;
}
}
for (String outp : outputPortsNames) {
if (sig.startsWith(outp) || sig.endsWith(outp)) {
isOutput = true;
}
}
for (String inoutp : inputOutputPortsNames) {
if (sig.startsWith(inoutp) || sig.endsWith(inoutp)) {
isOutput = true;
}
}
if (isOutput) {
outputs += " " + sig;
}
if (isInput) {
inputs += " " + sig;
}
if (isInput && isOutput) {
MessageDialog.openInformation(VAndVManagerCommand.shell, "The V&V Manager unable to distiguish input from output.",
"The following signal seems to be input and output at the same time: " + sig
+ " . Not sure how to submit it to the verification."
+ "\nPlease, consider renaming of the signals or of the ports.");
}
if (! isInput && ! isOutput) {
MessageDialog.openInformation(VAndVManagerCommand.shell, "The V&V Manager: signal neither input nor output.",
"The following signal could be identified neither as input nor as output: " + sig
+ " . Not sure how to submit it to the verification."
+ "\nPlease, consider renaming of the signals or of the ports.");
}
}
return ".inputs" + inputs + "\n.outputs" + outputs;
}
}