All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.orientechnologies.orient.core.id.ORecordId Maven / Gradle / Ivy

/*
 *
 *  *  Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
 *  *
 *  *  Licensed 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.
 *  *
 *  * For more information: http://www.orientechnologies.com
 *
 */
package com.orientechnologies.orient.core.id;

import com.orientechnologies.orient.core.db.ODatabaseRecordThreadLocal;
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.exception.ODatabaseException;
import com.orientechnologies.orient.core.record.ORecord;
import com.orientechnologies.orient.core.serialization.OBinaryProtocol;
import com.orientechnologies.orient.core.serialization.OMemoryStream;
import com.orientechnologies.orient.core.serialization.serializer.OStringSerializerHelper;
import com.orientechnologies.orient.core.storage.OStorage;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

public class ORecordId implements ORID {
  public static final ORecordId EMPTY_RECORD_ID        = new ORecordId();
  public static final byte[]    EMPTY_RECORD_ID_STREAM = EMPTY_RECORD_ID.toStream();
  public static final int       PERSISTENT_SIZE        = OBinaryProtocol.SIZE_SHORT + OBinaryProtocol.SIZE_LONG;
  private static final long     serialVersionUID       = 247070594054408657L;
  // INT TO AVOID JVM PENALTY, BUT IT'S STORED AS SHORT
  public int                    clusterId              = CLUSTER_ID_INVALID;
  public long                   clusterPosition        = CLUSTER_POS_INVALID;

  public ORecordId() {
  }

  public ORecordId(final int iClusterId, final long iPosition) {
    clusterId = iClusterId;
    checkClusterLimits();
    clusterPosition = iPosition;
  }

  public ORecordId(final int iClusterIdId) {
    clusterId = iClusterIdId;
    checkClusterLimits();
  }

  public ORecordId(final String iRecordId) {
    fromString(iRecordId);
  }

  /**
   * Copy constructor.
   * 
   * @param parentRid
   *          Source object
   */
  public ORecordId(final ORID parentRid) {
    clusterId = parentRid.getClusterId();
    clusterPosition = parentRid.getClusterPosition();
  }

  public static String generateString(final int iClusterId, final long iPosition) {
    final StringBuilder buffer = new StringBuilder(12);
    buffer.append(PREFIX);
    buffer.append(iClusterId);
    buffer.append(SEPARATOR);
    buffer.append(iPosition);
    return buffer.toString();
  }

  public static boolean isValid(final long pos) {
    return pos != CLUSTER_POS_INVALID;
  }

  public static boolean isPersistent(final long pos) {
    return pos > CLUSTER_POS_INVALID;
  }

  public static boolean isNew(final long pos) {
    return pos < 0;
  }

  public static boolean isTemporary(final long clusterPosition) {
    return clusterPosition < CLUSTER_POS_INVALID;
  }

  public static boolean isA(final String iString) {
    return iString.matches("#(-?[0-9]+):(-?[0-9]+)");
  }

  public void reset() {
    clusterId = CLUSTER_ID_INVALID;
    clusterPosition = CLUSTER_POS_INVALID;
  }

  public boolean isValid() {
    return clusterPosition != CLUSTER_POS_INVALID;
  }

  public boolean isPersistent() {
    return clusterId > -1 && clusterPosition > CLUSTER_POS_INVALID;
  }

  public boolean isNew() {
    return clusterPosition < 0;
  }

  public boolean isTemporary() {
    return clusterId != -1 && clusterPosition < CLUSTER_POS_INVALID;
  }

  @Override
  public String toString() {
    return generateString(clusterId, clusterPosition);
  }

  public StringBuilder toString(StringBuilder iBuffer) {
    if (iBuffer == null)
      iBuffer = new StringBuilder();

    iBuffer.append(PREFIX);
    iBuffer.append(clusterId);
    iBuffer.append(SEPARATOR);
    iBuffer.append(clusterPosition);
    return iBuffer;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (!(obj instanceof OIdentifiable))
      return false;
    final ORecordId other = (ORecordId) ((OIdentifiable) obj).getIdentity();

    if (clusterId != other.clusterId)
      return false;
    if (clusterPosition != other.clusterPosition)
      return false;
    return true;
  }

  @Override
  public int hashCode() {
    int result = clusterId;
    result = 31 * result + (int) (clusterPosition ^ (clusterPosition >>> 32));
    return result;
  }

  public int compareTo(final OIdentifiable iOther) {
    if (iOther == this)
      return 0;

    if (iOther == null)
      return 1;

    final int otherClusterId = iOther.getIdentity().getClusterId();
    if (clusterId == otherClusterId) {
      final long otherClusterPos = iOther.getIdentity().getClusterPosition();

      return (clusterPosition < otherClusterPos) ? -1 : ((clusterPosition == otherClusterPos) ? 0 : 1);
    } else if (clusterId > otherClusterId)
      return 1;

    return -1;
  }

