/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.value.properties;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.fudgemsg.MutableFudgeMsg;
import org.fudgemsg.types.IndicatorType;
import org.fudgemsg.wire.types.FudgeWireType;
import com.google.common.collect.Sets;
import com.opengamma.engine.fudgemsg.ValuePropertiesFudgeBuilder;
import com.opengamma.engine.value.ValueProperties;
/**
* Internal state used to implement a {@link ValueProperties} entry which has a single value.
*/
public final class SingletonValueProperty extends AbstractValueProperty {
private static final long serialVersionUID = 1L;
private final String _value;
// construction
public SingletonValueProperty(final String key, final boolean optional, final String value, final AbstractValueProperty next) {
super(key, optional, next);
_value = value;
}
@Override
public AbstractValueProperty copy(final AbstractValueProperty next) {
return new SingletonValueProperty(getKey(), isOptional(), _value, next);
}
@Override
protected AbstractValueProperty withOptional(final boolean optional) {
if (optional == isOptional()) {
return this;
} else {
return new SingletonValueProperty(getKey(), optional, _value, getNext());
}
}
// query/update self
@Override
public Set<String> getValues() {
return Collections.singleton(_value);
}
/* package */String getValueImpl() {
return _value;
}
@Override
protected AbstractValueProperty addValueImpl(final String value) {
if (_value.equals(value)) {
return this;
} else {
return new ArrayValueProperty(getKey(), isOptional(), new String[] {_value, value }, getNext());
}
}
@Override
protected AbstractValueProperty addValuesImpl(final String[] values) {
for (String value : values) {
if (_value.equals(value)) {
if (values.length > ArrayValueProperty.MAX_ARRAY_LENGTH) {
return new SetValueProperty(getKey(), isOptional(), Sets.newHashSet(values), getNext());
} else {
return new ArrayValueProperty(getKey(), isOptional(), Arrays.copyOf(values, values.length), getNext());
}
}
}
if (values.length > ArrayValueProperty.MAX_ARRAY_LENGTH - 1) {
final Set<String> copy = Sets.newHashSet(values);
copy.add(_value);
return new SetValueProperty(getKey(), isOptional(), copy, getNext());
} else {
final String[] copy = Arrays.copyOf(values, values.length + 1);
copy[values.length] = _value;
return new ArrayValueProperty(getKey(), isOptional(), copy, getNext());
}
}
@Override
protected AbstractValueProperty addValuesImpl(final Collection<String> values) {
final int size = values.size();
if (values.contains(_value)) {
if (size == 1) {
return this;
} else if (size <= ArrayValueProperty.MAX_ARRAY_LENGTH) {
return new ArrayValueProperty(getKey(), isOptional(), values.toArray(new String[size]), getNext());
} else {
return new SetValueProperty(getKey(), isOptional(), new HashSet<String>(values), getNext());
}
}
if (size > ArrayValueProperty.MAX_ARRAY_LENGTH - 1) {
final Set<String> copy = new HashSet<String>(values);
copy.add(_value);
return new SetValueProperty(getKey(), isOptional(), copy, getNext());
} else {
final String[] copy = values.toArray(new String[size + 1]);
copy[size] = _value;
return new ArrayValueProperty(getKey(), isOptional(), copy, getNext());
}
}
@Override
protected AbstractValueProperty addValuesToImpl(final AbstractValueProperty addTo) {
return addTo.addValueImpl(_value);
}
@Override
protected boolean containsValue(final String value) {
return _value.equals(value);
}
@Override
protected boolean containsAllValues(final String[] values) {
return false;
}
@Override
protected boolean containsAllValues(final Collection<String> values) {
return false;
}
@Override
protected boolean valuesContainedBy(final AbstractValueProperty other) {
return other.containsValue(_value);
}
@Override
public boolean isWildcard() {
return false;
}
@Override
public String getStrict() {
return _value;
}
@Override
public String getSingle() {
return _value;
}
@Override
protected AbstractValueProperty setWildcardImpl() {
return new WildcardValueProperty(getKey(), isOptional(), getNext());
}
@Override
protected boolean isSatisfiedBy(final String value) {
return _value.equals(value);
}
@Override
public boolean isSatisfyValue(final AbstractValueProperty property) {
return property.isSatisfiedBy(_value);
}
@Override
protected AbstractValueProperty intersectSingletonValue(final SingletonValueProperty other) {
if (_value.equals(other.getValueImpl())) {
return withOptional(other.isOptional());
} else {
return null;
}
}
@Override
protected AbstractValueProperty intersectArrayValue(final ArrayValueProperty other) {
for (String value : other.getValuesImpl()) {
if (_value.equals(value)) {
return withOptional(other.isOptional());
}
}
return null;
}
@Override
protected AbstractValueProperty intersectSetValue(final SetValueProperty other) {
if (other.getValuesImpl().contains(_value)) {
return withOptional(other.isOptional());
}
return null;
}
@Override
public AbstractValueProperty intersectValues(final AbstractValueProperty other) {
return other.intersectSingletonValue(this);
}
@Override
public void toFudgeMsg(final MutableFudgeMsg msg) {
if (isOptional()) {
final MutableFudgeMsg subMsg = msg.addSubMessage(getKey(), null);
subMsg.add(ValuePropertiesFudgeBuilder.OPTIONAL_FIELD, null, FudgeWireType.INDICATOR, IndicatorType.INSTANCE);
subMsg.add(null, 0, FudgeWireType.STRING, _value);
} else {
msg.add(getKey(), null, FudgeWireType.STRING, _value);
}
}
// Object
@Override
protected int valueHashCode() {
// Hash code of a singleton set
return _value.hashCode();
}
@Override
protected boolean equalsSingleton(final String value) {
return _value.equals(value);
}
@Override
protected boolean equalsArray(final String[] values) {
return false;
}
@Override
protected boolean equalsSet(final Set<String> values) {
return false;
}
@Override
protected boolean equalsValue(final AbstractValueProperty other) {
return other.equalsSingleton(_value);
}
}