View Javadoc

1   /***
2    * Java DAB EPG API - Serialize/Deserialize To/From POJOs to XML/Binary as per
3    * ETSI specifications TS 102 818 (XML Specification for DAB EPG) and TS 102 
4    * 371 (Transportation and Binary Encoding Specification for EPG).
5    * 
6    * Copyright (C) 2007 GCap Media PLC
7    *
8    * This library is free software; you can redistribute it and/or
9    * modify it under the terms of the GNU Lesser General Public
10   * License as published by the Free Software Foundation; either
11   * version 2.1 of the License, or (at your option) any later version.
12   *
13   * This library is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   * Lesser General Public License for more details.
17   *
18   * You should have received a copy of the GNU Lesser General Public
19   * License along with this library; if not, write to the Free Software
20   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21   */
22  package com.gcapmedia.dab.epg.binary;
23  
24  /***
25   * Defines an entry in the token table as per clause 4.9.1 of the binary
26   * encoding specification.
27   * 
28   * Frequently recurring strings in the EPG character data ("tokens") can
29   * be encoded using a token table. A token holds a tag used to represent
30   * an equivalent string. Whenever a decoder finds the tag in a stream it
31   * shall replace the tag with its equivalent string.
32   * 
33   * A token can only occur within the two top-level elements (epg and
34   * serviceInformation) and all children of the parent element.
35   */
36  public class Token implements Encodable {
37  	
38  	/***
39  	 * 
40  	 */
41  	private TokenTag tag;
42  		
43  	/***
44  	 * Contains either a string (4.5.1) or an enumerated data value
45  	 * (4.6) or a common data type (4.7)
46  	 */
47  	private Encodable value;
48  	
49  	/***
50  	 * Create a new attribute
51  	 * @param tag Attribute tag
52  	 * @param data Attribute value
53  	 */
54  	public Token(TokenTag tag, StringType value) {
55  		if(tag == null) {
56  			throw new IllegalArgumentException("Must specify a tag for this attribute");
57  		}
58  		this.tag = tag;
59  		if(value == null) {
60  			throw new IllegalArgumentException("Must specify a value for this attribute: " + this.getTag());
61  		}
62  		this.value = value;
63  	}
64  	
65  	/***
66  	 * @return Returns the attribute tag
67  	 */
68  	public TokenTag getTag() {
69  		return tag;
70  	}
71  	
72  	/***
73  	 * @return Returns the attribute value
74  	 */
75  	public Encodable getValue() {
76  		return value;
77  	}
78  
79  	/***
80  	 * @see com.gcapmedia.dab.epg.binary.Encodable#getBytes()
81  	 */
82  	public byte[] getBytes() {
83  		if(value == null) {
84  			throw new IllegalStateException("Bytes requested when value is null");
85  		}
86  		
87  		BitBuilder bits = new BitBuilder(16);
88  		int position = 0;
89  		
90  		// b0-b7: token tag
91  		bits.put(position, 8, tag.getBytes());
92  		position += 8;
93  		
94  		// b8-15: token data length 
95  		byte[] databytes = value.getBytes();
96  		int datalength = databytes.length;
97  		if(datalength >= 1<<8) {
98  			throw new IndexOutOfBoundsException("Token data length exceeds the maximum allowed (8bits): " + datalength + " > " + (1<<8));
99  		}
100 		bits.setSize(16 + datalength * 8);
101 		bits.put(position, 8, datalength);
102 		position += 8;
103 		
104 		// b16-16+(bytes*8): attribute data bytes
105 		bits.put(position, databytes.length * 8, databytes);
106 		position += databytes.length * 8;
107 		
108 		return bits.toByteArray();
109 	}
110 
111 	/***
112 	 * @see com.gcapmedia.dab.epg.binary.Encodable#getLength()
113 	 */
114 	public int getLength() {
115 		return getBytes().length;
116 	}
117 	
118 	/***
119 	 * Parse an object from its byte array representation
120 	 * @param parent Tag parent
121 	 * @param bytes Byte array representation
122 	 */
123 	public static Token fromBytes(byte[] bytes) {
124 		BitParser parser = new BitParser(bytes);
125 		
126 		// b0-7: attribute tag
127 		TokenTag tag = TokenTag.fromBytes(bytes);
128 		
129 		// b8-15: attribute length
130 		int length = parser.getInt(8, 8);
131 		
132 		// b16: attribute value data
133 		byte[] data = parser.getByteArray(16, length * 8);
134 		StringType value = StringType.fromBytes(data);
135 		
136 		Token token = new Token(tag, value);
137 
138 		return token;
139 	}
140 	
141 	/***
142 	 * @see java.lang.Object#equals(java.lang.Object)
143 	 */
144 	@Override
145 	public boolean equals(Object obj) {
146 		if(!(obj instanceof Token)) {
147 			return false;
148 		}
149 		Token that = (Token)obj;		
150 		return this.tag == that.tag && this.value.equals(that.value);
151 	}
152 
153 	/***
154 	 * @see java.lang.Object#toString()
155 	 */
156 	public String toString() {
157 		return tag + "=" + value;
158 	}
159 }