Skip Headers
Oracle® Communications Network Integrity Developer's Guide
Release 7.1

E23701-03
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
PDF · Mobi · ePub

16 POMS SDK

This chapter provides information about how the persistent object modeling service (POMS) manages persistent data in Oracle Communications Network Integrity.

About POMS

POMS manages all persisted data within Network Integrity. Developers use POMS for most cartridge development, but they rarely need to deal explicitly with persistence details.

POMS includes the Java definition of the entities and relationships described in Oracle Communications Information Model Reference and Network Integrity Information Model Reference.

While POMS includes both interface and implementation classes for the entities, developers work only with interfaces. These interfaces provide getters and setters for attributes and relationships. Use the PersistenceHelper POMS SDK class to instantiate entities.

Developers can use the POMS SDK Finder class to find and retrieve existing persisted entities.

POMS is built on the EclipseLink Java persistence API (JPA) platform. Developers do not usually need to know EclipseLink or JPA to use the POMS SDK. The exception is find operations where developers may have to know Java Persistence Query Language (JPQL). See "Working with the POMS Finder" for more information about the find operations.

Table 16-1 describes the POMS SDK APIs.

Table 16-1 POMS SDK API Description

POMS SDK APIs Description

Entities

The POMS SDK represents modelled entities as Java interfaces with getters and setters for attributes and relationships. See "Working with POMS Relationships".

Specifications and characteristics

The POMS SDK includes APIs that allow you to operate on specifications and characteristics. See "Working with Specifications and Characteristics".

PersistenceHelper

The POMS SDK provides methods to instantiate a POMS entity or POMS Finder. See "Working with POMS Entities" and "POMS SDK Interfaces".

Finder

The POMS SDK provides various methods to define a query and retrieve matching persisted entities. See "Working with the POMS Finder" and "POMS SDK Interfaces".


Working with POMS Entities

The POMS Java interface for an entity has the same name as the entity described in the model document. For example, entity Equipment becomes:

public interface Equipment

Attributes are accessed with familiar Java getters and setters. For example. The Equipment name attribute is defined by:

public java.lang.String getName();
public void setName( java.lang.String name );

An entity may contain enumerated values for certain attributes. POMS implements these as Java enumerations. For example, the EMSServiceState from LogicalDevice has the following:

