/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.math.curve; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.ArrayUtils; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.BeanDefinition; import org.joda.beans.JodaBeanUtils; import org.joda.beans.MetaProperty; import org.joda.beans.Property; import org.joda.beans.PropertyDefinition; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.ParallelArrayBinarySort; import com.opengamma.util.tuple.Pair; /** * Parent class for a family of curves that can have any time of data on the <i>x</i> and <i>y</i> axes, provided that the <i>x</i> data is {@link Comparable}. * It is possible to construct a curve using either unsorted (in <i>x</i>) data or sorted (ascending in <i>x</i>). Note that if the constructor * is told that unsorted data are sorted then no sorting will take place, which will give unpredictable results. * @param <T> The type of the x data * @param <U> The type of the y data */ @BeanDefinition public abstract class ObjectsCurve<T extends Comparable<T>, U> extends Curve<T, U> { @PropertyDefinition(get = "private", set = "private") private int _n; @PropertyDefinition(validate = "notNull", get = "manual", set = "private") private T[] _xData; @PropertyDefinition(validate = "notNull", get = "manual", set = "private") private U[] _yData; /** * Constructor for Joda-Beans. */ protected ObjectsCurve() { } /** * Creates an instance. * * @param xData the array of <i>x</i> data, not null * @param yData the array of <i>y</i> data, contains same number of entries as <i>x</i>, not null * @param isSorted whether the <i>x</i>-data is sorted ascending */ public ObjectsCurve(final T[] xData, final U[] yData, final boolean isSorted) { super(); ArgumentChecker.notNull(xData, "x data"); ArgumentChecker.notNull(yData, "y data"); _n = xData.length; ArgumentChecker.isTrue(_n == yData.length, "size of x data {} does not match size of y data {}", _n, yData.length); _xData = Arrays.copyOf(xData, _n); _yData = Arrays.copyOf(yData, _n); for (int i = 0; i < _n; i++) { ArgumentChecker.notNull(xData[i], "element " + i + " of x data"); ArgumentChecker.notNull(yData[i], "element " + i + " of y data"); } if (!isSorted) { ParallelArrayBinarySort.parallelBinarySort(_xData, _yData); } } /** * Creates an instance. * * @param data the map of <i>x-y</i> data, not null * @param isSorted whether the <i>x</i>-data is sorted ascending */ @SuppressWarnings("unchecked") public ObjectsCurve(final Map<T, U> data, final boolean isSorted) { super(); ArgumentChecker.noNulls(data.keySet(), "x values"); ArgumentChecker.noNulls(data.values(), "y values"); _n = data.size(); final Map.Entry<T, U> firstEntry = data.entrySet().iterator().next(); _xData = data.keySet().toArray((T[]) Array.newInstance(firstEntry.getKey().getClass(), 0)); _yData = data.values().toArray((U[]) Array.newInstance(firstEntry.getValue().getClass(), 0)); if (!isSorted) { ParallelArrayBinarySort.parallelBinarySort(_xData, _yData); } } /** * Creates an instance. * * @param data the set of <i>x-y</i> pairs, not null * @param isSorted whether the <i>x</i>-data is sorted ascending */ @SuppressWarnings("unchecked") public ObjectsCurve(final Set<Pair<T, U>> data, final boolean isSorted) { super(); ArgumentChecker.notNull(data, "data"); _n = data.size(); final List<T> xTemp = new ArrayList<>(_n); final List<U> yTemp = new ArrayList<>(_n); for (final Pair<T, U> entry : data) { ArgumentChecker.notNull(entry, "element of data"); xTemp.add(entry.getFirst()); yTemp.add(entry.getSecond()); } final Pair<T, U> firstEntry = data.iterator().next(); _xData = xTemp.toArray((T[]) Array.newInstance(firstEntry.getFirst().getClass(), 0)); _yData = yTemp.toArray((U[]) Array.newInstance(firstEntry.getSecond().getClass(), 0)); if (!isSorted) { ParallelArrayBinarySort.parallelBinarySort(_xData, _yData); } } /** * Creates an instance. * * @param xData the list of <i>x</i> data, not null * @param yData the list of <i>y</i> data, contains same number of entries as <i>x</i>, not null * @param isSorted whether the <i>x</i>-data is sorted ascending */ @SuppressWarnings("unchecked") public ObjectsCurve(final List<T> xData, final List<U> yData, final boolean isSorted) { super(); ArgumentChecker.notNull(xData, "x data"); ArgumentChecker.notNull(yData, "y data"); _n = xData.size(); ArgumentChecker.isTrue(_n == yData.size(), "size of x data {} does not match size of y data {}", _n, yData.size()); _xData = xData.toArray((T[]) Array.newInstance(xData.get(0).getClass(), 0)); _yData = yData.toArray((U[]) Array.newInstance(yData.get(0).getClass(), 0)); if (!isSorted) { ParallelArrayBinarySort.parallelBinarySort(_xData, _yData); } } //------------------------------------------------------------------------- /** * Creates an instance. * * @param xData the array of <i>x</i> data, not null * @param yData the array of <i>y</i> data, not null, contains same number of entries as <i>x</i> * @param isSorted whether the <i>x</i>-data is sorted ascending * @param name the name of the curve, not null */ public ObjectsCurve(final T[] xData, final U[] yData, final boolean isSorted, final String name) { super(name); ArgumentChecker.notNull(xData, "x data"); _n = xData.length; ArgumentChecker.notNull(yData, "y data"); ArgumentChecker.isTrue(_n == yData.length, "size of x data {} does not match size of y data {}", _n, yData.length); _xData = Arrays.copyOf(xData, _n); _yData = Arrays.copyOf(yData, _n); if (!isSorted) { ParallelArrayBinarySort.parallelBinarySort(_xData, _yData); } } /** * Creates an instance. * * @param data the map of <i>x-y</i> data, not null * @param isSorted whether the <i>x</i>-data is sorted ascending * @param name the name of the curve, not null */ @SuppressWarnings("unchecked") public ObjectsCurve(final Map<T, U> data, final boolean isSorted, final String name) { super(name); ArgumentChecker.noNulls(data.keySet(), "x values"); ArgumentChecker.noNulls(data.values(), "y values"); _n = data.size(); final Map.Entry<T, U> firstEntry = data.entrySet().iterator().next(); _xData = data.keySet().toArray((T[]) Array.newInstance(firstEntry.getKey().getClass(), 0)); _yData = data.values().toArray((U[]) Array.newInstance(firstEntry.getValue().getClass(), 0)); if (!isSorted) { ParallelArrayBinarySort.parallelBinarySort(_xData, _yData); } } /** * Creates an instance. * * @param data the set of <i>x-y</i> pairs, not null * @param isSorted whether the <i>x</i>-data is sorted ascending * @param name the name of the curve, not null */ @SuppressWarnings("unchecked") public ObjectsCurve(final Set<Pair<T, U>> data, final boolean isSorted, final String name) { super(name); ArgumentChecker.notNull(data, "data"); _n = data.size(); final List<T> xTemp = new ArrayList<>(_n); final List<U> yTemp = new ArrayList<>(_n); final int i = 0; for (final Pair<T, U> entry : data) { ArgumentChecker.notNull(entry, "element " + i + " of data"); xTemp.add(entry.getFirst()); yTemp.add(entry.getSecond()); } final Pair<T, U> firstEntry = data.iterator().next(); _xData = xTemp.toArray((T[]) Array.newInstance(firstEntry.getFirst().getClass(), 0)); _yData = yTemp.toArray((U[]) Array.newInstance(firstEntry.getSecond().getClass(), 0)); if (!isSorted) { ParallelArrayBinarySort.parallelBinarySort(_xData, _yData); } } /** * Creates an instance. * * @param xData the list of <i>x</i> data, not null * @param yData the list of <i>y</i> data, not null, contains same number of entries as <i>x</i> * @param isSorted whether the <i>x</i>-data is sorted ascending * @param name the name of the curve, not null */ @SuppressWarnings("unchecked") public ObjectsCurve(final List<T> xData, final List<U> yData, final boolean isSorted, final String name) { super(name); ArgumentChecker.notNull(xData, "x data"); ArgumentChecker.notNull(yData, "y data"); _n = xData.size(); ArgumentChecker.isTrue(_n == yData.size(), "size of x data {} does not match size of y data {}", _n, yData.size()); _xData = xData.toArray((T[]) Array.newInstance(xData.get(0).getClass(), 0)); _yData = yData.toArray((U[]) Array.newInstance(yData.get(0).getClass(), 0)); if (!isSorted) { ParallelArrayBinarySort.parallelBinarySort(_xData, _yData); } } //------------------------------------------------------------------------- @Override public T[] getXData() { return _xData; } @Override public U[] getYData() { return _yData; } @Override public int size() { return _n; } //------------------------------------------------------------------------- @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (getClass() != obj.getClass()) { return false; } final ObjectsCurve<?, ?> other = (ObjectsCurve<?, ?>) obj; return ArrayUtils.isEquals(_xData, other._xData) && ArrayUtils.isEquals(_yData, other._yData); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + Arrays.hashCode(_xData); result = prime * result + Arrays.hashCode(_yData); return result; } //------------------------- AUTOGENERATED START ------------------------- ///CLOVER:OFF /** * The meta-bean for {@code ObjectsCurve}. * @return the meta-bean, not null */ @SuppressWarnings("rawtypes") public static ObjectsCurve.Meta meta() { return ObjectsCurve.Meta.INSTANCE; } /** * The meta-bean for {@code ObjectsCurve}. * @param <R> the first generic type * @param <S> the second generic type * @param cls1 the first generic type * @param cls2 the second generic type * @return the meta-bean, not null */ @SuppressWarnings("unchecked") public static <R extends Comparable<R>, S> ObjectsCurve.Meta<R, S> metaObjectsCurve(Class<R> cls1, Class<S> cls2) { return ObjectsCurve.Meta.INSTANCE; } static { JodaBeanUtils.registerMetaBean(ObjectsCurve.Meta.INSTANCE); } @SuppressWarnings("unchecked") @Override public ObjectsCurve.Meta<T, U> metaBean() { return ObjectsCurve.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Gets the n. * @return the value of the property */ private int getN() { return _n; } /** * Sets the n. * @param n the new value of the property */ private void setN(int n) { this._n = n; } /** * Gets the the {@code n} property. * @return the property, not null */ public final Property<Integer> n() { return metaBean().n().createProperty(this); } //----------------------------------------------------------------------- /** * Sets the xData. * @param xData the new value of the property, not null */ private void setXData(T[] xData) { JodaBeanUtils.notNull(xData, "xData"); this._xData = xData; } /** * Gets the the {@code xData} property. * @return the property, not null */ public final Property<T[]> xData() { return metaBean().xData().createProperty(this); } //----------------------------------------------------------------------- /** * Sets the yData. * @param yData the new value of the property, not null */ private void setYData(U[] yData) { JodaBeanUtils.notNull(yData, "yData"); this._yData = yData; } /** * Gets the the {@code yData} property. * @return the property, not null */ public final Property<U[]> yData() { return metaBean().yData().createProperty(this); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("ObjectsCurve{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("n").append('=').append(JodaBeanUtils.toString(getN())).append(',').append(' '); buf.append("xData").append('=').append(JodaBeanUtils.toString(getXData())).append(',').append(' '); buf.append("yData").append('=').append(JodaBeanUtils.toString(getYData())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code ObjectsCurve}. * @param <T> the type * @param <U> the type */ public static class Meta<T extends Comparable<T>, U> extends Curve.Meta<T, U> { /** * The singleton instance of the meta-bean. */ @SuppressWarnings("rawtypes") static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code n} property. */ private final MetaProperty<Integer> _n = DirectMetaProperty.ofReadWrite( this, "n", ObjectsCurve.class, Integer.TYPE); /** * The meta-property for the {@code xData} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty<T[]> _xData = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "xData", ObjectsCurve.class, Object[].class); /** * The meta-property for the {@code yData} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty<U[]> _yData = (DirectMetaProperty) DirectMetaProperty.ofReadWrite( this, "yData", ObjectsCurve.class, Object[].class); /** * The meta-properties. */ private final Map<String, MetaProperty<?>> _metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "n", "xData", "yData"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty<?> metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 110: // n return _n; case 112945218: // xData return _xData; case 113868739: // yData return _yData; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder<? extends ObjectsCurve<T, U>> builder() { throw new UnsupportedOperationException("ObjectsCurve is an abstract class"); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override public Class<? extends ObjectsCurve<T, U>> beanType() { return (Class) ObjectsCurve.class; } @Override public Map<String, MetaProperty<?>> metaPropertyMap() { return _metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code n} property. * @return the meta-property, not null */ public final MetaProperty<Integer> n() { return _n; } /** * The meta-property for the {@code xData} property. * @return the meta-property, not null */ public final MetaProperty<T[]> xData() { return _xData; } /** * The meta-property for the {@code yData} property. * @return the meta-property, not null */ public final MetaProperty<U[]> yData() { return _yData; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 110: // n return ((ObjectsCurve<?, ?>) bean).getN(); case 112945218: // xData return ((ObjectsCurve<?, ?>) bean).getXData(); case 113868739: // yData return ((ObjectsCurve<?, ?>) bean).getYData(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 110: // n ((ObjectsCurve<T, U>) bean).setN((Integer) newValue); return; case 112945218: // xData ((ObjectsCurve<T, U>) bean).setXData((T[]) newValue); return; case 113868739: // yData ((ObjectsCurve<T, U>) bean).setYData((U[]) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((ObjectsCurve<?, ?>) bean)._xData, "xData"); JodaBeanUtils.notNull(((ObjectsCurve<?, ?>) bean)._yData, "yData"); super.validate(bean); } } ///CLOVER:ON //-------------------------- AUTOGENERATED END -------------------------- }