In an application I receive a list of strings. Then I want to use OclPs to find all objects where a specific attribute equals any of the strings in the list. E.g. if we have Person objects and receive a list of last names, find all persons whose last name appears in the list.
Although this can surely be done in MDriven's in-memory OCL engine, I can't seem to achieve this in the more limited OclPs (which translates the OCL to SQL and evaluates it as such in the database).
Attempt 1: First assign the list of names to vNames
(collection of strings), then:
Person.allInstances->select(p|vNames->exists(n|n = p.LastName))
This gives error "Loop variables can only have class type, not System.String".
Attempt 2: First assign a "|"
separated string of the sought names, including leading and trailing "|"
, to vNames
, then:
Person.allInstances->select(p|vNames.SqlLike('%|' + p.LastName + '|%'))
This gives error saying strings cant be added in Firebird. But Firebird does support string concatenation using the ||
operator.
Trying with .Contains(...)
instead of .SqlLike(...)
says it's not supported in OclPs. Besides, it would find persons with a last name that is CONTAINED in any of the sought names, i.e. an incorrect search.
I'm out of ideas...
In this case when you have a long list of strings and you want a list of objects I think you best option is to use SQL with sqlpassthroughobjects:
https://wiki.mdriven.net/index.php/OCLOperators_sqlpassthroughobjects
Person.sqlpassthroughobjects('select personid from person where lastname in ('+vNames->collect(n|'\''+n+'\'')->asCommaList+')')