public enum EMSServiceState {
      UNKNOWN( "UNKNOWN" ),
      IN_SERVICE( "IN_SERVICE" ),
      OUT_OF_SERVICE( "OUT_OF_SERVICE" ),
      TESTING( "TESTING" ),
      IN_MAINTENANCE( "IN_MAINTENANCE" );
 
public oracle.communications.inventory.api.entity.EMSServiceState         getNativeEmsServiceState();
public void setNativeEmsServiceState( oracle.communications.inventory.api.entity.EMSServiceState nativeEmsServiceState );

When creating results, for example in a Discovery Processor, developers must instantiate POMS entities. Use the PersistenceHelper class, passing the desired entity class to the makeEntity method:

Equipment equipment = PersistenceHelper.makeEntity(Equipment.class);

Working with POMS Relationships

Related entities are also accessed with getters and setters.

One-to-one Relationships

When a relationship refers to a single entity, the entity is accessed directly. For example, the mapped logical device on a physical device:

public oracle.communications.inventory.api.entity.LogicalDevice getMappedLogicalDevice();
public void setMappedLogicalDevice( oracle.communications.inventory.api.entity.LogicalDevice mappedLogicalDevice );

One-to-Many or Many-to-Many Relationships

When a relationship can refer to multiple entities, the entities are accessed through a collection. For example, the equipment to physical port relationship:

public java.util.List<oracle.communications.inventory.api.entity.PhysicalPort> getPhysicalPorts();
public void setPhysicalPorts( java.util.List<oracle.communications.inventory.api.entity.PhysicalPort> physicalPorts );

A getter never returns null for the collection. If there are no related entities, an empty collection is returned. That means the developer can safely add entities without creating a collection. For example:

equipment.getPhysicalPorts().add(physicalPort);

Ordered and Unordered Relationships

POMS uses a List for the collection because the Oracle Communications Information Model defines an ordered relationship for physical ports on equipment. In other cases, order does not matter and so POMS uses a Set for the collection. For example, the parent relationship from Equipment to EquipmentHolder:

public java.util.Set<oracle.communications.inventory.api.entity.EquipmentHolderEquipmentRel> getParentEquipmentHolders();
public void setParentEquipmentHolders(java.util.Set<oracle.communications.inventory.api.entity.EquipmentHolderEquipmentRel> equipmentHolders);

Bi-directional Relationships

Certain relationships in the model are bi-directional. POMS includes accessors on entities on both sides of a bi-directional relationship, and the relationship can be set from either side. The physical device to logical device relationship described in the "One-to-one Relationships" example is bi-directional. The other side of this relationship, on the logical device, is defined as:

public java.util.List<oracle.communications.inventory.api.entity.PhysicalDevice> getMappedPhysicalDevices();
public void setMappedPhysicalDevices( java.util.List<oracle.communications.inventory.api.entity.PhysicalDevice> mappedPhysicalDevices );

This is a many-to-one relationship, so there is a collection on the logical device side and single entity on the physical device side. To relate a physical and logical device, developers can either set from the physical device:

physicalDevice.setMappedLogicalDevice(logicalDevice);

or set from the logical device:

logicalDevice.getMappedPhysicalDevices ().add(physicalDevice);

Relationship Entities

In some cases, the model defines an intermediate relationship entity instead of relating two entities directly. For example, the Information Model defines EquipmentEquipmentRel to relate two pieces of equipment. To create this type of relationship, instantiate the relationship entity and set the related entities. For the equipment to equipment example:

EquipmentEquipmentRel parentEquipmentRel = PersistenceHelper.makeEntity(EquipmentEquipmentRel.class);
parentEquipmentRel.setChildEquipment(equipment);
parentEquipmentRel.setParentEquipment(parentEquipment);

Working with Specifications and Characteristics

Developers can use the generated specification helper classes to avoid directly dealing with specifications and characteristics. See "Model Extension Using Specifications" for a description of the underlying API form more information on when to directly manipulate specifications.

Developers can determine if an entity supports characteristics and specification by referencing the model documentation, or by checking the POMS interface. Entities that support characteristics and specifications extend the CharacteristicExtensible interface. For example:

oracle.communications.inventory.api.CharacteristicExtensible <oracle.communications.inventory.api.entity.EquipmentCharacteristic>;

The specification and characteristics are related entities like any other, characteristics being multi-valued:

public oracle.communications.inventory.api.entity.EquipmentSpecification getSpecification();
public void setSpecification( oracle.communications.inventory.api.entity.EquipmentSpecification specification );
 
public java.util.Set<oracle.communications.inventory.api.entity.EquipmentCharacteristic> getCharacteristics();
public void setCharacteristics( java.util.Set<oracle.communications.inventory.api.entity.EquipmentCharacteristic> characteristics );

As a convenience, POMS also lets developers access a characteristic by name through the map returned by getCharacteristicMap:

public java.util.Map<String, oracle.communications.inventory.api.entity.EquipmentCharacteristic> getCharacteristicMap();

Working with the POMS Finder

Developers can use the POMS Finder to retrieve previously persisted data, however, developers do not typically need to use the Finder.

The most basic use of the Finders is "Find by Entity". More powerful and flexible queries are possible with the Java Persistence Query Language (JPQL). Developers can also control whether entities are returned completely or a with a subset of attributes. Developers can also use paging to return data in manageable chunks where queries might return a large volume of data.

Find by Entity

To find entities matching an example entity, instantiate an entity of the appropriate type and set one or more attributes. Use the findByEntity method to return a collection of matching entities. Here is an example that looks for the specification for a Cisco 3640 physical device:

Finder finder = PersistenceHelper.makeFinder();
PhysicalDeviceSpecification example = 
    PersistenceHelper.makeEntity(PhysicalDeviceSpecification.class);
example.setName("Cisco3640");

Collection<PhysicalDeviceSpecification> specifications = 
    finder.findByEntity(example, "name");
if (specifications.size() == 1) {
    System.out.println("found specification");
}

Find by JPQL

Java Persistence Query Language (JPQL) is a powerful way to express queries. The following examples can be understood without knowing JPQL, especially if the developer is familiar with SQL; however, developers must learn JPQL to build their own queries.

For an introduction to JPQL, use the following link:

http://download.oracle.com/javaee/6/tutorial/doc/bnbtg.html.

To perform a JPQL query use the following workflow:

  1. Instantiate a Finder.

  2. Initialize any parameters (these parameters are bound to variables in the JPQL expression).

  3. Specify the desired result type.

