Package org.chaidb.db.api.keys

Source Code of org.chaidb.db.api.keys.NodeId

/*
* Copyright (C) 2006  http://www.chaidb.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
*/

package org.chaidb.db.api.keys;

import org.chaidb.db.exception.ChaiDBException;
import org.chaidb.db.exception.ErrorCode;
import org.chaidb.db.index.Key;

import java.util.ArrayList;
import java.util.StringTokenizer;

public class NodeId implements Key {

    // we need to hidden the doc id from outside
    private int docId;
    public int nodeId;
    private byte nodeType;
    private boolean isSpecialId = false;
    public static final boolean SPECIAL_NODE_ID = true;
    public static final boolean NORMAL_NODE_ID = false;

    /**
     * the byte array representation of this Id
     */
    private byte[] _bytesRep = null;

    /**
     * Construct a NodeIdKey from byte[].
     */
    public NodeId(byte[] encoded) {
        // retrieve docId
        docId = 0;
        docId = docId | ((encoded[0] & 0xff) << 16);
        docId = docId | ((encoded[1] & 0xff) << 8);
        docId = docId | ((encoded[2] & 0xff));
        // retrieve nodeType
        nodeType = (byte) (encoded[3] >> 4 & 0x0f);
        // take 0000000x of reserved byte as special flag
        int special = (int) (encoded[3] & 0x01);
        isSpecialId = (special == 0) ? NORMAL_NODE_ID : SPECIAL_NODE_ID;
        // retrieve nodeId
        nodeId = 0;
        nodeId = nodeId | ((encoded[4] & 0xff) << 24);
        nodeId = nodeId | ((encoded[5] & 0xff) << 16);
        nodeId = nodeId | ((encoded[6] & 0xff) << 8);
        nodeId = nodeId | ((encoded[7] & 0xff));
    }

    /**
     * Constructor
     */
    public NodeId(int docId, int nodeId, byte nodeType) {
        this.docId = docId;
        this.nodeId = nodeId;
        this.nodeType = nodeType;
        this.isSpecialId = NORMAL_NODE_ID;
    }

    /**
     * Constructor
     */
    public NodeId createSpecialNodeId() {
        NodeId specialNodeId = new NodeId(this.docId, this.nodeId, this.nodeType);
        specialNodeId.setToSpecialId();
        return specialNodeId;
    }

    /**
     * Constructor
     * create special node id by doc id , node id, node type
     */
    public static NodeId createSpecialNodeId(int docId, int nodeId, byte nodeType) {
        NodeId specialNodeId = new NodeId(docId, nodeId, nodeType);
        specialNodeId.setToSpecialId();
        return specialNodeId;
    }

    /**
     * Constructor
     * create normal node, node id by doc id , node id, node type
     */
    public static NodeId createNormalNodeId(int docId, int nodeId, byte nodeType) {
        NodeId specialNodeId = new NodeId(docId, nodeId, nodeType);
        specialNodeId.setToNormalId();
        return specialNodeId;
    }

    /**
     * Construct a NodeId object from the given str, which is a counterpart of
     * toString().
     */
    public NodeId(String str) {
        StringTokenizer tokens = new StringTokenizer(str, "-");
        this.docId = Integer.parseInt(tokens.nextToken());
        this.nodeId = Integer.parseInt(tokens.nextToken());
        this.nodeType = Byte.parseByte(tokens.nextToken());
        this.isSpecialId = tokens.nextToken().charAt(0) == '1';
    }

    // implemnt Key methods

    /**
     * Node ID length. A node is currently composed of 8 bytes,
     * 3 bytes for DocumentID,
     * 4 bits for node type,
     * 4 bits reserved,
     * 4 bytes for node number
     * NOTE: the returned byte[] is immutable !!!
     */
    public byte[] toBytes() {
        if (_bytesRep == null) {
            _bytesRep = _toBytes();
        }
        return _bytesRep;
    }

    private byte[] _toBytes() {
        byte[] ret = new byte[8];
        ret[0] = (byte) ((docId >>> 16) & 0xFF);
        ret[1] = (byte) ((docId >>> 8) & 0xFF);
        ret[2] = (byte) ((docId) & 0xFF);
        int specialByte = (isSpecialId) ? 0x01 : 0x00;
        ret[3] = (byte) ((nodeType << 4) | specialByte);
        ret[4] = (byte) ((nodeId >>> 24) & 0xFF);
        ret[5] = (byte) ((nodeId >>> 16) & 0xFF);
        ret[6] = (byte) ((nodeId >>> 8) & 0xFF);
        ret[7] = (byte) ((nodeId) & 0xFF);
        return ret;
    }

    public int size() {
        return 8;
    }

    /**
     * judge the node id is special node, it is used by Index
     */
    public boolean isSpecialId() {
        return isSpecialId;
    }

    public void setToSpecialId() {
        isSpecialId = true;
    }

    public void setToNormalId() {
        isSpecialId = false;
    }

    /**
     * "docId-nodeId-type-<0|1>"
     * 0 : normal Id
     * 1 : special Id
     */
    public String toString() {
        char specialId = this.isSpecialId ? '1' : '0';
        return new String(String.valueOf(docId) + '-' + String.valueOf(nodeId) + '-' + nodeType + '-' + specialId);
    }

    public int getKeyType() {
        return NODE_ID_KEY;
    }

    /**
     * get document id
     *
     * @return document id
     */
    public int getDocId() {
        return docId;
    }

    /**
     * Compares the whole key.
     *
     * @return 0 if the two key are exactly the same; negative integer (<0) if
     *         the other key's docId is bigger, or if the docIds are the same, the
     *         other key's nodeId is bigger; otherwise positive interger (>0).
     */
    public int compareTo(Key otherKey) throws ChaiDBException {
        checkKeyType(otherKey);
        return compare((NodeId) otherKey);
    }

    /**
     * small document special note, now we compare two node by doc id and node id,
     * so special node and normal node will be treated as same in BTree level.
     *
     * @param key2
     */
    private int compare(NodeId key2) {
        int ret = KeyTool.compareInt(docId, key2.getDocId());
        return ret != 0 ? ret : KeyTool.compareInt(nodeId, key2.nodeId);
    }

    private void checkKeyType(Key key) throws ChaiDBException {
        int keyType = key.getKeyType();
        if (keyType != NODE_ID_KEY) {
            ArrayList params = new ArrayList(2);
            // required
            params.add(Key.KEY_TYPES[Key.NODE_ID_KEY]);
            // found
            params.add(Key.KEY_TYPES[keyType]);
            throw new ChaiDBException(ErrorCode.INDEX_KEY_TYPE_ERROR, params);
        }
    }

    // own methods

    /**
     * Compares only document id.
     */
    public int compareDocId(Key otherKey) throws ChaiDBException {
        // checking whether the same key type
        checkKeyType(otherKey);

        NodeId key2 = (NodeId) otherKey;
        return KeyTool.compareInt(docId, key2.getDocId());
    }

    public short getNodeType() {
        return (short) nodeType;
    }

    // override java.lang.Object methods

    public int hashCode() {
        return docId ^ nodeId;
    }

    public boolean equals(Object obj) {
        if (obj instanceof NodeId) return compare((NodeId) obj) == 0;
        return false;
    }

    public Object clone() {
        if (this.isSpecialId) return createSpecialNodeId(docId, nodeId, nodeType);
        else return createNormalNodeId(docId, nodeId, nodeType);
    }
}
TOP

Related Classes of org.chaidb.db.api.keys.NodeId

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.