org.apache.jena.tdb.store.DecimalNode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jena-tdb Show documentation
Show all versions of jena-tdb Show documentation
TDB is a storage subsystem for Jena and ARQ, it is a native triple store providing persistent storage of triples/quads.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.tdb.store;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.apache.jena.atlas.lib.BitsLong ;
public class DecimalNode
{
//private static Logger log = LoggerFactory.getLogger(DecimalNode.class) ;
BigDecimal decimal = null ;
// signed 8 bits of scale, signed 48 bits of value.
// Decimal precision is 47 bits (it's signed) or around 14 places.
// Not finance industry accuracy nor XSD (18 places minimum) but still useful.
static final int SCALE_LEN = 8 ;
static final int VALUE_LEN = 48 ;
static final int ENC_LEN = 48+SCALE_LEN ;
static final long MAX_VALUE = (1L<< (VALUE_LEN-1) )-1 ;
static final long MIN_VALUE = -(1L<< (VALUE_LEN-1) ) ;
static final int MAX_SCALE = (1<< (SCALE_LEN-1) )-1 ;
static final int MIN_SCALE = -(1<< (SCALE_LEN-1) ) ;
static final BigInteger MAX_I = BigInteger.valueOf(MAX_VALUE) ;
static final BigInteger MIN_I = BigInteger.valueOf(MIN_VALUE) ;
// Bits counts
static private int SCALE_LO = 56-SCALE_LEN ;
static private int SCALE_HI = 56 ; // Exclusive index
static private int VALUE_LO = 0 ;
static private int VALUE_HI = VALUE_LO+VALUE_LEN ;
private int scale ;
private long value ;
public static DecimalNode valueOf(BigDecimal decimal)
{
int scale = decimal.scale() ;
BigInteger bigInt = decimal.unscaledValue() ;
if ( bigInt.compareTo(MAX_I) > 0 || bigInt.compareTo(MIN_I) < 0 )
// This check makes sure that bigInt.longValue() is safe
return null ;
return valueOf(bigInt.longValue(), scale) ;
}
public static DecimalNode valueOf(long binValue, int scale)
{
if ( scale < MIN_SCALE || scale > MAX_SCALE )
{
//log.warn("Scale out of range: ("+binValue+","+scale+")") ;
return null ;
}
if ( binValue < MIN_VALUE || binValue > MAX_VALUE )
{
//log.warn("Value out of range: ("+binValue+","+scale+")") ;
return null ;
}
return new DecimalNode(binValue, scale) ;
}
private DecimalNode(long value, int scale)
{
this.scale = scale ;
this.value = value ;
}
public long pack() { return pack(value, scale) ; }
public static long pack(long value, int scale)
{
// pack : DECIMAL , sign, scale, value
long v = BitsLong.pack(0, NodeId.DECIMAL, ENC_LEN, Long.SIZE) ;
v = BitsLong.pack(v, scale, SCALE_LO, SCALE_HI) ;
v = BitsLong.pack(v, value, VALUE_LO, VALUE_HI) ;
// No need to do something about negative numbers
return v ;
}
public static DecimalNode unpack(long v)
{
//assert BitsLong.unpack(v, 56, 64) == NodeId.DECIMAL ;
int scale = (int)BitsLong.unpack(v, SCALE_LO, SCALE_HI) ;
long value = BitsLong.unpack(v, VALUE_LO, VALUE_HI) ;
return new DecimalNode(value, scale) ;
}
public static BigDecimal unpackAsBigDecimal(long v)
{
// Can I say tuples-in-java? Or "Multiple return values"?
//assert BitsLong.unpack(v, 56, 64) == NodeId.DECIMAL ;
int scale = (int)BitsLong.unpack(v, SCALE_LO, SCALE_HI) ;
long value = BitsLong.unpack(v, VALUE_LO, VALUE_HI) ;
// Sign extend value.
if ( BitsLong.isSet(value, VALUE_HI-1) )
value = value | -1L<<(VALUE_HI) ;
return BigDecimal.valueOf(value, scale) ;
}
public BigDecimal get()
{
if ( decimal == null )
decimal = BigDecimal.valueOf(value, scale) ;
return decimal ;
}
@Override
public String toString()
{
return get().toPlainString() ;
}
public int getScale()
{
return scale ;
}
public long getValue()
{
return value ;
}
}