/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.timeseries.precise.instant;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.SortedMap;
import java.util.concurrent.ConcurrentSkipListMap;
import org.threeten.bp.Instant;
import com.opengamma.timeseries.precise.PreciseObjectTimeSeries;
/**
* Builder implementation for {@code ImmutableInstantObjectTimeSeries}.
*/
final class ImmutableInstantObjectTimeSeriesBuilder<V>
implements InstantObjectTimeSeriesBuilder<V> {
/**
* The time-series.
*/
private SortedMap<Long, V> _series = new ConcurrentSkipListMap<>(); // use this map to block nulls
/**
* Creates an instance.
*/
protected ImmutableInstantObjectTimeSeriesBuilder() {
}
//-------------------------------------------------------------------------
private static long convertToLong(Instant instant) {
return InstantToLongConverter.convertToLong(instant);
}
private static Instant convertFromLong(long instant) {
return InstantToLongConverter.convertToInstant(instant);
}
//-------------------------------------------------------------------------
@Override
public int size() {
return _series.size();
}
@Override
public InstantObjectEntryIterator<V> iterator() {
return new InstantObjectEntryIterator<V>() {
private Iterator<Entry<Long, V>> _iterator = _series.entrySet().iterator();
private int _index = -1;
private Entry<Long, V> _current;
@Override
public boolean hasNext() {
return _iterator.hasNext();
}
@Override
public Entry<Instant, V> next() {
return new SimpleImmutableEntry<>(nextTime(), currentValue());
}
@Override
public long nextTimeFast() {
if (hasNext() == false) {
throw new NoSuchElementException("No more elements in the iteration");
}
_index++;
_current = _iterator.next();
return _current.getKey();
}
@Override
public Instant nextTime() {
return convertFromLong(nextTimeFast());
}
@Override
public long currentTimeFast() {
if (_index < 0) {
throw new IllegalStateException("Iterator has not yet been started");
}
if (_current == null) {
throw new IllegalStateException("Element has been removed");
}
return _current.getKey();
}
@Override
public Instant currentTime() {
return convertFromLong(currentTimeFast());
}
@Override
public V currentValue() {
if (_index < 0) {
throw new IllegalStateException("Iterator has not yet been started");
}
if (_current == null) {
throw new IllegalStateException("Element has been removed");
}
return _current.getValue();
}
@Override
public int currentIndex() {
return _index;
}
@Override
public void remove() {
if (_index < 0) {
throw new IllegalStateException("Iterator has not yet been started");
}
if (_current == null) {
throw new IllegalStateException("Element has been removed");
}
_iterator.remove();
_current = null;
_index--;
}
};
}
//-------------------------------------------------------------------------
@Override
public InstantObjectTimeSeriesBuilder<V> put(Instant time, V value) {
return put(convertToLong(time), value);
}
@Override
public InstantObjectTimeSeriesBuilder<V> put(long time, V value) {
_series.put(time, value);
return this;
}
@Override
public InstantObjectTimeSeriesBuilder<V> putAll(Instant[] times, V[] values) {
if (times.length != values.length) {
throw new IllegalArgumentException("Arrays are of different sizes: " + times.length + ", " + values.length);
}
for (int i = 0; i < times.length; i++) {
put(times[i], values[i]);
}
return this;
}
@Override
public InstantObjectTimeSeriesBuilder<V> putAll(long[] times, V[] values) {
if (times.length != values.length) {
throw new IllegalArgumentException("Arrays are of different sizes: " + times.length + ", " + values.length);
}
for (int i = 0; i < times.length; i++) {
put(times[i], values[i]);
}
return this;
}
//-------------------------------------------------------------------------
@Override
public InstantObjectTimeSeriesBuilder<V> putAll(PreciseObjectTimeSeries<?, V> timeSeries) {
return putAll(timeSeries, 0, timeSeries.size());
}
@Override
public InstantObjectTimeSeriesBuilder<V> putAll(PreciseObjectTimeSeries<?, V> timeSeries, int startPos, int endPos) {
if (startPos < 0 || startPos > timeSeries.size()) {
throw new IndexOutOfBoundsException("Invalid start index: " + startPos);
}
if (endPos < 0 || endPos > timeSeries.size()) {
throw new IndexOutOfBoundsException("Invalid end index: " + endPos);
}
if (startPos > endPos) {
throw new IndexOutOfBoundsException("End index not be less than start index");
}
if (startPos == endPos) {
return this;
}
for (int i = startPos; i < endPos; i++) {
put(timeSeries.getTimeAtIndexFast(i), timeSeries.getValueAtIndex(i));
}
return this;
}
@Override
public InstantObjectTimeSeriesBuilder<V> putAll(Map<Instant, V> timeSeriesMap) {
if (timeSeriesMap.size() == 0) {
return this;
}
for (Entry<Instant, V> entry : timeSeriesMap.entrySet()) {
put(entry.getKey(), entry.getValue());
}
return this;
}
//-------------------------------------------------------------------------
@Override
public InstantObjectTimeSeriesBuilder<V> clear() {
_series.clear();
return this;
}
//-------------------------------------------------------------------------
@Override
public ImmutableInstantObjectTimeSeries<V> build() {
long[] times = new long[_series.size()];
@SuppressWarnings("unchecked")
V[] values = (V[]) new Object[_series.size()];
int i = 0;
for (Entry<Long, V> entry : _series.entrySet()) {
times[i] = entry.getKey();
values[i++] = entry.getValue();
}
return new ImmutableInstantObjectTimeSeries<V>(times, values);
}
//-------------------------------------------------------------------------
@Override
public String toString() {
return "Builder[size=" + _series.size() + "]";
}
}