blob: 5c3972971249deeab18a7af8709dcfbea501773a [file] [log] [blame]
/*
*
* 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
*
* 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.proton.codec.impl;
import java.nio.ByteBuffer;
import java.util.*;
import org.apache.qpid.proton.amqp.*;
import org.apache.qpid.proton.codec.Data;
public class DataImpl implements Data
{
private Element _first;
private Element _current;
private Element _parent;
public DataImpl()
{
}
@Override
public void free()
{
_first = null;
_current = null;
}
@Override
public void clear()
{
_first=null;
_current=null;
_parent=null;
}
@Override
public long size()
{
return _first == null ? 0 : _first.size();
}
@Override
public void rewind()
{
_current = null;
_parent = null;
}
@Override
public DataType next()
{
Element next = _current == null ? (_parent == null ? _first : _parent.child()) : _current.next();
if(next != null)
{
_current = next;
}
return next == null ? null : next.getDataType();
}
@Override
public DataType prev()
{
Element prev = _current == null ? null : _current.prev();
_current = prev;
return prev == null ? null : prev.getDataType();
}
@Override
public boolean enter()
{
if(_current != null && _current.canEnter())
{
_parent = _current;
_current = null;
return true;
}
return false;
}
@Override
public boolean exit()
{
if(_parent != null)
{
Element parent = _parent;
_current = parent;
_parent = _current.parent();
return true;
}
return false;
}
@Override
public DataType type()
{
return _current == null ? null : _current.getDataType();
}
@Override
public long encodedSize()
{
int size = 0;
Element elt = _first;
while(elt != null)
{
size += elt.size();
elt = elt.next();
}
return size;
}
@Override
public Binary encode()
{
byte[] data = new byte[(int)encodedSize()];
ByteBuffer buf = ByteBuffer.wrap(data);
encode(buf);
return new Binary(data);
}
@Override
public long encode(ByteBuffer buf)
{
Element elt = _first;
int size = 0;
while(elt != null )
{
final int eltSize = elt.size();
if(eltSize <= buf.remaining())
{
size += elt.encode(buf);
}
else
{
size+= eltSize;
}
elt = elt.next();
}
return size;
}
@Override
public long decode(ByteBuffer buf)
{
return DataDecoder.decode(buf, this);
}
private void putElement(Element element)
{
if(_first == null)
{
_first = element;
}
else
{
if(_current == null)
{
if (_parent == null) {
_first = _first.replaceWith(element);
element = _first;
} else {
element = _parent.addChild(element);
}
}
else
{
if(_parent!=null)
{
element = _parent.checkChild(element);
}
_current.setNext(element);
}
}
_current = element;
}
@Override
public void putList()
{
putElement(new ListElement(_parent, _current));
}
@Override
public void putMap()
{
putElement(new MapElement(_parent, _current));
}
@Override
public void putArray(boolean described, DataType type)
{
putElement(new ArrayElement(_parent, _current, described, type));
}
@Override
public void putDescribed()
{
putElement(new DescribedTypeElement(_parent, _current));
}
@Override
public void putNull()
{
putElement(new NullElement(_parent, _current));
}
@Override
public void putBoolean(boolean b)
{
putElement(new BooleanElement(_parent, _current, b));
}
@Override
public void putUnsignedByte(UnsignedByte ub)
{
putElement(new UnsignedByteElement(_parent, _current, ub));
}
@Override
public void putByte(byte b)
{
putElement(new ByteElement(_parent, _current, b));
}
@Override
public void putUnsignedShort(UnsignedShort us)
{
putElement(new UnsignedShortElement(_parent, _current, us));
}
@Override
public void putShort(short s)
{
putElement(new ShortElement(_parent, _current, s));
}
@Override
public void putUnsignedInteger(UnsignedInteger ui)
{
putElement(new UnsignedIntegerElement(_parent, _current, ui));
}
@Override
public void putInt(int i)
{
putElement(new IntegerElement(_parent, _current, i));
}
@Override
public void putChar(int c)
{
putElement(new CharElement(_parent, _current, c));
}
@Override
public void putUnsignedLong(UnsignedLong ul)
{
putElement(new UnsignedLongElement(_parent, _current, ul));
}
@Override
public void putLong(long l)
{
putElement(new LongElement(_parent, _current, l));
}
@Override
public void putTimestamp(Date t)
{
putElement(new TimestampElement(_parent,_current,t));
}
@Override
public void putFloat(float f)
{
putElement(new FloatElement(_parent,_current,f));
}
@Override
public void putDouble(double d)
{
putElement(new DoubleElement(_parent,_current,d));
}
@Override
public void putDecimal32(Decimal32 d)
{
putElement(new Decimal32Element(_parent,_current,d));
}
@Override
public void putDecimal64(Decimal64 d)
{
putElement(new Decimal64Element(_parent,_current,d));
}
@Override
public void putDecimal128(Decimal128 d)
{
putElement(new Decimal128Element(_parent,_current,d));
}
@Override
public void putUUID(UUID u)
{
putElement(new UUIDElement(_parent,_current,u));
}
@Override
public void putBinary(Binary bytes)
{
putElement(new BinaryElement(_parent, _current, bytes));
}
@Override
public void putBinary(byte[] bytes)
{
putBinary(new Binary(bytes));
}
@Override
public void putString(String string)
{
putElement(new StringElement(_parent,_current,string));
}
@Override
public void putSymbol(Symbol symbol)
{
putElement(new SymbolElement(_parent,_current,symbol));
}
@Override
public void putObject(Object o)
{
if(o == null)
{
putNull();
}
else if(o instanceof Boolean)
{
putBoolean((Boolean) o);
}
else if(o instanceof UnsignedByte)
{
putUnsignedByte((UnsignedByte)o);
}
else if(o instanceof Byte)
{
putByte((Byte)o);
}
else if(o instanceof UnsignedShort)
{
putUnsignedShort((UnsignedShort)o);
}
else if(o instanceof Short)
{
putShort((Short)o);
}
else if(o instanceof UnsignedInteger)
{
putUnsignedInteger((UnsignedInteger)o);
}
else if(o instanceof Integer)
{
putInt((Integer)o);
}
else if(o instanceof Character)
{
putChar((Character)o);
}
else if(o instanceof UnsignedLong)
{
putUnsignedLong((UnsignedLong)o);
}
else if(o instanceof Long)
{
putLong((Long)o);
}
else if(o instanceof Date)
{
putTimestamp((Date)o);
}
else if(o instanceof Float)
{
putFloat((Float)o);
}
else if(o instanceof Double)
{
putDouble((Double)o);
}
else if(o instanceof Decimal32)
{
putDecimal32((Decimal32)o);
}
else if(o instanceof Decimal64)
{
putDecimal64((Decimal64)o);
}
else if(o instanceof Decimal128)
{
putDecimal128((Decimal128)o);
}
else if(o instanceof UUID)
{
putUUID((UUID)o);
}
else if(o instanceof Binary)
{
putBinary((Binary)o);
}
else if(o instanceof String)
{
putString((String)o);
}
else if(o instanceof Symbol)
{
putSymbol((Symbol)o);
}
else if(o instanceof DescribedType)
{
putDescribedType((DescribedType)o);
}
else if(o instanceof Symbol[])
{
putArray(false, Data.DataType.SYMBOL);
enter();
for(Symbol s : (Symbol[]) o)
{
putSymbol(s);
}
exit();
}
else if(o instanceof Object[])
{
throw new IllegalArgumentException("Unsupported array type");
}
else if(o instanceof List)
{
putJavaList((List)o);
}
else if(o instanceof Map)
{
putJavaMap((Map)o);
}
else
{
throw new IllegalArgumentException("Unknown type " + o.getClass().getSimpleName());
}
}
@Override
public void putJavaMap(Map<Object, Object> map)
{
putMap();
enter();
for(Map.Entry<Object, Object> entry : map.entrySet())
{
putObject(entry.getKey());
putObject(entry.getValue());
}
exit();
}
@Override
public void putJavaList(List<Object> list)
{
putList();
enter();
for(Object o : list)
{
putObject(o);
}
exit();
}
@Override
public void putDescribedType(DescribedType dt)
{
putElement(new DescribedTypeElement(_parent,_current));
enter();
putObject(dt.getDescriptor());
putObject(dt.getDescribed());
exit();
}
@Override
public long getList()
{
if(_current instanceof ListElement)
{
return ((ListElement)_current).count();
}
throw new IllegalStateException("Current value not list");
}
@Override
public long getMap()
{
if(_current instanceof MapElement)
{
return ((MapElement)_current).count();
}
throw new IllegalStateException("Current value not map");
}
@Override
public long getArray()
{
if(_current instanceof ArrayElement)
{
return ((ArrayElement)_current).count();
}
throw new IllegalStateException("Current value not array");
}
@Override
public boolean isArrayDescribed()
{
if(_current instanceof ArrayElement)
{
return ((ArrayElement)_current).isDescribed();
}
throw new IllegalStateException("Current value not array");
}
@Override
public DataType getArrayType()
{
if(_current instanceof ArrayElement)
{
return ((ArrayElement)_current).getArrayDataType();
}
throw new IllegalStateException("Current value not array");
}
@Override
public boolean isDescribed()
{
return _current != null && _current.getDataType() == DataType.DESCRIBED;
}
@Override
public boolean isNull()
{
return _current != null && _current.getDataType() == DataType.NULL;
}
@Override
public boolean getBoolean()
{
if(_current instanceof BooleanElement)
{
return ((BooleanElement)_current).getValue();
}
throw new IllegalStateException("Current value not boolean");
}
@Override
public UnsignedByte getUnsignedByte()
{
if(_current instanceof UnsignedByteElement)
{
return ((UnsignedByteElement)_current).getValue();
}
throw new IllegalStateException("Current value not unsigned byte");
}
@Override
public byte getByte()
{
if(_current instanceof ByteElement)
{
return ((ByteElement)_current).getValue();
}
throw new IllegalStateException("Current value not byte");
}
@Override
public UnsignedShort getUnsignedShort()
{
if(_current instanceof UnsignedShortElement)
{
return ((UnsignedShortElement)_current).getValue();
}
throw new IllegalStateException("Current value not unsigned short");
}
@Override
public short getShort()
{
if(_current instanceof ShortElement)
{
return ((ShortElement)_current).getValue();
}
throw new IllegalStateException("Current value not short");
}
@Override
public UnsignedInteger getUnsignedInteger()
{
if(_current instanceof UnsignedIntegerElement)
{
return ((UnsignedIntegerElement)_current).getValue();
}
throw new IllegalStateException("Current value not unsigned integer");
}
@Override
public int getInt()
{
if(_current instanceof IntegerElement)
{
return ((IntegerElement)_current).getValue();
}
throw new IllegalStateException("Current value not integer");
}
@Override
public int getChar()
{
if(_current instanceof CharElement)
{
return ((CharElement)_current).getValue();
}
throw new IllegalStateException("Current value not char");
}
@Override
public UnsignedLong getUnsignedLong()
{
if(_current instanceof UnsignedLongElement)
{
return ((UnsignedLongElement)_current).getValue();
}
throw new IllegalStateException("Current value not unsigned long");
}
@Override
public long getLong()
{
if(_current instanceof LongElement)
{
return ((LongElement)_current).getValue();
}
throw new IllegalStateException("Current value not long");
}
@Override
public Date getTimestamp()
{
if(_current instanceof TimestampElement)
{
return ((TimestampElement)_current).getValue();
}
throw new IllegalStateException("Current value not timestamp");
}
@Override
public float getFloat()
{
if(_current instanceof FloatElement)
{
return ((FloatElement)_current).getValue();
}
throw new IllegalStateException("Current value not float");
}
@Override
public double getDouble()
{
if(_current instanceof DoubleElement)
{
return ((DoubleElement)_current).getValue();
}
throw new IllegalStateException("Current value not double");
}
@Override
public Decimal32 getDecimal32()
{
if(_current instanceof Decimal32Element)
{
return ((Decimal32Element)_current).getValue();
}
throw new IllegalStateException("Current value not decimal32");
}
@Override
public Decimal64 getDecimal64()
{
if(_current instanceof Decimal64Element)
{
return ((Decimal64Element)_current).getValue();
}
throw new IllegalStateException("Current value not decimal32");
}
@Override
public Decimal128 getDecimal128()
{
if(_current instanceof Decimal128Element)
{
return ((Decimal128Element)_current).getValue();
}
throw new IllegalStateException("Current value not decimal32");
}
@Override
public UUID getUUID()
{
if(_current instanceof UUIDElement)
{
return ((UUIDElement)_current).getValue();
}
throw new IllegalStateException("Current value not uuid");
}
@Override
public Binary getBinary()
{
if(_current instanceof BinaryElement)
{
return ((BinaryElement)_current).getValue();
}
throw new IllegalStateException("Current value not binary");
}
@Override
public String getString()
{
if (_current instanceof StringElement)
{
return ((StringElement) _current).getValue();
}
throw new IllegalStateException("Current value not string");
}
@Override
public Symbol getSymbol()
{
if(_current instanceof SymbolElement)
{
return ((SymbolElement)_current).getValue();
}
throw new IllegalStateException("Current value not symbol");
}
@Override
public Object getObject()
{
return _current == null ? null : _current.getValue();
}
@Override
public Map<Object, Object> getJavaMap()
{
if(_current instanceof MapElement)
{
return ((MapElement)_current).getValue();
}
throw new IllegalStateException("Current value not map");
}
@Override
public List<Object> getJavaList()
{
if(_current instanceof ListElement)
{
return ((ListElement)_current).getValue();
}
throw new IllegalStateException("Current value not list");
}
@Override
public Object[] getJavaArray()
{
if(_current instanceof ArrayElement)
{
return ((ArrayElement)_current).getValue();
}
throw new IllegalStateException("Current value not array");
}
@Override
public DescribedType getDescribedType()
{
if(_current instanceof DescribedTypeElement)
{
return ((DescribedTypeElement)_current).getValue();
}
throw new IllegalStateException("Current value not described type");
}
@Override
public String format()
{
StringBuilder sb = new StringBuilder();
Element el = _first;
boolean first = true;
while (el != null) {
if (first) {
first = false;
} else {
sb.append(", ");
}
el.render(sb);
el = el.next();
}
return sb.toString();
}
private void render(StringBuilder sb, Element el)
{
if (el == null) return;
sb.append(" ").append(el).append("\n");
if (el.canEnter()) {
render(sb, el.child());
}
render(sb, el.next());
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
render(sb, _first);
return String.format("Data[current=%h, parent=%h]{%n%s}",
System.identityHashCode(_current),
System.identityHashCode(_parent),
sb);
}
}