diff options
| author | Rupert Smith <rupertlssmith@apache.org> | 2008-02-14 16:01:15 +0000 |
|---|---|---|
| committer | Rupert Smith <rupertlssmith@apache.org> | 2008-02-14 16:01:15 +0000 |
| commit | e1f14213a9b4d1159aee92521891fda274912fdb (patch) | |
| tree | a3bb656129ae3e8eecfe6674781a19077e7d1645 /java/common | |
| parent | 91dfa2865cb9998a379e099ff58e830b4b1ba8a4 (diff) | |
| download | qpid-python-e1f14213a9b4d1159aee92521891fda274912fdb.tar.gz | |
QPID-9 : Nested field tables implemented. Also wrote a test that encodes/decodes one to check it works.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/M2.1@627789 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/common')
4 files changed, 331 insertions, 107 deletions
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQType.java b/java/common/src/main/java/org/apache/qpid/framing/AMQType.java index 6dda91a488..2c356d072c 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQType.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQType.java @@ -23,12 +23,24 @@ package org.apache.qpid.framing; import org.apache.mina.common.ByteBuffer;
import java.math.BigDecimal;
-import java.math.BigInteger;
+/**
+ * AMQType is a type that represents the different possible AMQP field table types. It provides operations for each
+ * of the types to perform tasks such as calculating the size of an instance of the type, converting types between AMQP
+ * and Java native types, and reading and writing instances of AMQP types in binary formats to and from byte buffers.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Get the equivalent one byte identifier for a type.
+ * <tr><td> Calculate the size of an instance of an AMQP parameter type. <td> {@link EncodingUtils}
+ * <tr><td> Convert an instance of an AMQP parameter into a compatable Java object tagged with its AMQP type.
+ * <td> {@link AMQTypedValue}
+ * <tr><td> Write an instance of an AMQP parameter type to a byte buffer. <td> {@link EncodingUtils}
+ * <tr><td> Read an instance of an AMQP parameter from a byte buffer. <td> {@link EncodingUtils}
+ * </table>
+ */
public enum AMQType
{
- //AMQP FieldTable Wire Types
-
LONG_STRING('S')
{
public int getEncodingSize(Object value)
@@ -36,7 +48,6 @@ public enum AMQType return EncodingUtils.encodedLongStringLength((String) value);
}
-
public String toNativeValue(Object value)
{
if (value != null)
@@ -58,12 +69,10 @@ public enum AMQType {
return EncodingUtils.readLongString(buffer);
}
-
},
INTEGER('i')
{
-
public int getEncodingSize(Object value)
{
return EncodingUtils.unsignedIntegerLength();
@@ -89,12 +98,11 @@ public enum AMQType }
else if ((value instanceof String) || (value == null))
{
- return Long.valueOf((String)value);
+ return Long.valueOf((String) value);
}
else
{
- throw new NumberFormatException("Cannot convert: " + value + "(" +
- value.getClass().getName() + ") to int.");
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName() + ") to int.");
}
}
@@ -111,22 +119,21 @@ public enum AMQType DECIMAL('D')
{
-
public int getEncodingSize(Object value)
{
- return EncodingUtils.encodedByteLength()+ EncodingUtils.encodedIntegerLength();
+ return EncodingUtils.encodedByteLength() + EncodingUtils.encodedIntegerLength();
}
public Object toNativeValue(Object value)
{
- if(value instanceof BigDecimal)
+ if (value instanceof BigDecimal)
{
return (BigDecimal) value;
}
else
{
- throw new NumberFormatException("Cannot convert: " + value + "(" +
- value.getClass().getName() + ") to BigDecimal.");
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to BigDecimal.");
}
}
@@ -150,7 +157,8 @@ public enum AMQType int unscaled = EncodingUtils.readInteger(buffer);
BigDecimal bd = new BigDecimal(unscaled);
- return bd.setScale(places);
+
+ return bd.setScale(places);
}
},
@@ -163,14 +171,14 @@ public enum AMQType public Object toNativeValue(Object value)
{
- if(value instanceof Long)
+ if (value instanceof Long)
{
return (Long) value;
}
else
{
- throw new NumberFormatException("Cannot convert: " + value + "(" +
- value.getClass().getName() + ") to timestamp.");
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to timestamp.");
}
}
@@ -179,37 +187,97 @@ public enum AMQType EncodingUtils.writeLong(buffer, (Long) value);
}
-
public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readLong(buffer);
}
},
+ /**
+ * Implements the field table type. The native value of a field table type will be an instance of
+ * {@link FieldTable}, which itself may contain name/value pairs encoded as {@link AMQTypedValue}s.
+ */
FIELD_TABLE('F')
{
+ /**
+ * Calculates the size of an instance of the type in bytes.
+ *
+ * @param value An instance of the type.
+ *
+ * @return The size of the instance of the type in bytes.
+ */
public int getEncodingSize(Object value)
{
- // TODO : fixme
- throw new UnsupportedOperationException();
+ // Ensure that the value is a FieldTable.
+ if (!(value instanceof FieldTable))
+ {
+ throw new IllegalArgumentException("Value is not a FieldTable.");
+ }
+
+ FieldTable ftValue = (FieldTable) value;
+
+ // Loop over all name/value pairs adding up size of each. FieldTable itself keeps track of its encoded
+ // size as entries are added, so no need to loop over all explicitly.
+ // EncodingUtils calculation of the encoded field table lenth, will include 4 bytes for its 'size' field.
+ return EncodingUtils.encodedFieldTableLength(ftValue);
}
+ /**
+ * Converts an instance of the type to an equivalent Java native representation.
+ *
+ * @param value An instance of the type.
+ *
+ * @return An equivalent Java native representation.
+ */
public Object toNativeValue(Object value)
{
- // TODO : fixme
- throw new UnsupportedOperationException();
+ // Ensure that the value is a FieldTable.
+ if (!(value instanceof FieldTable))
+ {
+ throw new IllegalArgumentException("Value is not a FieldTable.");
+ }
+
+ return (FieldTable) value;
}
+ /**
+ * Writes an instance of the type to a specified byte buffer.
+ *
+ * @param value An instance of the type.
+ * @param buffer The byte buffer to write it to.
+ */
public void writeValueImpl(Object value, ByteBuffer buffer)
{
- // TODO : fixme
- throw new UnsupportedOperationException();
+ // Ensure that the value is a FieldTable.
+ if (!(value instanceof FieldTable))
+ {
+ throw new IllegalArgumentException("Value is not a FieldTable.");
+ }
+
+ FieldTable ftValue = (FieldTable) value;
+
+ // Loop over all name/values writing out into buffer.
+ ftValue.writeToBuffer(buffer);
}
+ /**
+ * Reads an instance of the type from a specified byte buffer.
+ *
+ * @param buffer The byte buffer to write it to.
+ *
+ * @return An instance of the type.
+ */
public Object readValueFromBuffer(ByteBuffer buffer)
{
- // TODO : fixme
- throw new UnsupportedOperationException();
+ try
+ {
+ // Read size of field table then all name/value pairs.
+ return EncodingUtils.readFieldTable(buffer);
+ }
+ catch (AMQFrameDecodingException e)
+ {
+ throw new IllegalArgumentException("Unable to read field table from buffer.", e);
+ }
}
},
@@ -220,7 +288,6 @@ public enum AMQType return 0;
}
-
public Object toNativeValue(Object value)
{
if (value == null)
@@ -229,14 +296,13 @@ public enum AMQType }
else
{
- throw new NumberFormatException("Cannot convert: " + value + "(" +
- value.getClass().getName() + ") to null String.");
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to null String.");
}
}
public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- }
+ { }
public Object readValueFromBuffer(ByteBuffer buffer)
{
@@ -244,8 +310,6 @@ public enum AMQType }
},
- // Extended types
-
BINARY('x')
{
public int getEncodingSize(Object value)
@@ -253,21 +317,19 @@ public enum AMQType return EncodingUtils.encodedLongstrLength((byte[]) value);
}
-
public Object toNativeValue(Object value)
{
- if((value instanceof byte[]) || (value == null))
+ if ((value instanceof byte[]) || (value == null))
{
return value;
}
else
{
- throw new IllegalArgumentException("Value: " + value + " (" + value.getClass().getName() +
- ") cannot be converted to byte[]");
+ throw new IllegalArgumentException("Value: " + value + " (" + value.getClass().getName()
+ + ") cannot be converted to byte[]");
}
}
-
public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeLongstr(buffer, (byte[]) value);
@@ -277,7 +339,6 @@ public enum AMQType {
return EncodingUtils.readLongstr(buffer);
}
-
},
ASCII_STRING('c')
@@ -287,7 +348,6 @@ public enum AMQType return EncodingUtils.encodedLongStringLength((String) value);
}
-
public String toNativeValue(Object value)
{
if (value != null)
@@ -309,7 +369,6 @@ public enum AMQType {
return EncodingUtils.readLongString(buffer);
}
-
},
WIDE_STRING('C')
@@ -320,7 +379,6 @@ public enum AMQType return EncodingUtils.encodedLongStringLength((String) value);
}
-
public String toNativeValue(Object value)
{
if (value != null)
@@ -351,7 +409,6 @@ public enum AMQType return EncodingUtils.encodedBooleanLength();
}
-
public Object toNativeValue(Object value)
{
if (value instanceof Boolean)
@@ -360,12 +417,12 @@ public enum AMQType }
else if ((value instanceof String) || (value == null))
{
- return Boolean.valueOf((String)value);
+ return Boolean.valueOf((String) value);
}
else
{
- throw new NumberFormatException("Cannot convert: " + value + "(" +
- value.getClass().getName() + ") to boolean.");
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to boolean.");
}
}
@@ -374,7 +431,6 @@ public enum AMQType EncodingUtils.writeBoolean(buffer, (Boolean) value);
}
-
public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readBoolean(buffer);
@@ -388,7 +444,6 @@ public enum AMQType return EncodingUtils.encodedCharLength();
}
-
public Character toNativeValue(Object value)
{
if (value instanceof Character)
@@ -401,8 +456,8 @@ public enum AMQType }
else
{
- throw new NumberFormatException("Cannot convert: " + value + "(" +
- value.getClass().getName() + ") to char.");
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to char.");
}
}
@@ -415,7 +470,6 @@ public enum AMQType {
return EncodingUtils.readChar(buffer);
}
-
},
BYTE('b')
@@ -425,7 +479,6 @@ public enum AMQType return EncodingUtils.encodedByteLength();
}
-
public Byte toNativeValue(Object value)
{
if (value instanceof Byte)
@@ -434,12 +487,12 @@ public enum AMQType }
else if ((value instanceof String) || (value == null))
{
- return Byte.valueOf((String)value);
+ return Byte.valueOf((String) value);
}
else
{
- throw new NumberFormatException("Cannot convert: " + value + "(" +
- value.getClass().getName() + ") to byte.");
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to byte.");
}
}
@@ -456,13 +509,11 @@ public enum AMQType SHORT('s')
{
-
public int getEncodingSize(Object value)
{
return EncodingUtils.encodedShortLength();
}
-
public Short toNativeValue(Object value)
{
if (value instanceof Short)
@@ -475,16 +526,13 @@ public enum AMQType }
else if ((value instanceof String) || (value == null))
{
- return Short.valueOf((String)value);
+ return Short.valueOf((String) value);
}
-
else
{
- throw new NumberFormatException("Cannot convert: " + value + "(" +
- value.getClass().getName() + ") to short.");
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to short.");
}
-
-
}
public void writeValueImpl(Object value, ByteBuffer buffer)
@@ -521,12 +569,11 @@ public enum AMQType }
else if ((value instanceof String) || (value == null))
{
- return Integer.valueOf((String)value);
+ return Integer.valueOf((String) value);
}
else
{
- throw new NumberFormatException("Cannot convert: " + value + "(" +
- value.getClass().getName() + ") to int.");
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName() + ") to int.");
}
}
@@ -543,7 +590,6 @@ public enum AMQType LONG('l')
{
-
public int getEncodingSize(Object value)
{
return EncodingUtils.encodedLongLength();
@@ -551,7 +597,7 @@ public enum AMQType public Object toNativeValue(Object value)
{
- if(value instanceof Long)
+ if (value instanceof Long)
{
return (Long) value;
}
@@ -569,12 +615,12 @@ public enum AMQType }
else if ((value instanceof String) || (value == null))
{
- return Long.valueOf((String)value);
+ return Long.valueOf((String) value);
}
else
{
- throw new NumberFormatException("Cannot convert: " + value + "(" +
- value.getClass().getName() + ") to long.");
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to long.");
}
}
@@ -583,7 +629,6 @@ public enum AMQType EncodingUtils.writeLong(buffer, (Long) value);
}
-
public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readLong(buffer);
@@ -597,7 +642,6 @@ public enum AMQType return EncodingUtils.encodedFloatLength();
}
-
public Float toNativeValue(Object value)
{
if (value instanceof Float)
@@ -606,12 +650,12 @@ public enum AMQType }
else if ((value instanceof String) || (value == null))
{
- return Float.valueOf((String)value);
+ return Float.valueOf((String) value);
}
else
{
- throw new NumberFormatException("Cannot convert: " + value + "(" +
- value.getClass().getName() + ") to float.");
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to float.");
}
}
@@ -628,13 +672,11 @@ public enum AMQType DOUBLE('d')
{
-
public int getEncodingSize(Object value)
{
return EncodingUtils.encodedDoubleLength();
}
-
public Double toNativeValue(Object value)
{
if (value instanceof Double)
@@ -647,12 +689,12 @@ public enum AMQType }
else if ((value instanceof String) || (value == null))
{
- return Double.valueOf((String)value);
+ return Double.valueOf((String) value);
}
else
{
- throw new NumberFormatException("Cannot convert: " + value + "(" +
- value.getClass().getName() + ") to double.");
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to double.");
}
}
@@ -667,35 +709,87 @@ public enum AMQType }
};
+ /** Holds the defined one byte identifier for the type. */
private final byte _identifier;
+ /**
+ * Creates an instance of an AMQP type from its defined one byte identifier.
+ *
+ * @param identifier The one byte identifier for the type.
+ */
AMQType(char identifier)
{
_identifier = (byte) identifier;
}
+ /**
+ * Extracts the byte identifier for the typ.
+ *
+ * @return The byte identifier for the typ.
+ */
public final byte identifier()
{
return _identifier;
}
-
+ /**
+ * Calculates the size of an instance of the type in bytes.
+ *
+ * @param value An instance of the type.
+ *
+ * @return The size of the instance of the type in bytes.
+ */
public abstract int getEncodingSize(Object value);
+ /**
+ * Converts an instance of the type to an equivalent Java native representation.
+ *
+ * @param value An instance of the type.
+ *
+ * @return An equivalent Java native representation.
+ */
public abstract Object toNativeValue(Object value);
+ /**
+ * Converts an instance of the type to an equivalent Java native representation, packaged as an
+ * {@link AMQTypedValue} tagged with its AMQP type.
+ *
+ * @param value An instance of the type.
+ *
+ * @return An equivalent Java native representation, tagged with its AMQP type.
+ */
public AMQTypedValue asTypedValue(Object value)
{
return new AMQTypedValue(this, toNativeValue(value));
}
+ /**
+ * Writes an instance of the type to a specified byte buffer, preceded by its one byte identifier. As the type and
+ * value are both written, this provides a fully encoded description of a parameters type and value.
+ *
+ * @param value An instance of the type.
+ * @param buffer The byte buffer to write it to.
+ */
public void writeToBuffer(Object value, ByteBuffer buffer)
{
- buffer.put((byte)identifier());
+ buffer.put(identifier());
writeValueImpl(value, buffer);
}
+ /**
+ * Writes an instance of the type to a specified byte buffer.
+ *
+ * @param value An instance of the type.
+ * @param buffer The byte buffer to write it to.
+ */
abstract void writeValueImpl(Object value, ByteBuffer buffer);
+ /**
+ * Reads an instance of the type from a specified byte buffer.
+ *
+ * @param buffer The byte buffer to write it to.
+ *
+ * @return An instance of the type.
+ */
abstract Object readValueFromBuffer(ByteBuffer buffer);
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java b/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java index 7193580884..e5b1fad9a8 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java @@ -18,23 +18,40 @@ * under the License.
*
*/
-
package org.apache.qpid.framing;
import org.apache.mina.common.ByteBuffer;
+/**
+ * AMQTypedValue combines together a native Java Object value, and an {@link AMQType}, as a fully typed AMQP parameter
+ * value. It provides the ability to read and write fully typed parameters to and from byte buffers. It also provides
+ * the ability to create such parameters from Java native value and a type tag or to extract the native value and type
+ * from one.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Create a fully typed AMQP value from a native type and a type tag. <td> {@link AMQType}
+ * <tr><td> Create a fully typed AMQP value from a binary representation in a byte buffer. <td> {@link AMQType}
+ * <tr><td> Write a fully typed AMQP value to a binary representation in a byte buffer. <td> {@link AMQType}
+ * <tr><td> Extract the type from a fully typed AMQP value.
+ * <tr><td> Extract the value from a fully typed AMQP value.
+ * </table>
+ */
public class AMQTypedValue
{
+ /** The type of the value. */
private final AMQType _type;
- private final Object _value;
+ /** The Java native representation of the AMQP typed value. */
+ private final Object _value;
public AMQTypedValue(AMQType type, Object value)
{
- if(type == null)
+ if (type == null)
{
throw new NullPointerException("Cannot create a typed value with null type");
}
+
_type = type;
_value = type.toNativeValue(value);
}
@@ -42,10 +59,9 @@ public class AMQTypedValue private AMQTypedValue(AMQType type, ByteBuffer buffer)
{
_type = type;
- _value = type.readValueFromBuffer( buffer );
+ _value = type.readValueFromBuffer(buffer);
}
-
public AMQType getType()
{
return _type;
@@ -56,10 +72,9 @@ public class AMQTypedValue return _value;
}
-
public void writeToBuffer(ByteBuffer buffer)
{
- _type.writeToBuffer(_value,buffer);
+ _type.writeToBuffer(_value, buffer);
}
public int getEncodingSize()
@@ -70,11 +85,12 @@ public class AMQTypedValue public static AMQTypedValue readFromBuffer(ByteBuffer buffer)
{
AMQType type = AMQTypeMap.getType(buffer.get());
+
return new AMQTypedValue(type, buffer);
}
public String toString()
{
- return "["+getType()+": "+getValue()+"]";
+ return "[" + getType() + ": " + getValue() + "]";
}
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java index 7f851ab264..ee6762181d 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java +++ b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java @@ -18,7 +18,6 @@ * under the License. * */ - package org.apache.qpid.framing; import org.apache.mina.common.ByteBuffer; @@ -360,6 +359,41 @@ public class FieldTable } } + /** + * Extracts a value from the field table that is itself a FieldTable associated with the specified parameter name. + * + * @param string The name of the parameter to get the associated FieldTable value for. + * + * @return The associated FieldTable value, or <tt>null</tt> if the associated value is not of FieldTable type or + * not present in the field table at all. + */ + public FieldTable getFieldTable(String string) + { + return getFieldTable(new AMQShortString(string)); + } + + /** + * Extracts a value from the field table that is itself a FieldTable associated with the specified parameter name. + * + * @param string The name of the parameter to get the associated FieldTable value for. + * + * @return The associated FieldTable value, or <tt>null</tt> if the associated value is not of FieldTable type or + * not present in the field table at all. + */ + public FieldTable getFieldTable(AMQShortString string) + { + AMQTypedValue value = getProperty(string); + + if ((value != null) && (value.getType() == AMQType.FIELD_TABLE)) + { + return (FieldTable) value.getValue(); + } + else + { + return null; + } + } + public Object getObject(String string) { return getObject(new AMQShortString(string)); @@ -568,6 +602,32 @@ public class FieldTable return setProperty(string, AMQType.VOID.asTypedValue(null)); } + /** + * Associates a nested field table with the specified parameter name. + * + * @param string The name of the parameter to store in the table. + * @param ftValue The field table value to associate with the parameter name. + * + * @return The stored value. + */ + public Object setFieldTable(String string, FieldTable ftValue) + { + return setFieldTable(new AMQShortString(string), ftValue); + } + + /** + * Associates a nested field table with the specified parameter name. + * + * @param string The name of the parameter to store in the table. + * @param ftValue The field table value to associate with the parameter name. + * + * @return The stored value. + */ + public Object setFieldTable(AMQShortString string, FieldTable ftValue) + { + return setProperty(string, AMQType.FIELD_TABLE.asTypedValue(ftValue)); + } + public Object setObject(AMQShortString string, Object object) { if (object instanceof Boolean) diff --git a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java index e63b0df770..007da7423e 100644 --- a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java +++ b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java @@ -1,21 +1,21 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * http://www.apache.org/licenses/LICENSE-2.0 * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. * */ package org.apache.qpid.framing; @@ -439,6 +439,60 @@ public class PropertyFieldTableTest extends TestCase Assert.assertEquals("Hello", table1.getString("value")); } + /** Check that a nested field table parameter correctly encodes and decodes to a byte buffer. */ + public void testNestedFieldTable() + { + byte[] testBytes = new byte[] { 0, 1, 2, 3, 4, 5 }; + + FieldTable outerTable = new FieldTable(); + FieldTable innerTable = new FieldTable(); + + // Put some stuff in the inner table. + innerTable.setBoolean("bool", true); + innerTable.setByte("byte", Byte.MAX_VALUE); + innerTable.setBytes("bytes", testBytes); + innerTable.setChar("char", 'c'); + innerTable.setDouble("double", Double.MAX_VALUE); + innerTable.setFloat("float", Float.MAX_VALUE); + innerTable.setInteger("int", Integer.MAX_VALUE); + innerTable.setLong("long", Long.MAX_VALUE); + innerTable.setShort("short", Short.MAX_VALUE); + innerTable.setString("string", "hello"); + innerTable.setString("null-string", null); + + // Put the inner table in the outer one. + outerTable.setFieldTable("innerTable", innerTable); + + // Write the outer table into the buffer. + final ByteBuffer buffer = ByteBuffer.allocate((int) outerTable.getEncodedSize() + 4); + outerTable.writeToBuffer(buffer); + buffer.flip(); + + // Extract the table back from the buffer again. + try + { + FieldTable extractedOuterTable = EncodingUtils.readFieldTable(buffer); + + FieldTable extractedTable = extractedOuterTable.getFieldTable("innerTable"); + + Assert.assertEquals((Boolean) true, extractedTable.getBoolean("bool")); + Assert.assertEquals((Byte) Byte.MAX_VALUE, extractedTable.getByte("byte")); + assertBytesEqual(testBytes, extractedTable.getBytes("bytes")); + Assert.assertEquals((Character) 'c', extractedTable.getCharacter("char")); + Assert.assertEquals(Double.MAX_VALUE, extractedTable.getDouble("double")); + Assert.assertEquals(Float.MAX_VALUE, extractedTable.getFloat("float")); + Assert.assertEquals((Integer) Integer.MAX_VALUE, extractedTable.getInteger("int")); + Assert.assertEquals((Long) Long.MAX_VALUE, extractedTable.getLong("long")); + Assert.assertEquals((Short) Short.MAX_VALUE, extractedTable.getShort("short")); + Assert.assertEquals("hello", extractedTable.getString("string")); + Assert.assertEquals(null, extractedTable.getString("null-string")); + } + catch (AMQFrameDecodingException e) + { + fail("Failed to decode field table with nested inner table."); + } + } + public void testValues() { FieldTable table = new FieldTable(); |