  public int compare(final OIdentifiable iObj1, final OIdentifiable iObj2) {
    if (iObj1 == iObj2)
      return 0;

    if (iObj1 != null)
      return iObj1.compareTo(iObj2);

    return -1;
  }

  public ORecordId copy() {
    return new ORecordId(clusterId, clusterPosition);
  }

  public ORecordId fromStream(final InputStream iStream) throws IOException {
    clusterId = OBinaryProtocol.bytes2short(iStream);
    clusterPosition = OBinaryProtocol.bytes2long(iStream);
    return this;
  }

  public ORecordId fromStream(final OMemoryStream iStream) {
    clusterId = iStream.getAsShort();
    clusterPosition = iStream.getAsLong();
    return this;
  }

  public ORecordId fromStream(final byte[] iBuffer) {
    if (iBuffer != null) {
      clusterId = OBinaryProtocol.bytes2short(iBuffer, 0);
      clusterPosition = OBinaryProtocol.bytes2long(iBuffer, OBinaryProtocol.SIZE_SHORT);
    }
    return this;
  }

  public int toStream(final OutputStream iStream) throws IOException {
    final int beginOffset = OBinaryProtocol.short2bytes((short) clusterId, iStream);
    OBinaryProtocol.long2bytes(clusterPosition, iStream);
    return beginOffset;
  }

  public int toStream(final OMemoryStream iStream) throws IOException {
    final int beginOffset = OBinaryProtocol.short2bytes((short) clusterId, iStream);
    OBinaryProtocol.long2bytes(clusterPosition, iStream);
    return beginOffset;
  }

  public byte[] toStream() {
    final byte[] buffer = new byte[OBinaryProtocol.SIZE_SHORT + OBinaryProtocol.SIZE_LONG];

    OBinaryProtocol.short2bytes((short) clusterId, buffer, 0);
    OBinaryProtocol.long2bytes(clusterPosition, buffer, OBinaryProtocol.SIZE_SHORT);

    return buffer;
  }

  public int getClusterId() {
    return clusterId;
  }

  public long getClusterPosition() {
    return clusterPosition;
  }

  public void fromString(String iRecordId) {
    if (iRecordId != null)
      iRecordId = iRecordId.trim();

    if (iRecordId == null || iRecordId.isEmpty()) {
      clusterId = CLUSTER_ID_INVALID;
      clusterPosition = CLUSTER_POS_INVALID;
      return;
    }

    if (!OStringSerializerHelper.contains(iRecordId, SEPARATOR))
      throw new IllegalArgumentException("Argument '" + iRecordId
          + "' is not a RecordId in form of string. Format must be: :");

    final List parts = OStringSerializerHelper.split(iRecordId, SEPARATOR, PREFIX);

    if (parts.size() != 2)
      throw new IllegalArgumentException("Argument received '" + iRecordId
          + "' is not a RecordId in form of string. Format must be: #:. Example: #3:12");

    clusterId = Integer.parseInt(parts.get(0));
    checkClusterLimits();
    clusterPosition = Long.parseLong(parts.get(1));
  }

  public void copyFrom(final ORID iSource) {
    if (iSource == null)
      throw new IllegalArgumentException("Source is null");

    clusterId = iSource.getClusterId();
    clusterPosition = iSource.getClusterPosition();
  }

  @Override
  public void lock(final boolean iExclusive) {
    ODatabaseRecordThreadLocal.INSTANCE.get().getTransaction()
        .lockRecord(this, iExclusive ? OStorage.LOCKING_STRATEGY.EXCLUSIVE_LOCK : OStorage.LOCKING_STRATEGY.SHARED_LOCK);
  }

  @Override
  public boolean isLocked() {
    return ODatabaseRecordThreadLocal.INSTANCE.get().getTransaction().isLockedRecord(this);
  }

  @Override
  public void unlock() {
    ODatabaseRecordThreadLocal.INSTANCE.get().getTransaction().unlockRecord(this);
  }

  public String next() {
    return generateString(clusterId, clusterPosition + 1);
  }

  @Override
  public ORID nextRid() {
    return new ORecordId(clusterId, clusterPosition + 1);
  }

  public ORID getIdentity() {
    return this;
  }

  @SuppressWarnings("unchecked")
  public  T getRecord() {
    if (!isValid())
      return null;

    final ODatabaseDocument db = ODatabaseRecordThreadLocal.INSTANCE.get();
    if (db == null)
      throw new ODatabaseException(
          "No database found in current thread local space. If you manually control databases over threads assure to set the current database before to use it by calling: ODatabaseRecordThreadLocal.INSTANCE.set(db);");

    return (T) db.load(this);
  }

  private void checkClusterLimits() {
    if (clusterId < -2)
      throw new ODatabaseException("RecordId cannot support negative cluster id. You've used: " + clusterId);

    if (clusterId > CLUSTER_MAX)
      throw new ODatabaseException("RecordId cannot support cluster id major than 32767. You've used: " + clusterId);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy