Clover coverage report -
Coverage timestamp: Sun Nov 1 2009 23:08:24 UTC
file stats: LOC: 316   Methods: 22
NCLOC: 146   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Value.java 87.5% 91.5% 100% 92%
coverage coverage
 1    /*
 2    * Licensed to the Apache Software Foundation (ASF) under one or more
 3    * contributor license agreements. See the NOTICE file distributed with
 4    * this work for additional information regarding copyright ownership.
 5    * The ASF licenses this file to You under the Apache License, Version 2.0
 6    * (the "License"); you may not use this file except in compliance with
 7    * the License. You may obtain a copy of the License at
 8    *
 9    * http://www.apache.org/licenses/LICENSE-2.0
 10    *
 11    * Unless required by applicable law or agreed to in writing, software
 12    * distributed under the License is distributed on an "AS IS" BASIS,
 13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14    * See the License for the specific language governing permissions and
 15    * limitations under the License.
 16    *
 17    * $Id: Value.java 594315 2007-11-12 22:10:44Z vgritsenko $
 18    */
 19   
 20    package org.apache.xindice.core.data;
 21   
 22    import org.apache.xindice.util.XindiceRuntimeException;
 23   
 24    import java.io.ByteArrayInputStream;
 25    import java.io.IOException;
 26    import java.io.InputStream;
 27    import java.io.OutputStream;
 28    import java.io.UnsupportedEncodingException;
 29   
 30    /**
 31    * Value is the primary base class for all data storing objects.
 32    * The content window of value objects are immutable, but the
 33    * underlying byte array which was used for constructing the value might be not.
 34    *
 35    * @version $Revision: 594315 $, $Date: 2007-11-12 22:10:44 +0000 (Mon, 12 Nov 2007) $
 36    */
 37    public class Value implements Comparable {
 38   
 39    private final byte[] data;
 40    private final int pos;
 41    private final int len;
 42    private int hash;
 43   
 44    /**
 45    * Usually there is no need to create a copy of the value, since it is
 46    * an immutable object. This constructor is mainly used to create
 47    * key objects.
 48    *
 49    * @param value the value object which data will be used to construct this
 50    * value.
 51    */
 52  42987 public Value(Value value) {
 53  42987 this.data = value.data;
 54  42987 this.pos = value.pos;
 55  42987 this.len = value.len;
 56    }
 57   
 58  92167 public Value(byte[] data) {
 59  92167 this.data = data;
 60  92167 this.pos = 0;
 61  92167 this.len = data.length;
 62    }
 63   
 64  80811 public Value(byte[] data, int pos, int len) {
 65  80811 if (pos >= data.length || pos < 0 || pos + len > data.length) {
 66  0 throw new ArrayIndexOutOfBoundsException("Value cannot be created");
 67    }
 68   
 69  80811 this.data = data;
 70  80811 this.pos = pos;
 71  80811 this.len = len;
 72    }
 73   
 74  60372 public Value(String data) {
 75  60368 try {
 76  60376 this.data = data.getBytes("utf-8");
 77  60363 this.pos = 0;
 78  60387 this.len = this.data.length;
 79    } catch (UnsupportedEncodingException e) {
 80  0 throw new XindiceRuntimeException("Java doesn't support UTF-8 encoding", e);
 81    }
 82    }
 83   
 84    /**
 85    * getLength retrieves the length of the data being stored by the Value.
 86    *
 87    * @return The Value length
 88    */
 89  1426658 public final int getLength() {
 90  1426653 return len;
 91    }
 92   
 93    /**
 94    * getData retrieves a copy of the data which is being stored
 95    * by this value as a byte array.
 96    *
 97    * <p>Data copying is performed in order to ensure immutability of the Value.
 98    * Avoid using this method if possible.
 99    *
 100    * @return The data
 101    */
 102  36206 public final byte[] getData() {
 103  36206 byte[] b = new byte[len];
 104  36206 System.arraycopy(data, pos, b, 0, len);
 105  36206 return b;
 106    }
 107   
 108    //
 109    // Data extraction
 110    //
 111   
 112    /**
 113    * Returns the byte at the specified index.
 114    *
 115    * @param index byte index
 116    * @return the byte at the specified index.
 117    * @throws ArrayIndexOutOfBoundsException if index is negative number or
 118    * is not less that the length of Value data
 119    */
 120  103371 public final byte byteAt(int index) {
 121  103371 if (index < 0 || index >= len) {
 122  0 throw new ArrayIndexOutOfBoundsException(index);
 123    }
 124  103371 return data[pos + index];
 125    }
 126   
 127    /**
 128    * Returns the short value at the specified index.
 129    *
 130    * @param index short index
 131    * @return the short at the specified index.
 132    * @throws ArrayIndexOutOfBoundsException if index is negative number or
 133    * is not less that the length of the data array
 134    */
 135  17768 public final short shortAt(int index) {
 136  17768 return (short) ((data[index += pos] << 8) | data[index + 1]);
 137    }
 138   
 139    /**
 140    * Returns the int value at the specified index.
 141    *
 142    * @param index int index
 143    * @return the int at the specified index.
 144    * @throws ArrayIndexOutOfBoundsException if index is negative number or
 145    * is not less that the length of the data array
 146    */
 147  342 public final int intAt(int index) {
 148  342 return (short) ((data[index += pos] << 24) | (data[index + 1] << 16) | (data[index + 2] << 8) | data[index + 3]);
 149    }
 150   
 151    /**
 152    * Get a value that is part of this value object.
 153    *
 154    * @param start beginning index
 155    * @param len length of the new value
 156    * @return Value object
 157    * @throws ArrayIndexOutOfBoundsException if start index is either negative
 158    * or isn't less then length of original Value
 159    */
 160  68904 public final Value valueAt(int start, int len) {
 161  68904 return new Value(data, pos + start, len);
 162    }
 163   
 164    /**
 165    * Get a key that is part of this value object.
 166    *
 167    * @param start beginning index
 168    * @param len length of the new key
 169    * @return Key object
 170    * @throws ArrayIndexOutOfBoundsException if start index is either negative
 171    * or isn't less then length of original Value
 172    */
 173  8884 public final Key keyAt(int start, int len) {
 174  8884 return new Key(data, pos + start, len);
 175    }
 176   
 177    //
 178    // I/O
 179    //
 180   
 181    /**
 182    * Return an InputStream for the value.
 183    *
 184    * @return An InputStream
 185    */
 186  38967 public final InputStream getInputStream() {
 187  38967 return new ByteArrayInputStream(data, pos, len);
 188    }
 189   
 190    /**
 191    * Stream the content of the value into an OutputStream.
 192    *
 193    * @param out the OutputStream
 194    * @throws IOException if write failed
 195    */
 196  1217915 public final void streamTo(OutputStream out) throws IOException {
 197  1217914 out.write(data, pos, len);
 198    }
 199   
 200    /**
 201    * Copy contents of the value into supplied byte array.
 202    *
 203    * @param tdata byte array for the value
 204    * @param tpos starting position
 205    */
 206  3118 public final void copyTo(byte[] tdata, int tpos) {
 207  3118 System.arraycopy(data, pos, tdata, tpos, len);
 208    }
 209   
 210    /**
 211    * Copy <code>len</code> bytes of value's content into supplied
 212    * byte array.
 213    *
 214    * @param tdata byte array for the value
 215    * @param tpos starting position
 216    * @param len count of bytes to copy
 217    */
 218  4095 public final void copyTo(byte[] tdata, int tpos, int len) {
 219  4095 System.arraycopy(data, pos, tdata, tpos, len);
 220    }
 221   
 222    //
 223    // Comparisons
 224    //
 225   
 226  69 public final boolean startsWith(Value value) {
 227  69 if (len < value.len) {
 228  0 return false;
 229    }
 230   
 231  69 byte[] ddata = value.data;
 232  69 int dpos = value.pos;
 233   
 234  69 for (int i = 0; i < value.len; i++) {
 235  119 if (data[i + pos] != ddata[i + dpos]) {
 236  5 return false;
 237    }
 238    }
 239   
 240  64 return true;
 241    }
 242   
 243  838047 public final int compareTo(Value value) {
 244  838047 byte[] ddata = value.data;
 245  838047 int dpos = value.pos;
 246  838047 int dlen = value.len;
 247   
 248  838047 int stop = len > dlen ? dlen : len;
 249   
 250  838047 for (int i = 0; i < stop; i++) {
 251  4606006 byte b1 = data[pos + i];
 252  4606007 byte b2 = ddata[dpos + i];
 253   
 254  4606007 if (b1 != b2) {
 255    // get unsigned value
 256  663003 int s1 = ((int) b1) & 0xFF;
 257  663003 int s2 = ((int) b2) & 0xFF;
 258  663003 return s1 > s2 ? (i + 1) : -(i + 1);
 259    }
 260    }
 261   
 262  175044 if (len == dlen) {
 263  143111 return 0;
 264    } else {
 265  31933 return len > dlen ? stop + 1 : -(stop + 1);
 266    }
 267    }
 268   
 269  739883 public final int compareTo(Object obj) {
 270  739883 if (obj instanceof Value) {
 271  739883 return compareTo((Value) obj);
 272    }
 273   
 274  0 return compareTo(new Value(obj.toString()));
 275    }
 276   
 277    //
 278    // Object
 279    //
 280   
 281  275097 public int hashCode() {
 282    // modeled after String.hashCode()
 283  275097 if (hash == 0) {
 284  77389 int tempHash = 0;
 285  77389 for (int i = 0; i < len; i++) {
 286  569863 tempHash = 31 * tempHash + data[pos + i];
 287    }
 288  77389 this.hash = Math.abs(tempHash);
 289    }
 290  275096 return hash;
 291    }
 292   
 293  7839 public boolean equals(Value value) {
 294  7839 return len == value.len && compareTo(value) == 0;
 295    }
 296   
 297  75982 public boolean equals(Object obj) {
 298  75982 if (this == obj) {
 299  5864 return true;
 300    }
 301   
 302  70118 if (obj instanceof Value) {
 303  70116 return equals((Value) obj);
 304    }
 305   
 306  2 return obj != null && equals(new Value(obj.toString()));
 307    }
 308   
 309  192331 public final String toString() {
 310  192331 try {
 311  192331 return new String(data, pos, len, "utf-8");
 312    } catch (UnsupportedEncodingException e) {
 313  0 throw new XindiceRuntimeException("Java doesn't seem to support UTF-8!", e);
 314    }
 315    }
 316    }