Public Objects are Information Service objects which represent SAS information which is rooted in metadata. These
objects are typically transportable and implement several defined action/processor interfaces.
Overview
The public objects are used to represent metadata and content stored for the SAS system.
Terms
| Processor Interface | An interface used to define actions or processes that
can be defined for objects. |
| Type Descriptor | An interface which allows access to the information about
a public object. This information is defined in the metadata type
dictionary. |
Information Service
The public objects are accessed and used as any Information Service "smart object".
This is described in detail in the Information Service package description. A typical class would extend
the Metadata base class and would implement the necessary methods..
...
/**
* Example class for usage of Public Object framework.
*/
public class PublicStoredQuery extends Metadata
{
/**
* Serial version UID for serialization.
*/
private static final long serialVersionUID = -7014758897989051070L;
/**
* @param theClass
* @throws RemoteException
*/
protected PublicStoredQuery( Class theClass ) throws RemoteException {
super(theClass);
}
/**
* @throws RemoteException
*/
public PublicStoredQuery() throws RemoteException {
super(PublicStoredQuery.class);
}
/**
* @param o
* @param theClass
* @throws RemoteException
*/
protected PublicStoredQuery( Transformation o, Class theClass ) throws RemoteException {
super(o, theClass);
}
/**
* @param o
* @throws RemoteException
*/
public PublicStoredQuery( Transformation o ) throws RemoteException {
super(o, PublicStoredQuery.class);
}
/**
* @param o
* @param theClass
* @throws RemoteException
*/
protected PublicStoredQuery( TransformationImpl o, Class theClass ) throws RemoteException {
super(o, theClass);
}
/**
* @param o
* @throws RemoteException
*/
public PublicStoredQuery( TransformationImpl o ) throws RemoteException {
super(o, PublicStoredQuery.class);
}
/**
* @param o
* @param theClass
* @throws RemoteException
*/
protected PublicStoredQuery( TransformationImpl_Stub o, Class theClass ) throws RemoteException {
super(o, theClass);
}
/**
* @param o
* @throws RemoteException
*/
public PublicStoredQuery( TransformationImpl_Stub o ) throws RemoteException {
super(o, PublicStoredQuery.class);
}
/**
* Constructor which allows new object to be created within a repos and folder.
*
* @param repos The repository this object is contained in.
* @param name The name of the new PublicStoredQuery
* @param parent The parent folder for this object.
* @throws RemoteException
*/
public PublicStoredQuery( RepositoryInterface repos, String name, FolderInterface parent ) throws RemoteException {
super();
if ((repos == null) || (name == null))
throw new IllegalArgumentException();
try {
OMIRepositoryInterface omirepository = (OMIRepositoryInterface) repos;
Transformation transformation = (Transformation) omirepository.createMetadata(name,
MetadataObjects.TRANSFORMATION);
_repositoryObject = transformation;
_repositoryFlag = Metadata.REPOSITORY_OMR;
setRepository(repos);
if (parent != null) {
try {
parent.addItem(this);
}catch (Exception ex) {
}
}
}
catch (Throwable t) {
logMessage(LoggerInterface.WARN,
RB.getStringResource("Metadata.accessexcept.msg.txt"),
"com.sas.services.information.metadata.OMRColumn",
t);
}
}
...
|
Processor Interface(s)
The public object api uses a set of interfaces to describe the processes or actions an object supports. These processes
and/or actions are defined in an interface that extends com.sas.services.information.publicobject.ProcessorInterface.
the following interfaces are defined and can be supported by objects implementing the PublicObjectInterface.
These interfaces are accessed by the getProcessorInterface(String name) on the public object. This allows the objects
to adapt themselves to support functionality. Each of these interfaces is implemented by a adapter class and that interface is then registered
so that the adapter is returned when someone requests a processor interface.
Impact Analysis
To define a class as having the ImpactAnalysisProcessorInterface you would create a class that extends
the ImpactAnalysisAdapter and override any default implentations as necessary.
/**
* Inner class example used for Impact Analysis. This does not have to be an inner class, however if
* access is needed to private members of the PublicObjectInterface then you probably will need the
* access provided by the inner class.
*/
public class ImpactAnalysisAdapter extends com.sas.services.information.publicobject.ImpactAnalysisAdapter
{
/**
* Serial version UID for serialization.
*/
private static final long serialVersionUID = -3266458216525903986L;
/**
* @param publicObject
* @throws RemoteException
*/
public ImpactAnalysisAdapter( PublicObjectInterface publicObject ) throws RemoteException {
super(publicObject);
}
/**
* Overriding to get relationships from metadata.
*
* @see com.sas.services.information.publicobject.ImpactAnalysisAdapter#getRelatedObjects(int)
*/
public List getRelatedObjects( int relationshipType ) throws ServiceException, RemoteException
{
List returnValue = new ArrayList();
// We must get the underling object for this "Smart" object to allow traversal of metadata associations.
Object underlyingOMAObject = getRepositoryEntity();
if (underlyingOMAObject != null && underlyingOMAObject instanceof com.sas.metadata.remote.Transformation) {
com.sas.metadata.remote.Transformation jOMATransformationObject = (com.sas.metadata.remote.Transformation) underlyingOMAObject;
List metadataDependencies = null;
try {
// For each type of relationship get the proper set of related items.
switch (relationshipType) {
case ImpactAnalysisProcessorInterface.TYPE_CONSUMES_DATA_FROM:
metadataDependencies = jOMATransformationObject.getTransformationSources();
break;
case ImpactAnalysisProcessorInterface.TYPE_PROVIDES_DATA_FOR:
metadataDependencies = jOMATransformationObject.getTransformationTargets();
break;
default:
break;
}
}catch (com.sas.metadata.remote.MdException mde) {
ServiceException se = new ServiceException(mde, mde.getLocalizedMessage());
se.initCause(mde);
throw se;
}
// If we have objects from jOMA we must get the PublicObjectInterfaces for these from
// the information service.
if (metadataDependencies != null) {
Iterator it = metadataDependencies.iterator();
while (it.hasNext()) {
Object o = it.next();
returnValue.add(_repository.factoryProcess(o));
}
}
}
return returnValue;
}
}
|
Display / General Properties
It is also possible to implement just return the adapter if you
have no implementation. This is usually where the default adapter
class will suffice for the current usage. Notice in the example above
that the DisplayProcessorAdapter is the default one. This allows the
object to have a default implementation. There is no default
implementation for the impact analysis or the transport processors.
Registering Interfaces
Interface implementing classes are registered with public objects by implementations of the getProcessorInterface(String interfaceClassName) method.
/**
* Get the processor interface requested.
*
* @see com.sas.services.information.metadata.Metadata#getProcessorInterface(java.lang.String)
*/
public ProcessorInterface getProcessorInterface( String interfaceClassName ) throws ServiceException,
RemoteException
{
// If you want to override or specify the specific
if (interfaceClassName.equals(DisplayProcessorInterface.NAME))
return new DisplayAdapter(this);
if (interfaceClassName.equals(ImpactAnalysisProcessorInterface.NAME))
return new ImpactAnalysisAdapter(this);
return super.getProcessorInterface(interfaceClassName);
}
|
This allows a public object class to override and implement the necessary interfaces or to use the default adapters provided by the parent
class. In the example above the ImpactAnalysisAdapter is an inner class that extends the default adapter and the DisplayAdapter is the default
implementation. For all other interfaces, this class lets the super class provide the necessary information.
Transport Service and the Transport Handler Interface
The Transport Handler is used to process all transport operations. This interface is used to transport metadata and content. This is accessed by
the type descriptor for each type as necessary, however it is registered by adding a method on the public object class to allow retrieval.
/**
* Get the transport Handler for this type.
* @return
* @throws RemoteException
* @throws ServiceException
*/
public static TransportHandlerInterface getTransportHandler(TypeDescriptorInterface type) throws RemoteException, ServiceException
{
return new StoredQueryTransportHandler(type);
}
/**
* Create default handler class for use in transport. This only does metadata and no
* extra processing, so we don't override any super methods.
*
*/
private static class StoredQueryTransportHandler extends AbstractTransportHandler
{
/**
* This is the default constructor for the transport adapter.
* @param descriptor
*/
public StoredQueryTransportHandler( TypeDescriptorInterface descriptor ) {
super(descriptor);
}
}
|
This Transport Handler is a class used to override functionality of the AbstractTransportHandler. This allows overriding the default behavior and
adding specific functionality to support transport of content and any pre/post processing of transported information.