Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "VIATRA/Addon/Query Based Features/Legacy Code Generator"

Line 73: Line 73:
  
 
The most straightforward way is to call the getter method of the feature itself. However, if for some reason that is not possible, you can access the values using the getter methods of the [http://eclipse.org/incquery/javadoc/releases/0.7.0/org/eclipse/incquery/querybasedfeatures/runtime/QueryBasedFeatureHandler.html QueryBasedFeatureHandler] object. Apart from the generic getValue, there are specific methods (getIntValue, getSingleReferenceValue etc.), each returning a properly typed target for a given source element.
 
The most straightforward way is to call the getter method of the feature itself. However, if for some reason that is not possible, you can access the values using the getter methods of the [http://eclipse.org/incquery/javadoc/releases/0.7.0/org/eclipse/incquery/querybasedfeatures/runtime/QueryBasedFeatureHandler.html QueryBasedFeatureHandler] object. Apart from the generic getValue, there are specific methods (getIntValue, getSingleReferenceValue etc.), each returning a properly typed target for a given source element.
 +
 +
== Advanced issues ==
 +
 +
=== Creating an iteration query-based feature ===
 +
 +
It is possible to create a query-based feature that is not simply the result of the model query, but the value calculated by an iteration algorithm on the results of the query.
 +
 +
Important: the iteration algorithm must be able to compute the new value based on it's current value and the new or lost match of the used query.
 +
 +
In order to create your own iteration feature, you need to subclass [http://eclipse.org/incquery/javadoc/releases/0.8.0/org/eclipse/incquery/querybasedfeatures/runtime/QueryBasedFeature.html QueryBasedFeature] and implement the following methods:
 +
 +
* ''newMatchIteration(IPatternMatch)'': based on the match (that just appeared) passed to the method, return a notification that represents the changes in the value of the feature. Note that you should not send out this notification, that is the responsibility of the feature handler.
 +
* ''lostMatchIteration(IPatternMatch)'': based on the match (that just disappeared) passed to the method, return a notification that represents the changes in the value of the feature. Note that you should not send out this notification, that is the responsibility of the feature handler.
 +
* ''getValueIteration(Object)'': based on the source element passed to the method, return the value for the feature.
  
 
== Pitfalls ==
 
== Pitfalls ==

Revision as of 11:25, 10 July 2014

This page contains information relevant to the legacy code generation used for query-based features by default before EMF-IncQuery 0.8.0 and still supported by adding the generateIntoModelCode annotation parameter.

Developer documentation

Instantiating query-based feature handlers

The easiest way is to create a simple query-based feature and look at the generated code in the getter function.

If you need to create a handler for some reason, use the static getQueryBasedFeatureHandler() methods of the QueryBasedFeatureHelper class.

Example codes that were generated for the school example:

/**
 * EMF-IncQuery handler for query-based feature numberOfTeachers
 */
private QueryBasedFeatureHandler numberOfTeachersHandler;
 
/**
 * <!-- begin-user-doc --> <!-- end-user-doc -->
 * @derived getter created by EMF-IncQuery for query-based feature numberOfTeachers
 */
public int getNumberOfTeachers() {
 if (numberOfTeachersHandler == null) {
  numberOfTeachersHandler = QueryBasedFeatureHelper.getQueryBasedFeatureHandler(
    this, SchoolPackageImpl.Literals.SCHOOL__NUMBER_OF_TEACHERS,
    "teachers", "School", null, FeatureKind.COUNTER,
    true, false);
 }
 return numberOfTeachersHandler.getIntValue(this);
}
 
/**
 * EMF-IncQuery handler for query-based feature teachersWithMostCourses
 */
private QueryBasedFeatureHandler teachersWithMostCoursesHandler;
 
/**
 * <!-- begin-user-doc --> <!-- end-user-doc -->
 * @derived getter created by EMF-IncQuery for query-based feature teachersWithMostCourses
 */
public EList<Teacher> getTeachersWithMostCourses() {
 if (teachersWithMostCoursesHandler == null) {
  teachersWithMostCoursesHandler = QueryBasedFeatureHelper.getQueryBasedFeatureHandler(
    this, SchoolPackageImpl.Literals.SCHOOL__TEACHERS_WITH_MOST_COURSES,
    "teachersWithMostCourses", "School", "Teacher", FeatureKind.MANY_REFERENCE,
    true, false);
 }
 return teachersWithMostCoursesHandler.getManyReferenceValueAsEList(this);
}
 
/**
 * EMF-IncQuery handler for query-based feature lastYear
 */
private QueryBasedFeatureHandler lastYearHandler;
 
/**
 * <!-- begin-user-doc --> <!-- end-user-doc -->
 * @derived getter created by EMF-IncQuery for query-based feature lastYear
 */
public Year basicGetLastYear() {
 if (lastYearHandler == null) {
  lastYearHandler = QueryBasedFeatureHelper.getQueryBasedFeatureHandler(
   this, SchoolPackageImpl.Literals.SCHOOL__LAST_YEAR,
   "lastYear", "School", "Year", FeatureKind.SINGLE_REFERENCE,
   true, false);
 }
 return (school.Year) lastYearHandler.getSingleReferenceValue(this);
}

Accessing the current value of query-based features

The most straightforward way is to call the getter method of the feature itself. However, if for some reason that is not possible, you can access the values using the getter methods of the QueryBasedFeatureHandler object. Apart from the generic getValue, there are specific methods (getIntValue, getSingleReferenceValue etc.), each returning a properly typed target for a given source element.

Advanced issues

Creating an iteration query-based feature

It is possible to create a query-based feature that is not simply the result of the model query, but the value calculated by an iteration algorithm on the results of the query.

Important: the iteration algorithm must be able to compute the new value based on it's current value and the new or lost match of the used query.

In order to create your own iteration feature, you need to subclass QueryBasedFeature and implement the following methods:

  • newMatchIteration(IPatternMatch): based on the match (that just appeared) passed to the method, return a notification that represents the changes in the value of the feature. Note that you should not send out this notification, that is the responsibility of the feature handler.
  • lostMatchIteration(IPatternMatch): based on the match (that just disappeared) passed to the method, return a notification that represents the changes in the value of the feature. Note that you should not send out this notification, that is the responsibility of the feature handler.
  • getValueIteration(Object): based on the source element passed to the method, return the value for the feature.

Pitfalls

Code generation fails for derived feature query

Ensure that both the .genmodel file and the model project with the generated EMF model code is available in the same workspace as the EMF-IncQuery project with the query definitions.

UnsupportedOperationException during model editing, even after successful generation

If you have multiple inheritance in your metamodel, it is possible that the getter for a feature will be implemented in more than one place. The easy way to avoid this is to ensure, that query-based features are only inherited from one supertype and that supertype is used as the extension and not only as interface (i.e. that type must be the first in the values of the supertypes feature).

In the unfortunate case when you have query-based features in multiple supertypes, the generator will only override the getter in the implementation class of the defining EClass, so you will have to copy-paste the generated getter code and the handler into the subclass implementation as well.

Future versions of EMF-IncQuery may support the automatic generation into multiple implementation classes.

Alternatively, you can try the setting delegate based implementation, which avoids this problem.

Back to the top