/*
* Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
package org.csstudio.dal.impl;
import java.util.Iterator;
import java.util.LinkedList;
import org.csstudio.dal.Request;
import org.csstudio.dal.Response;
import org.csstudio.dal.ResponseEvent;
import org.csstudio.dal.ResponseListener;
import org.csstudio.dal.context.Identifiable;
/**
* Default implementation of request object. It conveniently stores
* responses up to the capacity and notifies request listener about new
* responses.
*
* @author Igor Kriznar (igor.kriznarATcosylab.com)
*/
public class RequestImpl<T> implements Request<T>
{
protected LinkedList<Response<T>> responses;
protected Identifiable source;
protected ResponseListener<T> listener = null;
private int capacity = 1;
public boolean isDone = false;
public T lastValue;
/**
* Creates new instance. Default response capacity is 1.
* @param source the source of responses
* @param l response listener
*
* @see #getCapacity()
*/
public RequestImpl(final Identifiable source, final ResponseListener<T> l)
{
this(source, l, 1);
}
/**
* Creates new instance with defined capacity for responses.
*
* @param source the source of reponses
* @param l listener
* @param capacity number of last responses stored, if 0 all responses are stored.
*
* @see #getCapacity()
*/
public RequestImpl(final Identifiable source, final ResponseListener<T> l, final int capacity)
{
if (source == null) {
throw new NullPointerException("source");
}
if (l == null) {
throw new NullPointerException("l");
}
if (capacity < 0) {
throw new IllegalArgumentException(
"Capaciti must be larger than 0, not " + capacity + ".");
}
responses = new LinkedList<Response<T>>();
this.source = source;
listener = l;
this.capacity = capacity;
}
/* (non-Javadoc)
* @see org.csstudio.dal.Request#getSource()
*/
@Override
public Identifiable getSource()
{
return source;
}
/* (non-Javadoc)
* @see org.csstudio.dal.Request#hasResponse()
*/
@Override
public synchronized boolean hasResponse()
{
return responses.size() > 0;
}
/* (non-Javadoc)
* @see org.csstudio.dal.Request#responses()
*/
@Override
public Iterator<Response<T>> responses()
{
return responses.iterator();
}
/**
* Adds new response to this request object and dispatches it to
* listener.
*
* @param r new response to be dispatched
*
* @throws NullPointerException if response is null
* @throws IllegalArgumentException if source of response and source of this request is not equal
*/
public void addResponse(final Response<T> r)
{
if (r == null) {
throw new NullPointerException("r");
}
if (r.getSource() != source) {
throw new IllegalArgumentException(
"Can not dispatch response which has different source identifeable.");
}
synchronized (this) {
responses.add(r);
while (capacity > 0 && responses.size() > capacity) {
responses.removeFirst();
}
}
if (listener != null) {
final ResponseEvent<T> e = new ResponseEvent<T>(source, this, r);
if (r.success()) {
listener.responseReceived(e);
} else {
listener.responseError(e);
}
}
if (r.isLast()) {
isDone = true;
lastValue = r.getValue();
synchronized (this) {
this.notifyAll();
}
// prevent memory leak by releasing listener reference once it is not needed any more.
listener=null;
}
}
/* (non-Javadoc)
* @see org.csstudio.dal.Request#isCompleted()
*/
@Override
public synchronized boolean isCompleted()
{
if (responses.size() > 0) {
return responses.getLast().isLast();
}
return false;
}
/**
* Capacity number defines how many of last responses is stored in
* this request. 0 means that all are stored.
*
* @return Returns the capacity.
*/
public int getCapacity()
{
return capacity;
}
public ResponseListener<T> getResponseListener()
{
return listener;
}
/*
* (non-Javadoc)
* @see org.csstudio.dal.Request#getFirstResponse()
*/
@Override
public synchronized Response<T> getFirstResponse() {
return responses.getFirst();
}
/*
* (non-Javadoc)
* @see org.csstudio.dal.Request#getLastResponse()
*/
@Override
public synchronized Response<T> getLastResponse() {
return responses.getLast();
}
/*
* (non-Javadoc)
* @see java.lang.Iterable#iterator()
*/
@Override
public Iterator<Response<T>> iterator() {
return responses();
}
/**
* Blocks call until last response is received. <br><b>NOTE: </b> call from this method is returned after events
* are dispatched on ResponseListeners.
*
* @return final value received with done event.
*/
@Override
public T waitUntilDone(){
while (isDone == false){
synchronized(this)
{
try {
this.wait();
} catch (final InterruptedException e) {
}
}
}
return lastValue;
}
}
/* __oOo__ */