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   * @author ben.poor
26   *
27   */
28  public class CData implements Encodable {
29  	
30  	/***
31  	 * CDATA tag 
32  	 */
33  	public static final byte TAG = 0x01;
34  
35  	/***
36  	 * CDATA content value, encoded using ISO/IEC 10646 with 
37  	 * UTF-8 encoding.
38  	 */
39  	private StringType value;
40  	
41  	/***
42  	 * Create new CDATA content
43  	 * @param value CDATA content value
44  	 */
45  	public CData(StringType value) {
46  		if(value == null) {
47  			throw new IllegalArgumentException("Must specify a value for this CDATA content");
48  		}
49  		this.value = value;
50  	}
51  	
52  	/***
53  	 * Create new CDATA content
54  	 * @param value CDATA content value
55  	 */
56  	public CData(String value) {
57  		if(value == null) {
58  			throw new IllegalArgumentException("Must specify a value for this CDATA content");
59  		}
60  		this.value = new StringType(value);
61  	}
62  
63  	/***
64  	 * @see com.gcapmedia.dab.epg.binary.Encodable#getBytes()
65  	 */
66  	public byte[] getBytes() {
67  		if(value == null) {
68  			throw new IllegalStateException("Bytes requested when value is null");
69  		}
70  		
71  		BitBuilder bits = new BitBuilder(8);
72  		
73  		// b0-b7: cdata tag
74  		bits.put(0, 8, TAG);
75  		
76  		// b8-15: cdata data length (0-253 bytes)
77  		// b16-31: extended cdata length (256-65536 bytes)
78  		// b16-39: extended cdata length (65537-16777216 bytes)
79  		byte[] databytes = value.getBytes();
80  		int datalength = databytes.length;
81  		if(datalength <= 253) {
82  			bits.setSize(bits.size() + 8);
83  			bits.put(8, 8, datalength);
84  		} else if(datalength >= 1<<8 && datalength <= 1<<16) {
85  			bits.setSize(bits.size() + 8 + 16);
86  			bits.put(8, 8, 0xFE);
87  			bits.put(16, 16, datalength);
88  		} else if(datalength > 1<<16 && datalength <= 1<<24) {
89  			bits.setSize(bits.size() + 8 + 24);
90  			bits.put(8, 8, 0xFF);
91  			bits.put(16, 24, datalength);
92  		} else {
93  			throw new IndexOutOfBoundsException("CDATA content length exceeds the maximum allowed by the extended cdata length (24bits): " + datalength + " > " + (1<<24));
94  		}
95  		
96  		// b16/32/40-(16/32/40 + bytes * 8): cdata data bytes
97  		bits.setSize(bits.size() + databytes.length * 8);
98  		bits.put(bits.position(), databytes.length * 8, databytes);
99  		
100 		return bits.toByteArray();
101 	}
102 
103 	/***
104 	 * @see com.gcapmedia.dab.epg.binary.Encodable#getLength()
105 	 */
106 	public int getLength() {
107 		return getBytes().length;
108 	}
109 	
110 	/***
111 	 * @return Returns the CDATA content
112 	 */
113 	public StringType getString() {
114 		return value;
115 	}
116 	
117 	/***
118 	 * Parse a CDATA object from its byte array representation
119 	 */
120 	public static CData fromBytes(byte[] bytes) {
121 		return fromBytes(bytes, null);
122 	}
123 	
124 	/***
125 	 * Parse a CDATA object from its byte array representation
126 	 */
127 	public static CData fromBytes(byte[] bytes, TokenTable tokens) {
128 		
129 		BitParser parser = new BitParser(bytes);
130 		
131 		// b0-7: element tag = 0x01
132 		
133 		// b8-15: cdata length
134 		int length = parser.getInt(8, 8);
135 		int position = 16;
136 		if(length == 0xFE) {
137 			// b16-31: extended cdata length (16bits)
138 			length = parser.getInt(16, 16);
139 			position = 32;
140 		} else if(length == 0xFE) {
141 			// b16-39: extended cdata length (24bits)
142 			length = parser.getInt(16, 24);
143 			position = 40;
144 		}
145 		
146 		// b16/32/40: cdata value data
147 		byte[] data = parser.getByteArray(position, bytes.length * 8 - position);
148 		if(tokens != null) data = tokens.expand(data);
149 		StringType content = StringType.fromBytes(data);
150 
151 		CData cdata = new CData(content);
152 		return cdata;
153 	}
154 	
155 	/***
156 	 * @see java.lang.Object#toString()
157 	 */
158 	public String toString() {
159 		return value.toString();
160 	}
161 
162 	/***
163 	 * @see java.lang.Object#equals(java.lang.Object)
164 	 */
165 	@Override
166 	public boolean equals(Object obj) {
167 		if(!(obj instanceof CData)) {
168 			return false;
169 		}
170 		CData that = (CData)obj;
171 		return this.value.equals(that.value);
172 	}
173 	
174 	
175 
176 }
177