/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.timeseries.date.localdate; 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.LocalDate; import com.opengamma.timeseries.date.DateDoubleTimeSeries; /** * Builder implementation for {@code ImmutableLocalDateDoubleTimeSeries}. */ final class ImmutableLocalDateDoubleTimeSeriesBuilder implements LocalDateDoubleTimeSeriesBuilder { /** * The current size. */ private int _size; /** * The times. */ private int[] _times = new int[128]; /** * The values. */ private double[] _values = new double[128]; /** * Creates an instance. */ ImmutableLocalDateDoubleTimeSeriesBuilder() { } //------------------------------------------------------------------------- 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, newSize); } } private static int convertToInt(LocalDate date) { return LocalDateToIntConverter.convertToInt(date); } private static LocalDate convertFromInt(int date) { return LocalDateToIntConverter.convertToLocalDate(date); } //------------------------------------------------------------------------- @Override public int size() { return _size; } @Override public LocalDateDoubleEntryIterator iterator() { return new LocalDateDoubleEntryIterator() { private int _index = -1; @Override public boolean hasNext() { return (_index + 1) < size(); } @Override public Entry<LocalDate, Double> next() { if (hasNext() == false) { throw new NoSuchElementException("No more elements in the iteration"); } _index++; int date = _times[_index]; double value = _values[_index]; return makeMapEntry(convertFromInt(date), value); } private Entry<LocalDate, Double> makeMapEntry(LocalDate key, Double value) { return new SimpleImmutableEntry<>(key, value); } @Override public int nextTimeFast() { if (hasNext() == false) { throw new NoSuchElementException("No more elements in the iteration"); } _index++; return _times[_index]; } @Override public LocalDate nextTime() { return convertFromInt(nextTimeFast()); } @Override public int currentTimeFast() { if (_index < 0) { throw new IllegalStateException("Iterator has not yet been started"); } return _times[_index]; } @Override public LocalDate currentTime() { return convertFromInt(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 LocalDateDoubleTimeSeriesBuilder put(LocalDate time, double value) { return put(convertToInt(time), value); } @Override public LocalDateDoubleTimeSeriesBuilder put(int 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 LocalDateDoubleTimeSeriesBuilder putAll(LocalDate[] 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 LocalDateDoubleTimeSeriesBuilder putAll(int[] 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 LocalDateDoubleTimeSeriesBuilder putAll(DateDoubleTimeSeries<?> timeSeries) { return putAll(timeSeries, 0, timeSeries.size()); } @Override public LocalDateDoubleTimeSeriesBuilder putAll(DateDoubleTimeSeries<?> 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 LocalDateDoubleTimeSeriesBuilder putAll(Map<LocalDate, Double> timeSeriesMap) { if (timeSeriesMap.size() == 0) { return this; } ensureCapacity(_size + timeSeriesMap.size()); for (Entry<LocalDate, Double> entry : timeSeriesMap.entrySet()) { put(entry.getKey(), entry.getValue()); } return this; } //------------------------------------------------------------------------- @Override public LocalDateDoubleTimeSeriesBuilder clear() { _size = 0; return this; } //------------------------------------------------------------------------- @Override public ImmutableLocalDateDoubleTimeSeries build() { if (_size == 0) { return ImmutableLocalDateDoubleTimeSeries.EMPTY_SERIES; } return new ImmutableLocalDateDoubleTimeSeries(Arrays.copyOf(_times, _size), Arrays.copyOf(_values, _size)); } //------------------------------------------------------------------------- @Override public String toString() { return "Builder[size=" + _size + "]"; } }