Skip to content
Snippets Groups Projects
Commit 1a77694e authored by Johannes Eder's avatar Johannes Eder
Browse files

removed all Constraint related stuff

parent bca08638
No related branches found
No related tags found
1 merge request!853891: FOCUSer removal
Showing
with 1 addition and 897 deletions
/*-------------------------------------------------------------------------+
| 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 org.fortiss.tooling.kernel.model.constraints.ConstraintInstance;
import org.fortiss.tooling.kernel.model.constraints.IConstrained;
import org.fortiss.tooling.kernel.model.constraints.IConstraintInstanceStatus;
import org.fortiss.tooling.kernel.service.IConstraintService;
/**
* Interface for constraints as required by {@link IConstraintService}.
*/
public interface IConstraint {
/** Verify the given constraint instance. */
IConstraintInstanceStatus verify(ConstraintInstance ci);
/**
* Hook to preprocess <code>cstrd</code> before computing its checksum. Typically useful to
* remove items which should not be considered when computing the checksum, e.g., layout
* information.
*/
void preprocessBeforeChecksum(IConstrained cstrd);
/** Cancels the last verification of <code>ci</code>. */
void cancel(ConstraintInstance ci);
/**
* Adds a constraint instance to the provided element.
*
* Subclasses shall return <code>null</code> if the provided element should not be constrained
* (whatever is the reason: the constraint is only judge here).
*/
ConstraintInstance addConstraintInstanceIfNeeded(IConstrained cstrd);
/**
* @return The name of the Group. This method will be implemented in all of the classes that
* implements this interface
*/
String getGroup();
}
/*-------------------------------------------------------------------------+
| Copyright 2016 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.base;
import static org.fortiss.tooling.kernel.utils.ConstraintsUtils.createConstraintInstance;
import static org.fortiss.tooling.kernel.utils.ConstraintsUtils.createOutdatedStatus;
import static org.fortiss.tooling.kernel.utils.ConstraintsUtils.getConstrained;
import static org.fortiss.tooling.kernel.utils.ConstraintsUtils.getConstraintInstanceOfType;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.fortiss.tooling.kernel.extension.IConstraint;
import org.fortiss.tooling.kernel.model.constraints.ConstraintInstance;
import org.fortiss.tooling.kernel.model.constraints.IConstrained;
import org.fortiss.tooling.kernel.model.constraints.IConstraintInstanceContainer;
import org.fortiss.tooling.kernel.model.constraints.IConstraintInstanceStatus;
/**
* Base for {@link IConstraint}.
*
* @author aravantinos
*/
public class ConstraintBases {
/** Most generic base. */
public abstract static class ConstraintBase implements IConstraint {
/** Returns the constraint instance container in the context of the given object. */
abstract public IConstraintInstanceContainer getConstraintInstanceContainer(EObject obj);
/** {@inheritDoc} */
@Override
public void preprocessBeforeChecksum(IConstrained cstrd) {
cstrd.getConstraintInstances().clear();
cstrd.getChecksumsPerConstraintName().clear();
// By default, we remove all the constraint-related information.
TreeIterator<EObject> it = cstrd.eAllContents();
List<EMap<String, BigInteger>> toClears = new ArrayList<>();
while(it.hasNext()) {
EObject obj = it.next();
if(obj instanceof IConstrained) {
((IConstrained)obj).getConstraintInstances().clear();
toClears.add(((IConstrained)obj).getChecksumsPerConstraintName());
}
}
toClears.stream().forEach(toClear -> toClear.clear());
}
/** {@inheritDoc} */
@Override
public void cancel(ConstraintInstance ci) {
// By default - and generally - nothing to do. Not all constraints are so heavy that
// they deserve to have a cancellation procedure.
}
/** {@inheritDoc} */
@Override
public ConstraintInstance addConstraintInstanceIfNeeded(IConstrained constrained) {
if(getConstraintInstanceOfType(constrained, this) != null) {
return null;
}
ConstraintInstance ci = createConstraintInstanceIfNeeded(constrained);
if(ci != null) {
createOutdatedStatus(ci);
}
if(ci != null) {
IConstraintInstanceContainer ciContainer =
getConstraintInstanceContainer(constrained);
ciContainer.getConstraintInstances().add(ci);
}
return ci;
}
/**
* Creates and return a constraint instance on the provided element.
*
* Subclasses shall return <code>null</code> if the provided element should not be
* constrained (whatever is the reason: the constraint is only judge here).
*/
public abstract ConstraintInstance
createConstraintInstanceIfNeeded(IConstrained constrained);
}
/**
* Base for a constraint which is as close as possible to the old constraint system:
* - the constrained element contains all the information necessary for the constraint
* (nothing stored in the constraint instance)
* - only one element is constrained
*/
public static abstract class ConstraintCheckerBase extends ConstraintBase {
/** {@inheritDoc} */
@Override
public IConstraintInstanceStatus verify(ConstraintInstance ci) {
IConstrained constrained = getConstrained(ci);
return isApplicable(constrained) ? verify(constrained) : null;
}
/** Verify the given constrained element. */
public abstract IConstraintInstanceStatus verify(IConstrained constrained);
/** Determines whether this constraint is applicable to the given model element. */
public abstract boolean isApplicable(IConstrained constrained);
/** {@inheritDoc} */
@Override
public ConstraintInstance addConstraintInstanceIfNeeded(IConstrained constrained) {
return isApplicable(constrained) ? super.addConstraintInstanceIfNeeded(constrained)
: null;
}
/** {@inheritDoc} */
@Override
public ConstraintInstance createConstraintInstanceIfNeeded(IConstrained constrained) {
return createConstraintInstance(this.getClass(), constrained);
}
}
}
CommandStackService.java 957bda69b5feb91f002aed4d25ed334e92801e7e GREEN
ConnectionCompositorService.java d69a60cd7a3d06e91d24fd32b9c00125ea71e0dd GREEN
ConstraintCheckerService.java 459b5eb717598e7e8bb71a0c87e57ea85cb00e4b GREEN
ConstraintService.java 139187909523300c80a22be920329f1c9d0fb654 GREEN
DummyTopLevelElement.java 8394597464707992cd053e68129bb87ce9f696db GREEN
ElementCompositorService.java 98c5d27e09881e60aa4f87c1ac0c7787cdec9f7c GREEN
LibraryPrototypeProvider.java b77eddbdca78f561ffb1233e98817be361c690ae GREEN
......@@ -10,6 +9,6 @@ LoggingService.java da784259f7b456b54bf75c41ec268f64919ce78d GREEN
MigrationService.java 632c13563a3d69681e2a608023fcdadbe5340c4b GREEN
PersistencyService.java 103eef642c038ef63fa49b743d803aaa3fea2724 GREEN
PrototypeService.java 18c3db05ab11f189a9711bf241c3c7f35c954a9e GREEN
ToolingKernelInternal.java d624a5f6b237ce993e150e2b8d1b4390e3fc8f7a GREEN
ToolingKernelInternal.java f6e7114825748683c7f1d040b41ab854a6c4d79b GREEN
TransformationService.java 3cdb86fe920158f93cd9466c6ef9697b2dd8ca7f GREEN
TutorialService.java 675d3f365ce062869f86baa3779d50687674bda0 GREEN
package org.fortiss.tooling.kernel.internal;
import static java.util.Collections.emptyList;
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 static org.fortiss.tooling.kernel.utils.EcoreUtils.copy;
import static org.fortiss.tooling.kernel.utils.LoggingUtils.warning;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.common.util.TreeIterator;
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.IConstraint;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.introspection.IIntrospectionDetailsItem;
import org.fortiss.tooling.kernel.introspection.IIntrospectionItem;
import org.fortiss.tooling.kernel.introspection.IIntrospectiveKernelService;
import org.fortiss.tooling.kernel.introspection.items.ConstraintVerificationServiceIntrospectionDetailsItem;
import org.fortiss.tooling.kernel.model.INamedElement;
import org.fortiss.tooling.kernel.model.constraints.ConstraintInstance;
import org.fortiss.tooling.kernel.model.constraints.IConstrained;
import org.fortiss.tooling.kernel.model.constraints.IConstraintInstanceStatus;
import org.fortiss.tooling.kernel.service.IConstraintService;
import org.fortiss.tooling.kernel.service.IKernelIntrospectionSystemService;
import org.fortiss.tooling.kernel.service.IPersistencyService;
/**
* Implementation of {@link IConstraintService}.
*
* @author aravantinos
*/
public final class ConstraintService implements IIntrospectiveKernelService, IConstraintService {
/** The singleton instance. */
private static final ConstraintService INSTANCE = new ConstraintService();
/** Stores the set of registered constraint classes by name. */
protected final Map<String, Class<? extends IConstraint>> handlerMap =
new HashMap<String, Class<? extends IConstraint>>();
/** Stores the set of registered constraints classes instantiations. */
protected final Map<Class<? extends IConstraint>, IConstraint> instanceMap =
new HashMap<Class<? extends IConstraint>, IConstraint>();
/** Returns singleton instance of the service. */
public static ConstraintService getInstance() {
return INSTANCE;
}
/** Starts the service. */
public void startService() {
IKernelIntrospectionSystemService.getInstance().registerService(this);
}
/** Initializes the service by setting up the handler map. */
public void initializeService() {
// nothing to do here
}
/** {@inheritDoc} */
@Override
public void registerConstraint(Class<? extends IConstraint> cstrClass) {
String name = cstrClass.getName();
Class<? extends IConstraint> existingCstr = handlerMap.get(name);
if(existingCstr != null) {
warning(ToolingKernelActivator.getDefault(),
"Encountered more than one registered constraint with name " + name);
}
handlerMap.put(name, cstrClass);
try {
instanceMap.put(cstrClass, cstrClass.getConstructor().newInstance());
} catch(InstantiationException | IllegalAccessException | IllegalArgumentException |
InvocationTargetException | NoSuchMethodException | SecurityException e) {
warning(ToolingKernelActivator.getDefault(),
"Instanciation of " + cstrClass.getName() + " threw an exception.");
}
}
/** {@inheritDoc} */
@Override
public String getIntrospectionDescription() {
return getIntrospectionLabel() + "\n\nThe service deals with constraints over AF3 models." +
"\nA constraint is a function over a model element (the \"constrained\" element) which returns true or false." +
"\nThe application of a constraint to a given model element is called a \"constraint instance\"." +
"\nContrarily to usual constraint systems, constraint instances are a first-class citizen for this service" +
"\nbecause it allows us to store the status of the constraint on the given element as well as the checksum of the constrained element." +
"\n\nThe service provides the following:" +
"\n- verification of a constraint instance," +
"\n- cancellation of a constraint instance verification (if provided by the relevant verifier)," +
"\n- check whether a constraint instance is up to date," +
"\n- provide a list of possible \"quick fixes\" for a given constraint instance in case it failed," +
"\n- complete a given project with instances of a given constraint if necessary" +
"\n (it is however advised to use instead, if possible, the equivalent function of the UI service which also installs" +
"\n the added constraint instances)." +
"\n\nThis service is fed with classes of type IConstraint." +
"\nSuch classes are responsible of the verification of constraints which return a status of the following form:" +
"\n- SUCCESS means the verification succeeded" +
"\n- FAIL means the verification failed" +
"\n- ERROR means the verification could not be run (typically because an error happened)" +
"\n- OUTDATED means the constrained items have changed and the constraint instance should be verified. " +
"\n- null if it is irrelevant to check the constraint - whatever is the reason. " +
"\nDo not hesitate to extend these statuses to define your own," +
"\nfor instance to provide more information about failure (thus possibly allowing automatic fixes)." +
"\n\nThe class org.fortiss.af3.project.utils.ConstraintsProjectUtils.AF3ProjectConstraintCheckerBase should" +
"\ngenerally provide a sufficient initial implementation." +
"\n\nSee the developer wiki page \"Add a new constraint on a metamodel\"" +
" for detailed documentation on developing a new sort of constraint.";
}
/** {@inheritDoc} */
@Override
public void verify(ConstraintInstance ci) {
IConstraint verifier = getConstraint(ci);
if(verifier != null) {
ITopLevelElement modelContext =
IPersistencyService.getInstance().getTopLevelElementFor(ci);
// It can happen that <code>modelContext</code> is null, e.g., if the verification is
// triggered while the constraint is actually being removed.
if(modelContext == null) {
return;
}
modelContext.runAsCommand(() -> {
// We update the checksums before verification to avoid detecting some fake changes
// during the verification.
updateChecksums(ci);
IConstraintInstanceStatus status = verifier.verify(ci);
ci.setStatus(status);
// And we also update the checksums after in case the verification had some side
// effects...
updateChecksums(ci);
currentlyUpdating.remove(ci);
});
}
}
/** Returns the short name of the constraint of the given instance. */
private String cstrShortName(ConstraintInstance ci) {
int dolIndex = ci.getConstraintName().lastIndexOf('$');
int dotIndex = ci.getConstraintName().lastIndexOf('.');
return ci.getConstraintName().substring(Math.max(dotIndex, dolIndex) + 1);
}
/** {@inheritDoc} */
@Override
public boolean isUpToDate(ConstraintInstance ci) {
if(ci == null) {
// silently return in case of a null constraint instance
return true;
}
for(IConstrained c : ci.getConstraineds()) {
BigInteger computeCheckSum = computeCheckSum(c, ci);
EMap<String, BigInteger> checksumMap = c.getChecksumsPerConstraintName();
BigInteger storedChecksum = checksumMap.get(ci.getConstraintName());
if(computeCheckSum == null || !computeCheckSum.equals(storedChecksum)) {
return false;
}
}
return true;
}
/** Updates all the checksums of <code>ci</code>. */
private void updateChecksums(ConstraintInstance ci) {
for(IConstrained c : ci.getConstraineds()) {
c.getChecksumsPerConstraintName().put(ci.getConstraintName(), computeCheckSum(c, ci));
}
}
/**
* Path to a directory where to store the constrained elements which are actually checksummed.
* This is useful since it is essential to control very precisely how checksums are computed.
* If equal to the empty string, debug is deactivated.
* This string should however only be set to a non-empty string on a local machine, never
* committed!
*/
private static final String DEBUG_FOLDER = null;
/** Number used to annotate the traces when debugging is active. */
private int debug_trace_number = 0;
/**
* Returns the checksum of <code>constrained</code>. Note that <code>ci</code> is necessary
* because it has a potential impact on what is relevant for the checksum or not.
*/
protected BigInteger computeCheckSum(IConstrained constrained, ConstraintInstance ci) {
if(constrained == null) {
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
final EObject hashRelevant = getChecksumRelevantEObject(constrained, ci);
try(ObjectOutputStream oos = new ObjectOutputStream(baos)) {
final ResourceSet rset = new ResourceSetImpl();
Resource resource = rset.createResource(URI.createURI("temp"));
resource.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);
resource.save(oos, options);
MessageDigest m = MessageDigest.getInstance("SHA1");
m.update(baos.toByteArray());
BigInteger res = new BigInteger(1, m.digest());
if(DEBUG_FOLDER != null) {
String filePrefix = DEBUG_FOLDER + "/trace" + debug_trace_number++;
String nameCstr = cstrShortName(ci);
String nameCstrd = constrained instanceof INamedElement
? ((INamedElement)constrained).getName() : constrained.toString();
String fileName = filePrefix + "_" + nameCstr + "_" + nameCstrd + ".xml";
try(FileOutputStream file = new FileOutputStream(fileName);
ObjectOutputStream oos2 = new ObjectOutputStream(file)) {
resource.save(oos2, options);
oos2.writeUTF("\nCHECKSUM: " + res.toString());
}
}
resource.getContents().remove(hashRelevant);
resource.delete(options);
return res;
} catch(Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Returns the object to be used to compute the checksum.
* Generally, all statuses and checksums are removed. Each constraint can also provide
* specific adaptations.
*/
protected EObject getChecksumRelevantEObject(IConstrained constrained, ConstraintInstance ci) {
IConstrained res = copy(constrained);
res.getChecksumsPerConstraintName().clear();
IConstraint verifier = getConstraint(ci);
if(verifier != null) {
verifier.preprocessBeforeChecksum(res);
}
return res;
}
/** @return The registered constraint whose <code>ci</code> is a constraint instance of. */
protected IConstraint getConstraint(ConstraintInstance ci) {
return instanceMap.get(handlerMap.get(ci.getConstraintName()));
}
/** {@inheritDoc} */
@Override
public void cancel(ConstraintInstance ci) {
getConstraint(ci).cancel(ci);
}
/** {@inheritDoc} */
@Override
public String getIntrospectionLabel() {
return "Constraint Service";
}
/** {@inheritDoc} */
@Override
public IIntrospectionDetailsItem getDetailsItem() {
return new ConstraintVerificationServiceIntrospectionDetailsItem(instanceMap.values());
}
/** {@inheritDoc} */
@Override
public boolean showInIntrospectionNavigation() {
return true;
}
/** {@inheritDoc} */
@Override
public Collection<IIntrospectionItem> getIntrospectionItems() {
return emptyList();
}
/** {@inheritDoc} */
@Override
public List<ConstraintInstance> addMissingConstraintsInstances(ITopLevelElement top,
Class<? extends IConstraint> cstrClass) {
List<ConstraintInstance> addedConstraints = new ArrayList<ConstraintInstance>();
IConstraint cstr = instanceMap.get(cstrClass);
TreeIterator<EObject> it = top.getRootModelElement().eAllContents();
while(it.hasNext()) {
EObject elt = it.next();
if(elt instanceof IConstrained) {
ConstraintInstance ci = cstr.addConstraintInstanceIfNeeded((IConstrained)elt);
if(ci != null) {
addedConstraints.add(ci);
}
}
}
return addedConstraints;
}
/** {@inheritDoc} */
@Override
public String getName(Class<? extends IConstraint> cstrClass) {
return cstrClass.getName();
}
/** {@inheritDoc} */
@Override
public Class<? extends IConstraint> getConstraintByName(String name) {
return handlerMap.get(name);
}
/**
* List of constraint instances being currently updated, to prevent triggering twice an update
* which is already on its way.
*/
List<ConstraintInstance> currentlyUpdating = new ArrayList<>();
/** {@inheritDoc} */
@Override
public boolean isUpdating(ConstraintInstance ci) {
return currentlyUpdating.contains(ci);
}
/** {@inheritDoc} */
@Override
public void markAsUpdating(ConstraintInstance ci) {
currentlyUpdating.add(ci);
}
/** {@inheritDoc} */
@Override
public String getGroupName(Class<? extends IConstraint> cstrClass) {
if(instanceMap.get(cstrClass).getGroup() != null) {
return instanceMap.get(cstrClass).getGroup().trim().toString();
}
return "";
}
}
......@@ -35,7 +35,6 @@ public final class ToolingKernelInternal {
CommandStackService.getInstance().initializeService();
ConnectionCompositorService.getInstance().initializeService();
ConstraintCheckerService.getInstance().initializeService();
ConstraintService.getInstance().initializeService();
ElementCompositorService.getInstance().initializeService();
MigrationService.getInstance().initializeService();
LibraryService.getInstance().initializeService();
......@@ -56,7 +55,6 @@ public final class ToolingKernelInternal {
CommandStackService.getInstance().startService();
ConnectionCompositorService.getInstance().startService();
ConstraintCheckerService.getInstance().startService();
ConstraintService.getInstance().startService();
ElementCompositorService.getInstance().startService();
MigrationService.getInstance().startService();
LibraryService.getInstance().startService();
......
/*-------------------------------------------------------------------------+
| Copyright 2016 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.introspection.items;
import java.util.Collection;
import org.fortiss.tooling.kernel.extension.IConstraint;
import org.fortiss.tooling.kernel.introspection.IIntrospectionDetailsItem;
import org.fortiss.tooling.kernel.service.IConstraintService;
/**
* {@link IIntrospectionDetailsItem} for the {@link IConstraintService}.
*
* @author aravantinos
*/
public class ConstraintVerificationServiceIntrospectionDetailsItem
implements IIntrospectionDetailsItem {
/** Read-only copy of the services handler list. */
protected final Collection<IConstraint> handlerSet;
/** Constructor. */
public ConstraintVerificationServiceIntrospectionDetailsItem(
Collection<IConstraint> handlerSet) {
this.handlerSet = handlerSet;
}
/** Returns the first registration classes. */
public Collection<IConstraint> getHandlerKeyClasses() {
return handlerSet;
}
/** Returns the registered constraint of the given name. */
public IConstraint getHandler(String name) {
return handlerSet.stream().filter(c -> name.equals(c.getClass().getName())).findFirst()
.get();
}
}
package org.fortiss.tooling.kernel.service;
import java.util.List;
import org.fortiss.tooling.kernel.extension.IConstraint;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.internal.ConstraintService;
import org.fortiss.tooling.kernel.model.constraints.ConstraintInstance;
import org.fortiss.tooling.kernel.model.constraints.OutdatedConstraintInstanceStatus;
/**
* The verification service allows to register constraints. See KISS documentation for more details.
*/
public interface IConstraintService {
/** Returns the service instance. */
public static IConstraintService getInstance() {
return ConstraintService.getInstance();
}
/**
* Verifies the constraint instance <code>ci</code>. The service always runs the verification
* in a command. Should not yield any "useless" change because verification should always update
* the constraint instance status and the checksums anyways.
*/
void verify(ConstraintInstance ci);
/**
* Tries to cancel the last verification of the constraint instance <code>ci</code>. The actual
* actions to take upon cancellation are up to the constraint.
*/
void cancel(ConstraintInstance ci);
/**
* @return <code>true</code> if the constraint instance <code>ci</code> is up to date.
* This does not just look at the status but computes a diff between the constrained
* element and the one for which the constraint instance was last time checked. In the
* standard case, it is enough to call IConstraintVerificationUIService.getStatus and
* see if the result is an instance of {@link OutdatedConstraintInstanceStatus}. You
* should use <code>isUpToDate</code> *only if
* IConstraintVerificationUIService.getStatus does not provide the information you
* want*.
*/
boolean isUpToDate(ConstraintInstance ci);
/**
* Completes <code>top</code> with missing constraints instances of constraint handled by
* <code>cstrClass</code>, if applicable.
*
* @return List of added constraints instances.
*
*/
List<ConstraintInstance> addMissingConstraintsInstances(ITopLevelElement top,
Class<? extends IConstraint> cstrClass);
/** Returns the name of the given constraint, usable for serialization. */
public String getName(Class<? extends IConstraint> cstrClass);
/**
* @param cstrClass
* @return name of the group that a particular constraint belong to
*/
public String getGroupName(Class<? extends IConstraint> cstrClass);
/** Returns a constraint, given its name. */
public Class<? extends IConstraint> getConstraintByName(String name);
/** Registers the given verifier with the service. */
void registerConstraint(Class<? extends IConstraint> cstrClass);
/** <code>true</code> if the given instance is queued for update. */
boolean isUpdating(ConstraintInstance ci);
/**
* Marks the given instance as being queued for update.
*
* ONLY FOR INTERNAL USE.
*/
void markAsUpdating(ConstraintInstance ci);
}
/*-------------------------------------------------------------------------+
| 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. |
| 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.utils;
import java.util.NoSuchElementException;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.fortiss.tooling.kernel.extension.IConstraint;
import org.fortiss.tooling.kernel.model.IIdLabeled;
import org.fortiss.tooling.kernel.model.constraints.ConstraintInstance;
import org.fortiss.tooling.kernel.model.constraints.ConstraintsFactory;
import org.fortiss.tooling.kernel.model.constraints.ErrorConstraintInstanceStatus;
import org.fortiss.tooling.kernel.model.constraints.FailedConstraintInstanceStatus;
import org.fortiss.tooling.kernel.model.constraints.IConstrained;
import org.fortiss.tooling.kernel.model.constraints.IConstraintInstanceContainer;
import org.fortiss.tooling.kernel.model.constraints.IConstraintInstanceStatus;
import org.fortiss.tooling.kernel.model.constraints.OutdatedConstraintInstanceStatus;
import org.fortiss.tooling.kernel.model.constraints.SuccessConstraintInstanceStatus;
import org.fortiss.tooling.kernel.service.IConstraintService;
/**
* Utility methods for dealing with constraints.
*
* @author aravantinos
*/
public class ConstraintsUtils {
/**
* Returns the container of <code>ci</code>. Assumes that it is of type
* {@link IConstraintInstanceContainer}!
*/
public static IConstraintInstanceContainer
getConstraintInstanceContainer(ConstraintInstance ci) {
return (IConstraintInstanceContainer)ci.eContainer();
}
/**
* Defines <code>constrained</code> as the <code>i</code>-th constrained model element of
* <code>ci</code>. Leaves the other elements as they are if they exist, fill them with
* <code>constrained</code> till <code>i</code> otherwise (we cannot set to <code>null</code>).
*/
public static void setConstrainedElement(ConstraintInstance ci, IConstrained constrained,
int i) {
EList<IConstrained> constraineds = ci.getConstraineds();
for(int j = constraineds.size(); j <= i; j++) {
constraineds.add(j, constrained);
}
if(!constrained.getConstraintInstances().contains(ci)) {
constrained.getConstraintInstances().add(ci);
}
}
/** @return the first constraint instance of type <code>cstr</code> in <code>c</code>. */
public static ConstraintInstance getConstraintInstanceOfType(IConstrained c, IConstraint cstr) {
return getConstraintInstanceOfType(c, cstr.getClass());
}
/** @return the first constraint instance of type <code>cstr</code> in <code>c</code>. */
public static ConstraintInstance getConstraintInstanceOfType(IConstrained c,
Class<? extends IConstraint> cstrClass) {
try {
String name = cstrClass.getName();
return c.getConstraintInstances().stream()
.filter(x -> name.equals(x.getConstraintName())).findFirst().get();
} catch(NoSuchElementException e) {
return null;
}
}
/** Exception which embeds a constraint error status. */
public static class ErrorEmbeddingException extends RuntimeException {
/** The embedded error. */
public ErrorConstraintInstanceStatus error;
/** Constructor. */
public ErrorEmbeddingException(ErrorConstraintInstanceStatus error) {
super();
this.error = error;
}
}
/** @return A "success" status. */
public static SuccessConstraintInstanceStatus createSuccessStatus() {
return ConstraintsFactory.eINSTANCE.createSuccessConstraintInstanceStatus();
}
/** @return A "outdated" status for <code>ci</code>. */
public static OutdatedConstraintInstanceStatus createOutdatedStatus(ConstraintInstance ci) {
OutdatedConstraintInstanceStatus status;
if(ci.getStatus() instanceof OutdatedConstraintInstanceStatus) {
status = (OutdatedConstraintInstanceStatus)ci.getStatus();
} else {
status = ConstraintsFactory.eINSTANCE.createOutdatedConstraintInstanceStatus();
ci.setStatus(status);
}
return status;
}
/** @return A "outdated" status. */
public static OutdatedConstraintInstanceStatus createOutdatedStatus() {
return ConstraintsFactory.eINSTANCE.createOutdatedConstraintInstanceStatus();
}
/** @return A "fail" status. */
public static FailedConstraintInstanceStatus createFailStatus() {
return ConstraintsFactory.eINSTANCE.createFailedConstraintInstanceStatus();
}
/** @return An "error" status. */
public static ErrorConstraintInstanceStatus createErrorStatus() {
return ConstraintsFactory.eINSTANCE.createErrorConstraintInstanceStatus();
}
/** @return the first element constrained by <code>ci</code> */
public static IConstrained getFirstConstrained(ConstraintInstance ci) {
try {
// get(0) because the constraint instance shall contain at least one constrained element
// (responsibility of the caller!) and because we want the first element.
return ci.getConstraineds().get(0);
} catch(IndexOutOfBoundsException e) {
return null;
}
}
/** Sets the first constrained element of <code>ci</code> to <code>constrained</code>. */
public static void setFirstConstrained(ConstraintInstance ci, IConstrained constrained) {
setConstrainedElement(ci, constrained, 0);
}
/** @return the second element constrained by <code>ci</code> */
public static IConstrained getSecondConstrained(ConstraintInstance ci) {
try {
// get(1) because the constraint instance shall contain at least one constrained element
// (responsibility of the caller!) and because we want the first element.
return ci.getConstraineds().get(1);
} catch(IndexOutOfBoundsException e) {
return null;
}
}
/** Sets the second constrained element of <code>ci</code> to <code>constrained</code>. */
public static void setSecondConstrained(ConstraintInstance ci, IConstrained constrained) {
setConstrainedElement(ci, constrained, 1);
}
/**
* @return the element constrained by <code>ci</code>.
* Use this function if your constraint constrains only one element!
*/
public static IConstrained getConstrained(ConstraintInstance ci) {
return getFirstConstrained(ci);
}
/**
* Sets the constrained element of <code>ci</code> to <code>constrained</code>.
* Use this function if your constraint constrains only one element!
*/
public static void setConstrained(ConstraintInstance ci, IConstrained constrained) {
setConstrainedElement(ci, constrained, 0);
}
/**
* @return a constraint instance of type <code>cstrClass</code> constraining
* <code>constrained</code>
*/
public static ConstraintInstance createConstraintInstance(
Class<? extends IConstraint> cstrClass, IConstrained constrained) {
ConstraintInstance ci = ConstraintsFactory.eINSTANCE.createConstraintInstance();
ci.setConstraintName(cstrClass.getName());
setConstrained(ci, constrained);
createOutdatedStatus(ci);
return ci;
}
/**
* @return a constraint instance of type <code>cstrClass</code> constraining
* <code>constrained1</code> and <code>constrained2</code>.
*/
public static ConstraintInstance createConstraintInstance(
Class<? extends IConstraint> cstrClass, IConstrained constrained1,
IConstrained constrained2) {
ConstraintInstance c = ConstraintsFactory.eINSTANCE.createConstraintInstance();
c.setConstraintName(IConstraintService.getInstance().getName(cstrClass));
setFirstConstrained(c, constrained1);
setSecondConstrained(c, constrained2);
createOutdatedStatus(c);
return c;
}
/** @return a successful status if <code>b</code> is true, a fail status otherwise */
static public IConstraintInstanceStatus successIfTrue(boolean b) {
return b ? createSuccessStatus() : createFailStatus();
}
/** Removes the IDs of the given object and of its sub-elements. */
public static void filterIDs(EObject obj) {
if(obj instanceof IIdLabeled) {
((IIdLabeled)obj).setId(0);
}
TreeIterator<EObject> it = obj.eAllContents();
while(it.hasNext()) {
EObject elt = it.next();
if(elt instanceof IIdLabeled) {
((IIdLabeled)elt).setId(0);
}
}
}
}
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