Programmatically execute an OCL query on a UML model - ocl

Can anyone provide an example of how to programmatically execute an OCL query on a UML model using Eclipse MDT/OCL implementation. I read the Eclipse documentation, but still could not find a working example and I keep getting different exceptions and errors.
Thanks for your help.

Here is an example how you can instantiate an ocl query. There exist two environment factories for OCL, one for Ecore which is used in this example and another one for UML. Since UML is implemented with Ecore you can also use the Ecore factory if you want to evaluate UML Models.
private final OCL<?, EClassifier, ?, ?, ?, EParameter, ?, ?, ?, Constraint, EClass, EObject> ocl;
private final OCLHelper<EClassifier, ?, ?, Constraint> helper;
this.ocl = OCL.newInstance(EcoreEnvironmentFactory.INSTANCE);
this.helper = ocl.createOCLHelper();
After you have instantiated the OCL and OCLHelper objects its important to set the context object for the OCL query:
helper.setContext(UMLPackage.eINSTANCE.getClass_());
UMLPackage.eInstance has a couple of getters for Class_, Property, Operation and other UML Classes, there is a similar object for Ecore: EcorePackage.eINSTANCE. Next you need to create an OCLExpression and then from it the query.
OCLExpression<EClassifier> expression = helper.createQuery("self.attribute->size() > 0");
Query<EClassifier, EClass, EObject> query = ocl.createQuery(expression);
Now you can check the query on some element:
boolean success = query.check(myElement);
If the check method returns true, then your query is valid for the given model. In that code myElement would be an object of your ECore model with the type Class. The object that you pass to the check method must match the context type that you have set in the helper.

Related

how to evaluate sql query using RelNode object

I am trying to convert sql query to Tinkerpop Gremlin. sql2Gremlin library does it but it looks on join as relation while I am relying on no join approach where you can refer relations with dot as delimiter between two entity.
I have parsed and validated query and I have RelRoot object.
Apache calcite returns RelRoot object which is root of algebraic expression.
Lets say I dont want to apply any query optimization, How do i use my RelNode Visitor to transform the RelRoot into TinkerPop Gremlin DSL.
Ideally I would first use From clause and then apply filters defined in where clause? How is select, filters, From clause represent in RelRoot tree?
What does apache calcite means by relational expression or RelNode?
Rephrasing the same question without TinkerPop Gremlin context:
How should I use RelRoot visitor to visit the RelRoot and transform the query to another DSL?
I don't know why you insist on RelRoot and not RelNode tree, but Apache Calcite is doing its optimizations of relational algebra in RelNode stack. There is a class called RelVisitor that you might find interesting, since it can do exactly what you need: visit all RelNodes. You can then extract information you need from them and build your DSL with it.
EDIT: In RelVisitor, you have access to the parent node and the child nodes of the currently visited node. You can extract all the information usually available to the RelNode object (see docs), and if you cast it to specific relational algebra operation, for example, Project, you can extract what fields are inside Project operation by doing node.getRowType().getFieldList().forEach(field -> names.add(field.getName())), where names is a previously defined Set<String>. You can find the full code here.
You should also take a look at the algebra docs to understand how SQL maps to relational algebra in Calcite before attempting this.

create generic list object from datatable which has different schema at runtime

Datatable should be converted to a generic list. The datatable may have different schema at runtime.so extracting the class type for the generic list becomes difficult. Because as the columns differ at run time, I could'nt create property for the class type accordingly. I want to know how to do that. i am using c#.

Using column length to validate

/**
* #Column(type="string", length=10)
*/
protected $name;
What exactly is the purpose of 'length'?
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#annref-column
At the above URL it states: "length: Used by the 'string' type to determine its maximum length in the database. Doctrine does not validate the length of a string values for you."
I have the length defined in my database, so what is the point of adding 'length' in Doctrine? Does 'length' have anything to do with validation?
The only thing I can figure out is it cuts off the excess characters before trying to insert it into the database. Very annoying when I want an exception or error.
Thanks :D
Doctrine does not apply any kind of validation on your entities: it just loads and saves data applying the required type conversions (and fails if something is wrong with your objects).
The length attribute is there just to aid during schema generation when you use Doctrine's schema tools.
You can still extract that value with the metadata API of Doctrine 2 ORM eventually, but consider using a proper validation library for such tasks.

Django ORM join with another table

I have a table known as messages. In my application, users can send different type of messages. Like forwarding an event, etc. As such, I have columns type and value in that table.
What I want to do is for a particular type, goto a particular table and make sure the value is valid (typically this maps to the id of that table). There could be multiple types, and each one has to be mapped to a different table. Is there a way to logically write this in the built in django ORM? Right now I'm only seeing this feasible if I use straight SQL, which I would rather not if I can get away with it...
Right now I'm doing something like:
Messages.objects.all().filter(Q(user_id=id))...etc
I want to add to the statement above checking the type and for the particular type, check the table associated with it.
It sounds like you have a "polymorphic association". There are a couple ways to do analogous things in Django, but I think the one that most closely matches what you described is the contenttypes module, which uses separate columns for the type and for the value as in your application.
You may just want to define a multi-table inheritance structure. This gets you the same result in that you have multiple types of messages and field inheritance, but you don't have to mess with a type field at all.
class Message(models.Model):
value = models.CharField(max_length=9000)
class Event(Message):
pass
class Tweet(Message):
pass
In view post handler:
...
if request.POST['type'] == 'event':
Event.objects.create(value=request.POST['value'])
elif request.POST['type'] == 'tweet':
Tweet.objects.create(value=request.POST['value'])
...
Then, get your objects:
all_tweets = Tweet.objects.all()
all_messages = Message.objects.all()
for message in all_messages:
try:
event = message.event
except Event.DoesNotExist:
# this message is not an Event
pass
If this sort of structure doesn't work for you, there are two other styles of Model inheritance supported by Django: Abstract base classes and Proxy models. You could also hold a GenericForeignKey as suggested by #AndrewGorcester.

Django - How to annotate QuerySet using multiple field values?

I have a model called "Story" that has two integer fields called "views" and "votes". When I retrieve all the Story objects I would like to annotate the returned QuerySet with a "ranking" field that is simply "views"/"votes". Then I would like to sort the QuerySet by "ranking". Something along the lines of...
Story.objects.annotate( ranking=CalcRanking('views','votes') ).sort_by(ranking)
How can I do this in Django? Or should it be done after the QuerySet is retrieved in Python (like creating a list that contains the ranking for each object in the QuerySet)?
Thanks!
PS: In my actual program, the ranking calculation isn't as simple as above and depends on other filters to the initial QuerySet, so I can't store it as another field in the Story model.
In Django, the things you can pass to annotate (and aggregate) must be subclasses of django.db.models.aggregates.Aggregate. You can't just pass arbitrary Python objects to it, since the aggregation/annotation actually happens inside the database (that's the whole point of aggregate and annotate). Note that writing custom aggregations is not supported in Django (there is no documentation for it). All information available on it is this minimal source code: https://code.djangoproject.com/browser/django/trunk/django/db/models/aggregates.py
This means you either have to store the calculations in the database somehow, figure out how the aggregation API works or use raw sql (raw method on the Manager) to do what you do.