com.dal.vv.type.AbstractValue.java Source code

Java tutorial

Introduction

Here is the source code for com.dal.vv.type.AbstractValue.java

Source

/*
 * Copyright (C) 1995-2016Dal Solutions, Inc.
 * All Rights Reserved
 * Inquire at License@dal-solutions.com
 */
package com.dal.vv.type;

import com.dal.a.type.Size;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.List;

import com.dal.a.type.ValueType;
import com.dal.a.model.dictionary.Value;
import com.dal.vv.cfg.ConfigurationFactory;
import com.dal.vv.cfg.def.VoxelSettings;
import org.apache.commons.configuration.Configuration;

/**
 *
 * @author Dan Adams
 */
abstract class AbstractValue implements Value {
    static final Configuration cfg = ConfigurationFactory.getConfiguration();
    protected final Size size;
    protected byte[] value;

    public abstract ValueType getType();

    AbstractValue(Size bits) {
        size = bits;
        value = new byte[size.getBytes()];
    }

    AbstractValue(String sequence) {
        String charSet = cfg.getString(VoxelSettings.CHAR_SET);
        try {
            value = sequence.getBytes(charSet);
            size = Size.variable;
        } catch (UnsupportedEncodingException ex) {
            throw new RuntimeException("Fatal error mapping " + charSet, ex);
        }
    }

    AbstractValue(List<? extends Value> list) {
        size = Size.variable;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final AbstractValue other = (AbstractValue) obj;
        return Arrays.equals(this.value, other.value);
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 83 * hash + Arrays.hashCode(this.value);
        return hash;
    }

    @Override
    public String toString() {
        try {
            return asString();
        } catch (InvalidConversionException | OverflowException x) {
        }

        return null;
    }

    @Override
    public boolean asBoolean() {
        for (byte b : value) {
            if (0 < b) {
                return true;
            }
        }

        return false;
    }

    @Override
    public byte asByte() {
        byte result = 0;

        switch (size) {
        case variable:
        case sixtyfour:
        case thirtytwo:
        case sixteen:
            throw new OverflowException("Data loss mapping to 8 bits");
        case eight:
        case four:
        case one:
            result += value[0];
        }

        return result;
    }

    @Override
    public double asDouble() {
        return Double.longBitsToDouble(asLong());
    }

    @Override
    public float asFloat() {
        return Float.intBitsToFloat(asInt());
    }

    @Override
    @SuppressWarnings("fallthrough")
    public int asInt() {
        int result = 0;

        switch (size) {
        case variable:
        case sixtyfour:
            throw new OverflowException("Data loss mapping to 32 bits");
        case thirtytwo:
            result += ((int) (0xFF & value[3]) << 24);
            result += ((int) (0xFF & value[2]) << 16);
        case sixteen:
            result += ((int) (0xFF & value[1]) << 8);
        case eight:
        case four:
        case one:
            result += ((int) (0xFF & value[0]));
        }

        return result;
    }

    @Override
    @SuppressWarnings("fallthrough")
    public long asLong() {
        long result = 0l;

        switch (size) {
        case variable:
            throw new OverflowException("Data loss mapping to 64 bits");
        case sixtyfour:
            result += ((long) (0xFF & value[4]) << 32);
            result += ((long) (0xFF & value[5]) << 40);
            result += ((long) (0xFF & value[6]) << 48);
            result += ((long) (0xFF & value[7]) << 56);
        case thirtytwo:
            result += ((long) (0xFF & value[3]) << 24);
            result += ((long) (0xFF & value[2]) << 16);
        case sixteen:
            result += ((long) (0xFF & value[1]) << 8);
        case eight:
        case four:
        case one:
            result += (long) (0xFF & value[0]);
        }

        return result;
    }

    @Override
    @SuppressWarnings("fallthrough")
    public short asShort() {
        short result = 0;

        switch (size) {
        case variable:
        case sixtyfour:
        case thirtytwo:
            throw new OverflowException("Data loss mapping to 16 bits");
        case sixteen:
            result += ((short) 0xFF & value[1]) << 8;
        case eight:
        case four:
        case one:
            result += ((short) 0xFF & value[0]);
        }

        return result;
    }

    @Override
    public Value clear() {
        for (int index = 0; index < value.length; ++index) {
            value[index] = 0;
        }

        return this;
    }

