diff --git a/quickfixj-core/src/main/java/quickfix/FieldMap.java b/quickfixj-core/src/main/java/quickfix/FieldMap.java index 2e9202f3fa..2e53e17440 100644 --- a/quickfixj-core/src/main/java/quickfix/FieldMap.java +++ b/quickfixj-core/src/main/java/quickfix/FieldMap.java @@ -207,69 +207,102 @@ Field getField(int field, Field defaultValue) { return f; } + private Field getField(int field, boolean notFoundException) throws FieldNotFound { + final Field f = fields.get(field); + if (f == null && notFoundException) { + throw new FieldNotFound(field); + } + return f; + } + + public String getString(int field) throws FieldNotFound { return getField(field).getObject(); } public boolean getBoolean(int field) throws FieldNotFound { + Field f = getField(field, true); + if(f instanceof BooleanField) + return ((BooleanField)f).getValue(); try { - return BooleanConverter.convert(getString(field)); + return BooleanConverter.convert(f.objectAsString()); } catch (final FieldConvertError e) { throw newIncorrectDataException(e, field); } } public char getChar(int field) throws FieldNotFound { + Field f = getField(field, true); + if(f instanceof CharField) + return ((CharField)f).getValue(); try { - return CharConverter.convert(getString(field)); + return CharConverter.convert(f.objectAsString()); } catch (final FieldConvertError e) { throw newIncorrectDataException(e, field); } } public int getInt(int field) throws FieldNotFound { + Field f = getField(field, true); + if(f instanceof IntField) + return ((IntField)f).getValue(); try { - return IntConverter.convert(getString(field)); + return IntConverter.convert(f.objectAsString()); } catch (final FieldConvertError e) { throw newIncorrectDataException(e, field); } } public double getDouble(int field) throws FieldNotFound { + Field f = getField(field, true); + if(f instanceof DoubleField) + return ((DoubleField)f).getValue(); try { - return DoubleConverter.convert(getString(field)); + return DoubleConverter.convert(f.objectAsString()); } catch (final FieldConvertError e) { throw newIncorrectDataException(e, field); } } public BigDecimal getDecimal(int field) throws FieldNotFound { + Field f = getField(field, true); + if(f instanceof DecimalField) + return ((DecimalField)f).getValue(); try { - return DecimalConverter.convert(getString(field)); + return DecimalConverter.convert(f.objectAsString()); } catch (final FieldConvertError e) { throw newIncorrectDataException(e, field); } } public Date getUtcTimeStamp(int field) throws FieldNotFound { + Field f = getField(field, true); + if(f instanceof UtcTimeStampField) + return ((UtcTimeStampField)f).getValue(); try { - return UtcTimestampConverter.convert(getString(field)); + return UtcTimestampConverter.convert(f.objectAsString()); } catch (final FieldConvertError e) { throw newIncorrectDataException(e, field); } } public Date getUtcTimeOnly(int field) throws FieldNotFound { + Field f = getField(field, true); + if(f instanceof UtcTimeOnlyField) + return ((UtcTimeOnlyField)f).getValue(); try { - return UtcTimeOnlyConverter.convert(getString(field)); + return UtcTimeOnlyConverter.convert(f.objectAsString()); } catch (final FieldConvertError e) { throw newIncorrectDataException(e, field); } } public Date getUtcDateOnly(int field) throws FieldNotFound { + Field f = getField(field, true); + if(f instanceof UtcDateOnlyField) + return ((UtcDateOnlyField)f).getValue(); try { - return UtcDateOnlyConverter.convert(getString(field)); + return UtcDateOnlyConverter.convert(f.objectAsString()); } catch (final FieldConvertError e) { throw newIncorrectDataException(e, field); } @@ -279,43 +312,47 @@ public void setField(int key, Field field) { fields.put(key, field); } - public void setField(StringField field) { - if (field.getValue() == null) { + private void setField(Field field) { + if (field.getObject() == null) { throw new NullPointerException("Null field values are not allowed."); } fields.put(field.getField(), field); } + public void setField(StringField field) { + setField((Field)field); + } + public void setField(BooleanField field) { - setBoolean(field.getField(), field.getValue()); + setField((Field) field); } public void setField(CharField field) { - setChar(field.getField(), field.getValue()); + setField((Field) field); } public void setField(IntField field) { - setInt(field.getField(), field.getValue()); + setField((Field)field); } public void setField(DoubleField field) { - setDouble(field.getField(), field.getValue()); + fields.put(field.getField(), field); } public void setField(DecimalField field) { - setDecimal(field.getField(), field.getValue()); + setField((Field) field); } public void setField(UtcTimeStampField field) { - setUtcTimeStamp(field.getField(), field.getValue(), field.showMilliseconds()); + setField((Field) field); } public void setField(UtcTimeOnlyField field) { - setUtcTimeOnly(field.getField(), field.getValue(), field.showMilliseconds()); + setField((Field) field); } public void setField(UtcDateOnlyField field) { - setUtcDateOnly(field.getField(), field.getValue()); + setField((Field)field); } public void setField(BytesField field) { @@ -344,35 +381,100 @@ public StringField getField(StringField field) throws FieldNotFound { } public BooleanField getField(BooleanField field) throws FieldNotFound { - return updateValue(field, getBoolean(field.getField())); + Field f = getField(field.getField(), true); + if(f instanceof BooleanField) + field.setObject(((BooleanField)f).getObject()); + else try { + field.setObject(BooleanConverter.convert(f.objectAsString())); + } catch (final FieldConvertError e) { + throw newIncorrectDataException(e, field.getField()); + } + return field; } + public CharField getField(CharField field) throws FieldNotFound { - return updateValue(field, getChar(field.getField())); + Field f = getField(field.getField(), true); + if(f instanceof CharField) + field.setObject(((CharField) f).getObject()); + else try { + field.setObject(CharConverter.convert(f.objectAsString())); + } catch (final FieldConvertError e) { + throw newIncorrectDataException(e, field.getField()); + } + return field; } public IntField getField(IntField field) throws FieldNotFound { - return updateValue(field, getInt(field.getField())); + Field f = getField(field.getField(), true); + if(f instanceof IntField) + field.setObject(((IntField)f).getObject()); + else try { + field.setObject(IntConverter.convert(f.objectAsString())); + } catch (final FieldConvertError e) { + throw newIncorrectDataException(e, field.getField()); + } + return field; } public DoubleField getField(DoubleField field) throws FieldNotFound { - return updateValue(field, getDouble(field.getField())); + Field f = getField(field.getField(), true); + if(f instanceof DoubleField) + field.setObject(((DoubleField)f).getObject()); + else try { + field.setObject(DoubleConverter.convert(f.objectAsString())); + } catch (final FieldConvertError e) { + throw newIncorrectDataException(e, field.getField()); + } + return field; } public DecimalField getField(DecimalField field) throws FieldNotFound { - return updateValue(field, getDecimal(field.getField())); + Field f = getField(field.getField(), true); + if(f instanceof DecimalField) + field.setObject(((DecimalField)f).getObject()); + else try { + field.setObject(DecimalConverter.convert(f.objectAsString())); + } catch (final FieldConvertError e) { + throw newIncorrectDataException(e, field.getField()); + } + return field; } public UtcTimeStampField getField(UtcTimeStampField field) throws FieldNotFound { - return updateValue(field, getUtcTimeStamp(field.getField())); + Field f = getField(field.getField(), true); + if(f instanceof UtcTimeStampField) + field.setObject(((UtcTimeStampField)f).getObject()); + else try { + field.setObject(UtcTimestampConverter.convert(f.objectAsString())); + } catch (final FieldConvertError e) { + throw newIncorrectDataException(e, field.getField()); + } + return field; } public UtcTimeOnlyField getField(UtcTimeOnlyField field) throws FieldNotFound { - return updateValue(field, getUtcTimeOnly(field.getField())); + Field f = getField(field.getField(), true); + if(f instanceof UtcTimeOnlyField) + field.setObject(((UtcTimeOnlyField)f).getObject()); + else try { + field.setObject(UtcTimeOnlyConverter.convert(f.objectAsString())); + } catch (final FieldConvertError e) { + throw newIncorrectDataException(e, field.getField()); + } + return field; } public UtcDateOnlyField getField(UtcDateOnlyField field) throws FieldNotFound { - return updateValue(field, getUtcDateOnly(field.getField())); + Field f = getField(field.getField(), true); + if(f instanceof UtcDateOnlyField) + field.setObject(((UtcDateOnlyField)f).getObject()); + else try { + field.setObject(UtcDateOnlyConverter.convert(f.objectAsString())); + } catch (final FieldConvertError e) { + throw newIncorrectDataException(e, field.getField()); + } + return field; } private FieldException newIncorrectDataException(FieldConvertError e, int tag) { @@ -543,14 +645,10 @@ public void addGroupRef(Group group) { protected void setGroupCount(int countTag, int groupSize) { try { - StringField count; - if (groupSize == 1) { - count = new StringField(countTag, "1"); - setField(countTag, count); - } else { - count = getField(countTag); - } - count.setValue(Integer.toString(groupSize)); + if (groupSize == 1) + setField(countTag, new StringField(countTag, "1")); + else + getField(countTag).setValue(NumbersCache.get(groupSize)); } catch (final FieldNotFound e) { // Shouldn't happen throw new RuntimeError(e); diff --git a/quickfixj-core/src/main/java/quickfix/MessageComponent.java b/quickfixj-core/src/main/java/quickfix/MessageComponent.java index f172764dae..44f4dc34b7 100644 --- a/quickfixj-core/src/main/java/quickfix/MessageComponent.java +++ b/quickfixj-core/src/main/java/quickfix/MessageComponent.java @@ -18,38 +18,30 @@ protected MessageComponent(int[] fieldOrder) { } public void copyFrom(FieldMap fields) { - try { - for (int componentField : getFields()) { - if (fields.isSetField(componentField)) { - setField(componentField, fields.getField(componentField)); - } + for (int componentField : getFields()) { + if (fields.isSetField(componentField)) { + setField(componentField, fields.getField(componentField, null)); } - for (int groupField : getGroupFields()) { - if (fields.isSetField(groupField)) { - setField(groupField, fields.getField(groupField)); - setGroups(groupField, fields.getGroups(groupField)); - } + } + for (int groupField : getGroupFields()) { + if (fields.isSetField(groupField)) { + setField(groupField, fields.getField(groupField, null)); + setGroups(groupField, fields.getGroups(groupField)); } - } catch (FieldNotFound e) { - // should not happen } } public void copyTo(FieldMap fields) { - try { - for (int componentField : getFields()) { - if (isSetField(componentField)) { - fields.setField(componentField, getField(componentField)); - } + for (int componentField : getFields()) { + if (isSetField(componentField)) { + fields.setField(componentField, getField(componentField, null)); } - for (int groupField : getGroupFields()) { - if (isSetField(groupField)) { - fields.setField(groupField, getField(groupField)); - fields.setGroups(groupField, getGroups(groupField)); - } + } + for (int groupField : getGroupFields()) { + if (isSetField(groupField)) { + fields.setField(groupField, getField(groupField, null)); + fields.setGroups(groupField, getGroups(groupField)); } - } catch (FieldNotFound e) { - // should not happen } } diff --git a/quickfixj-core/src/main/java/quickfix/NumbersCache.java b/quickfixj-core/src/main/java/quickfix/NumbersCache.java new file mode 100644 index 0000000000..a3c72707ac --- /dev/null +++ b/quickfixj-core/src/main/java/quickfix/NumbersCache.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) quickfixengine.org All rights reserved. + * + * This file is part of the QuickFIX FIX Engine + * + * This file may be distributed under the terms of the quickfixengine.org + * license as defined by quickfixengine.org and appearing in the file + * LICENSE included in the packaging of this file. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING + * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * See http://www.quickfixengine.org/LICENSE for licensing information. + * + * Contact ask@quickfixengine.org if any conditions of this licensing + * are not clear to you. + ******************************************************************************/ + +package quickfix; + +import java.util.ArrayList; + +/** + * A cache for commonly used string representing numbers. + * Hold values from 0 to 999999 and from 1000 to 200 000 000 by step of 1000 + */ +public final class NumbersCache { + + private static final int littleNumbersLength = 1000000; + private static final int bigNumbersLength = 200000; + private static final int bigNumbersOffset = 1000; + private static final int bigNumbersMax = bigNumbersLength * bigNumbersOffset; + + public static final ArrayList littleNumbers; + public static final ArrayList bigNumbers; + + static { + littleNumbers = new ArrayList(littleNumbersLength); + bigNumbers = new ArrayList(bigNumbersLength); + for (int i = 0; i < littleNumbersLength; i++) + littleNumbers.add(Integer.toString(i)); + for (long i = 0; i < bigNumbersLength;) + bigNumbers.add(Long.toString(++i * bigNumbersOffset)); + + } + + /** + * Get the string representing the given number + * + * @param i the long to convert + * @return the String representing the long + */ + public static String get(long i) { + if (i < littleNumbersLength) + return littleNumbers.get((int)i); + if (i <= bigNumbersMax && i % bigNumbersOffset == 0) + return bigNumbers.get((int)(i/bigNumbersOffset)-1); + return String.valueOf(i); + } + + /** + * Get the string representing the given double if it's an integer + * + * @param d the double to convert + * @return the String representing the double or null if the double is not an integer + */ + public static String get(double d) { + long l = (long)d; + if (d == (double)l) + return get(l); + return null; + } +}