/*****************************************************************************
* Limpet - the Lightweight InforMation ProcEssing Toolkit
* http://limpet.info
*
* (C) 2015-2016, Deep Blue C Technologies Ltd
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html)
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*****************************************************************************/
package info.limpet.data.operations.arithmetic;
import info.limpet.ICommand;
import info.limpet.IContext;
import info.limpet.IOperation;
import info.limpet.IQuantityCollection;
import info.limpet.IStore;
import info.limpet.ITemporalQuantityCollection;
import info.limpet.ITemporalQuantityCollection.InterpMethod;
import java.util.Collection;
import java.util.List;
import javax.measure.Measurable;
import javax.measure.quantity.Quantity;
public class AddQuantityOperation<Q extends Quantity> extends
CoreQuantityOperation<Q> implements IOperation<IQuantityCollection<Q>>
{
@Override
protected void addInterpolatedCommands(
List<IQuantityCollection<Q>> selection, IStore destination,
Collection<ICommand<IQuantityCollection<Q>>> res, IContext context)
{
ITemporalQuantityCollection<Q> longest = getLongestTemporalCollections(selection);
if (longest != null)
{
ICommand<IQuantityCollection<Q>> newC = new AddQuantityValues(
"Add numeric values in provided series (interpolated)", selection,
destination, longest, context);
res.add(newC);
}
}
protected void addIndexedCommands(List<IQuantityCollection<Q>> selection,
IStore destination, Collection<ICommand<IQuantityCollection<Q>>> res,
IContext context)
{
ICommand<IQuantityCollection<Q>> newC = new AddQuantityValues(
"Add numeric values in provided series (indexed)", selection,
destination, context);
res.add(newC);
}
protected boolean appliesTo(List<IQuantityCollection<Q>> selection)
{
boolean nonEmpty = getATests().nonEmpty(selection);
boolean allQuantity = getATests().allQuantity(selection);
boolean suitableLength = getATests().allTemporal(selection)
|| getATests().allEqualLengthOrSingleton(selection);
boolean equalDimensions = getATests().allEqualDimensions(selection);
boolean equalUnits = getATests().allEqualUnits(selection);
return nonEmpty && allQuantity && suitableLength && equalDimensions && equalUnits;
}
public class AddQuantityValues extends CoreQuantityCommand
{
public AddQuantityValues(String name,
List<IQuantityCollection<Q>> selection, IStore store, IContext context)
{
this(name, selection, store, null, context);
}
public AddQuantityValues(String name,
List<IQuantityCollection<Q>> selection, IStore destination,
ITemporalQuantityCollection<Q> timeProvider, IContext context)
{
super(name, "Add datasets", destination, false, false, selection,
timeProvider, context);
}
@Override
protected Double calcThisElement(int elementCount)
{
Double thisResult = null;
for (int seriesCount = 0; seriesCount < getInputs().size(); seriesCount++)
{
IQuantityCollection<Q> thisC = getInputs().get(seriesCount);
Measurable<Q> thisV = thisC.getValuesCount() == 1 ? thisC.getValues().get(0)
: (Measurable<Q>) thisC.getValues().get(elementCount);
// is this the first field?
if (thisResult == null)
{
thisResult = thisV.doubleValue(thisC.getUnits());
}
else
{
thisResult += thisV.doubleValue(thisC.getUnits());
}
}
return thisResult;
}
@Override
protected Double calcThisInterpolatedElement(long time)
{
Double thisResult = null;
for (int seriesCount = 0; seriesCount < getInputs().size(); seriesCount++)
{
IQuantityCollection<Q> thisC = (IQuantityCollection<Q>) getInputs()
.get(seriesCount);
final Measurable<Q> thisV;
if (thisC.isTemporal())
{
// find the value to use
ITemporalQuantityCollection<Q> tq = (ITemporalQuantityCollection<Q>) thisC;
thisV = tq.interpolateValue(time, InterpMethod.Linear);
}
else
{
if (thisC.getValuesCount() == 1)
{
// ok, it's a singleton that we're applying to all values
thisV = thisC.getValues().get(0);
}
else
{
throw new RuntimeException(
"We should not be adding a non-singleton non-temporal to a temporal");
}
}
if (thisV != null)
{
// is this the first field?
if (thisResult == null)
{
thisResult = thisV.doubleValue(thisC.getUnits());
}
else
{
thisResult += thisV.doubleValue(thisC.getUnits());
}
}
}
return thisResult;
}
@Override
protected String getOutputName()
{
return getContext().getInput("Add datasets",
"Please provide a name for the dataset",
"Sum of " + super.getSubjectList());
}
}
}