PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/YOYOPlayer/src/com/hadeslee/audiotag/tag/datatype/StringFixedLength.java

http://yoyoplayer.googlecode.com/
Java | 231 lines | 147 code | 17 blank | 67 comment | 19 complexity | ddd7530d6faa5ce4262db5ef39412259 MD5 | raw file
  1. /**
  2. * @author : Paul Taylor
  3. * @author : Eric Farng
  4. *
  5. * Version @version:$Id: StringFixedLength.java,v 1.11 2007/08/07 14:36:15 paultaylor Exp $
  6. *
  7. * MusicTag Copyright (C)2003,2004
  8. *
  9. * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
  10. * General Public License as published by the Free Software Foundation; either version 2.1 of the License,
  11. * or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
  14. * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. * See the GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License along with this library; if not,
  18. * you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. * Description:
  22. *
  23. */
  24. package com.hadeslee.audiotag.tag.datatype;
  25. import com.hadeslee.audiotag.tag.id3.AbstractTagFrameBody;
  26. import com.hadeslee.audiotag.tag.InvalidDataTypeException;
  27. import com.hadeslee.audiotag.tag.id3.valuepair.TextEncoding;
  28. import java.nio.ByteBuffer;
  29. import java.nio.CharBuffer;
  30. import java.nio.charset.*;
  31. /**
  32. * Represents a fixed length String, whereby the length of the String is known. The String
  33. * will be encoded based upon the text encoding of the frame that it belongs to.
  34. */
  35. public class StringFixedLength
  36. extends AbstractString
  37. {
  38. /**
  39. * Creates a new ObjectStringFixedsize datatype.
  40. *
  41. * @param identifier
  42. * @param size
  43. * @throws IllegalArgumentException
  44. */
  45. public StringFixedLength(String identifier, AbstractTagFrameBody frameBody, int size)
  46. {
  47. super(identifier, frameBody);
  48. if (size < 0)
  49. {
  50. throw new IllegalArgumentException("size is less than zero: " + size);
  51. }
  52. setSize(size);
  53. }
  54. public StringFixedLength(StringFixedLength copyObject)
  55. {
  56. super(copyObject);
  57. this.size = copyObject.size;
  58. }
  59. /**
  60. *
  61. *
  62. * @param obj
  63. * @return if obj is equivalent to this
  64. */
  65. public boolean equals(Object obj)
  66. {
  67. if ((obj instanceof StringFixedLength) == false)
  68. {
  69. return false;
  70. }
  71. StringFixedLength object = (StringFixedLength) obj;
  72. if (this.size != object.size)
  73. {
  74. return false;
  75. }
  76. return super.equals(obj);
  77. }
  78. /**
  79. * Read a string from buffer of fixed size(size has already been set in constructor)
  80. *
  81. * @param arr this is the buffer for the frame
  82. * @param offset this is where to start reading in the buffer for this field
  83. */
  84. public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException
  85. {
  86. logger.info("Reading from array from offset:" + offset);
  87. try
  88. {
  89. String charSetName = getTextEncodingCharSet();
  90. CharsetDecoder decoder = Charset.forName(charSetName).newDecoder();
  91. //Decode buffer if runs into problems should through exception which we
  92. //catch and then set value to empty string.
  93. logger.finest("Array length is:" + arr.length + "offset is:" + offset + "Size is:" + size);
  94. if(arr.length - offset < size)
  95. {
  96. throw new InvalidDataTypeException("byte array is to small to retrieve string of declared length:"+size);
  97. }
  98. String str = decoder.decode(ByteBuffer.wrap(arr, offset, size)).toString();
  99. if (str == null)
  100. {
  101. throw new NullPointerException("String is null");
  102. }
  103. value = str;
  104. }
  105. catch (CharacterCodingException ce)
  106. {
  107. logger.severe(ce.getMessage());
  108. value = "";
  109. }
  110. logger.info("Read StringFixedLength:" + value);
  111. }
  112. /**
  113. * Write String into byte array
  114. *
  115. * The string will be adjusted to ensure the correct number of bytes are written, If the current value is null
  116. * or to short the written value will have the 'space' character appended to ensure this. We write this instead of
  117. * the null character because the null character is likely to confuse the parser into misreading the next field.
  118. *
  119. * @return the byte array to be written to the file
  120. */
  121. public byte[] writeByteArray()
  122. {
  123. ByteBuffer dataBuffer = null;
  124. byte[] data;
  125. //Create with a series of empty of spaces to try and ensure integrity of field
  126. if(value==null)
  127. {
  128. logger.warning("Value of StringFixedlength Field is null using default value instead");
  129. data = new byte[size];
  130. for(int i=0;i<size;i++)
  131. {
  132. data[i]=' ';
  133. }
  134. return data;
  135. }
  136. try
  137. {
  138. String charSetName = getTextEncodingCharSet();
  139. CharsetEncoder encoder = Charset.forName(charSetName).newEncoder();
  140. dataBuffer = encoder.encode(CharBuffer.wrap((String) value));
  141. }
  142. catch (CharacterCodingException ce)
  143. {
  144. logger.warning("There was a problem writing the following StringFixedlength Field:"+value+":"+ce.getMessage()+"using default value instead");
  145. data = new byte[size];
  146. for(int i=0;i<size;i++)
  147. {
  148. data[i]=' ';
  149. }
  150. return data;
  151. }
  152. // We must return the defined size.
  153. // To check now because size is in bytes not chars
  154. if (dataBuffer != null)
  155. {
  156. //Everything ok
  157. if (dataBuffer.limit() == size)
  158. {
  159. data = new byte[dataBuffer.limit()];
  160. dataBuffer.get(data, 0, dataBuffer.limit());
  161. return data;
  162. }
  163. //There is more data available than allowed for this field strip
  164. else if (dataBuffer.limit() > size)
  165. {
  166. logger.warning("There was a problem writing the following StringFixedlength Field:"
  167. +value
  168. +" when converted to bytes has length of:"+dataBuffer.limit()
  169. +" but field was defined with length of:"+size
  170. +" too long so stripping extra length");
  171. data = new byte[size];
  172. dataBuffer.get(data, 0, size);
  173. return data;
  174. }
  175. //There is not enough data
  176. else
  177. {
  178. logger.warning("There was a problem writing the following StringFixedlength Field:"
  179. +value
  180. +" when converted to bytes has length of:"+dataBuffer.limit()
  181. +" but field was defined with length of:"+size
  182. +" too short so padding with spaces to make up extra length");
  183. data = new byte[size];
  184. dataBuffer.get(data, 0, dataBuffer.limit());
  185. for(int i=dataBuffer.limit();i<size;i++)
  186. {
  187. data[i]=' ';
  188. }
  189. return data;
  190. }
  191. }
  192. else
  193. {
  194. logger.warning("There was a serious problem writing the following StringFixedlength Field:"+value+":"+"using default value instead");
  195. data = new byte[size];
  196. for(int i=0;i<size;i++)
  197. {
  198. data[i]=' ';
  199. }
  200. return data;
  201. }
  202. }
  203. /**
  204. *
  205. * @return the encoding of the frame body this datatype belongs to
  206. */
  207. protected String getTextEncodingCharSet()
  208. {
  209. byte textEncoding = this.getBody().getTextEncoding();
  210. String charSetName = TextEncoding.getInstanceOf().getValueForId(textEncoding);
  211. logger.finest("text encoding:"+textEncoding + " charset:"+charSetName);
  212. return charSetName;
  213. }
  214. }