/**
* Copyright (C) 2010-14 diirt developers. See COPYRIGHT.TXT
* All rights reserved. Use is subject to license terms. See LICENSE.TXT
*/
package org.diirt.datasource.extra;
import java.util.ArrayList;
import java.util.List;
import org.diirt.datasource.ReadRecipe;
import org.diirt.datasource.DataSource;
import org.diirt.datasource.expression.DesiredRateExpression;
import org.diirt.datasource.expression.DesiredRateExpressionImpl;
import org.diirt.datasource.ExceptionHandler;
import org.diirt.datasource.PVManager;
import org.diirt.datasource.expression.DesiredRateExpressionListImpl;
/**
* A expression that returns the result of a dynamically managed group.
* Once the group is created, any {@link DesiredRateExpression} can be
* added dynamically. The exceptions eventually generated by those
* expressions can be obtained through {@link #lastExceptions() }.
*
* @author carcassi
*/
public class DynamicGroup extends DesiredRateExpressionImpl<List<Object>> {
private final DataSource dataSource = PVManager.getDefaultDataSource();
private final List<ReadRecipe> recipes = new ArrayList<ReadRecipe>();
/**
* Creates a new group.
*/
public DynamicGroup() {
super(new DesiredRateExpressionListImpl<Object>(), new DynamicGroupFunction(), "dynamic group");
}
DynamicGroupFunction getGroup() {
return (DynamicGroupFunction) getFunction();
}
/**
* Returns the last exception for each expression in the group (if present).
*
* @return a list of exceptions (never null)
*/
public List<Exception> lastExceptions() {
synchronized (getGroup()) {
return new ArrayList<Exception>(getGroup().getExceptions());
}
}
/**
* Removes all the expressions currently in the group.
*
* @return this
*/
public synchronized DynamicGroup clear() {
for (int index = recipes.size() - 1; index >= 0; index--) {
ReadRecipe recipe = recipes.remove(index);
dataSource.disconnectRead(recipe);
synchronized (getGroup()) {
getGroup().getArguments().remove(index);
getGroup().getExceptions().remove(index);
getGroup().getPreviousValues().remove(index);
}
}
return this;
}
/**
* Returns the number of expressions in the group.
*
* @return number of expressions in the group
*/
public synchronized int size() {
return recipes.size();
}
/**
* Adds the expression at the end.
*
* @param expression the expression to be added
* @return this
*/
public synchronized DynamicGroup add(DesiredRateExpression<?> expression) {
// DataRecipe recipe = expression.getDataRecipe();
// recipe = recipe.withExceptionHandler(handlerFor(recipes.size()));
synchronized (getGroup()) {
getGroup().getArguments().add(expression.getFunction());
getGroup().getExceptions().add(null);
getGroup().getPreviousValues().add(null);
}
// dataSource.connect(recipe);
// recipes.add(recipe);
return this;
}
/**
* Removes the expression at the given location.
*
* @param index the position to remove
* @return this
*/
public synchronized DynamicGroup remove(int index) {
ReadRecipe recipe = recipes.remove(index);
dataSource.disconnectRead(recipe);
synchronized (getGroup()) {
getGroup().getArguments().remove(index);
getGroup().getExceptions().remove(index);
getGroup().getPreviousValues().remove(index);
}
return this;
}
/**
* Changes the expression to the given location.
*
* @param index the position to remove
* @param expression the new expression
* @return this
*/
public synchronized DynamicGroup set(int index, DesiredRateExpression<?> expression) {
// DataRecipe recipe = expression.getDataRecipe();
// recipe = recipe.withExceptionHandler(handlerFor(index));
ReadRecipe oldRecipe = recipes.get(index);
dataSource.disconnectRead(oldRecipe);
synchronized (getGroup()) {
getGroup().getArguments().set(index, expression.getFunction());
getGroup().getExceptions().set(index, null);
getGroup().getPreviousValues().set(index, null);
}
// dataSource.connect(recipe);
// recipes.set(index, recipe);
return this;
}
private ExceptionHandler handlerFor(final int index) {
return new ExceptionHandler() {
@Override
public void handleException(Exception ex) {
synchronized (getGroup()) {
getGroup().getExceptions().set(index, ex);
}
}
};
}
}