    @Override
    public byte[] getBytes() {
        return Arrays.copyOf(value, value.length);
    }

    @Override
    public int getByteSize() {
        return size.getBytes();
    }

    @Override
    public int getBitSize() {
        return size.getBits();
    }

    @Override
    public Value load(byte data) {
        return loadNumber(data);
    }

    @Override
    public Value load(boolean data) {
        clear();
        if (Size.variable == size) {
            value = new byte[1];
        }
        value[0] = (data ? (byte) 1 : 0);

        return this;
    }

    @Override
    public Value load(short data) {
        return loadNumber(data);
    }

    @Override
    public Value load(int data) {
        return loadNumber(data);
    }

    @Override
    public Value load(byte[] data) {
        clear();
        int dataLength = data.length;
        int valueLength = size.getBytes();

        if (0 != valueLength && dataLength > valueLength) {
            throw new OverflowException("Unable to load byte array, potential data loss at byte " + valueLength);
        }

        if (Size.variable == size) {
            value = new byte[dataLength];
        }

        for (int index = 0; index < dataLength; ++index) {
            value[index] = data[index];
        }

        return this;
    }

    @Override
    public Value load(long data) {
        Value result;
        result = loadNumber(data);
        return result;
    }

    @Override
    public Value load(float data) {
        return load(Float.floatToRawIntBits(data));
    }

    @Override
    public Value load(double data) {
        return load(Double.doubleToRawLongBits(data));
    }

    @Override
    public Value load(String data) throws InvalidConversionException {
        Value result = null;
        try {
            result = load(data.getBytes(cfg.getString(VoxelSettings.CHAR_SET)));
        } catch (UnsupportedEncodingException x) {
            throw new InvalidConversionException("Failure encoding String data", x);
        }

        return result;
    }

    @SuppressWarnings("fallthrough")
    private Value loadNumber(long data) {
        clear();
        int actualSize = 64 - Long.numberOfLeadingZeros(Math.abs(data)) - (data < 0 ? 1 : 0);
        int availableBits = size.getBits();
        if (actualSize > availableBits) {
            if (Size.variable == size) {
                value = new byte[(1 + actualSize) / 8];
            } else {
                throw new OverflowException("Unable to load[" + data + "] " + actualSize + " bits only "
                        + availableBits + " available");
            }
        }

        int avail = size.getBytes();

        if (Size.variable == size) {
            avail = value.length;
        }

        switch (avail) {
        case 8:
            value[7] = (byte) ((data >> 56) & 0xFF);
            value[6] = (byte) ((data >> 48) & 0xFF);
            value[5] = (byte) ((data >> 40) & 0xFF);
            value[4] = (byte) ((data >> 32) & 0xFF);
        case 7:
        case 6:
        case 5:
        case 4:
            value[3] = (byte) ((data >> 24) & 0xFF);
            value[2] = (byte) ((data >> 16) & 0xFF);
        case 3:
        case 2:
            value[1] = (byte) ((data >> 8) & 0xFF);
        case 1:
            value[0] = (byte) (data & 0xFF);
        default:
        }

        return this;
    }

    protected static byte[] longBytes(long data) {
        byte[] result = new byte[8];

        result[7] = (byte) ((data >> 56) & 0xFF);
        result[6] = (byte) ((data >> 48) & 0xFF);
        result[5] = (byte) ((data >> 40) & 0xFF);
        result[4] = (byte) ((data >> 32) & 0xFF);
        result[3] = (byte) ((data >> 24) & 0xFF);
        result[2] = (byte) ((data >> 16) & 0xFF);
        result[1] = (byte) ((data >> 8) & 0xFF);
        result[0] = (byte) (data & 0xFF);

        return result;
    }

    protected static byte[] intBytes(long data) {
        byte[] result = new byte[4];

        result[3] = (byte) ((data >> 24) & 0xFF);
        result[2] = (byte) ((data >> 16) & 0xFF);
        result[1] = (byte) ((data >> 8) & 0xFF);
        result[0] = (byte) (data & 0xFF);

        return result;
    }

    protected static byte[] shortBytes(short data) {
        byte[] result = new byte[2];

        result[1] = (byte) ((data >> 8) & 0xFF);
        result[0] = (byte) (data & 0xFF);

        return result;
    }
}