PageRenderTime 18ms CodeModel.GetById 2ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/protocols/smpp/src/main/java/org/mobicents/protocols/smpp/message/tlv/TLVTableImpl.java

http://mobicents.googlecode.com/
Java | 258 lines | 128 code | 22 blank | 108 comment | 21 complexity | 09950570ff79f759f1498d16db13428a MD5 | raw file
  1/*
  2 * JBoss, Home of Professional Open Source
  3 * Copyright 2011, Red Hat, Inc. and individual contributors
  4 * by the @authors tag. See the copyright.txt in the distribution for a
  5 * full listing of individual contributors.
  6 *
  7 * This is free software; you can redistribute it and/or modify it
  8 * under the terms of the GNU Lesser General Public License as
  9 * published by the Free Software Foundation; either version 2.1 of
 10 * the License, or (at your option) any later version.
 11 *
 12 * This software is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 15 * Lesser General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU Lesser General Public
 18 * License along with this software; if not, write to the Free
 19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 21 */
 22
 23package org.mobicents.protocols.smpp.message.tlv;
 24
 25import java.io.IOException;
 26import java.text.MessageFormat;
 27import java.util.BitSet;
 28import java.util.LinkedHashMap;
 29import java.util.Map;
 30
 31import org.mobicents.protocols.smpp.message.param.ParamDescriptor;
 32import org.mobicents.protocols.smpp.util.PacketDecoder;
 33import org.mobicents.protocols.smpp.util.PacketEncoder;
 34
 35/**
 36 * Implementation of the TLVTable interface.
 37 * This implementation will maintain the ordering of added parameters.
 38 * @version $Id: TLVTableImpl.java 457 2009-01-15 17:37:42Z orank $
 39 */
 40public class TLVTableImpl extends LinkedHashMap<Tag, Object> implements TLVTable {
 41    private static final long serialVersionUID = 2L;
 42
 43    public TLVTableImpl() {
 44    }
 45    
 46    /**
 47     * Decode a full set of optional parameters from a byte array.
 48     */
 49    public void readFrom(PacketDecoder decoder, int length) {
 50        int endIndex = (decoder.getParsePosition() + length) - 1;
 51        while (decoder.getParsePosition() < endIndex) {
 52            Object val = null;
 53            Tag tag = Tag.getTag(decoder.readUInt2());
 54            int valueLen = decoder.readUInt2();
 55            ParamDescriptor descriptor = tag.getParamDescriptor();
 56            val = descriptor.readObject(decoder, valueLen);
 57            put(tag, val);
 58        }
 59    }
 60
 61    /**
 62     * Encode all the optional parameters in this table to an output stream.
 63     * 
 64     * @param out
 65     *            The output stream to encode the parameters to.
 66     * @throws java.io.IOException
 67     *             If an error occurs writing to the output stream.
 68     */
 69    public void writeTo(PacketEncoder encoder) throws IOException {
 70        for (Map.Entry<Tag, Object> entry : entrySet()) {
 71            Tag tag = entry.getKey();
 72            Object value = entry.getValue();
 73            ParamDescriptor descriptor = tag.getParamDescriptor();
 74            int valueLen = descriptor.sizeOf(value);
 75            encoder.writeUInt2(tag.intValue());
 76            encoder.writeUInt2(valueLen);
 77            descriptor.writeObject(value, encoder);
 78        }
 79    }
 80
 81    /**
 82     * Get the value for a tag. This is a convenience method to convert
 83     * the tag integer to its appropriate Tag object and then look that
 84     * tag up in the map.
 85     * @param tag The tag&apos;s integer value.
 86     */
 87    public Object get(int tag) {
 88        Tag tagObj = Tag.getTag(tag);
 89        return get(tagObj);
 90    }
 91
 92    /**
 93     * Get the tag&apos;s value as a string.
 94     * @param tag The tag to retrieve the value for.
 95     * @return The value as a string, or <code>null</code> if the specified
 96     * tag is not set in this table.
 97     */
 98    public String getString(Tag tag) {
 99        Object obj = get(tag);
100        return obj != null ? obj.toString() : null;
101    }
102
103    /**
104     * Get the tag&apos;s value as an int.
105     * @param tag The tag to retrieve the value for.
106     * @return The value as an integer, or <code>-1</code> if the specified
107     * tag is not set in this table.
108     * @throws ClassCastException If the value for the specified tag is not
109     * a number (castable as a <code>java.lang.Number</code>).
110     */
111    public int getInt(Tag tag) {
112        Object obj = get(tag);
113        if (obj != null) {
114            return ((Number) obj).intValue();
115        } else {
116            return -1;
117        }
118    }
119    
120    /**
121     * Get the tag&apos;s value as a long.
122     * @param tag The tag to retrieve the value for.
123     * @return The value as a long, or <code>-1</code> if the specified
124     * tag is not set in this table.
125     * @throws ClassCastException If the value for the specified tag is not
126     * a number (castable as a <code>java.lang.Number</code>).
127     */
128    public long getLong(Tag tag) {
129        Object obj = get(tag);
130        if (obj != null) {
131            return ((Number) obj).intValue();
132        } else {
133            return -1;
134        }
135    }
136
137    /**
138     * Get the tag&apos;s value as a bit set.
139     * @param tag The tag to retrieve the value for.
140     * @return The value, cast as a <code>java.util.BitSet</code>, or
141     * <code>null</code> if the specified tag is not set in this table.
142     * @throws ClassCastException If the value for the specified tag is not
143     * a bit mask.
144     */
145    public BitSet getBitmask(Tag tag) {
146        return ((BitSet) get(tag));
147    }
148    
149    /**
150     * Get the tag&apos;s value as a byte array.
151     * @param tag The tag to retrieve the value for.
152     * @return The value, cast as a <code>byte[]</code>, or <code>null</code>
153     * if the specified tag is not set in this table.
154     * @throws ClassCastException If the value for the specified tag is not
155     * a byte array.
156     */
157    public byte[] getBytes(Tag tag) {
158        return ((byte[]) get(tag));
159    }
160    
161    /**
162     * Set the value of a TLV.
163     * @param tag The tag of the parameter to set.
164     * @param value The tag&apos;s value.
165     * @throws BadValueTypeException If <code>tag</code> does not accept
166     * the type that <code>value</code> is.
167     * @throws InvalidSizeForValueException If <code>value</code>
168     * exceeds either the minimum or maximum size allowed by <code>tag</code>.
169     */
170    @Override
171    public Object put(Tag tag, Object value)
172            throws BadValueTypeException, InvalidSizeForValueException {
173        ParamDescriptor descriptor = tag.getParamDescriptor();
174        if (descriptor.equals(BasicDescriptors.NULL) && value != null) {
175            String error = MessageFormat.format(
176                    "Tag {0} does not accept any value.",
177                    new Object[] {tag});
178            throw new BadValueTypeException(error);
179        } else if (value == null) {
180            String error = MessageFormat.format(
181                    "Tag {0} does not accept a null value.",
182                    new Object[] {tag});
183            throw new BadValueTypeException(error);
184        }
185
186        // Enforce the length restrictions on the Value specified by the
187        // Tag.
188        int min = tag.getMinLength();
189        int max = tag.getMaxLength();
190        int actual = descriptor.sizeOf(value);
191        if ((min > -1 && actual < min) || (max > -1 && actual > max)) {
192            throw new InvalidSizeForValueException("Tag "
193                    + tag.toHexString()
194                    + " must have a length in the range " + min
195                    + " <= len <= " + max);
196        }
197        return super.put(tag, value);
198    }
199
200    public Object put(Tag tag, char value) {
201        return put(tag, Character.valueOf(value));
202    }
203    
204    public Object put(Tag tag, short value) {
205        return put(tag, Short.valueOf(value));
206    }
207    
208    public Object put(Tag tag, int value) {
209        return put(tag, Integer.valueOf(value));
210    }
211    
212    public Object put(Tag tag, long value) {
213        return put(tag, Long.valueOf(value));
214    }
215    
216    /**
217     * Remove (or un-set) a tag/value from this table.
218     * @param tag The tag to remove from the table.
219     */
220    public void remove(int tag) {
221        super.remove(Tag.getTag(tag));
222    }
223    
224    @Override
225    public String toString() {
226        StringBuffer buffer = new StringBuffer();
227        for (Map.Entry<Tag, Object> entry : entrySet()) {
228            ParamDescriptor descriptor = entry.getKey().getParamDescriptor();
229            Object value = entry.getValue();
230            buffer.append('{')
231            .append(entry.getKey().toHexString())
232            .append(',').append(descriptor.sizeOf(value))
233            .append(',').append(value);
234        }
235        return buffer.toString();
236    }
237
238    /**
239     * Get the length the parameters in the table would encode as. The length of
240     * an SMPP packet is determined by: <br>
241     * <code>sizeof (smpp_header) + sizeof (mandatory_parameters)
242     * + sizeof (optional_parameters).</code>
243     * <br>
244     * The value returned for this method is the last clause in this equation.
245     * 
246     * @return The full length that the optional parameters would encode as.
247     */
248    public int getLength() {
249        // Length is going to be (number of options) * (2 bytes for tag) * (2
250        // bytes for length) + (size of all encoded values)
251        int length = size() * 4;
252        for (Map.Entry<Tag, Object> entry : entrySet()) {
253            Tag tag = entry.getKey();
254            length += tag.getParamDescriptor().sizeOf(entry.getValue());
255        }
256        return length;
257    }
258}