| /* |
| * |
| * 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); |
| } |
| } |