//
// Copyright (c)1998-2011 Pearson Education, Inc. or its affiliate(s).
// All rights reserved.
//
package openadk.library.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import openadk.library.ADKException;
import openadk.library.Agent;
import openadk.library.ElementDef;
import openadk.library.Provisioner;
import openadk.library.ProvisioningOptions;
import openadk.library.Publisher;
import openadk.library.PublishingOptions;
import openadk.library.QueryResults;
import openadk.library.QueryResultsOptions;
import openadk.library.ReportPublisher;
import openadk.library.ReportPublishingOptions;
import openadk.library.SIFContext;
import openadk.library.SIFDTD;
import openadk.library.Subscriber;
import openadk.library.SubscriptionOptions;
import openadk.library.reporting.ReportingDTD;
/**
* Provides a matrix of provisioning options for an agent, zone, or topic, divided by context. Any provisioning
* that is done is either done in the default context or in a specific context. This class
* enables all the provisioning registrations to be handled easily by the Zone, Agent, or Topic classes.
*
* To register a generic handler for any object type, the key that is used is SIFDTD.SIF_MESSAGE
*
* @author Andrew
*
*/
public class ProvisioningMatrix implements Provisioner {
private List<ContextMatrix> fAllContexts = new ArrayList<ContextMatrix>();
public synchronized void setPublisher(Publisher publisher)
throws ADKException
{
setPublisher( publisher, null, null );
}
/* (non-Javadoc)
* @see openadk.library.Provisioner#setPublisher(openadk.library.Publisher, openadk.library.ElementDef)
*/
public synchronized void setPublisher(Publisher publisher, ElementDef objectType )
throws ADKException
{
setPublisher( publisher, objectType, null );
}
/* (non-Javadoc)
* @see openadk.library.Provisioner#setPublisher(openadk.library.Publisher, openadk.library.ElementDef, openadk.library.PublishingOptions)
*/
public synchronized void setPublisher(Publisher publisher, ElementDef objectType, PublishingOptions options)
throws ADKException
{
if( objectType != null && objectType == ReportingDTD.SIF_REPORTOBJECT ){
throw new IllegalArgumentException( "You must call setReportPublisher() for SIF_ReportObject type. " );
}
if( options == null ){
options = new PublishingOptions();
}
for( SIFContext context : options.getSupportedContexts() ){
getOrCreateContextMatrix( context ).setPublisher( publisher, objectType, options );
}
}
/* (non-Javadoc)
* @see openadk.library.Provisioner#setReportPublisher(openadk.library.ReportPublisher)
*/
public synchronized void setReportPublisher(ReportPublisher publisher )
throws ADKException
{
setReportPublisher(publisher, null);
}
/* (non-Javadoc)
* @see openadk.library.Provisioner#setReportPublisher(openadk.library.ReportPublisher, openadk.library.ReportPublishingOptions)
*/
public synchronized void setReportPublisher(ReportPublisher publisher, ReportPublishingOptions options)
throws ADKException
{
if( options == null ){
options = new ReportPublishingOptions();
}
for( SIFContext context : options.getSupportedContexts() ){
getOrCreateContextMatrix( context ).setReportPublisher( publisher, options );
}
}
/* (non-Javadoc)
* @see openadk.library.Provisioner#setSubscriber(openadk.library.Subscriber, openadk.library.ElementDef)
*/
public synchronized void setSubscriber(Subscriber subscriber, ElementDef objectType )
throws ADKException
{
setSubscriber( subscriber, objectType, null );
}
/* (non-Javadoc)
* @see openadk.library.Provisioner#setSubscriber(openadk.library.Subscriber, openadk.library.ElementDef, openadk.library.SubscriptionOptions)
*/
public synchronized void setSubscriber(Subscriber subscriber, ElementDef objectType, SubscriptionOptions options)
throws ADKException
{
if( options == null ){
options = new SubscriptionOptions();
}
for( SIFContext context : options.getSupportedContexts() ){
getOrCreateContextMatrix( context ).setSubscriber( subscriber, objectType, options );
}
}
/* (non-Javadoc)
* @see openadk.library.Provisioner#setQueryResults(openadk.library.QueryResults)
*/
public synchronized void setQueryResults(QueryResults queryResults)
throws ADKException
{
setQueryResults( queryResults, null, null );
}
/* (non-Javadoc)
* @see openadk.library.Provisioner#setQueryResults(openadk.library.QueryResults, openadk.library.ElementDef)
*/
public synchronized void setQueryResults(QueryResults queryResults, ElementDef objectType )
throws ADKException
{
setQueryResults( queryResults, objectType, null );
}
/* (non-Javadoc)
* @see openadk.library.Provisioner#setQueryResults(openadk.library.QueryResults, openadk.library.ElementDef, openadk.library.QueryResultsOptions)
*/
public synchronized void setQueryResults(QueryResults queryResults, ElementDef objectType, QueryResultsOptions options)
throws ADKException
{
if( options == null ){
options = new QueryResultsOptions();
}
for( SIFContext context : options.getSupportedContexts() ){
getOrCreateContextMatrix( context ).setQueryResults( queryResults, objectType, options );
}
}
/**
* Looks up the report publisher for the specified context
* @param context
* @param sif_reportobject
* @return
*/
public ReportPublisher lookupReportPublisher( SIFContext context ) {
ContextMatrix handler = lookupContextMatrix( context );
if( handler != null ){
ProvisionedObject<ReportPublisher,ReportPublishingOptions> objHandler = handler.getReportPublisher();
if( objHandler != null ){
return objHandler.getHandler();
}
}
return null;
}
/**
* Looks up the report publisher for the specified context
* @param context
* @param sif_reportobject
* @return
*/
public ReportPublisher lookupServicePublisher( SIFContext context ) {
ContextMatrix handler = lookupContextMatrix( context );
if( handler != null ){
ProvisionedObject<ReportPublisher,ReportPublishingOptions> objHandler = handler.getReportPublisher();
if( objHandler != null ){
return objHandler.getHandler();
}
}
return null;
}
/**
* Looks up the publisher for the specified context and object type
* @param context
* @param objectType
* @return
*/
public synchronized Publisher lookupPublisher( SIFContext context, ElementDef objectType ){
ContextMatrix handler = lookupContextMatrix( context );
if( handler != null ){
return handler.lookupPublisher( objectType );
}
return null;
}
/**
* Returns all of the Publisher options for all contexts
* @param excludeWildcard
* @return
*/
public synchronized List<ProvisionedObject<Publisher, PublishingOptions>> getAllPublishers( boolean excludeWildcard )
{
List<ProvisionedObject<Publisher, PublishingOptions>> list = new ArrayList<ProvisionedObject<Publisher, PublishingOptions>>();
for( ContextMatrix context : fAllContexts ){
getAll( context.fPubs, list, excludeWildcard );
}
return list;
}
/**
* Returns all of the ReportPublishing options for all contexts
* @return
*/
public synchronized List<ProvisionedObject<ReportPublisher, ReportPublishingOptions>> getAllReportPublishers()
{
List<ProvisionedObject<ReportPublisher, ReportPublishingOptions>> list = new ArrayList<ProvisionedObject<ReportPublisher, ReportPublishingOptions>>();
for( ContextMatrix context : fAllContexts ){
ProvisionedObject<ReportPublisher,ReportPublishingOptions> handler = context.getReportPublisher();
if( handler != null ){
list.add( handler );
}
}
return list;
}
/**
* Returns all of the Subscriptions options for all contexts
* @param excludeWildcard
* @return
*/
public synchronized List<ProvisionedObject<Subscriber, SubscriptionOptions>> getAllSubscribers( boolean excludeWildcard )
{
List<ProvisionedObject<Subscriber, SubscriptionOptions>> list = new ArrayList<ProvisionedObject<Subscriber, SubscriptionOptions>>();
for( ContextMatrix context : fAllContexts ){
getAll( context.fSubs, list, excludeWildcard );
}
return list;
}
/**
* Returns all of the QueryResults options for all contexts
* @param excludeWildcard
* @return
*/
public synchronized List<ProvisionedObject<QueryResults, QueryResultsOptions>> getAllQueryResults( boolean excludeWildcard )
{
List<ProvisionedObject<QueryResults, QueryResultsOptions>> list = new ArrayList<ProvisionedObject<QueryResults, QueryResultsOptions>>();
for( ContextMatrix context : fAllContexts ){
getAll( context.fQueryResults, list, excludeWildcard );
}
return list;
}
private synchronized <K,Y extends ProvisioningOptions> void getAll(
Map<ElementDef,ProvisionedObject<K,Y >> items,
List<ProvisionedObject<K,Y>> list, boolean excludeWildcard )
{
for( Map.Entry<ElementDef,ProvisionedObject<K, Y>> entry : items.entrySet() ){
if( excludeWildcard && entry.getKey() == SIFDTD.SIF_MESSAGE ){
continue;
}
list.add( entry.getValue() );
}
}
/**
* Looks up the subscriber for the specified context and object type
* @param context
* @param objectType
* @return
*/
public synchronized QueryResults lookupQueryResults( SIFContext context, ElementDef objectType ){
ContextMatrix handler = lookupContextMatrix( context );
if( handler != null ){
return handler.lookupQueryResults( objectType );
}
return null;
}
/**
* Looks up the subscriber for the specified context and object type
* @param context
* @param objectType
* @return
*/
public synchronized Subscriber lookupSubscriber( SIFContext context, ElementDef objectType ){
ContextMatrix handler = lookupContextMatrix( context );
if( handler != null ){
return handler.lookupSubscriber( objectType );
}
return null;
}
private ContextMatrix lookupContextMatrix( SIFContext context )
{
for( ContextMatrix handler : fAllContexts ){
if( handler.fContext.equals( context ) ){
return handler;
}
}
return null;
}
/**
* Looks up the ContextMatrix for the specified SIFContext
* @param context
* @return
*/
private ContextMatrix getOrCreateContextMatrix( SIFContext context )
{
ContextMatrix handler = lookupContextMatrix( context );
if( handler == null ){
handler = new ContextMatrix( context );
fAllContexts.add( handler );
}
return handler;
}
/**
* Contains references to all the message handlers supported for a specific SIF Context
* @author Andrew
*
*/
private static class ContextMatrix
{
/**
* The Subscribers registered with this context. The map consists of Handler
* objects keyed by SIF data object names (e.g. "StudentPersonal"). If a
* Subscriber is registered for all object types, it is keyed by the
* string "*".
*/
private Map<ElementDef, ProvisionedObject<Subscriber, SubscriptionOptions>> fSubs =
new HashMap<ElementDef, ProvisionedObject<Subscriber, SubscriptionOptions>>();
/**
* The Publishers registered with this context. The map consists of Handler
* objects keyed by SIF data object names (e.g. "StudentPersonal"). If a
* Publisher is registered for all object types, it is keyed by the string "*".
*/
private Map<ElementDef, ProvisionedObject<Publisher, PublishingOptions>> fPubs =
new HashMap<ElementDef, ProvisionedObject<Publisher, PublishingOptions>>();
/**
* The QueryResults objects registered in this context. The map is keyed by
* SIF data object names (e.g. "StudentPersonal"). If a QueryResults object
* is registered for all object types, it is keyed by the string "*".
*/
private Map<ElementDef, ProvisionedObject<QueryResults, QueryResultsOptions>> fQueryResults =
new HashMap<ElementDef, ProvisionedObject<QueryResults, QueryResultsOptions>>();
/**
* The context that this context handler covers
*/
private SIFContext fContext;
/**
* The ReportPublisher instance for this context
*/
private ProvisionedObject<ReportPublisher, ReportPublishingOptions> fReportPublisher;
public ContextMatrix( SIFContext context ){
fContext = context;
}
/**
* Returns the report publisher for this context
* @return
*/
public ProvisionedObject<ReportPublisher,ReportPublishingOptions> getReportPublisher() {
return fReportPublisher;
}
/**
* Sets the ReportPublisher instance for this context
* @param rp
*/
public void setReportPublisher( ReportPublisher rp, ReportPublishingOptions options ){
if( rp == null ){
ADKUtils._throw( new IllegalArgumentException("ReportPublisher object cannot be null"),Agent.getLog() );
}
if( ReportingDTD.SIF_REPORTOBJECT == null ){
ADKUtils._throw( new IllegalStateException("The ADK Reporting package is not loaded"),Agent.getLog() );
}
fReportPublisher = new ProvisionedObject<ReportPublisher,ReportPublishingOptions>( ReportingDTD.SIF_REPORTOBJECT, rp, options );
}
/**
* Sets the publisher for this context and object type
* @param publisher
* @param objectType
* @param options
*/
public void setPublisher(
Publisher publisher,
ElementDef objectType,
PublishingOptions options )
{
setHandler( fPubs, publisher, objectType, options );
}
/**
* Sets the subscriber for this context and object type
* @param subscriber
* @param objectType
* @param options
*/
public void setSubscriber(
Subscriber subscriber,
ElementDef objectType,
SubscriptionOptions options )
{
setHandler( fSubs, subscriber, objectType, options );
}
/**
* Sets the Query results handler for this context and object type
* @param qr
* @param objectType
* @param options
*/
public void setQueryResults(
QueryResults qr,
ElementDef objectType,
QueryResultsOptions options )
{
setHandler( fQueryResults, qr, objectType, options );
}
/**
* Looks up the publisher for the specified object type
* @param objectType
* @return
*/
public Publisher lookupPublisher(ElementDef objectType) {
return lookupHandler( objectType, fPubs );
}
/**
* Looks up the subscriber for the specified object type
* @param objectType
* @return
*/
public Subscriber lookupSubscriber(ElementDef objectType) {
return lookupHandler( objectType, fSubs );
}
/**
* Looks up the subscriber for the specified object type
* @param objectType
* @return
*/
public QueryResults lookupQueryResults(ElementDef objectType) {
return lookupHandler( objectType, fQueryResults );
}
/**
* Sets a handler of a specific type
* @param <T>
* @param map
* @param handler
* @param objType
* @param options
*/
public <T, V extends ProvisioningOptions> void setHandler( Map<ElementDef, ProvisionedObject<T,V>> map,
T handler,
ElementDef objType,
V options )
{
if( objType == null ){
objType = SIFDTD.SIF_MESSAGE;
}
ProvisionedObject<T,V> item = new ProvisionedObject<T,V>(objType, handler, options );
map.put( objType, item );
}
/**
* Looks up a handler of a specific type
* @param <T>
* @param def
* @param map
* @return
*/
public <T, V extends ProvisioningOptions > T lookupHandler(ElementDef def, Map<ElementDef, ProvisionedObject<T,V>> map ){
ProvisionedObject<T,?> item = map.get( def );
if( item == null ){
// Look for a default handler
item = map.get( SIFDTD.SIF_MESSAGE );
}
if( item != null ){
return item.getHandler();
}
return null;
}
}
}