org.opendof.datatransfer.snapshot.SnapshotProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dof-data-transfer-snapshot Show documentation
Show all versions of dof-data-transfer-snapshot Show documentation
The Java Data Transfer Snapshot Library provides an API for developers to send and receive snapshots of data using OpenDOF protocols.
The newest version!
package org.opendof.datatransfer.snapshot;
import java.util.ArrayList;
import java.util.Hashtable;
import org.opendof.core.oal.DOF;
import org.opendof.core.oal.DOFApplicationErrorException;
import org.opendof.core.oal.DOFException;
import org.opendof.core.oal.DOFInterface;
import org.opendof.core.oal.DOFInterfaceID;
import org.opendof.core.oal.DOFObject;
import org.opendof.core.oal.DOFObjectID;
import org.opendof.core.oal.DOFOperation;
import org.opendof.core.oal.DOFRequest;
import org.opendof.core.oal.DOFSystem;
import org.opendof.core.oal.DOFValue;
import org.opendof.core.oal.value.DOFBlob;
import org.opendof.datatransfer.ValueSet;
import org.opendof.datatransfer.internal.AttributeUtil;
import org.opendof.datatransfer.internal.DataSinkInterface;
import org.opendof.datatransfer.internal.DataSnapshotInterface;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class allows an application to become a provider of snapshot information for objects.
*
* The SLF4J library is used for all non-OpenDOF logging. If logging of the OpenDOF OAL library is desired, a logger must
* be added to the OAL by calling {@link DOF.Log#addListener}.
*/
public class SnapshotProvider {
private final DOFSystem system;
private final SnapshotActivateListener activateListener;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final ArrayList snapshotInterestListeners = new ArrayList();
private final ArrayList currentActivates = new ArrayList();
private final Hashtable snapshotProviders = new Hashtable();
private boolean isShutdown = false;
/**
* Terminate and close this instance.
*/
public void close() {
if(isShutdown) return;
isShutdown = true;
system.removeActivateInterestListener(activateListener);
synchronized(snapshotProviders){
for(DataSnapshotInterfaceProvider snapshotProvider : snapshotProviders.values()){
snapshotProvider.close();
}
snapshotProviders.clear();
}
synchronized(snapshotInterestListeners){
for(SnapshotInterestListener listener : snapshotInterestListeners){
try{
listener.removed(this);
} catch (Throwable t){
logger.debug("Exception thrown in callback method SnapshotInterestListener.removed(): " + t, t);
}
}
snapshotInterestListeners.clear();
}
synchronized(currentActivates){
currentActivates.clear();
}
}
/**
* Construct a new SnapshotProvider.
* @param system The DOFSystem instance allowing this class to use OpenDOF to facilitate network communications. Must not be null.
*/
public SnapshotProvider(DOFSystem system) {
if(system == null) throw new IllegalArgumentException("system == null");
this.system = system;
this.activateListener = new SnapshotActivateListener();
system.addActivateInterestListener(activateListener);
}
/**
* Updates the snapshot for a specified object and interface.
* This will cause a provide to be started for the snapshot if one does not already exist.
* @param objectID The object to which the snapshot applies. Must not be null.
* @param interfaceID The interface to which the snapshot applies. Must not be null.
* @param snapshot The current snapshot to be sent. This also indicates the definition of the snapshot. Must not be null.
* The definition must match any previous definition used for the same object and interface combination.
*
* @throws Exception Thrown if the provider is unable to send the snapshot update.
*/
public void send(DOFObjectID objectID, DOFInterfaceID interfaceID, ValueSet.Row snapshot) throws Exception {
if(objectID == null) throw new IllegalArgumentException("oid == null");
if(interfaceID == null) throw new IllegalArgumentException("interfaceID == null");
if(isShutdown) throw new IllegalStateException("SnapshotProvider has been terminated.");
DOFObjectID providerID = AttributeUtil.getIDWithInterfaceAttribute(objectID, interfaceID);
DOFValue value = snapshot.getSnapshot(DataSnapshotInterface.InterfaceID);
DataSnapshotInterfaceProvider snapshotProvider = null;
synchronized (snapshotProviders)
{
if(!snapshotProviders.containsKey(providerID)){
snapshotProviders.put(providerID, new DataSnapshotInterfaceProvider(this, system, providerID, snapshot.getDefinition(), value));
return;
}
snapshotProvider = snapshotProviders.get(providerID);
}
snapshotProvider.updateValue(value);
}
// /**
// * Updates the snapshot for a specified object.
// * This will cause a provide to be started for the snapshot if one does not already exist.
// * @param oid The object to which the snapshot applies. The object must contain a session attribute. Must not be null.
// * @param snapshot The current snapshot to be sent. This also indicates the definition of the snapshot. Must not be null.
// * The definition must match any previous definition used for the same object.
// */
// public void send(DOFObjectID oid, ValueSet.Row snapshot) throws DuplicateProvideException {
// }
/**
* Stops the snapshot provider for the specified object and interface.
* @param objectID The object for which the snapshot will be stopped. Must not be null.
* @param interfaceID The interface for which the snapshot will be stopped. Must not be null.
*/
public void stop(DOFObjectID objectID, DOFInterfaceID interfaceID) {
if(objectID == null) throw new IllegalArgumentException("oid == null");
if(interfaceID == null) throw new IllegalArgumentException("interfaceID == null");
if(isShutdown) throw new IllegalStateException("SnapshotProvider has been terminated.");
DOFObjectID providerID = AttributeUtil.getIDWithInterfaceAttribute(objectID, interfaceID);
DataSnapshotInterfaceProvider snapshotProvider = null;
synchronized(snapshotProviders){
if(!snapshotProviders.containsKey(providerID)){
return;
}
snapshotProvider = snapshotProviders.remove(providerID);
}
snapshotProvider.close();
}
// /**
// * Stops the snapshot provider for the specified object and definition.
// * @param oid The object for which the snapshot will be stopped. The object must contain a session attribute. Must not be null.
// */
// public void stop(DOFObjectID oid) {
//
// }
/**
* Adds a listener, which will receive notifications that there is interest added for a snapshot.
* The current set of snapshots with interest will be delivered to the listener when added, and updated over time until removed.
* @param listener The listener to be added. Must not be null.
*/
public void addInterestListener(SnapshotInterestListener listener) {
if(listener == null) throw new IllegalArgumentException("listener == null");
synchronized(snapshotInterestListeners){ snapshotInterestListeners.add(listener); }
synchronized (currentActivates)
{
for(DOFObjectID oid : currentActivates){
DOFInterfaceID interfaceID = AttributeUtil.getIIDFromObjectAttribute(oid);
DOFObjectID objectID = AttributeUtil.getIDWithoutInterfaceAttribute(oid);
try{
listener.snapshotInterestAdded(this, objectID, interfaceID);
} catch (Throwable t){
logger.debug("Exception thrown in callback method snapshotInterestAdded(): " + t, t);
}
}
}
}
/**
* Removes a previously added listener.
* @param listener The listener to be removed. Must not be null.
*/
public void removeInterestListener(SnapshotInterestListener listener) {
if(listener == null) throw new IllegalArgumentException("listener == null");
synchronized(snapshotInterestListeners){ snapshotInterestListeners.remove(listener); }
try{
listener.removed(this);
} catch (Throwable t){
logger.debug("Exception thrown in callback method SnapshotInterestListener.removed(): " + t, t);
}
}
private void activateAdded(DOFObjectID objectID){
logger.trace("activateAdded: " + objectID);
synchronized (currentActivates) { currentActivates.add(objectID); }
DOFInterfaceID interfaceID = AttributeUtil.getIIDFromObjectAttribute(objectID);
DOFObjectID oid = AttributeUtil.getIDWithoutInterfaceAttribute(objectID);
synchronized(snapshotInterestListeners){
for(SnapshotInterestListener listener : snapshotInterestListeners){
try{
listener.snapshotInterestAdded(this, oid, interfaceID);
} catch (Throwable t){
logger.debug("Exception thrown in callback method snapshotInterestAdded(): " + t, t);
}
}
}
}
private void activateRemoved(DOFObjectID objectID){
logger.trace("activateRemoved: " + objectID);
synchronized (currentActivates){ currentActivates.remove(objectID); }
DOFInterfaceID interfaceID = AttributeUtil.getIIDFromObjectAttribute(objectID);
DOFObjectID oid = AttributeUtil.getIDWithoutInterfaceAttribute(objectID);
synchronized(snapshotInterestListeners){
for(SnapshotInterestListener listener : snapshotInterestListeners){
try{
listener.snapshotInterestRemoved(this, oid, interfaceID);
} catch (Throwable t){
logger.debug("Exception thrown in callback method snapshotInterestRemoved(): " + t, t);
}
}
}
}
private class SnapshotActivateListener implements DOFSystem.ActivateInterestListener{
@Override
public void activate(DOFSystem system, DOFRequest request, DOFObjectID objectID, DOFInterfaceID interfaceID)
{
if(!interfaceID.equals(DataSnapshotInterface.InterfaceID))
return;
activateAdded(objectID);
}
@Override
public void cancelActivate(DOFSystem system, DOFRequest request, DOFObjectID objectID, DOFInterfaceID interfaceID)
{
if(!interfaceID.equals(DataSnapshotInterface.InterfaceID))
return;
activateRemoved(objectID);
}
@Override
public void removed(DOFSystem system, DOFException exception)
{
//TODO ?
}
}
private static class DataSnapshotInterfaceProvider extends DOFObject.DefaultProvider {
private final SnapshotProvider snapshotProvider;
private DOFValue currentValue;
private DOFBlob definitionBlob;
private DOFObject provider;
private DOFOperation.Provide provideOp;
public DataSnapshotInterfaceProvider(SnapshotProvider snapshotProvider, DOFSystem system, DOFObjectID objectID, ValueSet.Definition definition, DOFValue startValue)
{
this.snapshotProvider = snapshotProvider;
this.currentValue = startValue;
this.definitionBlob = new DOFBlob(definition.getTransferBytes(DataSinkInterface.InterfaceID));
provider = system.createObject(objectID);
provideOp = provider.beginProvide(DataSnapshotInterface.DEF, DOF.TIMEOUT_NEVER, this, null);
}
public void updateValue(DOFValue newValue){
this.currentValue = newValue;
provider.changed(DataSnapshotInterface.DEF.getProperty(DataSnapshotInterface.SnapshotItem));
}
@Override
public void get(DOFOperation.Provide operation, DOFRequest.Get request, DOFInterface.Property property) {
try{
if(property.getInterfaceID().equals(DataSnapshotInterface.InterfaceID)){
switch(property.getItemID()){
case DataSnapshotInterface.DefinitionItem:
request.respond(definitionBlob);
break;
case DataSnapshotInterface.SnapshotItem:
request.respond(currentValue);
}
}
}catch(Exception e){
request.respond(new DOFApplicationErrorException());
snapshotProvider.logger.warn("Exception in SnapshotProvider get callback method: " + e, e);
}
}
@Override
public void subscribe(DOFOperation.Provide operation, DOFRequest.Subscribe request, DOFInterface.Property property, int minPeriod) {
try{
snapshotProvider.logger.warn("Subscribe(): {} - {} - {}", operation.getInterface().getInterfaceID(), operation.getObject().getObjectID(), property);
request.respond();
}catch(Exception e){
request.respond(new DOFApplicationErrorException());
snapshotProvider.logger.warn("Exception in SnapshotProvider subscribe callback method: " + e, e);
}
}
/**
* Terminate and close this instance.
*/
public void close()
{
if(provideOp != null) provideOp.cancel();
if(provider != null) provider.destroy();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy