Skip to content
Snippets Groups Projects
Commit 5285bd4d authored by Vincent Aravantinos's avatar Vincent Aravantinos
Browse files

new form of contracts

refs 2334
parent c6dafe9c
No related branches found
No related tags found
No related merge requests found
......@@ -23,6 +23,7 @@ Export-Package: org.fortiss.tooling.kernel;uses:="org.eclipse.core.runtime,org.o
org.fortiss.tooling.kernel.introspection,
org.fortiss.tooling.kernel.introspection.items,
org.fortiss.tooling.kernel.model;uses:="org.eclipse.emf.ecore",
org.fortiss.tooling.kernel.model.constraints,
org.fortiss.tooling.kernel.model.impl;uses:="org.fortiss.tooling.kernel.model",
org.fortiss.tooling.kernel.model.util;
uses:="org.eclipse.emf.ecore,
......
......@@ -119,4 +119,42 @@
<eParameters name="target" eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject"/>
</eOperations>
</eClassifiers>
<eSubpackages name="constraints" nsURI="http://www.fortiss.org/tooling/base/model/element/constraints"
nsPrefix="org-fortiss-tooling-kernel-constraints">
<eClassifiers xsi:type="ecore:EClass" name="IConstrained" abstract="true" interface="true">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Element which can be constrained. Keeps track of all the constraints which apply to it."/>
</eAnnotations>
<eStructuralFeatures xsi:type="ecore:EReference" name="constraints" upperBound="-1"
eType="#//constraints/IConstraint" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="IConstraint" abstract="true" interface="true">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Constraint. Can be anything as long as there is a corresponding ConstraintVerifier."/>
</eAnnotations>
<eStructuralFeatures xsi:type="ecore:EReference" name="constrainedsWithChecksum"
upperBound="-1" eType="#//constraints/ConstrainedWithChecksum"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="verificationStatus" eType="#//constraints/IConstraintVerificationStatus"
containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="IConstraintVerificationStatus" abstract="true"
interface="true">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Status of verification of a constraint. Typically, should denote &quot;Success&quot;, &quot;Fail&quot;, &quot;Outdated&quot; or &quot;Error&quot; with possible specializations depending on the particular constraints."/>
</eAnnotations>
<eStructuralFeatures xsi:type="ecore:EReference" name="constraint" eType="#//constraints/IConstraint"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="ConstrainedWithChecksum">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="documentation" value="Pair of a reference to a constrained element, and the checksum of this element when the constraint was last checked."/>
</eAnnotations>
<eStructuralFeatures xsi:type="ecore:EReference" name="constrained" eType="#//constraints/IConstrained"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="checksum" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBigInteger"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="IAutoCheck" abstract="true" interface="true"/>
<eClassifiers xsi:type="ecore:EClass" name="OutdatedVerificationStatus" eSuperTypes="#//constraints/IConstraintVerificationStatus"/>
<eClassifiers xsi:type="ecore:EClass" name="FailVerificationStatus" eSuperTypes="#//constraints/IConstraintVerificationStatus"/>
<eClassifiers xsi:type="ecore:EClass" name="ErrorVerificationStatus" eSuperTypes="#//constraints/IConstraintVerificationStatus"/>
<eClassifiers xsi:type="ecore:EClass" name="SuccessVerificationStatus" eSuperTypes="#//constraints/IConstraintVerificationStatus"/>
</eSubpackages>
</ecore:EPackage>
......@@ -53,5 +53,31 @@
<genParameters ecoreParameter="kernel.ecore#//ISpeciallyCopyiable/canPaste/target"/>
</genOperations>
</genClasses>
<nestedGenPackages prefix="Constraints" basePackage="org.fortiss.tooling.kernel.model"
disposableProviderFactory="true" ecorePackage="kernel.ecore#//constraints">
<genClasses image="false" ecoreClass="kernel.ecore#//constraints/IConstrained">
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference kernel.ecore#//constraints/IConstrained/constraints"/>
</genClasses>
<genClasses image="false" ecoreClass="kernel.ecore#//constraints/IConstraint">
<genFeatures notify="false" createChild="false" propertySortChoices="true"
ecoreFeature="ecore:EReference kernel.ecore#//constraints/IConstraint/constrainedsWithChecksum"/>
<genFeatures notify="false" createChild="false" propertySortChoices="true"
ecoreFeature="ecore:EReference kernel.ecore#//constraints/IConstraint/verificationStatus"/>
</genClasses>
<genClasses ecoreClass="kernel.ecore#//constraints/IConstraintVerificationStatus">
<genFeatures notify="false" createChild="false" propertySortChoices="true"
ecoreFeature="ecore:EReference kernel.ecore#//constraints/IConstraintVerificationStatus/constraint"/>
</genClasses>
<genClasses ecoreClass="kernel.ecore#//constraints/ConstrainedWithChecksum">
<genFeatures notify="false" createChild="false" propertySortChoices="true"
ecoreFeature="ecore:EReference kernel.ecore#//constraints/ConstrainedWithChecksum/constrained"/>
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute kernel.ecore#//constraints/ConstrainedWithChecksum/checksum"/>
</genClasses>
<genClasses image="false" ecoreClass="kernel.ecore#//constraints/IAutoCheck"/>
<genClasses ecoreClass="kernel.ecore#//constraints/OutdatedVerificationStatus"/>
<genClasses ecoreClass="kernel.ecore#//constraints/FailVerificationStatus"/>
<genClasses ecoreClass="kernel.ecore#//constraints/ErrorVerificationStatus"/>
<genClasses ecoreClass="kernel.ecore#//constraints/SuccessVerificationStatus"/>
</nestedGenPackages>
</genPackages>
</genmodel:GenModel>
......@@ -11,6 +11,7 @@
<extension-point id="modelConnectionCompositor" name="Model Connection Compositor" schema="schema/modelConnectionCompositor.exsd"/>
<extension-point id="transformationProvider" name="Transformation Provider" schema="schema/transformationProvider.exsd"/>
<extension-point id="migrationProvider" name="Model Migration Provider" schema="schema/migrationProvider.exsd"/>
<extension-point id="constraintVerifier" name="Constraint Verifier" schema="schema/constraintVerifier.exsd"/>
<extension
point="org.eclipse.emf.ecore.generated_package">
<package
......
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.fortiss.af3.verification" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appinfo>
<meta.schema plugin="org.fortiss.tooling.kernel" id="constraintVerifier" name="Constraint Verifier"/>
</appinfo>
<documentation>
[Enter description of this extension point.]
</documentation>
</annotation>
<element name="extension">
<annotation>
<appinfo>
<meta.element />
</appinfo>
</annotation>
<complexType>
<sequence>
<element ref="constraintVerifier" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appinfo>
<meta.attribute translatable="true"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="constraintVerifier">
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="constraint" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
<attribute name="constraintVerifier" type="string">
<annotation>
<documentation>
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.fortiss.tooling.kernel.extension.IConstraintVerifier"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="constraint">
<complexType>
<attribute name="constraint" type="string">
<annotation>
<documentation>
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.fortiss.tooling.kernel.model.constraints.IConstraint"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appinfo>
<meta.section type="since"/>
</appinfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="examples"/>
</appinfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="apiinfo"/>
</appinfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appinfo>
<meta.section type="implementation"/>
</appinfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
</schema>
/*--------------------------------------------------------------------------+
$Id$
| |
| Copyright 2015 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.tooling.kernel.extension;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.fortiss.tooling.kernel.model.constraints.IConstraint;
import org.fortiss.tooling.kernel.model.constraints.IConstraintVerificationStatus;
import org.fortiss.tooling.kernel.service.IConstraintVerificationService.IFix;
import org.fortiss.tooling.kernel.service.base.IEObjectAware;
/**
* Interface for constraint verifiers.
*
* @author aravantinos
* @author $Author$
* @version $Rev$
* @ConQAT.Rating YELLOW Hash: 0B7B6771FF679E18B7D7AC77D5BE5A70
*/
public interface IConstraintVerifier<T extends IConstraint> extends IEObjectAware<T> {
/** Verify the given constraint. */
public void verify(T constraint);
/**
* @param obj
* Alters <code>obj</code> so that the contained items which should not be considered
* when computing the checksum have been removed.
*/
public void getChecksumRelevantEObject(EObject obj);
/**
* Returns a list of possible automatic fixes for the (constraint of the) given status.
* A status should be candidate to fixing if it is anything but successful or outdated.
*/
public List<IFix> fixes(IConstraintVerificationStatus status);
}
package org.fortiss.tooling.kernel.internal;
import static org.eclipse.emf.ecore.xmi.XMLResource.OPTION_PROCESS_DANGLING_HREF;
import static org.eclipse.emf.ecore.xmi.XMLResource.OPTION_PROCESS_DANGLING_HREF_DISCARD;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.fortiss.tooling.kernel.ToolingKernelActivator;
import org.fortiss.tooling.kernel.extension.IConstraintVerifier;
import org.fortiss.tooling.kernel.model.constraints.ConstrainedWithChecksum;
import org.fortiss.tooling.kernel.model.constraints.ConstraintsFactory;
import org.fortiss.tooling.kernel.model.constraints.IConstrained;
import org.fortiss.tooling.kernel.model.constraints.IConstraint;
import org.fortiss.tooling.kernel.model.constraints.IConstraintVerificationStatus;
import org.fortiss.tooling.kernel.service.IConstraintVerificationService;
import org.fortiss.tooling.kernel.service.base.EObjectAwareServiceBase;
import org.fortiss.tooling.kernel.utils.EcoreUtils;
import org.fortiss.tooling.kernel.utils.LoggingUtils;
/**
* Implementation of {@link IConstraintVerificationService}.
*
* @author aravantinos
* @author $Author$
* @version $Rev$
* @ConQAT.Rating YELLOW Hash: B05A05B14D8FC6C1B85465F70CA4748C
*/
public final class ConstraintVerificationService extends
EObjectAwareServiceBase<IConstraintVerifier<IConstraint>> implements
IConstraintVerificationService {
/** {@inheritDoc} */
@Override
public void verify(IConstraint constraint) {
IConstraintVerifier<IConstraint> verifier = getFirstVerifier(constraint);
if(verifier != null) {
verifier.verify(constraint);
// Updating checksums must be done *after* verification because the verification can
// have side effects.
updateChecksums(constraint);
}
}
/** {@inheritDoc} */
@Override
public List<IFix> fixes(IConstraintVerificationStatus status) {
if(status != null) {
IConstraintVerifier<IConstraint> verifier = getFirstVerifier(status.getConstraint());
if(verifier != null) {
return verifier.fixes(status);
}
}
return new ArrayList<IFix>();
}
/**
* @param constraint
* @return <code>true</code> if <code>constraint</code> is up to date, <code>false</code>
* otherwise.
*/
@Override
public boolean isUpToDate(IConstraint constraint) {
for(ConstrainedWithChecksum cwc : constraint.getConstrainedsWithChecksum()) {
BigInteger computeCheckSum = computeCheckSum(cwc.getConstrained(), constraint);
if(computeCheckSum == null || !computeCheckSum.equals(cwc.getChecksum())) {
return false;
}
}
return true;
}
/**
* @param constraint
* Updates all the checksums of <code>constraint</code>.
*/
private void updateChecksums(IConstraint constraint) {
List<ConstrainedWithChecksum> newCwcs = new ArrayList<ConstrainedWithChecksum>();
for(ConstrainedWithChecksum cwc : constraint.getConstrainedsWithChecksum()) {
ConstrainedWithChecksum newCwc =
ConstraintsFactory.eINSTANCE.createConstrainedWithChecksum();
newCwc.setConstrained(cwc.getConstrained());
newCwc.setChecksum(computeCheckSum(cwc.getConstrained(), constraint));
newCwcs.add(newCwc);
}
EcoreUtils.disableNotificationsOf(constraint);
constraint.getConstrainedsWithChecksum().clear();
constraint.getConstrainedsWithChecksum().addAll(newCwcs);
EcoreUtils.enableNotificationsOf(constraint);
}
/**
* Flag to print the object which is actually checksummed in a file.
* TODO: remove when the experimental phase for constraints is over.
*/
private final boolean DEBUG = false;
/**
* @param constrained
* @param constraint
* @return the checksum of <code>constrained</code>. Note that <code>constraint</code> is
* necessary because it has a potential impact on what is relevant for the checksum or
* not.
*/
protected BigInteger computeCheckSum(IConstrained constrained, IConstraint constraint) {
if(constrained == null) {
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
final ObjectOutputStream oos;
final EObject hashRelevant = getChecksumRelevantEObject(constrained, constraint);
try {
final ResourceSet rset = new ResourceSetImpl();
oos = new ObjectOutputStream(baos);
Resource res = rset.createResource(URI.createURI("temp"));
res.getContents().add(hashRelevant);
Map<String, String> options = new HashMap<>();
// The option below is to allow computing the hashsum of an incomplete ecore sub-model,
// which is wanted in case parts of the model which are not checksum relevant are still
// referred to.
options.put(OPTION_PROCESS_DANGLING_HREF, OPTION_PROCESS_DANGLING_HREF_DISCARD);
res.save(oos, options);
if(DEBUG) {
FileOutputStream file = new FileOutputStream("/home/aravantinos/temp.xml");
ObjectOutputStream oos2 = new ObjectOutputStream(file);
res.save(oos2, options);
oos2.close();
}
oos.close();
MessageDigest m = MessageDigest.getInstance("SHA1");
m.update(baos.toByteArray());
res.getContents().remove(hashRelevant);
res.delete(options);
return new BigInteger(1, m.digest());
} catch(Exception e) {
e.printStackTrace();
return null;
}
}
/**
* @param constrained
* @return The object to be used to compute the check sum.
* Generally, all verification statuses and checksums are removed. Each verifier can
* also provide per-constraint adaptations.
*/
protected EObject getChecksumRelevantEObject(IConstrained constrained, IConstraint constraint) {
EObject res = EcoreUtils.copy(constrained);
IConstraintVerifier<IConstraint> verifier = getFirstVerifier(constraint);
if(verifier != null) {
verifier.getChecksumRelevantEObject(res);
}
return res;
}
/**
* @param constraint
* @return the first registered verifier which can verify <code>constraint</code>
*/
protected IConstraintVerifier<IConstraint> getFirstVerifier(IConstraint constraint) {
List<IConstraintVerifier<IConstraint>> list = getRegisteredHandlers(constraint.getClass());
if(list == null || list.isEmpty()) {
LoggingUtils.error(ToolingKernelActivator.getDefault(),
String.format("Cannot find verifier for constraint %s", constraint.getClass()));
return null;
}
// get(0) because we know the list is not empty and because we want the first element
return list.get(0);
}
/** {@inheritDoc} */
@Override
protected String getExtensionPointName() {
return "org.fortiss.tooling.kernel.constraintVerifier";
}
/** {@inheritDoc} */
@Override
protected String getConfigurationElementName() {
return "constraintVerifier";
}
/** {@inheritDoc} */
@Override
protected String getHandlerClassAttribute() {
return "constraintVerifier";
}
/** {@inheritDoc} */
@Override
protected String getClassAttribute() {
return "constraint";
}
/** {@inheritDoc} */
@Override
protected String getClassConfigurationElement() {
return "constraint";
}
}
package org.fortiss.tooling.kernel.service;
import java.util.List;
import java.util.function.Consumer;
import org.fortiss.tooling.kernel.internal.ConstraintVerificationService;
import org.fortiss.tooling.kernel.model.constraints.IConstraint;
import org.fortiss.tooling.kernel.model.constraints.IConstraintVerificationStatus;
/**
* The verification service allows to register "constraint verifiers", e.g.,
* a test suite runner, a temporal logic verifier, a WCET checker, a requirement review system.
*
* @author aravantinos
* @author $Author$
* @version $Rev$
* @ConQAT.Rating YELLOW Hash: 4B668DE0AB4D3B36FB5A7B8C72CA6B98
*/
public interface IConstraintVerificationService {
/** Returns the singleton instance of the service. */
public static final IConstraintVerificationService INSTANCE =
new ConstraintVerificationService();
/** Verifies the given constraint. */
public void verify(IConstraint constraint);
/** True if the given constraint is up to date. */
public boolean isUpToDate(IConstraint constraint);
/**
* Returns a list of possible automatic fixes for the (constraint of the) given status.
* A status should be candidate to fixing if it is anything but successful or outdated.
*/
public List<IFix> fixes(IConstraintVerificationStatus status);
/** Interface for a "fix". */
public interface IFix {
/**
* Description of the fix. Useful to allow the user distinguish the fix in case there are
* several.
*/
public String getDescription();
/**
* @param status
* Fixes (the constraint of) <code>status</code>.
*/
public void runFix(IConstraintVerificationStatus status);
}
/** Base for fixes. */
public static class FixBase implements IFix {
/** The description. */
private String description;
/** The fix itself. */
private Consumer<IConstraintVerificationStatus> fix;
/** Constructor. */
public FixBase(String description, Consumer<IConstraintVerificationStatus> fix) {
this.description = description;
this.fix = fix;
}
/** {@inheritDoc} */
@Override
public String getDescription() {
return description;
}
/** {@inheritDoc} */
@Override
public void runFix(IConstraintVerificationStatus status) {
fix.accept(status);
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment