2 * Copyright (c) 2007, Solido Systems
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
15 * Neither the name of Solido Systems nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 package com.solidosystems.tuplesoup.core;
38 * The Value class holds a single data value.
39 * Current size estimate without string data: 8+4+4+8+8 = 32 bytes pr value in mem
42 public final static int NULL=0;
43 public final static int STRING=1;
44 public final static int INT=2;
45 public final static int LONG=3;
46 public final static int FLOAT=4;
47 public final static int DOUBLE=5;
48 public final static int BOOLEAN=6;
49 public final static int TIMESTAMP=7;
50 public final static int BINARY=8;
52 private byte type=NULL; // The type of the value being held
53 private String str_value=null;
54 private long int_value=0;
55 private double float_value=0.0;
56 private byte[] binary=null;
59 * Returns the numerical type id for this value.
66 * Returns the name this value's type.
68 public String getTypeName(){
70 case STRING : return "string";
71 case INT : return "int";
72 case LONG : return "long";
73 case FLOAT : return "float";
74 case DOUBLE : return "double";
75 case BOOLEAN : return "boolean";
76 case TIMESTAMP : return "timestamp";
77 case BINARY : return "binary";
83 * An implementation of the hashCode method as defined in java.lang.Object
85 * @return a hash code value for this object
87 public int hashCode(){
90 case STRING : hash+=str_value.hashCode();
91 case INT : hash+=(int)int_value;
92 case LONG : hash+=(int)int_value;
93 case FLOAT : hash+=(int)float_value;
94 case DOUBLE : hash+=(int)float_value;
95 case BOOLEAN : hash+=(int)int_value;
96 case TIMESTAMP : hash+=(int)int_value;
97 case BINARY : hash+=binary.hashCode();
103 * Returns true only if this Value has specifically been set to null.
105 * @return true if the data being held is null, false otherwise
107 public boolean isNull(){
112 * Returns -1, 0 or 1 if this value is smaller, equal or larger than the value given as a parameter.
114 public int compareTo(Value value){
116 return str_value.compareTo(value.getString());
118 if(lessThan(value))return -1;
119 if(greaterThan(value))return 1;
124 * Attempts to compare this Value to the value given as parameter and returns true if this value is less than the value given as a parameter.
125 * The types used for the comparison will always be based on the type of this Value based on the following rules.
127 * <li>If this Value is a numeric type, then the other Value will be asked to deliver the same numeric type for the comparison.
128 * <li>If this Value is a string, then both values will be asked to deliver a double value for the comparison.
129 * <li>If this Value is a timestamp, then both values will be asked to deliver a long value for the comparison.
130 * <li>If this Value is a boolean, false will be returned.
133 * @param value the value this value should be compared to
134 * @return true if this value is less than the value given as a parameter, false otherwise
136 public boolean lessThan(Value value){
138 case STRING : return getDouble()<value.getDouble();
139 case INT : return getInt()<value.getInt();
140 case LONG : return getLong()<value.getLong();
141 case FLOAT : return getFloat()<value.getFloat();
142 case DOUBLE : return getDouble()<value.getDouble();
143 case TIMESTAMP : return getLong()<value.getLong();
149 * Attempts to compare this Value to the value given as parameter and returns true if this value is greater than the value given as a parameter.
150 * The types used for the comparison will always be based on the type of this Value based on the following rules.
152 * <li>If this Value is a numeric type, then the other Value will be asked to deliver the same numeric type for the comparison.
153 * <li>If this Value is a string, then both values will be asked to deliver a double value for the comparison.
154 * <li>If this Value is a timestamp, then both values will be asked to deliver a long value for the comparison.
155 * <li>If this Value is a boolean, false will be returned.
158 * @param value the value this value should be compared to
159 * @return true if this value is greater than the value given as a parameter, false otherwise
161 public boolean greaterThan(Value value){
163 case STRING : return getDouble()>value.getDouble();
164 case INT : return getInt()>value.getInt();
165 case LONG : return getLong()>value.getLong();
166 case FLOAT : return getFloat()>value.getFloat();
167 case DOUBLE : return getDouble()>value.getDouble();
168 case TIMESTAMP : return getLong()>value.getLong();
174 * Returns true if the string representation of this value starts with the string representation of the value given as parameter.
176 public boolean startsWith(Value value){
177 return getString().startsWith(value.getString());
181 * Returns true if the string representation of this value ends with the string representation of the value given as parameter.
183 public boolean endsWith(Value value){
184 return getString().endsWith(value.getString());
188 * Returns true if the string representation of this value contains the string representation of the value given as parameter.
190 public boolean contains(Value value){
191 return getString().indexOf(value.getString())>-1;
195 * Returns true if the contents of this value equals the contents of the value given as parameter.
197 public boolean equals(Object obj){
199 Value val=(Value)obj;
202 case NULL : return true;
203 case STRING : return str_value.equals(val.str_value);
204 case INT : return int_value==val.int_value;
205 case LONG : return int_value==val.int_value;
206 case FLOAT : return float_value==val.float_value;
207 case DOUBLE : return float_value==val.float_value;
208 case BOOLEAN : return int_value==val.int_value;
209 case TIMESTAMP : return int_value==val.int_value;
210 case BINARY : if(binary.length==val.binary.length){
211 for(int i=0;i<binary.length;i++){
212 if(binary[i]!=val.binary[i])return false;
218 }catch(Exception e){}
223 * Returns a string representation of this object.
225 public String toString(){
230 * Returns a string representation of this object (identical to toString)
237 * Returns this value as an xml tag with the given key set as an attribute called name.
238 * The following string is an example of the int value 1234 created with the key foo <value name="foo" type="int">1234</value>
240 public String toBasicXMLString(String key){
242 case STRING : return "<value name=\""+key+"\" type=\"string\">"+str_value+"</value>";
243 case INT : return "<value name=\""+key+"\" type=\"int\">"+int_value+"</value>";
244 case LONG : return "<value name=\""+key+"\" type=\"long\">"+int_value+"</value>";
245 case FLOAT : return "<value name=\""+key+"\" type=\"float\">"+float_value+"</value>";
246 case DOUBLE : return "<value name=\""+key+"\" type=\"double\">"+float_value+"</value>";
247 case BOOLEAN : if(int_value==1){
248 return "<value name=\""+key+"\" type=\"boolean\">TRUE</value>";
250 return "<value name=\""+key+"\" type=\"boolean\">FALSE</value>";
252 case TIMESTAMP : return "<value name=\""+key+"\" type=\"timestamp\">"+new Date(int_value).toString()+"</value>";
253 case BINARY : return "<value name=\""+key+"\" type=\"binary\">"+getString()+"</value>";
255 return "<value name=\""+key+"\" type=\"null\"></value>";
259 * Returns this value as an xml tag.
260 * The following string is an example of the int value 1234 <value type="int">1234</value>
262 public String toBasicXMLString(){
264 case STRING : return "<value type=\"string\">"+str_value+"</value>";
265 case INT : return "<value type=\"int\">"+int_value+"</value>";
266 case LONG : return "<value type=\"long\">"+int_value+"</value>";
267 case FLOAT : return "<value type=\"float\">"+float_value+"</value>";
268 case DOUBLE : return "<value type=\"double\">"+float_value+"</value>";
269 case BOOLEAN : if(int_value==1){
270 return "<value type=\"boolean\">TRUE</value>";
272 return "<value type=\"boolean\">FALSE</value>";
274 case TIMESTAMP : return "<value type=\"timestamp\">"+new Date(int_value).toString()+"</value>";
275 case BINARY : return "<value type=\"binary\">"+getString()+"</value>";
277 return "<value type=\"null\"></value>";
281 * Returns a string representation of this value
283 public String getString(){
285 case STRING : return str_value;
286 case INT : return ""+int_value;
287 case LONG : return ""+int_value;
288 case FLOAT : return ""+float_value;
289 case DOUBLE : return ""+float_value;
290 case BOOLEAN : if(int_value==1){
295 case TIMESTAMP : return new Date(int_value).toString();
296 case BINARY : StringBuffer buf=new StringBuffer();
297 for(int i=0;i<binary.length;i++){
299 buf.append(Integer.toHexString((b & 0xFF) | 0x100).substring(1,3));
301 return buf.toString();
307 * Attempts to return an integer representation of this value.
308 * Numerical values will be returned directly (demoted if necessary).
309 * Boolean values will be returned as 1 or 0.
310 * Timestamp values will be returned as a unix timestamp representation divided by 1000.
311 * String values will be atempted to be converted into an int, if that fails, 0 will be returned.
312 * Everything else will return 0.
317 case STRING : return Integer.parseInt(str_value);
318 case INT : return (int)int_value;
319 case LONG : return (int)int_value;
320 case FLOAT : return (int)float_value;
321 case DOUBLE : return (int)float_value;
322 case BOOLEAN : return (int)int_value;
323 case TIMESTAMP : return (int)(int_value/1000);
325 }catch(Exception e){}
330 * Attempts to return a long representation of this value.
331 * Numerical values will be returned directly.
332 * Boolean values will be returned as 1 or 0.
333 * Timestamp values will be returned as a unix timestamp representation.
334 * String values will be atempted to be converted into an int, if that fails, 0 will be returned.
335 * Everything else will return 0.
337 public long getLong(){
340 case STRING : return Long.parseLong(str_value);
341 case INT : return int_value;
342 case LONG : return int_value;
343 case FLOAT : return (long)float_value;
344 case DOUBLE : return (long)float_value;
345 case BOOLEAN : return int_value;
346 case TIMESTAMP : return int_value;
348 }catch(Exception e){}
353 * Attempts to return a float representation of this value.
354 * Numerical values will be returned directly (demoted if necessary).
355 * Boolean values will be returned as 1 or 0.
356 * Timestamp values will be returned as a unix timestamp representation divided by 1000.
357 * String values will be atempted to be converted into a float, if that fails, 0 will be returned.
358 * Everything else will return 0.
360 public float getFloat(){
363 case STRING : return Float.parseFloat(str_value);
364 case INT : return (float)int_value;
365 case LONG : return (float)int_value;
366 case FLOAT : return (float)float_value;
367 case DOUBLE : return (float)float_value;
368 case BOOLEAN : return (float)int_value;
369 case TIMESTAMP : return (float)(int_value/1000);
371 }catch(Exception e){}
376 * Attempts to return a double representation of this value.
377 * Numerical values will be returned directly.
378 * Boolean values will be returned as 1 or 0.
379 * Timestamp values will be returned as a unix timestamp representation divided by 1000.
380 * String values will be atempted to be converted into a float, if that fails, 0 will be returned.
381 * Everything else will return 0.
383 public double getDouble(){
386 case STRING : return Double.parseDouble(str_value);
387 case INT : return (double)int_value;
388 case LONG : return (double)int_value;
389 case FLOAT : return (double)float_value;
390 case DOUBLE : return (double)float_value;
391 case BOOLEAN : return (double)int_value;
392 case TIMESTAMP : return (double)(int_value);
394 }catch(Exception e){}
399 * Returns a boolean representation of this value.
400 * Boolean values will be returned directly.
401 * Integer values equalling 1 will be returned as true.
402 * String values equalling true,1,t,yes,on will be returned as true (case insensitive).
403 * Everything else will be returned as false.
405 * @return a boolean representation of this value.
407 public boolean getBoolean(){
410 case STRING : if(str_value.toLowerCase().trim().equals("true"))return true;
411 if(str_value.trim().equals("1"))return true;
412 if(str_value.toLowerCase().trim().equals("t"))return true;
413 if(str_value.toLowerCase().trim().equals("yes"))return true;
414 if(str_value.toLowerCase().trim().equals("on"))return true;
415 case INT : if(int_value==1)return true;
416 case LONG : if(int_value==1)return true;
417 case FLOAT : if(float_value==1.0f)return true;
418 case DOUBLE : if(float_value==1.0)return true;
419 case BOOLEAN : if(int_value==1)return true;
421 }catch(Exception e){}
426 * Attempts to return this value as a Date object.
427 * For non date numerical values, the following rules will be used for conversion:
428 * int and float will be multiplied by 1000 and used as a unix timestamp.
429 * long and double will be used directly as a unix timestamp.
430 * Any other type will result in a Date object initialized with 0.
432 * @return a Date object representation of this value
434 public Date getTimestamp(){
437 case INT : return new Date(int_value*1000l);
438 case LONG : return new Date(int_value);
439 case FLOAT : return new Date((long)(float_value*1000l));
440 case DOUBLE : return new Date((long)float_value);
441 case TIMESTAMP : return new Date(int_value);
443 }catch(Exception e){}
447 public byte[] getBinary(){
449 case BINARY : return binary;
455 * Attempts to write this Value to the given DataOutputStream.
456 * The Value will be written as a byte signifying the type of the Value, followed by the actual Value in the native format used by DataOutput.
457 * The exception to this is the string which is written as an integer followed by each character as a single char.
459 * @param out the DataOutputStream the Value should be written to
461 public void writeToStream(DataOutputStream out) throws IOException{
464 case STRING : out.writeInt(str_value.length());
465 for(int i=0;i<str_value.length();i++){
466 out.writeChar(str_value.charAt(i));
469 case INT : out.writeInt((int)int_value);
471 case LONG : out.writeLong(int_value);
473 case FLOAT : out.writeFloat((float)float_value);
475 case DOUBLE : out.writeDouble(float_value);
477 case BOOLEAN: out.writeBoolean(int_value==1);
479 case TIMESTAMP: out.writeLong(int_value);
481 case BINARY : out.writeInt(binary.length);
482 out.write(binary,0,binary.length);
488 * Attempts to write this Value to the given DataOutputStream.
489 * The Value will be written as a byte signifying the type of the Value, followed by the actual Value in the native format used by DataOutput.
490 * The exception to this is the string which is written as an integer followed by each character as a single char.
492 * @param out the DataOutputStream the Value should be written to
494 public void writeToFile(DataOutput out) throws IOException{
497 case STRING : out.writeInt(str_value.length());
498 for(int i=0;i<str_value.length();i++){
499 out.writeChar(str_value.charAt(i));
502 case INT : out.writeInt((int)int_value);
504 case LONG : out.writeLong(int_value);
506 case FLOAT : out.writeFloat((float)float_value);
508 case DOUBLE : out.writeDouble(float_value);
510 case BOOLEAN: out.writeBoolean(int_value==1);
512 case TIMESTAMP: out.writeLong(int_value);
514 case BINARY : out.writeInt(binary.length);
515 out.write(binary,0,binary.length);
520 * Attempts to read a new Value from the given DataInputStream.
521 * The Value should be in the format delivered by writeToStream.
523 * @param in the DataInputStream the Value should be read from
524 * @return the Value read from the stream
526 public static Value readFromStream(DataInputStream in) throws IOException{
527 byte type=in.readByte();
529 case STRING : int size=in.readInt();
530 StringBuffer buf=new StringBuffer();
531 for(int i=0;i<size;i++){
532 buf.append(in.readChar());
534 return new Value(buf.toString());
535 case INT : return new Value(in.readInt());
536 case LONG : return new Value(in.readLong());
537 case FLOAT : return new Value(in.readFloat());
538 case DOUBLE : return new Value(in.readDouble());
539 case BOOLEAN: return new Value(in.readBoolean());
540 case TIMESTAMP: return new Value(new Date(in.readLong()));
541 case BINARY : int length=in.readInt();
542 byte[] abuf=new byte[length];
545 read+=in.read(abuf,read,length-read);
547 return new Value(abuf);
554 * Initializes this Value with the given String.
556 * @param val the value this Value object should represent
558 public Value(String val){
563 public Value(byte[] val){
569 * Initializes this Value with the given Date.
570 * The Dates internal long value delivered by the getTime() method will be used.
572 * @param val the value this Value object should represent
574 public Value(Date val){
575 int_value=val.getTime();
580 * Initializes this Value as null.
587 * Initializes this Value with the given int.
589 * @param val the value this Value object should represent
591 public Value(int val){
597 * Initializes this Value with the given long.
599 * @param val the value this Value object should represent
601 public Value(long val){
607 * Initializes this Value with the given float.
609 * @param val the value this Value object should represent
611 public Value(float val){
617 * Initializes this Value with the given double.
619 * @param val the value this Value object should represent
621 public Value(double val){
627 * Initializes this Value with the given boolean.
629 * @param val the value this Value object should represent
631 public Value(boolean val){