Home > Query Language > Basic Concepts > Path Expressions
Field References and Path Expressions
An important requirement for the query language to work is the ability to easily reference fields of the class model, i.e. attributes, navigable associations and inferred fields. Moreover you must be able to create path expressions, i.e. sequences of fields.
// fields can be referenced with the ".P." notation Person.P.birthplace Address.P.street // within a query these field references must be encapsulated within "P()" P(Person.P.birthplace) P(Address.P.street) // path expressions can be created with the "nav()" operator nav( P(Person.P.birthplace), P(Address.P.street) )
Navigate beyond collection-valued fields?
What happens if a field references a collection-valued field? Are you enforced to finish your path expression at collection-valued fields or can you go on and add more fields to your path?
The following example shows a valid path expression which contains the collection-valued field "children" and appends the field "name" afterwards. Hence an expression can navigate beyond collection-valued fields.
// a path expression can navigate beyond collection-valued fields
nav( P(Person.P.children), P(Person.P.name) )
The terminating elements of a path expression determine whether navigation is allowed. If an expression contains a single-valued or collection-valued field, the navigation can continue to an object that is related to the field. However, an expression cannot navigate beyond fields that represent mapped attribute objects (e.g. "org.oomega.base.String" which is mapped to "java.lang.String") or primitive types, i.e. "byte" or "natural".
The "IN" operator
Object-oriented query languages, e.g. the Java Persistence Query Language, often support the so called "IN" operator, which must be used in order to navigate beyond collection-valued fields.
SELECT p FROM Person p, IN (p.children) c
By contrast, OOMEGA's query language does not offer that "IN" operator, because collection-valued fields are not terminating elements of path expressions. Instead reasonable semantics for this new kind of a path expression are defined.
Examples
Person.P.children
If you apply the field reference "Person.P.children" to a given person, e.g. with the help of our reflection API, you get the children collection.
// get the person's children // alternative 1 Collection<Person> children = person.mget(Person.P.children); // alternative 2 Collection<Person> children = person.getChildren();
nav( P(Person.P.children), P(Person.P.name) )
If you apply the path expression "nav( P(Person.P.children), P(Person.P.name) )" to a given person, you receive the names of the children.
// get the names of the person's children // alternative 1 Collection<Object> names = person.evaluate( nav( P(Person.P.children), P(Person.P.name) ) ); // alternative 2 Collection<Object> names = new HashSet<String>(); for (Person child : person.getChildren()) { names.add(child.getName()); }
nav( P(Person.P.children), P(Person.P.children) )
If you apply the path expression "nav( P(Person.P.children), P(Person.P.children) )" to a given person, you receive the grandchildren. Please note that the children are not part of the result.
// get the person's grandchildren // alternative 1 Collection<Object> grandchildren = person.evaluate( nav( P(Person.P.children), P(Person.P.children) ) ); // alternative 2 Collection<Object> grandchildren = new HashSet<Person>(); for (Person child : person.getChildren()) { grandchildren.addAll(child.getChildren()); }
nav( P(Person.P.children), P(Person.P.children), P(Person.P.name) )
If you apply the path expression "nav( P(Person.P.children), P(Person.P.children), P(Person.P.name) )" to a given person, you receive the grandchildren's names. Please note that the children's names are not part of the result.
// get the names of the person's grandchildren // alternative 1 Collection<Object> names = person.evaluate( nav( P(Person.P.children), P(Person.P.children), P(Person.P.name) ) ); // alternative 2 Collection<Object> names = new HashSet<String>(); for (Person child : person.getChildren()) { for (Person grandchild : child.getChildren()) { names.add(grandchild.getName()); } }
Next chapter: Input Parameters