Resource Filter bundle provides a number of services and utilities to identify and filter resources in a resource tree.
ResourceStream
is a general utility. It provides two functions. The first is access to a Stream<Resource>
which traverses a resource and it's subtree. The function takes a Predicate<Resource>
object which is used to select the child nodes to be part of the traversal.
ResourceStream rs = new ResourceStream(resource);
In addition there is a getChildren(Predicate)
method which returns a filtered list of children of the given resource.
ResourcePredicate
is a service that allows you to convert a string that defines a simple matching requirements into a Predicate<Resource>
for use with the Collections and the Streams Java API. In addition it also allows you to add parameters to the underlying context that the script will use.
@Reference
ResourcePredicates rp;
Predicate<Resource> predicate = rp.parse("[jcr:content/created] < 2013-08-08T16:32");
resourceCollection.stream().filter(predicate).forEach(
resource -> System.out.println(resource.getPath())
);
ResourceFilterStream
combines the ResourceStream
functionality with the ResourcePredicates
service to provide an ability to define a Stream<Resource>
that follows specific child pages and looks for specific Resources as defined by the resources filter script. The ResourceStreamFilter is access by adaption.
ResourceFilterStream rfs = resource.adaptTo(ResourceFilterStream.class);
rfs
.setBranchSelector("[jcr:primaryType] == 'cq:Page'")
.setChildSelector("[jcr:content/sling:resourceType] != 'apps/components/page/folder'")
.stream()
.collect(Collectors.toList());
To ease the creation of a Predicate<Resource>
a scripting implementation was developed that was designed to be visually similar to JCRSQL use of property identification where a property is compared to one or more values.
Name | Comparison Type | Description |
---|---|---|
and | NA | Logical AND |
&& | NA | Logical AND |
or | NA | Logical OR |
|| | NA | Logical OR |
== | String | Equal operator for Strings |
< | Number | Less than operator for Numbers |
<= | Number | Less than or equal operator for Numbers |
> | Number | Greater than operator for Numbers |
>= | Number | Greater than or equal operator for Numbers |
!= | String | Is not equal to for Strings |
~= | String - Regex | Regex match against String |
less than | Number | less than operator for Numbers |
greater than | Number | greater than operator for Numbers |
is | String | Equal operator for Strings |
is not | String | Is not equal operator for Strings |
like | String - Regex | Regex match against String |
is like | String - Regex | Regex match against String |
not like | String - Regex | Regex does not match String |
contains | String[] | String[] contains all of items |
contains not | String[] | String[] does not contain all of the items |
contains any | String[] | String[] contains at least one of items |
contains not any | String[] | String[] does not contain any of the items |
The 'and' and 'or' operators are logical operators that string together conditions. 'And' operators take precedence. 'Or' operators evaluate from left to right
Values for comparison are obtained through multiple methods
Method | Description |
---|---|
Literal | Single(') or double (") quoted text in the query will be interpreted as a String. Boolean values of true and false will be translated to a String. |
Property | A String between square brackets '[',']'s will be interpreted as a property value and will be retrieved from the Resource using the get method |
Function | A string followed by parens containing an optional comma separated list of values. |
All types are converted to either a String or a Number. For direct equivalence the comparison is done as a String. For relational comparisons the object will be adapted to a number.
Dates are special, there are multiple ways to enter a date.
In line, as part of the query, a date can be identified as a string that conforms to a standard ISO-8601 date time.
'2013-08-08T16:32:59.000'
'2013-08-08T16:32:59'
'2013-08-08T16:32'
Are all valid date representations that are defaulting to the UTC timezone.
For a ISO8601 date with timezone offset use the date function.
date('2013-08-08T16:32:59.000+02:00')
If you need a different date format then the date function can accommodate that
date('2013-08-08','yyyy-MM-dd')
Or you can add your own custom Function
Dates are transitionally represented as a java.util.Instant which is then converted to a String in ISO-8601 format or as a Long number based on the type of comparison. The number representing the time in milliseconds since the EPOCH UTC region
Functions provide additional functionality to the Filter language. A Function is written in the format
string '(' comma, separated, list() ')'
OOTB Functions are:
Name | Arguments | Returns | Description |
---|---|---|---|
name | none | String | Provides the name of the resource |
date | 0 - 2 | Instant | First argument is string representation of the date, second argument is a standard Java DateFormat representation of the value. No argument returns the current time. |
path | none | String | path of the tested resource |
The ResourceFilter and ResourceFilteStream can have key value pairs added so that the values may be used as part of the script resolution. Parameters are accessed by using the dollar sign '$'
rfs.setBranchSelector("[jcr:content/sling:resourceType] != $type").addParam("type","apps/components/page/folder");
Similar to indexing in a query there are strategies that you can do within a tree traversal so that traversals can be done in an efficient manner across a large number of resources. The following strategies will assist in traversal optimization.
In a naive implementation of a tree traversal the traversal occurs across all nodes in the tree regardless of the ability of the tree structure to support the nodes that are being looked for. An example of this is a tree of Page resources that have have a child node of jcr:content which contains a subtree of data to define the page structure. If the jcr:content node is not capable of having a child resource of type Page and the goal of the traversal is to identify Page resources that match a specific criteria then the traversal of the jcr:content node can not lead to additional matches. Using this knowledge of the resource structure, you can improve performance by adding a branch selector that prevents the traversal from proceeding down a non productive path
The instantiation of a Resource object from the underlying ResourceResolver is a non trivial consumption of memory. When the focus of a tree traversal is obtaining information from thousands of Resources, an effective method is to extract the information as part of the stream processing or utilizing the forEach method of the ResourceStream object which allows the resource to be garbage collected in an efficient manner.