/** * 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.Arrays; import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; import org.threeten.bp.Instant; import com.opengamma.timeseries.precise.PreciseDoubleTimeSeries; /** * Builder implementation for {@code ImmutableInstantDoubleTimeSeries}. */ final class ImmutableInstantDoubleTimeSeriesBuilder implements InstantDoubleTimeSeriesBuilder { /** * The current size. */ private int _size; /** * The times. */ private long[] _times = new long[128]; /** * The values. */ private double[] _values = new double[128]; /** * Creates an instance. */ ImmutableInstantDoubleTimeSeriesBuilder() { } //------------------------------------------------------------------------- private void ensureCapacity(int newSize) { if (newSize > _times.length) { newSize = Math.max(newSize + 8, (_size * 3) / 2); _times = Arrays.copyOf(_times, newSize); _values = Arrays.copyOf(_values, _size * 2); } } 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 _size; } @Override public InstantDoubleEntryIterator iterator() { return new InstantDoubleEntryIterator() { private int _index = -1; @Override public boolean hasNext() { return (_index + 1) < size(); } @Override public Entry<Instant, Double> next() { if (hasNext() == false) { throw new NoSuchElementException("No more elements in the iteration"); } _index++; long instant = _times[_index]; double value = _values[_index]; return makeMapEntry(convertFromLong(instant), value); } private Entry<Instant, Double> makeMapEntry(Instant key, Double value) { return new SimpleImmutableEntry<>(key, value); } @Override public long nextTimeFast() { if (hasNext() == false) { throw new NoSuchElementException("No more elements in the iteration"); } _index++; return _times[_index]; } @Override public Instant nextTime() { return convertFromLong(nextTimeFast()); } @Override public long currentTimeFast() { if (_index < 0) { throw new IllegalStateException("Iterator has not yet been started"); } return _times[_index]; } @Override public Instant currentTime() { return convertFromLong(currentTimeFast()); } @Override public Double currentValue() { if (_index < 0) { throw new IllegalStateException("Iterator has not yet been started"); } return _values[_index]; } @Override public double currentValueFast() { if (_index < 0) { throw new IllegalStateException("Iterator has not yet been started"); } return _values[_index]; } @Override public int currentIndex() { return _index; } @Override public void remove() { if (_index < 0) { throw new IllegalStateException("Iterator has not yet been started"); } if (_index < _size) { System.arraycopy(_times, _index + 1, _times, _index, _size - _index); System.arraycopy(_values, _index + 1, _values, _index, _size - _index); } _size--; _index--; } }; } //------------------------------------------------------------------------- @Override public InstantDoubleTimeSeriesBuilder put(Instant time, double value) { return put(convertToLong(time), value); } @Override public InstantDoubleTimeSeriesBuilder put(long time, double value) { int search = Arrays.binarySearch(_times, 0, _size, time); if (search >= 0) { _values[search] = value; } else { ensureCapacity(_size + 1); int pos = -(search + 1); System.arraycopy(_times, pos, _times, pos + 1, _size - pos); System.arraycopy(_values, pos, _values, pos + 1, _size - pos); _times[pos] = time; _values[pos] = value; _size++; } return this; } @Override public InstantDoubleTimeSeriesBuilder putAll(Instant[] times, double[] values) { if (times.length != values.length) { throw new IllegalArgumentException("Arrays are of different sizes: " + times.length + ", " + values.length); } ensureCapacity(_size + times.length); for (int i = 0; i < times.length; i++) { put(times[i], values[i]); } return this; } @Override public InstantDoubleTimeSeriesBuilder putAll(long[] times, double[] values) { if (times.length != values.length) { throw new IllegalArgumentException("Arrays are of different sizes: " + times.length + ", " + values.length); } ensureCapacity(_size + times.length); for (int i = 0; i < times.length; i++) { put(times[i], values[i]); } return this; } //------------------------------------------------------------------------- @Override public InstantDoubleTimeSeriesBuilder putAll(PreciseDoubleTimeSeries<?> timeSeries) { return putAll(timeSeries, 0, timeSeries.size()); } @Override public InstantDoubleTimeSeriesBuilder putAll(PreciseDoubleTimeSeries<?> 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; } int sizeToAdd = endPos - startPos; ensureCapacity(_size + sizeToAdd); if (_size == 0) { System.arraycopy(timeSeries.timesArrayFast(), startPos, _times, 0, sizeToAdd); System.arraycopy(timeSeries.valuesArrayFast(), startPos, _values, 0, sizeToAdd); _size = sizeToAdd; } else { for (int i = startPos; i < endPos; i++) { put(timeSeries.getTimeAtIndexFast(i), timeSeries.getValueAtIndexFast(i)); } } return this; } @Override public InstantDoubleTimeSeriesBuilder putAll(Map<Instant, Double> timeSeriesMap) { if (timeSeriesMap.size() == 0) { return this; } ensureCapacity(_size + timeSeriesMap.size()); for (Entry<Instant, Double> entry : timeSeriesMap.entrySet()) { put(entry.getKey(), entry.getValue()); } return this; } //------------------------------------------------------------------------- @Override public InstantDoubleTimeSeriesBuilder clear() { _size = 0; return this; } //------------------------------------------------------------------------- @Override public ImmutableInstantDoubleTimeSeries build() { if (_size == 0) { return ImmutableInstantDoubleTimeSeries.EMPTY_SERIES; } return new ImmutableInstantDoubleTimeSeries(Arrays.copyOf(_times, _size), Arrays.copyOf(_values, _size)); } //------------------------------------------------------------------------- @Override public String toString() { return "Builder[size=" + _size + "]"; } }