HDR Query

The query framework provides a RIM-like Java interface to retrieve data from the HDR repository. This document introduces constructs and features included with the query framework to retrieve information.

At the high level, a query is defined in terms of fetch and criteria objects. A fetch corresponds to a request for a certain type of information (for example, an ActFetch is a request for act information). Fetches are used in combination with criteria, which specify conditions objects must meet if they are to be retrieved by the query. In SQL query terms, a fetch corresponds to the SELECT/FROM clause and the criteria to the WHERE clause.

The code samples below help you do the following:

Query Submission Diagram Conventions:

  • Fetches are represented by red boxes.
  • Criteria are represented by boxes that correspond to standard RIM diagram colors for their object type.
  • Text adjacent to links distinguishes between link types where necessary (such as Player vs Scoper).

Scenario

This scenario illustrates the following query fundamentals:

  • Submitting a query.
  • Combining fetches and criteria to retrieve data.
  • Resulting object graph and the fetch graph symmetry.
  • Navigating object graph results.

Figure 7.5.1 describes how to retrieve a patient (including the playing entity) based on the patient id. The following information must be retrieved:

  • The patient role with the id attribute.
  • The playing person entity with the name, address, birth time and administrative gender code attributes.

Figure 7-1 Scenario Description

Scenario Description

Fetches

A fetch is a request for information. Queries consist of one or more connected fetches that request some combination of Act, ActRelationship, Participation, Entity and Role data. These sections describe important fetch functions used in querying:

Flexible Retrieval

Flexible retrieval is the ability to specify a subset of attributes to retrieve in a query. This lets you optimize performance by retrieving only the data necessary to satisfy application requirements. For each fetch there are several retrieve<AttributeName>(boolean bool) methods that can be used to specify which attributes should be retrieved.

Example 7-6 Retrieve the Patient Id

The following code line requests the retrieval of the patient id:

patRoleFetch.retrieveId(true);

By default, no attributes are retrieved so you must call the appropriate retrieve method for all of the attributes you require. For convenience, fetches include a retrieveAll() method that specifies that all attributes of the class should be retrieved. There is also a retrieveNone() method that acts in reverse to the retrieveAll() method. The retrieve methods used by a fetch specify the minimum set of data that the system must retrieve to fulfill the query; the platform may retrieve additional data beyond that requested.

Set Criteria on Fetches

Criteria are used in combination with fetches to constrain the data retrieved by a query. You can associate criteria with a fetch in two ways:

  • Pass the criteria as a parameter to the factory method for the fetch. Each fetch factory method is overloaded to accept a criteria object of the corresponding HL7 type (Example 7-16).
  • Call setTopLevel<HL7Class>Criteria, which associates a criteria with a preexisting fetch.

Note:

Use of either method (Examples 7-16, 7-17) is discretionary; there is no functional difference between the two methods.

Example 7-7 Construct Patient Role

In the introductory scenario the patient role fetch was constructed with the role criteria using the following code line:

RoleFetch patRoleFetch = queryComponentFactory.newRoleFetch(patRoleCriteria);

Associating Patient Role Criteria with Role Fetch: Each fetch has a setTopLevel<HL7Class>Criteria(...) method that associates criteria with a pre-constructed fetch.

Example 7-8 Associate Patient Role Criteria with Role Fetch

To associate the patient role criteria with a pre-constructed role fetch, use the following code:

RoleFetch patRoleFetch = queryComponentFactory.newRoleFetch();patRoleFetch.setTopLevelRoleCriteria(patRoleCriteria);

Add Detail Fetches

Fetches can be linked together to retrieve related Act, ActRelationship, Participation, Role and Entity data in a single query. The added fetches are called detail fetches. Detail fetches behave like normal fetches allowing specific attributes to be retrieved and criteria to be specified, but they only retrieve data associated with their master.

Detail fetches are added using the add<RelatedObject>Fetch(...) APIs on the fetch class. These APIs are specific to each fetch to restrict the query results to a RIM consistent structure. As the API name suggests, it is possible to add multiple detail fetches of the same type to a master, each having their own set of attributes to retrieve, with their own criteria. This lets you group detail objects by criteria. For example, you can retrieve the subject participations and attending physician participations of an act separately by adding two participation detail fetches (one with criteria for subject participations and the other with criteria for the attending physician participations) to the main act fetch.

Detail fetches also play an important role in navigating the result graph, as every result object is related to the fetch that caused it to be retrieved.

Note:

Navigate the Result Graph for more information about detail fetches.

Incremental Fetches

The query framework has a pseudo-incremental fetch mechanism that lets you retrieve blocks of results by a fetch. This is useful to improve query response time and to page through results when processing large result sets.

Developers specify the size of the result set (window size) required using the setRetrievalWindow(int first, int last) API on the top level fetch. To implement a paging solution, submit the same fetch graph to the RimService multiple times modifying the retrieval window accordingly. To ensure that subsequent queries return consistent results, you should apply an ordering directive on the fetch (described in the next section). Sample code demonstrating a paging solution follows the ordering fetch results discussion (see Example 7-18 ).

Note:

Read consistency is not guaranteed between calls. If data that matches the query criteria is persisted between subsequent fetches the newly persisted data is retrieved.

Order Fetch Results

To facilitate incremental fetching, the query framework lets you order results in ascending or descending order of a subset of attributes. This is to ensure that the result set is ordered, so that subsequent incremental fetch results are consistent.

