Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » OCL » Checking OCL programmatically(Problem setting correct context)
Checking OCL programmatically [message #1086603] Wed, 14 August 2013 12:14 Go to next message
Boel NFriend
Messages: 4
Registered: July 2013
Junior Member
Hi,

I am trying to perform an OCL check on a UML model programmatically. For this I am using the OCL class from the Pivot package (org.eclipse.ocl.examples.pivot.OCL). The model and profile were created using Papyrus. The model and profile I've created are attached to this message. The validation works as it should using the Papyrus GUI and the default UML2 Editor GUI. However, when trying to simulate the GUI the code fails.

It seems however that I am setting the context in the OCLHelper incorrect, which results in a ParserException when the query is created from the OCLHelper. At the moment my context gets set to Stereotype, but I would expect it to be Stereotype1 from my attached profile. The error message I get from the diagnostic is:
Errors in 'self.number < 10'
1: Unresolved Property 'uml::Stereotype::number'

My conclusion is that I am probably missing some essential steps to make this work, but so far I haven't found any solution to this anywhere. Actually it is quite hard to find a clear enough example of the call order to make this work.
Below is the code I use for the OCL check:

import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.ocl.examples.pivot.ExpressionInOCL;
import org.eclipse.ocl.examples.pivot.OCL;
import org.eclipse.ocl.examples.pivot.ParserException;
import org.eclipse.ocl.examples.pivot.helper.OCLHelper;
import org.eclipse.ocl.examples.pivot.manager.MetaModelManager;
import org.eclipse.ocl.examples.pivot.utilities.PivotEnvironment;
import org.eclipse.ocl.examples.pivot.utilities.PivotEnvironmentFactory;
import org.eclipse.ocl.examples.pivot.utilities.PivotUtil;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Namespace;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.Profile;


public void validate(Model model) {

final Model myModel = model;


EList<Constraint> constraints = new BasicEList<Constraint>(myModel.getOwnedRules());
                           
// Get all OCL rules from the model
final TreeIterator<EObject> iterator = myModel.eAllContents();
while(iterator.hasNext()){
       EObject tempObject = iterator.next();
                                  
       if (tempObject instanceof NamedElement) {
              NamedElement ne = (NamedElement) tempObject;
                                         
              if(ne.getNamespace() != null) {
                     final EList<Constraint> temp = ne.getNamespace().getOwnedRules();
                                                
                     if(!constraints.containsAll(temp)){
                           constraints.addAll(temp);
                     }
              }
       }
}
                           
// Get all OCL rules from the profiles applied to the model
for(Profile profile : myModel.getAllAppliedProfiles()){
final TreeIterator<EObject> profileIterator = profile.eAllContents();
       while(profileIterator.hasNext()){
              EObject tempObject = profileIterator.next();
                                         
              if (tempObject instanceof NamedElement) {
                     NamedElement ne = (NamedElement) tempObject;
                                                
                     if(ne.getNamespace() != null) {
                     final EList<Constraint> temp = ne.getNamespace().getOwnedRules();
                                  
                         if(!constraints.containsAll(temp)){
                             constraints.addAll(temp);
                         }
                     }
              }
       }      
}

// Check if any OCL constraint is violated
for (Constraint constraint : constraints) {
    String constraintName = constraint.getName();
                                  
    if (constraint.getSpecification() instanceof OpaqueExpression) {
        OpaqueExpression opaqueExpression = ((OpaqueExpression) constraint.getSpecification());

              // Find the body named OCL
              int indexOfOCLBody = -1;
        for (int i = 0; i < opaqueExpression.getLanguages().size() && indexOfOCLBody == -1; i++) {
            if (opaqueExpression.getLanguages().get(i).equals("OCL")) {
                indexOfOCLBody = i;
             }
         }
                                         
    // If the body was found, continue the check
         if (indexOfOCLBody != -1) {
             final String expression = opaqueExpression.getBodies().get(indexOfOCLBody);
             final Namespace contextObject = constraint.getContext();

             ResourceSet resourceSet = new ResourceSetImpl();
             Resource resource = resourceSet.getResource(myModel.eResource().getURI(), true);
                                                
             MetaModelManager metaModelManager = PivotUtil.getMetaModelManager(resource); 
             PivotEnvironmentFactory envFactory = new PivotEnvironmentFactory(null, metaModelManager);
             PivotEnvironment environment = envFactory.createEnvironment();
                                                
             OCL.initialize(null);
                                                
             OCL ocl = OCL.newInstance(environment);
             OCLHelper oclHelper = ocl.createOCLHelper(contextObject); 
                                                                                  
                                                
             oclHelper.setContext(contextObject.eClass());
             try {
             // Turn the expression into a query and evaluate it
             ExpressionInOCL createQuery = oclHelper.createQuery(expression);
             Object result = ocl.evaluate(contextObject, createQuery);
             } catch (ParserException e) {
             Diagnostic diagnostic = e.getDiagnostic();
             System.out.println(diagnostic.getMessage());
             }
         }
       }
    }
}


Does anyone know why this isn't working? Thanks in advance!
Regards,
Boel
Re: Checking OCL programmatically [message #1086612 is a reply to message #1086603] Wed, 14 August 2013 12:30 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
HI

Please attach a zipped project rather than files from which I have to
construct the project.

Regards

Ed Willink

On 14/08/2013 13:14, Boel N wrote:
> Hi,
>
> I am trying to perform an OCL check on a UML model programmatically. For this I am using the OCL class from the Pivot package (org.eclipse.ocl.examples.pivot.OCL). The model and profile were created using Papyrus. The model and profile I've created are attached to this message. The validation works as it should using the Papyrus GUI and the default UML2 Editor GUI. However, when trying to simulate the GUI the code fails.
>
> It seems however that I am setting the context in the OCLHelper incorrect, which results in a ParserException when the query is created from the OCLHelper. At the moment my context gets set to Stereotype, but I would expect it to be Stereotype1 from my attached profile. The error message I get from the diagnostic is:
> Errors in 'self.number < 10'
> 1: Unresolved Property 'uml::Stereotype::number'
>
> My conclusion is that I am probably missing some essential steps to make this work, but so far I haven't found any solution to this anywhere. Actually it is quite hard to find a clear enough example of the call order to make this work.
> Below is the code I use for the OCL check:
>
>
> import org.eclipse.emf.common.util.Diagnostic;
> import org.eclipse.emf.common.util.EList;
> import org.eclipse.emf.common.util.TreeIterator;
> import org.eclipse.emf.ecore.resource.Resource;
> import org.eclipse.emf.ecore.resource.ResourceSet;
> import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
> import org.eclipse.ocl.examples.pivot.ExpressionInOCL;
> import org.eclipse.ocl.examples.pivot.OCL;
> import org.eclipse.ocl.examples.pivot.ParserException;
> import org.eclipse.ocl.examples.pivot.helper.OCLHelper;
> import org.eclipse.ocl.examples.pivot.manager.MetaModelManager;
> import org.eclipse.ocl.examples.pivot.utilities.PivotEnvironment;
> import org.eclipse.ocl.examples.pivot.utilities.PivotEnvironmentFactory;
> import org.eclipse.ocl.examples.pivot.utilities.PivotUtil;
> import org.eclipse.uml2.uml.Constraint;
> import org.eclipse.uml2.uml.Model;
> import org.eclipse.uml2.uml.NamedElement;
> import org.eclipse.uml2.uml.Namespace;
> import org.eclipse.uml2.uml.OpaqueExpression;
> import org.eclipse.uml2.uml.Profile;
>
>
> public void validate(Model model) {
>
> final Model myModel = model;
>
>
> EList<Constraint> constraints = new BasicEList<Constraint>(myModel.getOwnedRules());
>
> // Get all OCL rules from the model
> final TreeIterator<EObject> iterator = myModel.eAllContents();
> while(iterator.hasNext()){
> EObject tempObject = iterator.next();
>
> if (tempObject instanceof NamedElement) {
> NamedElement ne = (NamedElement) tempObject;
>
> if(ne.getNamespace() != null) {
> final EList<Constraint> temp = ne.getNamespace().getOwnedRules();
>
> if(!constraints.containsAll(temp)){
> constraints.addAll(temp);
> }
> }
> }
> }
>
> // Get all OCL rules from the profiles applied to the model
> for(Profile profile : myModel.getAllAppliedProfiles()){
> final TreeIterator<EObject> profileIterator = profile.eAllContents();
> while(profileIterator.hasNext()){
> EObject tempObject = profileIterator.next();
>
> if (tempObject instanceof NamedElement) {
> NamedElement ne = (NamedElement) tempObject;
>
> if(ne.getNamespace() != null) {
> final EList<Constraint> temp = ne.getNamespace().getOwnedRules();
>
> if(!constraints.containsAll(temp)){
> constraints.addAll(temp);
> }
> }
> }
> }
> }
>
> // Check if any OCL constraint is violated
> for (Constraint constraint : constraints) {
> String constraintName = constraint.getName();
>
> if (constraint.getSpecification() instanceof OpaqueExpression) {
> OpaqueExpression opaqueExpression = ((OpaqueExpression) constraint.getSpecification());
>
> // Find the body named OCL
> int indexOfOCLBody = -1;
> for (int i = 0; i < opaqueExpression.getLanguages().size() && indexOfOCLBody == -1; i++) {
> if (opaqueExpression.getLanguages().get(i).equals("OCL")) {
> indexOfOCLBody = i;
> }
> }
>
> // If the body was found, continue the check
> if (indexOfOCLBody != -1) {
> final String expression = opaqueExpression.getBodies().get(indexOfOCLBody);
> final Namespace contextObject = constraint.getContext();
>
> ResourceSet resourceSet = new ResourceSetImpl();
> Resource resource = resourceSet.getResource(myModel.eResource().getURI(), true);
>
> MetaModelManager metaModelManager = PivotUtil.getMetaModelManager(resource);
> PivotEnvironmentFactory envFactory = new PivotEnvironmentFactory(null, metaModelManager);
> PivotEnvironment environment = envFactory.createEnvironment();
>
> OCL.initialize(null);
>
> OCL ocl = OCL.newInstance(environment);
> OCLHelper oclHelper = ocl.createOCLHelper(contextObject);
>
>
> oclHelper.setContext(contextObject.eClass());
> try {
> // Turn the expression into a query and evaluate it
> ExpressionInOCL createQuery = oclHelper.createQuery(expression);
> Object result = ocl.evaluate(contextObject, createQuery);
> } catch (ParserException e) {
> Diagnostic diagnostic = e.getDiagnostic();
> System.out.println(diagnostic.getMessage());
> }
> }
> }
> }
> }
>
> Does anyone know why this isn't working? Thanks in advance!
> Regards,
> Boel
>
Re: Checking OCL programmatically [message #1087112 is a reply to message #1086612] Thu, 15 August 2013 06:35 Go to previous messageGo to next message
Boel NFriend
Messages: 4
Registered: July 2013
Junior Member
Hi Ed,

I've now created a plugin that runs the code. The check is started from the menu OCL menu->OCL Check.

Regards,
Boel
  • Attachment: OCLPlugin.zip
    (Size: 14.34KB, Downloaded 181 times)
Re: Checking OCL programmatically [message #1087794 is a reply to message #1087112] Fri, 16 August 2013 05:23 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
HI

Apologies. You are suffering from
https://bugs.eclipse.org/bugs/show_bug.cgi?id=413532.

You can download
https://hudson.eclipse.org/hudson/job/buckminster-ocl-branch-tests/lastSuccessfulBuild/artifact/MDT-OCL.downloads/mdt-ocl-Update-tools-201308151834.zip
now to fix the problem.

The fix will be in the M1 build on Monday.

Regards

Ed Willink

On 15/08/2013 07:35, Boel N wrote:
> Hi Ed,
>
> I've now created a plugin that runs the code. The check is started from the menu OCL menu->OCL Check.
>
> Regards,
> Boel
Re: Checking OCL programmatically [message #1097283 is a reply to message #1087794] Thu, 29 August 2013 13:38 Go to previous messageGo to next message
Ronan B is currently offline Ronan BFriend
Messages: 273
Registered: July 2009
Senior Member
Hi,
I'm following this up on Boel's behalf. After updating to http://www.eclipse.org/modeling/download.php?file=/modeling/mdt/ocl/downloads/drops/4.2.0/S201308191305/mdt-ocl-Update-4.2.0M1.zip I see no change in behaviour. I get the exact same issue

Errors in 'self.number < 10'
1: Unresolved Property 'uml::Stereotype::number'

To be honest I don't think the issue required an MDT OCL update as the validation works in Papyrus and the standard UML2 tree editor, when using their validate menus. However, when running the code that Boel wrote (attached in the plugin provided) validation does not work.

Any ideas?

Regards,
Ronan
Re: Checking OCL programmatically [message #1097763 is a reply to message #1097283] Fri, 30 August 2013 06:11 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

Yes. I got distracted by the bug that crept in that prevented me
verifying my suspicion that 'self.number < 10' was at fault. That bug is
fixed in M1.

As often happens the error message very accurate. There is no 'number'
property in a 'uml::Stereotype', the property is in the application
of/instance of a particular Stereotype.

The code iterates over all the Constraints and validates the declared
constraint context. Having found a constraint, it should search for all
instances of the declared constraint context and validate them. Model
searches are not very clever, so it is better to iterate over the model
and nest over the constraints since the constraints are more cacheable.

------

Overall the code has severe performance issues that will become a
concern once you use it for your intended purpose.

A MetaModelManager is a heavyweight object that provides efficient
uniform access to your metamodels. Never create more than one if you can
possibly avoid it, so hoist it outside your loops.

Similarly the OCL facade object should be reused.

Similarly other initialization code.

Regards

Ed Willink






On 29/08/2013 14:38, Ronan B wrote:
> Hi,
> I'm following this up on Boel's behalf. After updating to
> http://www.eclipse.org/modeling/download.php?file=/modeling/mdt/ocl/downloads/drops/4.2.0/S201308191305/mdt-ocl-Update-4.2.0M1.zip
> I see no change in behaviour. I get the exact same issue
> Errors in 'self.number < 10'
> 1: Unresolved Property 'uml::Stereotype::number'
>
> To be honest I don't think the issue required an MDT OCL update as the
> validation works in Papyrus and the standard UML2 tree editor, when
> using their validate menus. However, when running the code that Boel
> wrote (attached in the plugin provided) validation does not work.
>
> Any ideas?
>
> Regards,
> Ronan
Re: Checking OCL programmatically [message #1097990 is a reply to message #1097763] Fri, 30 August 2013 12:43 Go to previous messageGo to next message
Ronan B is currently offline Ronan BFriend
Messages: 273
Registered: July 2009
Senior Member
Hi,
Thanks for the reply. I understand the problem and the error message but I just don't follow the OCL API for how to get the context correct. When I set oclHelper.setContext I must supply an EClass so it is always a Classifier rather than an instance that is the context for the OCL evaluator. I cannot see an obvious way to set up the context correctly. Any pointers?


Yep I agree about the performance issues. That is easily fixed as you indicate.

Regards,
Ronan
Re: Checking OCL programmatically [message #1098584 is a reply to message #1097990] Sat, 31 August 2013 09:48 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

I started trying to make the code work, but it's a nightmare. Internally
it's trying to use org.eclipse.uml2.uml.Constraint rather than
org.eclipse.ocl.examples.pivot.Constraint and so struggling with major
compatibility issues.

The whole benefit of a _single_ metamodel conversion from UML to Pivot
is that many irregularities, such as stereotype properties at the wrong
metalevel, unnavigable opposites, open classes, ... can be normalized to
make life much much easier for the subsequent OCL parser/evaluator.

Look at
http://help.eclipse.org/kepler/topic/org.eclipse.ocl.doc/help/PivotParsingDocuments.html?cp=38_6_6
foe an example of how it can be done easily and sensibly.

[Lazy conversion of UML to PIvot is something that I'm thinking about to
perhaps help when only a tiny query needs conversion or to support the
full UML vocabulary of UseCase/Action/.... but don't hold your breath.]

Regards

Ed Willink



On 30/08/2013 13:43, Ronan B wrote:
> Hi,
> Thanks for the reply. I understand the problem and the error message
> but I just don't follow the OCL API for how to get the context
> correct. When I set oclHelper.setContext I must supply an EClass so it
> is always a Classifier rather than an instance that is the context for
> the OCL evaluator. I cannot see an obvious way to set up the context
> correctly. Any pointers?
>
>
> Yep I agree about the performance issues. That is easily fixed as you
> indicate.
>
> Regards,
> Ronan
Re: Checking OCL programmatically [message #1100584 is a reply to message #1098584] Tue, 03 September 2013 09:44 Go to previous messageGo to next message
Ronan B is currently offline Ronan BFriend
Messages: 273
Registered: July 2009
Senior Member
Hi!
Okay this is indeed hard work. I have the clone of the GIT repo and have tried to understand the documentation at http://help.eclipse.org/kepler/index.jsp?topic=%2Forg.eclipse.ocl.doc%2Fhelp%2FPivotProgrammersGuide.html&cp=38_6

It is still not clear to me what is going on. I assume you have created a Pivot adapted UML2 API which is capable of sorting out the MM level issues associated with UML Stereotypes. Do you have a clear example of this form of validation working for UML stereotypes?

Some findings so far:
1) If I put the Stereotype directly into the model the validation works fine. It was nice to get something working Smile
2) I'm thinking I need to perform some form of adaptation of my UML2 Model to a Pivot compliant UML model via UML2Pivot.importFromUML(). When I do that I get a Root which doesn't ofter the API I had with my UML2 Model API. How can I get that equivalent API in Pivot?
3) I tried the UML2Pivot.importFromUML() for the Element being passed into the ocl.evaluate and it produced a different error probably because the rest of the model hasn't been pivotified? This time I did not call setContent and the ExpressionInOCL returned correctly(I think). I get the following error:

"'Real' rather than 'OclVoid' value required ocl"

As usual all help is appreciated Smile

Regards,
Ronan
Re: Checking OCL programmatically [message #1100631 is a reply to message #1100584] Tue, 03 September 2013 11:13 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

\GIT\org.eclipse.ocl\tests\org.eclipse.ocl.examples.xtext.tests\src\org\eclipse\ocl\examples\pivot\tests\StereotypesTest.java

contains the tests for Stereotype functionality, so you can see the
'inner API' that I mostly use.

I'm afraid that polishing the 'outer API' is one of many things on my
to-do list.

You seem to be trying incredibly hard to avoid the simple solution. In
the documentation example the line

// parse the contents as an OCL document
Resource asResource = ocl.parse(uri);

does all the work for you.

Regards

Ed Willink


On 03/09/2013 10:44, Ronan B wrote:
> Hi!
> Okay this is indeed hard work. I have the clone of the GIT repo and
> have tried to understand the documentation at
> http://help.eclipse.org/kepler/index.jsp?topic=%2Forg.eclipse.ocl.doc%2Fhelp%2FPivotProgrammersGuide.html&cp=38_6
>
> It is still not clear to me what is going on. I assume you have
> created a Pivot adapted UML2 API which is capable of sorting out the
> MM level issues associated with UML Stereotypes. Do you have a clear
> example of this form of validation working for UML stereotypes?
>
> Some findings so far:
> 1) If I put the Stereotype directly into the model the validation
> works fine. It was nice to get something working :)
> 2) I'm thinking I need to perform some form of adaptation of my UML2
> Model to a Pivot compliant UML model via UML2Pivot.importFromUML().
> When I do that I get a Root which doesn't ofter the API I had with my
> UML2 Model API. How can I get that equivalent API in Pivot?
> 3) I tried the UML2Pivot.importFromUML() for the Element being passed
> into the ocl.evaluate and it produced a different error probably
> because the rest of the model hasn't been pivotified? This time I did
> not call setContent and the ExpressionInOCL returned correctly(I
> think). I get the following error:
>
> "'Real' rather than 'OclVoid' value required ocl"
>
> As usual all help is appreciated :)
>
> Regards,
> Ronan
Re: Checking OCL programmatically [message #1100745 is a reply to message #1100631] Tue, 03 September 2013 14:36 Go to previous messageGo to next message
Ronan B is currently offline Ronan BFriend
Messages: 273
Registered: July 2009
Senior Member
Hi,
At last I have something working. Some quick questions before I show what I did.

1) You said I should just call Resource asResource = ocl.parse(uri); You're assuming I have the possibility to have all my OCL in a seperate document I guess? This is not the case. I'm clearly doing this work as I have UML models with OCL embedded in them. This is why you guys put all the effort into the Pivot isn't it?

2) As you will see in the code I use UML2Pivot.importFromUML(metaModelManager, "xx", sa) to get the Pivot version of my Stereotype Application. This is combination with not setting an explicit context is the only way I could get the code working. Is this what you expect? A side question what use is the alias? Just curious Smile

Here is what I came up with to get soemthing working. I have not tested this so much so i'm sure there are some issues:

package oclplugin.logic;

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
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.eclipse.ocl.examples.pivot.ExpressionInOCL;
import org.eclipse.ocl.examples.pivot.OCL;
import org.eclipse.ocl.examples.pivot.ParserException;
import org.eclipse.ocl.examples.pivot.helper.OCLHelper;
import org.eclipse.ocl.examples.pivot.manager.MetaModelManager;
import org.eclipse.ocl.examples.pivot.uml.UML2Pivot;
import org.eclipse.ocl.examples.pivot.utilities.PivotEnvironment;
import org.eclipse.ocl.examples.pivot.utilities.PivotEnvironmentFactory;
import org.eclipse.ocl.examples.pivot.utilities.PivotUtil;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.Stereotype;


public class OCLValidator {
	
	
	
	public void validate(Model model) {

		final Model myModel = model;

		//set up the required pivot/metamodel/model/OCL environment
        ResourceSet resourceSet = new ResourceSetImpl();
        Resource resource = resourceSet.getResource(myModel.eResource().getURI(), true);   
        
        MetaModelManager metaModelManager = PivotUtil.getMetaModelManager(resource); 
        PivotEnvironmentFactory envFactory = new PivotEnvironmentFactory(null, metaModelManager);
        PivotEnvironment environment = envFactory.createEnvironment();                                    
        OCL ocl = OCL.newInstance(environment);
        
		EList<Constraint> constraints = new BasicEList<Constraint>(myModel.getOwnedRules());
		                           
		// Get all OCL rules from the model
		getOCLRulesFromModel(myModel, constraints);
		                           
		// Get all OCL rules from the profiles applied to the model
		getOCLRulesFromAppliedProfiles(myModel, constraints);

		//Now that we have all the constrains see if any are violated in the model
  		for (Constraint constraint : constraints) {
  			
  			String expression = getOCLExpressionFromConstraint(constraint);
  			
			//loop over the elements the constraint constrains
  			final EList<Element> ceList = constraint.getConstrainedElements();  	
  			for(Element ce : ceList)
  			{
  				System.out.println(ce);//TODO:Remove this later it is here just for sanity
  				OCLHelper oclHelper = null;
  				
  				//stereotypes must be handled specially
                if(ce instanceof Stereotype)
                {
                	//look for all the elements in the model that have the stereotype applied
                	final EList<Element> oeList = myModel.allOwnedElements();
                	for(Element oe : oeList)
          			{
                		if(oe.isStereotypeApplied((Stereotype)ce))
                		{
                        	final EList<EObject> saList = oe.getStereotypeApplications();
                        	for(EObject sa : saList)
                  			{
                           		//make the EObject work with the Pivot concept i.e. so the stereotype properties are available
                        		org.eclipse.ocl.examples.pivot.Element psa= null;

                        		try
           		               	{
           		               		psa = UML2Pivot.importFromUML(metaModelManager, "xx", sa);//TODO:What use if the alias??
        	               		}
                        		catch(Exception e)//TODO:Maybe handle this better
           		               	{
           		               		e.printStackTrace();
           		               	}
                        		if(psa != null)
                        		{
                        			 oclHelper = ocl.createOCLHelper(psa);
                        			//finally let's run the OCL!!
                        			evaluateOCL(ocl,oclHelper,expression,psa);              			 
                        		}
                  			}
                		}
          			}
                }
                else
                {
                	 oclHelper = ocl.createOCLHelper(ce);
      		         oclHelper.setContext(ce.eClass());//Note:We only set the context for non Stereotype Applications
      		         //finally let's run the OCL!!
      		         evaluateOCL(ocl,oclHelper,expression,ce);    		         
                }       
  			}
  		}
	}

	private EList<Constraint> getOCLRulesFromAppliedProfiles(Model myModel, EList<Constraint> constraints)
	{
		for(Profile profile : myModel.getAllAppliedProfiles()){
		final TreeIterator<EObject> profileIterator = profile.eAllContents();
		       while(profileIterator.hasNext()){
		              EObject tempObject = profileIterator.next();
		                                         
		              if (tempObject instanceof NamedElement) {
		                     NamedElement ne = (NamedElement) tempObject;
		                                                
		                     if(ne.getNamespace() != null) {
		                     final EList<Constraint> temp = ne.getNamespace().getOwnedRules();
		                                  
		                         if(!constraints.containsAll(temp)){
		                             constraints.addAll(temp);
		                         }
		                     }
		              }
		       }      
		}
		return constraints;
	}
	
	private EList<Constraint> getOCLRulesFromModel(Model myModel, EList<Constraint> constraints)
	{
		final TreeIterator<EObject> iterator = myModel.eAllContents();
		
		while(iterator.hasNext()){
		       EObject tempObject = iterator.next();
		                                  
		       if (tempObject instanceof NamedElement) {
		              NamedElement ne = (NamedElement) tempObject;
		                                         
		              if(ne.getNamespace() != null) {
		                     final EList<Constraint> temp = ne.getNamespace().getOwnedRules();
		                                                
		                     if(!constraints.containsAll(temp)){
		                           constraints.addAll(temp);
		                     }
		              }
		       }
		}
		return constraints;
	}
	
	private String getOCLExpressionFromConstraint(Constraint constraint)
	{
		if (constraint.getSpecification() instanceof OpaqueExpression) {
				OpaqueExpression opaqueExpression = ((OpaqueExpression) constraint.getSpecification());

				// Find the body named OCL
			    int indexOfOCLBody = -1;
			    for (int i = 0; i < opaqueExpression.getLanguages().size() && indexOfOCLBody == -1; i++) {
			    	if (opaqueExpression.getLanguages().get(i).equals("OCL")) {
			    		indexOfOCLBody = i;
			        }
			    }
			                                         
			    // If the body was found, continue the check
			    if (indexOfOCLBody != -1) {
			    	return opaqueExpression.getBodies().get(indexOfOCLBody);
			    }
			}	
		return null;//there was no proper OCL to be found
	}
	
	private void evaluateOCL(OCL ocl,OCLHelper oclHelper,String expression, Object context)
	{
		 try {
				
          	// Turn the expression into a query and evaluate it
          	ExpressionInOCL createQuery = oclHelper.createQuery(expression);
          	Object result = ocl.evaluate(context, createQuery);
          	System.out.println("result: "+result);
	             
          } catch (ParserException e) {
	             Diagnostic diagnostic = e.getDiagnostic();
	             System.out.println(diagnostic.getMessage());
          }  
	}
}



Regards,
Ronan
Re: Checking OCL programmatically [message #1101291 is a reply to message #1100745] Wed, 04 September 2013 09:02 Go to previous message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

Thanks for getting back.

I've added https://bugs.eclipse.org/bugs/show_bug.cgi?id=351214#c1 to my
queue of things that I really must get round to.

Regards

Ed Willink


On 03/09/2013 15:36, Ronan B wrote:
> package oclplugin.logic;
>
> import org.eclipse.emf.common.util.BasicEList;
> import org.eclipse.emf.common.util.Diagnostic;
> import org.eclipse.emf.common.util.EList;
> import org.eclipse.emf.common.util.TreeIterator;
> 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.eclipse.ocl.examples.pivot.ExpressionInOCL;
> import org.eclipse.ocl.examples.pivot.OCL;
> import org.eclipse.ocl.examples.pivot.ParserException;
> import org.eclipse.ocl.examples.pivot.helper.OCLHelper;
> import org.eclipse.ocl.examples.pivot.manager.MetaModelManager;
> import org.eclipse.ocl.examples.pivot.uml.UML2Pivot;
> import org.eclipse.ocl.examples.pivot.utilities.PivotEnvironment;
> import org.eclipse.ocl.examples.pivot.utilities.PivotEnvironmentFactory;
> import org.eclipse.ocl.examples.pivot.utilities.PivotUtil;
> import org.eclipse.uml2.uml.Constraint;
> import org.eclipse.uml2.uml.Element;
> import org.eclipse.uml2.uml.Model;
> import org.eclipse.uml2.uml.NamedElement;
> import org.eclipse.uml2.uml.OpaqueExpression;
> import org.eclipse.uml2.uml.Profile;
> import org.eclipse.uml2.uml.Stereotype;
>
>
> public class OCLValidator {
>
>
>
> public void validate(Model model) {
>
> final Model myModel = model;
>
> //set up the required pivot/metamodel/model/OCL environment
> ResourceSet resourceSet = new ResourceSetImpl();
> Resource resource =
> resourceSet.getResource(myModel.eResource().getURI(), true);
> MetaModelManager metaModelManager =
> PivotUtil.getMetaModelManager(resource);
> PivotEnvironmentFactory envFactory = new PivotEnvironmentFactory(null,
> metaModelManager);
> PivotEnvironment environment =
> envFactory.createEnvironment();
> OCL ocl = OCL.newInstance(environment);
> EList<Constraint> constraints = new
> BasicEList<Constraint>(myModel.getOwnedRules());
> // Get all OCL rules from
> the model
> getOCLRulesFromModel(myModel, constraints);
> // Get all OCL rules from
> the profiles applied to the model
> getOCLRulesFromAppliedProfiles(myModel, constraints);
>
> //Now that we have all the constrains see if any are violated
> in the model
> for (Constraint constraint : constraints) {
>
> String expression =
> getOCLExpressionFromConstraint(constraint);
>
> //loop over the elements the constraint constrains
> final EList<Element> ceList =
> constraint.getConstrainedElements();
> for(Element ce : ceList)
> {
> System.out.println(ce);//TODO:Remove this later it is
> here just for sanity
> OCLHelper oclHelper = null;
>
> //stereotypes must be handled specially
> if(ce instanceof Stereotype)
> {
> //look for all the elements in the model that have
> the stereotype applied
> final EList<Element> oeList =
> myModel.allOwnedElements();
> for(Element oe : oeList)
> {
> if(oe.isStereotypeApplied((Stereotype)ce))
> {
> final EList<EObject> saList =
> oe.getStereotypeApplications();
> for(EObject sa : saList)
> {
> //make the EObject work with the
> Pivot concept i.e. so the stereotype properties are available
> org.eclipse.ocl.examples.pivot.Element
> psa= null;
>
> try
> {
> psa =
> UML2Pivot.importFromUML(metaModelManager, "xx", sa);//TODO:What use if
> the alias??
> }
> catch(Exception e)//TODO:Maybe handle
> this better
> {
> e.printStackTrace();
> }
> if(psa != null)
> {
> oclHelper = ocl.createOCLHelper(psa);
> //finally let's run the OCL!!
>
> evaluateOCL(ocl,oclHelper,expression,psa);
> }
> }
> }
> }
> }
> else
> {
> oclHelper = ocl.createOCLHelper(ce);
> oclHelper.setContext(ce.eClass());//Note:We only
> set the context for non Stereotype Applications
> //finally let's run the OCL!!
>
> evaluateOCL(ocl,oclHelper,expression,ce);
> } }
> }
> }
>
> private EList<Constraint> getOCLRulesFromAppliedProfiles(Model
> myModel, EList<Constraint> constraints)
> {
> for(Profile profile : myModel.getAllAppliedProfiles()){
> final TreeIterator<EObject> profileIterator =
> profile.eAllContents();
> while(profileIterator.hasNext()){
> EObject tempObject = profileIterator.next();
>
> if (tempObject instanceof NamedElement) {
> NamedElement ne = (NamedElement) tempObject;
>
> if(ne.getNamespace() != null) {
> final EList<Constraint> temp =
> ne.getNamespace().getOwnedRules();
>
> if(!constraints.containsAll(temp)){
> constraints.addAll(temp);
> }
> }
> }
> } }
> return constraints;
> }
>
> private EList<Constraint> getOCLRulesFromModel(Model myModel,
> EList<Constraint> constraints)
> {
> final TreeIterator<EObject> iterator = myModel.eAllContents();
>
> while(iterator.hasNext()){
> EObject tempObject = iterator.next();
> if
> (tempObject instanceof NamedElement) {
> NamedElement ne = (NamedElement) tempObject;
>
> if(ne.getNamespace() != null) {
> final EList<Constraint> temp =
> ne.getNamespace().getOwnedRules();
>
> if(!constraints.containsAll(temp)){
> constraints.addAll(temp);
> }
> }
> }
> }
> return constraints;
> }
>
> private String getOCLExpressionFromConstraint(Constraint constraint)
> {
> if (constraint.getSpecification() instanceof OpaqueExpression) {
> OpaqueExpression opaqueExpression =
> ((OpaqueExpression) constraint.getSpecification());
>
> // Find the body named OCL
> int indexOfOCLBody = -1;
> for (int i = 0; i <
> opaqueExpression.getLanguages().size() && indexOfOCLBody == -1; i++) {
> if
> (opaqueExpression.getLanguages().get(i).equals("OCL")) {
> indexOfOCLBody = i;
> }
> }
>
> // If the body was found, continue the check
> if (indexOfOCLBody != -1) {
> return
> opaqueExpression.getBodies().get(indexOfOCLBody);
> }
> }
> return null;//there was no proper OCL to be found
> }
>
> private void evaluateOCL(OCL ocl,OCLHelper oclHelper,String
> expression, Object context)
> {
> try {
>
> // Turn the expression into a query and evaluate it
> ExpressionInOCL createQuery =
> oclHelper.createQuery(expression);
> Object result = ocl.evaluate(context, createQuery);
> System.out.println("result: "+result);
> } catch (ParserException e) {
> Diagnostic diagnostic = e.getDiagnostic();
> System.out.println(diagnostic.getMessage());
> } }
> }
Previous Topic:(Pivot) Parsing OCL Document which complements a UML model
Next Topic:Traversing AST nodes of an OCL constraint programatically
Goto Forum:
  


Current Time: Fri Mar 29 10:38:01 GMT 2024

Powered by FUDForum. Page generated in 0.03202 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top