/*******************************************************************************
* Copyright (c) 2013 Luigi Sgro. All rights reserved. This
* program and the accompanying materials are made available under the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Luigi Sgro - initial API and implementation
******************************************************************************/
package com.quantcomponents.algo;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.quantcomponents.core.model.IMutableSeries;
import com.quantcomponents.core.model.ISeries;
import com.quantcomponents.core.model.ISeriesPoint;
import com.quantcomponents.core.series.LinkedListSeries;
/**
* Simple synchronous input series streamer
*/
public class InputSeriesStreamer implements IInputSeriesStreamer {
private final Map<String, IMutableSeries<Date, Double, ? extends ISeriesPoint<Date, Double>>> streamingSeries = new ConcurrentHashMap<String, IMutableSeries<Date, Double, ? extends ISeriesPoint<Date, Double>>>();
private final Map<String, ? extends ISeries<Date, Double, ? extends ISeriesPoint<Date, Double>>> sourceSeries;
private volatile Date lastTimestamp;
private Map<String, Iterator<ISeriesPoint<Date, Double>>> iteratorMap;
private Map<String, ISeriesPoint<Date, Double>> lastValueMap;
public InputSeriesStreamer(Map<String, ? extends ISeries<Date, Double, ? extends ISeriesPoint<Date, Double>>> sourceSeries, Map<String, ? extends IMutableSeries<Date, Double, ? extends ISeriesPoint<Date, Double>>> targetSeries) {
this.sourceSeries = sourceSeries;
for (String key : sourceSeries.keySet()) {
streamingSeries.put(key, targetSeries.get(key));
}
}
@Override
public Map<String, ? extends ISeries<Date, Double, ? extends ISeriesPoint<Date, Double>>> getStreamingSeries() {
return Collections.unmodifiableMap(streamingSeries);
}
@Override
public Date getLastTimestamp() {
return lastTimestamp;
}
private void fetchNextPoints() {
for (Map.Entry<String, ISeriesPoint<Date, Double>> lastValueEntry : lastValueMap.entrySet()) {
if (lastValueEntry.getValue() == null) {
Iterator<ISeriesPoint<Date, Double>> pointIterator = iteratorMap.get(lastValueEntry.getKey());
if (pointIterator.hasNext()) {
lastValueEntry.setValue(pointIterator.next());
}
}
}
}
private Map.Entry<String, ISeriesPoint<Date, Double>> findFirstPoint() {
Map.Entry<String, ISeriesPoint<Date, Double>> firstPointEntry = null;
for (Map.Entry<String, ISeriesPoint<Date, Double>> lastValueEntry : lastValueMap.entrySet()) {
if (firstPointEntry == null || (lastValueEntry.getValue() != null && lastValueEntry.getValue().getEndIndex().before(firstPointEntry.getValue().getEndIndex()))) {
firstPointEntry = lastValueEntry;
}
}
if (firstPointEntry != null && firstPointEntry.getValue() != null) {
lastTimestamp = firstPointEntry.getValue().getEndIndex();
}
return firstPointEntry;
}
private void addToStreamingSeries(Map.Entry<String, ISeriesPoint<Date, Double>> pointEntry) {
@SuppressWarnings("unchecked")
LinkedListSeries<Date, Double, ISeriesPoint<Date, Double>> series = (LinkedListSeries<Date, Double, ISeriesPoint<Date, Double>>) streamingSeries.get(pointEntry.getKey());
series.addLast(pointEntry.getValue());
pointEntry.setValue(null);
}
@Override
public void run() {
iteratorMap = new HashMap<String, Iterator<ISeriesPoint<Date, Double>>>();
lastValueMap = new HashMap<String, ISeriesPoint<Date, Double>>();
for (Map.Entry<String, ? extends ISeries<Date, Double, ? extends ISeriesPoint<Date, Double>>> seriesEntry : sourceSeries.entrySet()) {
@SuppressWarnings("unchecked")
ISeries<Date, Double, ISeriesPoint<Date, Double>> series = (ISeries<Date, Double, ISeriesPoint<Date, Double>>) seriesEntry.getValue();
iteratorMap.put(seriesEntry.getKey(), series.iterator());
lastValueMap.put(seriesEntry.getKey(), null);
}
while (true) {
fetchNextPoints();
Map.Entry<String, ISeriesPoint<Date, Double>> nextPoint = findFirstPoint();
if (nextPoint == null || nextPoint.getValue() == null) {
break;
}
addToStreamingSeries(nextPoint);
}
}
}