/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.comparison;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.fudgemsg.FudgeField;
import org.fudgemsg.FudgeMsg;
import org.fudgemsg.mapping.FudgeSerializer;
import org.fudgemsg.wire.types.FudgeWireType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.opengamma.core.security.Security;
import com.opengamma.master.security.ManageableSecurityFudgeBuilder;
/* package */final class SecurityInfo extends AbstractInfo<Security> {
private static final Logger s_logger = LoggerFactory.getLogger(SecurityInfo.class);
private final Map<Object, Object> _info = new HashMap<Object, Object>();
public SecurityInfo(final ComparisonContext context, final Security security) {
super(security);
s_logger.debug("Extracting core information from {}", security);
final FudgeSerializer serializer = context.getFudgeSerializer();
serializer.reset();
final FudgeMsg rawMsg = serializer.objectToFudgeMsg(security);
s_logger.debug("Raw message = {}", rawMsg);
final Iterator<FudgeField> itr = rawMsg.iterator();
while (itr.hasNext()) {
final FudgeField field = itr.next();
if (ManageableSecurityFudgeBuilder.UNIQUE_ID_FIELD_NAME.equals(field.getName()) || ManageableSecurityFudgeBuilder.IDENTIFIERS_FIELD_NAME.equals(field.getName())) {
continue;
}
addFieldToMap(field, _info);
}
s_logger.debug("Info = {}", _info);
}
@SuppressWarnings({"unchecked", "rawtypes" })
private static void addValueToMap(final Object key, final Object value, final Map<Object, Object> info) {
final Object existing = info.get(key);
if (existing != null) {
if (existing instanceof List) {
((List) existing).add(value);
} else {
final List list = new ArrayList();
list.add(existing);
list.add(value);
}
} else {
info.put(key, value);
}
}
private static void addFieldValueToMap(final FudgeField field, final Object value, final Map<Object, Object> info) {
if (field.getName() != null) {
addValueToMap(field.getName(), value, info);
} else {
addValueToMap(field.getOrdinal(), value, info);
}
}
private static void addFieldToMap(final FudgeField field, final Map<Object, Object> info) {
final Object value;
switch (field.getType().getTypeId()) {
case FudgeWireType.BYTE_ARRAY_TYPE_ID:
case FudgeWireType.BYTE_ARRAY_4_TYPE_ID:
case FudgeWireType.BYTE_ARRAY_8_TYPE_ID:
case FudgeWireType.BYTE_ARRAY_16_TYPE_ID:
case FudgeWireType.BYTE_ARRAY_20_TYPE_ID:
case FudgeWireType.BYTE_ARRAY_32_TYPE_ID:
case FudgeWireType.BYTE_ARRAY_64_TYPE_ID:
case FudgeWireType.BYTE_ARRAY_128_TYPE_ID:
case FudgeWireType.BYTE_ARRAY_256_TYPE_ID:
case FudgeWireType.BYTE_ARRAY_512_TYPE_ID:
value = new ComparableByteArray((byte[]) field.getValue());
break;
case FudgeWireType.DOUBLE_ARRAY_TYPE_ID:
value = new ComparableDoubleArray((double[]) field.getValue());
break;
case FudgeWireType.FLOAT_ARRAY_TYPE_ID:
value = new ComparableFloatArray((float[]) field.getValue());
break;
case FudgeWireType.INT_ARRAY_TYPE_ID:
value = new ComparableIntArray((int[]) field.getValue());
break;
case FudgeWireType.LONG_ARRAY_TYPE_ID:
value = new ComparableLongArray((long[]) field.getValue());
break;
case FudgeWireType.SHORT_ARRAY_TYPE_ID:
value = new ComparableShortArray((short[]) field.getValue());
break;
case FudgeWireType.SUB_MESSAGE_TYPE_ID: {
final Map<Object, Object> subMsg = new HashMap<Object, Object>();
for (FudgeField subField : (FudgeMsg) field.getValue()) {
addFieldToMap(subField, subMsg);
}
value = subMsg;
break;
}
default:
value = field.getValue();
break;
}
addFieldValueToMap(field, value, info);
}
private abstract static class ComparableArray<T> {
private final T _data;
private final int _hashCode;
protected ComparableArray(final int hashCode, final T data) {
_hashCode = hashCode;
_data = data;
}
protected T getData() {
return _data;
}
@Override
public final int hashCode() {
return _hashCode;
}
protected abstract boolean equalsImpl(final ComparableArray<?> o);
@Override
public final boolean equals(final Object o) {
if (o == this) {
return true;
}
if (!(o instanceof ComparableArray<?>)) {
return false;
}
final ComparableArray<?> other = (ComparableArray<?>) o;
if (other.hashCode() != hashCode()) {
return false;
}
return equalsImpl(other);
}
protected abstract String toString(final T data);
@Override
public String toString() {
return toString(getData());
}
}
private static final class ComparableByteArray extends ComparableArray<byte[]> {
private ComparableByteArray(final byte[] data) {
super(Arrays.hashCode(data), data);
}
@Override
protected boolean equalsImpl(final ComparableArray<?> o) {
if (o instanceof ComparableByteArray) {
return Arrays.equals(((ComparableByteArray) o).getData(), getData());
} else {
return false;
}
}
@Override
protected String toString(final byte[] data) {
return Arrays.toString(data);
}
}
private static final class ComparableDoubleArray extends ComparableArray<double[]> {
private ComparableDoubleArray(final double[] data) {
super(Arrays.hashCode(data), data);
}
@Override
protected boolean equalsImpl(final ComparableArray<?> o) {
if (o instanceof ComparableDoubleArray) {
return Arrays.equals(((ComparableDoubleArray) o).getData(), getData());
} else {
return false;
}
}
@Override
protected String toString(final double[] data) {
return Arrays.toString(data);
}
}
private static final class ComparableFloatArray extends ComparableArray<float[]> {
private ComparableFloatArray(final float[] data) {
super(Arrays.hashCode(data), data);
}
@Override
protected boolean equalsImpl(final ComparableArray<?> o) {
if (o instanceof ComparableFloatArray) {
return Arrays.equals(((ComparableFloatArray) o).getData(), getData());
} else {
return false;
}
}
@Override
protected String toString(final float[] data) {
return Arrays.toString(data);
}
}
private static final class ComparableIntArray extends ComparableArray<int[]> {
private ComparableIntArray(final int[] data) {
super(Arrays.hashCode(data), data);
}
@Override
protected boolean equalsImpl(final ComparableArray<?> o) {
if (o instanceof ComparableIntArray) {
return Arrays.equals(((ComparableIntArray) o).getData(), getData());
} else {
return false;
}
}
@Override
protected String toString(final int[] data) {
return Arrays.toString(data);
}
}
private static final class ComparableLongArray extends ComparableArray<long[]> {
private ComparableLongArray(final long[] data) {
super(Arrays.hashCode(data), data);
}
@Override
protected boolean equalsImpl(final ComparableArray<?> o) {
if (o instanceof ComparableLongArray) {
return Arrays.equals(((ComparableLongArray) o).getData(), getData());
} else {
return false;
}
}
@Override
protected String toString(final long[] data) {
return Arrays.toString(data);
}
}
private static final class ComparableShortArray extends ComparableArray<short[]> {
private ComparableShortArray(final short[] data) {
super(Arrays.hashCode(data), data);
}
@Override
protected boolean equalsImpl(final ComparableArray<?> o) {
if (o instanceof ComparableShortArray) {
return Arrays.equals(((ComparableShortArray) o).getData(), getData());
} else {
return false;
}
}
@Override
protected String toString(final short[] data) {
return Arrays.toString(data);
}
}
public String getName() {
return getUnderlying().getName();
}
public String getSecurityType() {
return getUnderlying().getSecurityType();
}
private Map<Object, Object> getInfo() {
return _info;
}
@Override
public boolean equals(final Object o) {
if (o == this) {
return true;
}
if (!(o instanceof SecurityInfo)) {
return false;
}
final SecurityInfo other = (SecurityInfo) o;
// Info message contains all fields necessary for equality
return getInfo().equals(other.getInfo());
}
@Override
public int hashCode() {
return getInfo().hashCode();
}
}