The Application Framework provides two search functionalities:
The Application Framework Simple Search uses only framework-specific data, so it is simpler to use and supports all needed query operations. This search interface is also the recommended one to use.
The Application Framework JAXR-based Search combines framework and JAXR-based data. The advantage of this search is that it can use the whole JAXR-based functionality to query the registry. The disadvantage is that in order to use it, the user must have considerable knowledge of JAXR.
The Application Framework Simple Search uses framework-specific data only and its usage has been made as simple as possible.
Creating a search object
In order to search the registry, the user must create a search object
using a BeanPool instance. The BeanPool offers several methods for creating
search objects:
BeanPool.createSearch();
This creates a search object which, when executed, searches for objects in the registry from all registered bean types (see the section Bean Types Managed by CSAF).
BeanPool.createSearch(List<Class<? extends RegistryBean>> beanClasses)
The created search object searches through all objects in the registry, from the specified list of types.
BeanPool.createSearch(Class<? extends RegistryBean bean> beanClass)
The search object searches the registry only for items from the specified type.
The search object has a result()
method which
searches the registry and returns a list of all RegistryBean objects that
satisfy the search criteria.
Example:
BeanPool beanPool = sessionContext.getCurrentBeanPool();
Search search = beanPool.createSearch();
The predicate is an object representation of a query criterion used to
restrict the search results. Predicates can be created from a factory-like
class called Predicates (com.softwareag.centrasite.appl.framework.persistence.search.Predicates
).
It provides two static methods for creating each specific predicate:
Predicates.eq(String propertyName, Object value)
Predicates.eq(String propertyName, Object value,Class<? extends RegistryBean> beanType)
where
method name is the comparison operator:
and | logical conjunction |
eq | equal |
ge | greater than or equal to |
gt | greater than |
le | less than or equal to |
like | matches a string that can include wildcards |
lt | less than |
ne | not equal |
or | logical disjunction |
property name is the name of the property to be compared. This property name is a string value representing the name of the Java property (getName() corresponds to “name”). The search functionality supports adding a sequence of properties. This is accomplished by knowing the searched RegistryBean property hierarchy and by separating following properties with a dot ".".
Example:
Predicates.eq( "externalLink.uri ", value) | The predicate is created for the URI property of the externalLinks of the searched RegistryBean, which should be equal to the given value. |
value is the value to compare against. Most methods
expect an Object value because the search can handle a variety of objects
including String, Number, Date, Calendar,
Key,
RegistryBean and others. There are also methods
that expect a specific value type. An example is like(String
propertyName
, String value
), which
supports wildcards and therefore the expected value type is String. Other
object types that are worth mentioning are the so-called support types
(TelephoneNumbers, InternationalString, LocalizedString, EmailAddress,
PostalAddress, etc.). They can be used for search criteria but not as a
searched object because they are not registry beans. For example, the following
search is valid:
Search search = beanPool.createSearch(User.class)
; Predicates.eq("telephoneNumbers.countryCode
", "someCountryCode");
But the following search is not valid:
Search search = beanPool.createSearch(EmailAddress.class)
;
beanType is the bean type for which the predicate will be applied.
Important:
If no beanType is specified then the predicate is applied
to the first bean type in the Search object's list of bean types. Note that the
first item of that list must support the property passed to the predicate,
otherwise the search will fail. In cases where the search object is created for
all supported bean types, the list is filled randomly so the user must be aware
of all common properties supported by these RegistryBean types.
Each predicate can be added to the search object by invoking the search method:
addPredicate(Predicate predicate);
A search object can add multiple predicates, which can be treated as predicates joined by an "and" operator. For example:
Search search = beanPool.createSearch(); search.addPredicate(predicate1); search.addPredicate(predicate2); search.addPredicate(predicate3);
is equal to "predicate1 and predicate2 and predicate3" in the query to be executed.
There are two more methods in the Predicates class:
and(Predicate p1, Predicate p2)
and
or(Predicate p1, Predicate p2)
. These methods create a
so-called combine predicate. They join two predicates by logical conjunction or
logical disjunction respectively. This predicate can be added to the search
object in the same way as the common predicates explained above.
All supported predicates are created from methods in the Predicates
class (com.softwareag.centrasite.appl.framework.persistence.search.Predicates
).
Like Predicate
A predicate that supports usage of wildcards. The value field of the creating methods:
like(String propertyName, String value)
like(String propertyName, String value, Class<?
extends RegistryBean>
beanType)
is of Type String, so the user may add strings (possibly including wildcards).
Example:
like("name","%partOfExpectedName");
Wildcards
The like predicate supports wildcards in the manner of SQL and UDDI. For more details, refer to the section About wildcards in the UDDI specification: http://uddi.org/pubs/uddi-v3.0.2-20041019.htm#_Toc85908082. The wildcard characters are as follows:
Wildcard character | Indicates |
---|---|
% | Any value for any number of characters |
_ | Any value for a single character |
The following special cases are supported:
To represent... | use the character string... |
---|---|
% | \% |
_ | \_ |
\ | \\ |
Greater Than Predicate
A predicate that compares Number, Date or Calendar, returning true if the compared object value is greater than the value given in the predicate's creating method “value” field:
gt(String propertyName, Object value)
gt(String propertyName, Object value, Class<?
extends RegistryBean>
beanType)
The value must be one of the following types: Number, Date, Calendar.
Example:
Calendar calendar = Calendar.getInstance(); Predicate predicate = Predicates.gt("requestDate",calendar);
Less Than Predicate
A predicate that compares Number, Date or Calendar, returning true if the compared object value is less than the value given in the predicate's creating method “value” field:
lt(String propertyName, Object value)
lt(String propertyName, Object value, Class<?
extends RegistryBean>
beanType)
The value must be one of the following types: Number, Date, Calendar.
Example:
Predicate predicate = Predicates.lt("copyNumber",203);
Greater or Equal Predicate
A predicate that compares Number, Date or Calendar, returning true if the compared object value is greater than or equal to the value given in the predicate's creating method “value” field:
ge(String propertyName, Object value)
ge(String propertyName, Object value, Class<?
extends RegistryBean>
beanType)
The value must be one of the following types: Number, Date, Calendar.
Example:
Predicate predicate = Predicates.ge("copyNumber",203);
Less or Equal Predicate
A predicate that compares Number, Date or Calendar, returning true if the compared object value is less than or equal to the value given in the predicate's creating method “value” field:
le(String propertyName, Object value)
le(String propertyName, Object value, Class<?
extends RegistryBean>
beanType)
The value must be one of the following types: Number, Date, Calendar.
Example:
Predicate predicate = Predicates.le("copyNumber",203);
Equal Predicate
A predicate that returns true if the compared object value is equal to the value given in the predicate's creating method “value” field:
eq(String propertyName, Object value)
eq (String propertyName, Object value, Class<?
extends RegistryBean>
beanType)
The value must be one of the following types: Number, Date, Calendar, String, Key, RegistryBean.
If the value is of type RegistryBean then the comparison is made by the RegistryBean's key.
Example:
Predicate predicate = Predicates.eq("name","somePropertyname");
Not Equal Predicate
A predicate that returns true if the compared object value is not equal to the value given in the predicate's creating method “value” field:
ne(String propertyName, Object value)
ne (String propertyName, Object value, Class<?
extends RegistryBean>
beanType)
The value must be one of the following types: Number, Date, Calendar, String, Key, RegistryBean.
If the value is of type RegistryBean then the comparison is made by the RegistryBean's key.
Example:
Predicate predicate = Predicates.ne("name","somePropertyname");
AND Predicate
A predicate that joins two predicates in a logical conjunction. The method that creates this predicate:
public static Predicate and(Predicate p1, Predicate
p2)
expects two predicates as arguments.
Example:
Predicate predicate1 = Predicates.eq("name","somePropertyname"); Predicate predicate2 = Predicates.eq("name","somePropertyname2"); Predicate andPredicate = Predicates.and (predicate1, predicate2);
OR Predicate
A predicate that joins two predicates in a logical disjunction. The method that creates this predicate:
public static Predicate or(Predicate p1, Predicate
p2)
expects two predicates as arguments.
Example:
Predicate predicate1 = Predicates.eq("name","somePropertyname"); Predicate predicate2 = Predicates.eq("name","somePropertyname2"); Predicate orPredicate = Predicates.or (predicate1, predicate2);
Order can be created by using one of the Order (com.softwareag.centrasite.appl.framework.persistence.search.Order)
static methods: asc(String propertyName)
or desc(String
propertyName)
, creating ascending or descending order respectively for a
given property. The rules for the property name when creating Order are the
same as when creating a Predicate. The user must know whether the bean types
added to the search object support the property passed to the Order asc(String
propertyName) or desc(String propertyName) methods. Multiple orders may be
added to the search object.
Example:
Order order = Order.asc("description");
After adding the necessary predicates and orders to the search object,
the search can be executed by invoking the result()
method on the search object. It returns a list of all RegistryBean objects in
the registry that applied the predicate conditions in the specified order. The
result is lazy loading compatible.
Here is an example of a Search lifecycle:
List searchTypes = new ArrayList(); searchTypes.add(ReviewRequestOutcome.class); searchTypes.add(ServiceInterfaceVersion.class); Search search = beanPool.createSearch(searchTypes); Predicate predicate1 = Predicates.eq("ExternalLink.URI", "http://www.softwareag.com"); Predicate predicate2 = Predicates.eq("name","somePropertyname2"); Predicate orPredicate = Predicates.or (predicate1, predicate2); Search.addPredicate(orPredicate); search.addOrder("name"); List<RegistryBean> result = (List<RegistryBean>) search.result();
This means that all ReviewRequestOutcomes and ServiceInterfaceVersions will be searched and the ones that have name equal to “somePropertyname2” or ExternalLink with URI equal to “http://www.softwareag.com” will be returned in the resulting List of RegistryBean objects ordered by name.
There are several points where the user can extend the existing Application Framework functionality.
Each Java bean property is internally represented as a com.softwareag.centrasite.appl.framework.mapping.Property instance.
The recommended way of creating a new property is by extending,
directly or indirectly, the BaseProperty
class
(com.softwareag.centrasite.appl.framework.mapping.BaseProperty).
In order to map the information from a given annotation to the new Property correctly, a user-defined Property Processor that implements the PropertyAnnotationProcessor (com.softwareag.centrasite.appl.framework.PropertyAnnotationProcessor) must be created.
Then the newly created PropertyProcessor must be added to the list of
processors in the BeanTypeAnnotationProcessor (com.softwareag.centrasite.appl.framework.BeanTypeAnnotationProcessor)
using the addAnnnotationProcessor(Class<?> annotationType,
PropertyAnnotationProcessor annotationProcessor)
method.
Each property value must be transferred to/from the underlying registry object. For that purpose, CSAF provides the (com.softwareag.centrasite.appl.framework.persistence.mapper.PropertyMapper) interface.
Users can provide their own implementation of the PropertyMapper
interface by hooking it to a given type of Property. Such a property mapper is
registered using the
com.softwareag.centrasite.appl.framework.persistence.mapper.PropertyMapperFactory.addHandler(PropertyMapperFactory.Handler)
method.
The preferred method of creating a custom defined predicate is to
extend the DefaultPredicate
(com.softwareag.centrasite.appl.framework.persistence.search.impl.DefaultPredicate)
class directly or indirectly. Another way is to directly implement the
Predicate interface (com.softwareag.centrasite.appl.framework.persistence.search.Predicate),
although this is not recommended because it does not offer default
behavior.
In order to use this newly-created predicate, the user must create a custom defined predicate handler, which must implement the PredicateHandler interface (com.softwareag.centrasite.appl.framework.persistence.search.PredicateHandler). This predicate handler must be added to the PredicateFactory (com.softwareag.centrasite.appl.framework.persistence.search.impl.PredicateFactory) list of predicate handlers by calling addPredicateHandler(PredicateHandler handler).
Whereas the BeanPool interface takes care of the standard CRUD operations to the registry, the queries are performed using the Query interface (com.softwareag.centrasite.appl.framework.persistence.Query):
package com.softwareag.centrasite.appl.framework.persistence; public interface Query<T extends RegistryBean> { List<T> run(QueryContext pContext) throws JAXRException, CSAppFrameworkException; }
In order to do a query, one should implement this interface and place
the querying routines in the run()
method
implementation. The query is then executed via
BeanPool.run()
:
<T extends RegistryBean> List<T> run(Query<T> pQuery) throws CSAppFrameworkException;
The returned data is then in the form of beans.
This mechanism still requires knowledge of JAXR. The benefit is that JAXR is isolated in this interface. Below is a sample implementation of Query:
final Query<EntryCode> q = new Query<EntryCode>() { public List<EntryCode> run(QueryContext context) throws JAXRException { final RegistryAccessor regDAO = context.getRegistryAccessor(); final Concept concept = regDAO.findConceptByPath("CSAF-Taxonomy", "/ClassificationInstances/EntryCodeType"); final List<EntryCode> result = new ArrayList<EntryCode>(); for (Concept c : (Collection<Concept>) concep.getChildrenConcepts()) { try { EntryCode ec = context.getCurrentBeanPool().read(EntryCode.class, c.getKey().getId()); result.add(ec); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } return result; } }; List<RegistryBean> queryResult = getBeanPool().run(q);
In general, a Query would use the JAXR-based API to find and retrieve the data, and then the keys of registry objects that were found are passed to the BeanPool to build the beans. These beans are then returned as the result of the query execution.