Specify the set of ordering attributes by using the addOrderBy(String attribute, int order API on the top level fetch. Results can be ordered by a restricted set of attributes represented by constants in QueryComponentFactory (look for ORDER_BY_<ATTRIBUTE_NAME> constants).

Example 7-9 Incremental Fetch / Ordering

The following example illustrates how to use the incremental fetch and ordering features of the query framework to retrieve ten acts at a time:

// create Act fetch and criteria
   // order the fetch by 1 or more orderable act attributes
   actFetch.addOrderBy(QueryComponentFactory.ORDER_BY_ACT_EXISTENCE_TIME_LOW, 
    QueryComponentFactory.ORDER_BY_ASCENDING);
   // set the intial window size
   actFetch.setRetrievalWindow(1, 10);
   // execute the query
   Iterator firstTenResults = rimService.queryActs(serviceLocator, actFetch);
   // display first 10 results
   ...
   // set the next window size
   actFetch.setRetrievalWindow(11, 20);
   // execute the results
   Iterator secondTenResults = rimService.queryActs(serviceLocator, actFetch);
   // display second 10 results
   ...

Cyclic (Recursive) Fetches

Fetches can be linked in cycles to retrieve data that is recursively related. This lets you avoid coding individual fetches for each component in the recursive relationship. This is particularly useful for retrieving a series of related acts.

Figure 7-2 Cyclic Recursive Fetches

Cyclic Recursive Fetches

Figure 7-2 illustrates how cyclic fetches can be used to retrieve an entire chain of acts, avoiding the need to code an entire chain of fetch/criteria objects:

Note:

Exercise care when using this feature; the query response time and memory consumption is relative to the depth of recursion and there is no mechanism to restrict the level of results retrieved. If you have data that exists in a deeply recursive structure and you only want to recurse to a certain level it may be better to explicitly code the expanded fetch graph rather that use the cyclic fetch functionality.

Criteria

Query criteria are used to specify conditions HL7 objects must satisfy to be retrieved by a particular query–a criteria graph is analogous to the WHERE clause in a SQL Select statement.

Criteria exist for the main HL7 objects (Acts, ActRelationships, Participations, Roles and Entities) as well as the more complex datatypes that provide a high degree control in restricting the data being retrieved.

There are two fundamental types of criteria:

  • Attribute criteria, which let you set restrictions on attributes such as an Act class code.
  • Connective criteria, which allow attribute criteria to be ANDed and ORed together to construct more complex conditions.

Criteria described in further detail:

Attribute Criteria

AttributeCriteria are used to specify conditions that object attributes must satisfy to be retrieved by a query. Specific criteria classes exist for the core HL7 objects and for datatypes where necessary. The criteria classes provide a combination of query-by-criteria (QBC) and query-by-example (QBE) APIs depending upon the type of attribute. The following table lists all of the attribute types and indicates whether a QBE or QBC interface is exposed for each type:

Attribute Types

Query-by-Example Types

Query-by-Criteria Types

BL

AD

CS

ADXP

CD/CE

CD/CE

II

EN

INT

ENXP

REAL

GTS

ST

IVL<DATATYPE>

TS

MO

URL

PQ

RTO<DATATYPE, DATATYPE>

SC

TEL

ED

Query-by-Example (QBE) APIs

Query-by-example interfaces are provided for attributes where constraints can be adequately specified using an example datatype. The following attribute types fall into this category:

  • BL
  • CS
  • CD
  • CE
  • II
  • INT
  • REAL
  • ST
  • TS
  • URL

Where the attribute is represented by a single datatype the interface has the following form:

public void set<AttributeName>(SearchOperator op, <DataType> value);

where SearchOperator is one of the following:

  • EQUALS
  • NOT_EQUALS
  • GREATER_THAN
  • LESS_THAN
  • GREATER_THAN_OR_EQUAL
  • LESS_THAN_OR_EQUAL
  • IS_NULL
  • IS_NULL
  • IS_NOT_NULL
  • LIKE
  • NOT_LIKE

Example 7-10 Using QBE API to Set Class Code Criteria

The following code sample illustrates the usage of this style of API for setting a class code criteria for an entity:

entityAttributeCriteria.setClassCode(SearchOperator.EQUALS, EntityClass.PSN);

The following interface is exposed for set based attributes (SET<CS>, SET<CD>, SET_II etc):

public void set<AttributeName>(SetSearchOperator op, <DataType>[] values);

The following special operators are provided to support set based searching: ALL and ANY. The ALL operator is used to specify that the target search object must have all of the values passed in the array type. The ANY operator means that the object must have at least one of the values passed in the array to match.

Example 7-11 Using QBE API to Set Instance Identifier Criteria

The following code sample illustrates typical usage of this form of API when setting Instance Identifier criteria for an object:

II[] patientIIs = new II[1];
...
 
patientIIs[0] = dataTypeFactory.newII(dataTypeFactory.newUID("ROOT"),
                                         dataTypeFactory.newST("EXTENSION"),
                                         dataTypeFactory.newBL(true));
   patRoleCriteria.setId(SetSearchOperator.ANY, patientIIs);

Query-by-Criteria (QBC) APIs

Query-by-Criteria interfaces are provided for attributes represented by complex datatypes-those where using an example datatype to specify a constraint is not flexible enough to meet common uses. For example, there is a criteria interface for EN attributes because it consists of a set of use codes (SET<CS>), a list of name parts (LIST<ENXP>), a formatted string (ST), and a valid time (IVL<TS>, all of which require individual constraints to be set in various use cases. This cannot be specified with a QBE interface. The attribute sets that fit into this category are represented by the following datatypes:

  • AD
  • ADXP
  • ED
  • EN
  • ENXP
  • GTS
  • IVL<INT>
  • IVL<MO>
  • IVL<PQ>
  • IVL<REAL>
  • IVL<TS>
  • MO
  • PQ
  • RTO<MO,PQ>
  • RTO<PQ>
  • SC
  • TEL

...where the attribute is represented by a complex datatype the interface has the following form:

public void set<AttributeName>Criteria(<Datatype>Criteria criteria);

The API differs from the QBC interface for complex datatypes by accepting a versioning type parameter. This is used to specify whether the neighboring criteria should be applied to the version that is directly related to the master object (version dependent), or to any version of the detail object (version independent). Versioning and query are discussed in more detail in Versioning and Query.

CodedTypeCriteria APIs

You can use CodedTypeCriteria expose functionality, in the API, to query by qualifiers, classifications, and equivalence. Classifications and equivalence are defined in ETS (Enterprise Terminology Services). You can combine three types of queries using ConnectiveCriteria. You can apply only one type of query on any single Criteria object.

Querying-by-Qualifiers

Queries on CD.qualifier follow the Query-by-Criteria pattern described in the Criteria section. The following operators can be used for qualifier queries:

  • SearchOperator.IS_NULL
  • SetSearchOperator.ANY
  • SetSearchOperator.NONE
  • SetSearchOperator.ALL

CodedTypeAttributeCriteria.includeEquivalentCodes(boolean, String, boolean) cannot be used with the CodedTypeAttributeCriteria.setQualifier(SearchOperator, CR[]) method.

CodedTypeAttributeCriteria codedTypeCriteria = queryComponentFactory.newCodedTypeAttributeCriteria(); // use the DataTypeFactory to instantiate the data types codedTypeCriteria.setCode(parentCode); codedTypeCriteria.setCodeSystem(parentCodeSystem); codedTypeCriteria.setQualifier(SearchOperator.IS_NULL, new CR[] { } );

// null values are passed in for the II, the StatusCode and the CurrentVersionFlag, because we are not // querying using these attributes RoleAttributeCriteria roleCriteria = queryComponentFactory.newRoleAttributeCriteria(RoleClass.ACCESS, roleCode, null, null, null);

roleCriteria.setTargetSiteCode(codedTypeCriteria); RoleFetch roleFetch = queryComponentFactory.newRoleFetch(roleCriteria); roleFetch.retrieveAll(); Iterator fetchedRoles = rimService.queryRoles(localServiceLocator, roleFetch);

Querying-by-Classifications

Classification queries are constructed using ClassificationCriteria, which is a subclass of CodedTypeCriteria. Only ClassificationAttributeCriteria.setCode(ST) applies to a query by classification. Other methods inherited from CodedTypeAttributeCriteria are not applicable. This is because the value is predetermined to be one appropriate to the code system that contains classifications or because the method does not apply to this type of query.

ClassificationAttributeCriteria classificationCriteria = qcf.newClassificationAttributeCriteria();

// Set the classification code; no code system is needed because classifications are all

// stored in a specific code system that is known to the system.

classificationCriteria.setCode(classificationCode);

ActAttributeCriteria actCriteria = this.queryComponentFactory.newActAttributeCriteria(); actCriteria.setCode(codedTypeAttrCriteria); actCriteria.setId(SetSearchOperator.ALL, ii); ActFetch actFetch = this.queryComponentFactory.newActFetch(actCriteria); actFetch.retrieveAll(); Iterator fetchedActs = rimService.queryActs(localServiceLocator, actFetch);

Querying-by-Equivalence

Equivalence queries must use CodedTypeAttributeCriteria.includeEquivalentCodes(boolean, String, boolean) method. These queries must specify a code and code system. The setQualifierMethod(SearchOperator, CR[]) method cannot be invoked on a CodedTypeAttributeCriteria instance where includeEquivalentCodes(..) has been called.

CodedTypeAttributeCriteria codedTypeAttrCriteria = this.queryComponentFactory.newCodedTypeAttributeCriteria(); codedTypeAttrCriteria.setCode(actCode); codedTypeAttrCriteria.setCodeSystem(actCodeSystem); codedTypeAttrCriteria.includeEquivalentCodes(true, null, true); ActAttributeCriteria actCriteria = this.queryComponentFactory.newActAttributeCriteria(); actCriteria.setCode(codedTypeAttrCriteria); actCriteria.setId(SetSearchOperator.ALL, ii);

ActFetch actFetch = this.queryComponentFactory.newActFetch(actCriteria); actFetch.retrieveAll(); Iterator fetchedActs = rimService.queryActs(localServiceLocator, actFetch);

Implicit AND Behavior for Attribute Criteria

When multiple criteria are set on an instance of an AttributeCriteria (regardless of the type), they are implicitly ANDed together. For example, see Example 7-21:

Example 7-12 Implicit AND Behavior: Restricting Retrieved Results

In this code sample, the retrieved results are restricted to those Acts that have a ...

actAttributeCriteria.setMoodCode(SearchOperator.EQUALS, ActMood.EVN);
...
ctAttributeCriteria.setClassCode(SearchOperator.EQUALS, ActClass.OBS);

ConnectiveCriteria can be used to build more complex criteria where ANDs and ORs can be used.

Connective Criteria

Connective criteria are used to AND and OR attribute criteria together, permitting more complex queries to be constructed. You must use connective criteria with attribute criteria of the same type. For example, you can use an ActConnectiveCriteria to AND/OR multiple Act criteria (attribute or connective) together. You should exercise care with regard to the level the connective is applied; otherwise the results may not be what you expected.

Figure 7-3 Retrieve active encounter event and observation event Acts: Example 1:

Connective Criteria: Example 1

Figure 7-3 illustrates the use of connective criteria. In this example, two equivalent fetch diagrams show that the same result can be achieved in different ways. In the first diagram, an OR connective is used between two act attribute criteria to fetch the required results. The result of the query will be the union of the results returned by the execution of the two attribute criteria independently. The criteria on the left retrieves all active encounter event acts, and the criteria on the right retrieves all active observation events. The resulting set of retrieved acts will be the union of the two sets.

The second diagram is semantically equivalent but achieves the result using a combination of AND and OR connectives. The left side of the AND connective retrieves all active acts in EVN mood and the right side retrieves all acts of class ENC or OBS. The end result is the intersection of the two individual sets-all active encounter and observation events.

Figure 7-4 Retrieve encounter events that have a subject participation to an identified patient role with an attending participation to an identified employee role: Example 2:

Connective Criteria: Example 2

As in Example 1, you must exercise care to ensure that the connective is made at the correct level.

Figure 7-4 shows two branches of criteria connected at the top level by an AND connective. The result of the query will be the intersection of the results returned by the execution of the two branched independently. The left branch retrieves all encounter events that have an SBJ participation to a PAT role. The right branch retrieves all encounter events that have an ATND participation to an EMP role.

Figure 7-5

Connective Criteria: Example 3

Figure 7-5 shows a typical mistake of specifying the above criteria with the connective at the participation level. Logically this can be thought of as asking for encounter events that have a participation with a class code of SBJ and ATND-an impossible construct that returns no results.

Navigate the Result Graph

Complex queries that consist of several fetches return a RIM object structure that replicates the fetch graph that was submitted (assuming that existing data matches the criteria specified). The core RIM classes contain specific APIs that let you navigate from the master object to its related details. The following table lists the complete set of core RIM navigational APIs:

Core RIM Navigational APIs

Class

Navigational API

Description

Act

getParticipations(...)

Returns act participations fetched by a detail participation fetch.

getIBActRelationships(...)

Returns inbound act relationships fetched by a detail inbound act relationship fetch.

getOBActRelationships(...)

Returns outbound act relationships fetched by a detail outbound act relationship fetch.

ActRelationship

getSource(...)

Returns the source act that was fetched by a detail act fetch.

getTarget(...)

Returns the target act that was fetched by a detail act fetch.

Participation

getAct(...)

Returns the act that was fetched by a detail act fetch.

getRole(...)

Returns the role that was fetched by a detail role fetch.

Role

getParticipations(...)

Returns participations fetched by a detail participation fetch

getPlayerEntity(...)

Returns entities fetched by a detail player entity fetch

getScoperEntity(...)

Returns entities fetched by a detail scoper entity fetch

Entity

getPlayedRoles(...)

Returns roles fetched by a detail played role fetch

getScopedRoles(...)

Returns roles fetched by a detail scoped role fetch

getOwnedPlayedRoles(...)

Returns roles fetched by a detail owned played role fetch

getOwnedScopedRoles(...)

Returns roles fetched by a detail owned scoped role fetch

Note:

Fetches have additional navigation methods for HDR extensions such as control act and merge navigations, discussed in HDR RIM Extensions.

Two types of navigational APIs provide flexibility when navigating the result graph. The simplest form accepts no parameters and returns all details retrieved regardless of which particular fetch was responsible for the result being retrieved.

The overloaded form accepts a fetch parameter and returns results directly related to the execution of the detail fetch passed in. This API is used when multiple detail fetches of the same type are added to a fetch.

For example, to retrieve an act, subject and attending physician participations you could have an act fetch and add separate subject and attending physician participation fetches. To navigate from the act to the participations, you can retrieve both concurrently by calling the no parameter getParticipations method, or you can access each participation individually by calling the navigation method that takes a participation fetch parameter passing in the particular fetch.

Figure 7-6

Fetch and Result Graphs

Figure 7-6 illustrates Fetch and Result Graphs.

HDR RIM Extensions

Versioning and Query

The query framework provides several APIs on the core fetch and criteria classes that let you fetch particular versions of objects and specify criteria on the different object versions. These APIs are described below.

Versioning and Fetches

In the context of fetches, the versioning behavior determines whether all versions or the referenced version of a detail object are retrieved by a detail fetch. The version of a detail object to retrieve is specified on the detail fetch by using the fetch factory methods (on QueryComponentFactory) that accept a versioning parameter. The QueryComponentFactory defines two versioning constants to be used with the following factory methods:

  • QueryComponentFactory.VERSION_DEPENDENT
  • QueryComponentFactory.VERSION_INDEPENDENT

It is possible to use the same factory methods to construct the top level fetch. However, the versioning constant supplied is ignored as it only applies to detail fetches. To specify particular versions for the top level fetch you must set the version on the criteria for that fetch.

Note:

By default, navigations are version dependent. Detail navigations that retrieve a single object, such as Participation to Role, return an undefined version of the detail object unless a specific version is requested (via a criteria with setCurrentVersion(...) or setVersionNum(...) methods).

Versioning and Criteria

The core attribute criteria classes provide APIs for specifying particular versions of objects as well as versions of detail objects. These APIs are described in the following sections.

Retrieving the Current Version

To restrict retrieval to the most current version of an object you can use the following AttributeCriteria method:

setCurrentVersion(boolean currentVersionFlag);

This method, combined with a version independent detail navigation, effectively retrieves the most current version of a related object. Alternatively, this method can be used to retrieve all but the current version of an object by passing false as the argument.

Retrieving a Specific Version

To retrieve a specific version of an object, use the following API:

setVersionNum(int versionNumber);

As with any other criteria specified, if the version specified does not exist no results are returned.

Detail Criteria Versioning Behavior

The criteria setters for neighboring core objects accept a versioning parameter that specifies whether the detail criteria is applied to the referenced version or any version of the detail object.

Detail Fetches

Assuming patient role version 1 and both versions of the player entity match the criteria, to retrieve patient and person information a detail player entity fetch is attached to the role fetch. When constructing the entity fetch you can specify either the VERSION_DEPENDENT or VERSION_INDEPENDENT constant for the versioning parameter (provided you use the EntityFetch newEntityFetch(EntityCriteria criteria, int versioningType) API on QueryComponentFactory). If you construct the entity fetch with the VERSION_DEPENDENT constant the person directly linked to the role is returned–in this case, version 1 of the person. If you construct the entity fetch with the VERSION_INDEPENDENT constant the current version (version 2) of the person is returned.

Detail Criteria

Assuming you have a role criteria that matches version 1 of the patient role, you can add a detail player entity criteria and specify either the VERSION_DEPENDENT orVERSION_INDEPENDENT constant for the versioning parameter. If you added a detail player entity criteria that matched person entities with name John Smith, the role would only be fetched if its playing entity has that name.

ControlAct Querying

You can retrieve or base queries on the ControlAct associated with an object using methods in the fetch and criteria interfaces. To fetch the creating/updating ControlAct, add a detail fetch using the following API:

addControlActFetch(ActFetch actFetch);

To specify criteria based on the creating or updating ControlAct, add a dependent criteria using the following API:

setControlActCriteria(ActCriteria actCriteria);

Both of these APIs work in the same way as other dependent fetch/criteria setter methods except that they exclude any versioning behavior; there is only one version of ControlActs associated with a particular version of an object.

Person Merge Querying

Person merge is the ability to collate data from a number of person entities (typically entered in different systems) into a single person that contains the superset of data. The single entity at the end of a potential chain of merges is typically called the ultimate survivor and the group of entities involved in a set of merge operations (including the ultimate survivor) is called the merge peers group.

The query framework exposes methods on the entity fetch and criteria classes that let you fetch and specify criteria for the merge group. To fetch members of the merge group, add a detail fetch using the following API:

addMergePeersEntityFetch(EntityFetch fetch);

To specify criteria for the merge group, add a detail criteria using the following API:

setMergePeersCriteria(EntityCriteria entityCriteria);

The EntityAttributeCriteria class also contains the following method that lets you specify whether or not the entity is the ultimate survivor of a merge:

setUltimateSurvivor(boolean ultimateSurvivor);

The ultimate surviving person of a set of potential merges can be found efficiently by combining the merge peers navigation with the setUltimateSurvivor(...) criteria specification.

Example 7-13 Retrieve Ultimate Survivor of an Entity

The following example shows how to retrieve the ultimate survivor of an entity:

// create the ultimate survivor fetch and criteria
   EntityAttributeCriteria ultimateSurvivorCriteria = mQueryComponentFactory.newEntityAttributeCriteria();
   ultimateSurvivorCriteria.setUltimateSurvivor(true);
   EntityFetch survivorFetch = mQueryComponentFactory.newEntityFetch(ultimateSurvivorCriteria, 
    QueryComponentFactory.VERSION_INDEPENDENT);
   survivorFetch.retrieveId(true);
 
   // create the fetch and criteria for an entity that has been merged
   EntityAttributeCriteria entityACriteria = mQueryComponentFactory.newEntityAttributeCriteria();
   entityACriteria.setCurrentVersion(true);
   entityACriteria.setId(SetSearchOperator.ANY, new II[]{sEntityAII});
   EntityFetch entityAFetch = mQueryComponentFactory.newEntityFetch(entityACriteria);
   entityAFetch.retrieveId(true);
 
   // add the ultimate survivor fetch
   entityAFetch.addMergePeersEntityFetch(survivorFetch);

Owned Roles

Owned roles are a HDR extension to the RIM that lets your create roles that do not directly participate in an act (the role is linked to or owned by an entity). The query framework supports the retrieval of owned roles specifically through detail fetch and criteria methods in the entity fetch and criteria classes respectively. To fetch an owned role, add a detail fetch to an EntityFetch using the following API:

addOwned<Played/Scoped>RoleFetch(RoleFetch ownedplayedroleFetch);

To specify criteria for an owned role, add a detail criteria using the following API:

setOwned<Played/Scoped>RoleCriteria(RoleCriteria roleCriteria, int versioningType);

Note:

The query framework does not distinguish between typical roles and owned roles when the standard fetch and criteria APIs are used. In a role fetch where both normal and owned roles match the criteria they are all returned by the query. To return only owned roles you must use the detail fetch and criteria APIs on the entity fetch and criteria interfaces illustrated above.

Example 7-14 Patient Query by ID Code Sample

Find a person associated with a known patient Id, retrieving basic demographic information:

/**
 * Finds roles with the following attributes:
 * - class code = PAT
 * - id = id of the particular patient
 *
 * and must meet the following detail criteria:
 *
 * 1. be played by a PSN entity
 *
 * The query should return the patient, the player entity.
 *
 */
package oracle.hsgbu.hdr.sample.scenarios;
 
 
import java.io.IOException;
import oracle.hsgbu.hdr.exception.HDRRimException;
import oracle.hsgbu.hdr.hl7.query.EntityAttributeCriteria;
import oracle.hsgbu.hdr.hl7.query.SearchOperator;
import oracle.hsgbu.hdr.hl7.query.EntityFetch;
import oracle.hsgbu.hdr.hl7.query.RoleAttributeCriteria;
import oracle.hsgbu.hdr.hl7.query.SetSearchOperator;
import oracle.hsgbu.hdr.hl7.query.RoleFetch;
import oracle.hsgbu.hdr.hl7.rim.domain.EntityClass;
import oracle.hsgbu.hdr.hl7.rim.domain.RoleClass;
import oracle.hsgbu.hdr.hl7.rim.factories.QueryComponentFactory;
import oracle.hsgbu.hdr.hl7.rim.factories.DataTypeFactory;
import oracle.hsgbu.hdr.hl7.rim.types.II;
import oracle.hsgbu.hdr.hl7.rim.Role;
import oracle.hsgbu.hdr.hl7.rim.Entity;
 
 
import java.util.Iterator;
import java.util.Properties;
import oracle.hsgbu.hdr.exception.CommonException;
import oracle.hsgbu.hdr.fwk.servicelocator.common.ServiceLocator;
 
public class PatientSearchById 
{
  public void executeScenario() throws HDRRimException, CommonException, IOException
  {
    ServiceLocator serviceLocator = getServiceLocator();  
    QueryComponentFactory queryComponentFactory = QueryComponentFactory.getInstance();
    DataTypeFactory dataTypeFactory = DataTypeFactory.getInstance();
    
    // create an EntityAttributeCriteria and specify that the class code should equal PSN
    EntityAttributeCriteria eCriteria = queryComponentFactory.newEntityAttributeCriteria();
    eCriteria.setClassCode(SearchOperator.EQUALS, EntityClass.PSN);
 
    // create a person Entity fetch with the PSN entity criteria and specify that the name, administrative gender 
    // code, birth time, code and addr attributes should be retrieved.
    EntityFetch entityFetch = queryComponentFactory.newEntityFetch(eCriteria, 
    QueryComponentFactory.VERSION_DEPENDENT);
    entityFetch.retrieveId(true);
    entityFetch.retrieveName(true);
    entityFetch.retrieveAdministrativeGenderCode(true);
    entityFetch.retrieveBirthTime(true);
    entityFetch.retrieveCode(true);
    entityFetch.retrieveAddr(true);
 
     // create the patient II which will be used in the role criteria
    II[] patientIIs = new II[1];
    patientIIs[0] = dataTypeFactory.newII(dataTypeFactory.newUID("1.2.3.4"),
                                          dataTypeFactory.newST("PAT_ROLE_1_II_EXT"),
                                          dataTypeFactory.newBL(true));
 
    // create an EntityAttributeCriteria and specify that the class code should equal PAT and that the id 
    // should be one of the id's in the II array
    RoleAttributeCriteria patRoleCriteria = queryComponentFactory.newRoleAttributeCriteria();
    patRoleCriteria.setClassCode(SearchOperator.EQUALS, RoleClass.PAT);
    patRoleCriteria.setId(SetSearchOperator.ANY, patientIIs);
 
    // create the patient Role fetch with the PAT role criteria and specify that the id should be retrieved
    RoleFetch patRoleFetch = queryComponentFactory.newRoleFetch(patRoleCriteria);
    patRoleFetch.retrieveId(true);
    patRoleFetch.retrieveClassCode(true);
 
    // link the person fetch to the patient fetch
    patRoleFetch.addPlayerEntityFetch(entityFetch);
 
    // submit the query
    Iterator patientRoles = serviceLocator.getRimService().queryRoles(serviceLocator, patRoleFetch);
 
    System.err.println("PatientSearchById Query Results:");
    System.err.println("********************************");
    for(;patientRoles.hasNext();)
    {
      Role patientRole = (Role)patientRoles.next();
      System.err.println("Role Id: " + patientRole.getId());
      System.err.println("Role Class: " + patientRole.getClassCode());
 
      Entity playerEntity = patientRole.getPlayerEntity(entityFetch);
      System.err.println("Entity Id: " + playerEntity.getId());
      System.err.println("Entity Version Number: " + playerEntity.getVersionNum());
      System.err.println("Entity Class Code: " + playerEntity.getClassCode());      
    }
  }
  
   private  ServiceLocator getServiceLocator() throws IOException, CommonException {
        Properties props = new Properties();
        props.load(this.getClass().getClassLoader().getResourceAsStream("jndi.properties"));
        return ServiceLocator.getInstance(props);
    }  
}

Example 7-15 Query for Identified Patient Roles and Player Entities

This code sample queries for new or active encounters admitted by a known staff member; retrieves the associated subject patient with basic demographics, as well as the location of the encounter:

/**
 * The roles must have the following attributes:
 * - class code = ENC
 * - mood code = EVN 
 * - status code = NEW or ACTIVE
 * - code = ??? 
 * - current version = true
 *
 * and must meet the following criteria:
 *
 * 1. have an ADM participation to either a EMP or ASSIGNED role where the role id is that of the staff practitioner 
 * 2. have an SUBJ participation to a PAT role played by a PSN entity 
 * 3. have a LOC participation to a SDLOC role
 *
 * The query should return the encounters along with the ADM, SUBJ and LOC participations
 * along with their corresponding roles and player entities.
 *
 */
 
package oracle.hsgbu.hdr.sample.scenarios;
 
import java.io.IOException;
import oracle.hsgbu.hdr.exception.HDRRimException;
import oracle.hsgbu.hdr.hl7.rim.types.II;
import oracle.hsgbu.hdr.hl7.rim.types.CD;
import oracle.hsgbu.hdr.hl7.query.RoleAttributeCriteria;
import oracle.hsgbu.hdr.hl7.query.SetSearchOperator;
import oracle.hsgbu.hdr.hl7.query.SearchOperator;
import oracle.hsgbu.hdr.hl7.query.ParticipationAttributeCriteria;
import oracle.hsgbu.hdr.hl7.query.ActAttributeCriteria;
import oracle.hsgbu.hdr.hl7.query.ActFetch;
import oracle.hsgbu.hdr.hl7.query.RoleFetch;
import oracle.hsgbu.hdr.hl7.query.ParticipationFetch;
import oracle.hsgbu.hdr.hl7.query.EntityAttributeCriteria;
import oracle.hsgbu.hdr.hl7.query.EntityFetch;
import oracle.hsgbu.hdr.hl7.query.ActCriteria;
import oracle.hsgbu.hdr.hl7.rim.domain.RoleClass;
import oracle.hsgbu.hdr.hl7.rim.domain.ParticipationType;
import oracle.hsgbu.hdr.hl7.rim.domain.ActClass;
import oracle.hsgbu.hdr.hl7.rim.domain.ActMood;
import oracle.hsgbu.hdr.hl7.rim.domain.ActStatus;
import oracle.hsgbu.hdr.hl7.rim.domain.EntityClass;
import oracle.hsgbu.hdr.hl7.rim.factories.QueryComponentFactory;
import oracle.hsgbu.hdr.hl7.rim.factories.DataTypeFactory;
import oracle.hsgbu.hdr.hl7.rim.Act;
import oracle.hsgbu.hdr.hl7.rim.Participation;
import oracle.hsgbu.hdr.hl7.rim.Role;
import oracle.hsgbu.hdr.hl7.rim.Entity;
 
import java.util.Iterator;
import java.util.Properties;
import oracle.hsgbu.hdr.exception.CommonException;
import oracle.hsgbu.hdr.fwk.servicelocator.common.ServiceLocator;
import oracle.hsgbu.hdr.hl7.rim.domain.NullFlavor;
 
public class EncountersByStaffPractitioner {
 
    public void executeScenario() throws HDRRimException, CommonException, IOException {
        ServiceLocator serviceLocator = getServiceLocator();
        QueryComponentFactory queryComponentFactory = QueryComponentFactory.getInstance();
        DataTypeFactory dataTypeFactory = DataTypeFactory.getInstance();
 
        // create the staff II which will be used in the role criteria
        II[] practitionerIIs = new II[1];
        practitionerIIs[0] = dataTypeFactory.newII(dataTypeFactory.newUID("1.2.3.4"),
                dataTypeFactory.newST("STAFF_ROLE_1_II_EXT"),
                dataTypeFactory.newBL(true));
 
        // practitioner role
        RoleAttributeCriteria rAssignedCriteria = queryComponentFactory.newRoleAttributeCriteria();
        rAssignedCriteria.setClassCode(SearchOperator.EQUALS, RoleClass.ASSIGNED);
        rAssignedCriteria.setId(SetSearchOperator.ANY, practitionerIIs); //Particular practitioner
        RoleAttributeCriteria rEmpCriteria = queryComponentFactory.newRoleAttributeCriteria();
        rEmpCriteria.setClassCode(SearchOperator.EQUALS, RoleClass.EMP);
        rEmpCriteria.setId(SetSearchOperator.ANY, practitionerIIs); //Particular practitioner
        RoleAttributeCriteria rCriteria = (RoleAttributeCriteria) queryComponentFactory.or(rAssignedCriteria, rEmpCriteria);
 
        // ADM participation
        ParticipationAttributeCriteria pCriteria = queryComponentFactory.newParticipationAttributeCriteria();
        pCriteria.setRoleCriteria(rCriteria, QueryComponentFactory.VERSION_INDEPENDENT);
        pCriteria.setTypeCode(SearchOperator.EQUALS, ParticipationType.ADM);
 
        // act criteria
        ActAttributeCriteria aCriteria = queryComponentFactory.newActAttributeCriteria();
        aCriteria.setCurrentVersion(true);
        aCriteria.setClassCode(SearchOperator.EQUALS, ActClass.ENC);
        aCriteria.setMoodCode(SearchOperator.EQUALS, ActMood.EVN);
 
        //    aCriteria.setCode(SearchOperator.EQUALS, actCd);
        aCriteria.setParticipationCriteria(pCriteria, QueryComponentFactory.VERSION_INDEPENDENT);
 
        // create an act criteria to retrieve new and active acts
        ActAttributeCriteria activeActStatus = queryComponentFactory.newActAttributeCriteria();
        activeActStatus.setStatusCode(SearchOperator.EQUALS, ActStatus.ACTIVE);
        activeActStatus.setClassCode(SearchOperator.EQUALS, ActClass.ENC);
        activeActStatus.setMoodCode(SearchOperator.EQUALS, ActMood.EVN);
        CD actCd = dataTypeFactory.newCD(dataTypeFactory.newST("AMB"),
                dataTypeFactory.nullUID(NullFlavor.NI), dataTypeFactory.newST("ActCode"), dataTypeFactory.nullST(NullFlavor.NI),
                dataTypeFactory.nullED(NullFlavor.NI));
 
        activeActStatus.setCode(SearchOperator.EQUALS, actCd);
        activeActStatus.setCurrentVersion(true);
        activeActStatus.setParticipationCriteria(pCriteria, QueryComponentFactory.VERSION_INDEPENDENT);
        ActAttributeCriteria newActStatus = queryComponentFactory.newActAttributeCriteria();
        newActStatus.setStatusCode(SearchOperator.EQUALS, ActStatus.NEW);
        newActStatus.setClassCode(SearchOperator.EQUALS, ActClass.ENC);
        newActStatus.setMoodCode(SearchOperator.EQUALS, ActMood.EVN);
        newActStatus.setCurrentVersion(true);
 
        newActStatus.setCode(SearchOperator.EQUALS, actCd);
        newActStatus.setParticipationCriteria(pCriteria, QueryComponentFactory.VERSION_INDEPENDENT);
        ActCriteria activeOrNewStatus = (ActCriteria) queryComponentFactory.or(activeActStatus, newActStatus);
 
        ActFetch actFetchMain = queryComponentFactory.newActFetch(activeOrNewStatus,
                QueryComponentFactory.VERSION_INDEPENDENT);
        actFetchMain.retrieveId(true);
 
        // Add location to a fetch
        RoleAttributeCriteria lrCriteria = queryComponentFactory.newRoleAttributeCriteria();
        lrCriteria.setClassCode(SearchOperator.EQUALS, RoleClass.SDLOC);
        RoleFetch lrFetch = queryComponentFactory.newRoleFetch(lrCriteria,
                QueryComponentFactory.VERSION_INDEPENDENT);
        lrFetch.retrieveId(true);
        lrFetch.addPlayerEntityFetch(queryComponentFactory.newEntityFetch());
        ParticipationAttributeCriteria lpCriteria = queryComponentFactory.newParticipationAttributeCriteria();
        lpCriteria.setTypeCode(SearchOperator.EQUALS, ParticipationType.LOC);
        ParticipationFetch lpFetch = queryComponentFactory.newParticipationFetch(lpCriteria,
                QueryComponentFactory.VERSION_INDEPENDENT);
        lpFetch.addRoleFetch(lrFetch);
 
        actFetchMain.addParticipationFetch(lpFetch);
 
        // Add patient to a fetch
        EntityAttributeCriteria eCriteria = queryComponentFactory.newEntityAttributeCriteria();
        eCriteria.setClassCode(SearchOperator.EQUALS, EntityClass.PSN);
        EntityFetch eFetch = queryComponentFactory.newEntityFetch(eCriteria);
        eFetch.retrieveName(true);
        eFetch.retrieveAdministrativeGenderCode(true);
        eFetch.retrieveBirthTime(true);
        eFetch.retrieveCode(true);
        RoleAttributeCriteria patRoleCriteria = queryComponentFactory.newRoleAttributeCriteria();
        patRoleCriteria.setClassCode(SearchOperator.EQUALS, RoleClass.PAT);
        RoleFetch patRoleFetch = queryComponentFactory.newRoleFetch(patRoleCriteria,
                QueryComponentFactory.VERSION_INDEPENDENT);
        patRoleFetch.retrieveId(true);
        patRoleFetch.addPlayerEntityFetch(eFetch);
        ParticipationAttributeCriteria patPartCriteria = queryComponentFactory.newParticipationAttributeCriteria();
        patPartCriteria.setTypeCode(SearchOperator.EQUALS, ParticipationType.SBJ);
        ParticipationFetch patPartFetch = queryComponentFactory.newParticipationFetch(patPartCriteria,
                QueryComponentFactory.VERSION_INDEPENDENT);
        patPartFetch.addRoleFetch(patRoleFetch);
 
        actFetchMain.addParticipationFetch(patPartFetch);
 
        Iterator fetchedActs = ServiceLocator.getInstance().queryActs(serviceLocator, actFetchMain);
 
        System.err.println("EncountersByStaffPractitioner Query Results:");
        System.err.println("********************************************");
        for (; fetchedActs.hasNext();) {
            Act fetchedAct = (Act) fetchedActs.next();
            System.err.println("Act class code: " + fetchedAct.getClassCode());
            System.err.println("Act mood code: " + fetchedAct.getMoodCode());
            System.err.println("Act status code: " + fetchedAct.getStatusCode());
 
            Iterator fetchedPatientParticipations = fetchedAct.getParticipations(patPartFetch);
            for (; fetchedPatientParticipations.hasNext();) {
                Participation fetchedPatientParticipation = (Participation) fetchedPatientParticipations.next();
                System.err.println("Participation type code: " + fetchedPatientParticipation.getTypeCode());
 
                Role fetchedPatientRole = (Role) fetchedPatientParticipation.getRole(patRoleFetch);
                System.err.println("Role class code: " + fetchedPatientRole.getClassCode());
 
                Entity fetchedPlayerEntity = fetchedPatientRole.getPlayerEntity(eFetch);
                System.err.println("Player entity class code: " + fetchedPlayerEntity.getClassCode());
            }
        }
    }
 
    private ServiceLocator getServiceLocator() throws IOException, CommonException {
        Properties props = new Properties();
        props.load(this.getClass().getClassLoader().getResourceAsStream("jndi.properties"));
        return ServiceLocator.getInstance(props);
    }
}

Original Coded Attributes

Coded attributes are commonly coerced into equivalent concepts during persistence into HDR. By default these coerced concepts are retrieved by Rim Query. You can retrieve the original data, using the oracle.hsgbu.hdr.hl7.util.CodedTypeUtility.getOriginalAttributes(CD) method.

Since qualifiers are not copied from original to coerced code, qualifiers can only be retrieved from CD datatypes that have been obtained via the getOriginalAttributes method.

See also:

  • oracle.hsgbu.hdr.hl7 package for further information about HDR HL7 interfaces.
  • oracle.hsgbu.hdr.hl7.query package for further information about HDR Query interfaces.