  4. Use the findByJPQL method to return matching results.

In following example queries, the first is equivalent to the example in the section "Find by Entity" , and returns a particular specification. The second uses a join in the JPQL expression to return all physical devices that use this specification.

Finder finder = PersistenceHelper.makeFinder();
finder.addParameter("name", "Cisco3640");
finder.setRsultClass(PhysicalDeviceSpecification.class);
Collection< PhysicalDeviceSpecification> specifications = finder.findByJPQL(
                 "SELECT o FROM PhysicalDeviceSpecification o " + 
                 "WHERE o.name = :name");
 
finder.setRsultClass(PhysicalDevice.class);
Collection< PhysicalDevice> cisco3640Devices = finder.findByJPQL(
                 "SELECT o FROM PhysicalDevice o JOIN o.specification s " +
                 "WHERE s.name = :name");

A JPQL query does not need to return complete entities. It can return one or more attributes from matched entities. To return only name and ID from a physical device, the developer would modify the previous example as follows:

Collection cisco3640Devices = finder.findByJPQL(
                 "SELECT o.name,o.id FROM PhysicalDevice o JOIN o.specification s WHERE s.name = :name");
for (Oject device : cisco3640Devices) {
    Object[] attributes = (cisco3640DevicesObject[]) device;
    System.out.println("Found Cisco 3640 named " + attributes[0] + " with id " + 
    attributes[1]);
} 

The code snippet also shows how to iterate over the results. Since the returned type is not a POMS entity, the attribute values are available as Object arrays. Developers would not set the result class in this case.

While JPQL and the Finder support operations that modify persisted data (update, delete, and so on), developers should never modify POMS data with JPQL. The Finder is intended only for read operations.

Find with Paged Results

When working with a large number of entities, process them in smaller batches to reduce memory usage. The Finder supports paged results. Initialize the Finder normally, then specify the range of value to retrieve. This modifies the original physical device example to page through devices 20 at a time:

int pageSize = 20;
int start = 0;
while (true) {
   finder.setRange(start, start + pageSize - 1);
   Collection<Physicaldevice> cisco3640Devices = finder.findByJPQL(
       "SELECT o FROM PhysicalDevice o JOIN o.specification s WHERE s.name = :name");
    for (PhysicalDevice device : cisco3640Devices) {
        System.out.println(device.getName());
        if (cisco3640Devices.size()) < pageSize) {
            break;
        }
        start += pageSize;
    }
}

POMS SDK Interfaces

The following are the PersistenceHelper API methods:

public static < E extends Object > E makeEntity( Class< E > entity );
public static oracle.communications.platform.persistence.Finder makeFinder( ) ;

The following are the Finder API methods:

/**
     * Set the result Class to query.
     * 
     * @param resultClass
     *            the interface of each result in the result set
     */
    public void setResultClass(Class resultClass);
 
/**
     * Set the range of the result set to return, starting of the zero-based
     * start index and ending at the end index, exclusive. For example,
     * setRange(0,5) returns 5 results indexed at 0 thru 4.
     * 
     * <p>
     * Setting the range is meaningless if the order of the results is not
     * consistent. setOrdering is assumed.
     * 
     * @param start
     *            zero-based start index
     * @param end
     *            ending index, exclusive
     * @see javax.jdo.Query#setRange
     */
    public void setRange(long start, long end);
 
    /**
     * Add the parameter name and value that are used to define the filter.
     * 
     * <p>
     * Parameter names beginning with an underscore ('_') are illegal. They may
     * conflict with additional parameters used internally by this Finder.
     * 
     * @param names
     *            the parameter name to be declared
     * @param param
     *            the parameter value to be bound to the query
     * @throws java.lang.IllegalArgumentException
     *             if illegal parameters are passed
     */
    public void addParameter(String name, Object param);
/**
     * Find entities by example.
     * Any non-null attributes in the example entity is used as the search criteria, however
     * the attribute names in the mustUseAttributes argument are used as criteria if the
     * attribute is null.
     * 
     * <p>
     * This is a convenience method that performs a simple query in one call.
     * Incremental query construction is not over-written by calling this
     * method.
     * 
     * @param entity
     *            the example entity which non-null attributes are used as the search criteria.
     * @param attributes
     *            list of attribute names which must be used as search criteria even if their values
     *            in the example entity are null.
     * @param <E>
     *            a oracle.communications.platform.persistence.Persistent type
     * @return Collection of results of the matching entities
     */
    public < E extends Persistent > Collection< E > findByEntity( E entity, String ... mustUseAttributes );
/**
     * This method returns the result of executing a JPQL search using the passed expression.
     * The caller can pass the query parameter with {@link #addParameter(Integer, Object) addParameter} or
     * {@link #addParameter(String, Object) addParameter}.
     * 
     * @param jpql The JPQL
     * @return Collection of search results
     */
    public Collection findByJPQL(String jpql);

About Persist Results

The persistResults method is available in the context of discovery, import and assimilation scan action types. This method persists in-memory result entities to the database and invalidates the entities. You may or may not need to explicitly call this method, depending on the sort of results that your action produces for a given invocation.

If the result set is small (for example, one result group for a particular device), then there is no need to call this method. Your result entities are automatically persisted when the action completes.

If the result set is large (for example multiple devices imported from an inventory system), call persistResults to write the information to the database, reducing memory consumption. In the context of an import action, you would likely want to call the persistResults after results for each device are modeled.

Since persistResults invalidates any in-memory entities, you should not hold a reference to any result entity across a call to persist results.