/*
* This file is part of the HyperGraphDB source distribution. This is copyrighted
* software. For permitted uses, licensing options and redistribution, please see
* the LicensingInformation file at the root level of the distribution.
*
* Copyright (c) 2005-2010 Kobrix Software, Inc. All rights reserved.
*/
package org.hypergraphdb.atom;
import org.hypergraphdb.HGHandle;
/**
* <p>
* An instance <code>HGAtomRef</code> represents a reference to a HyperGraph atom. Atom
* references can be used as atom values or as values of projections of composite types.
* </p>
*
* <p>
* An <code>HGAtomRef</code> is more than a <code>HGHandle</code> because it has a special
* relationship with its referent and <strong>may</strong> play a role in the latter's lifetime.
* While a <code>HGHandle</code> can be thought of as a plain pointer, a <code>HGAtomRef</code>
* is more like a <em>smart pointer</em>. When a <code>HGAtomRef</code> is removed from HyperGraph,
* the underlying referent might be affected depending on the <em>mode</em> of the reference.
* </p>
*
* <p>
* The mode of an atom reference defines how it affects the lifetime of the atom it refers to.
* There are several possibilities and an application must choose the most suitable one:
*
* <ol>
* <li>The referent is an atom that is mainly accessed through its <code>HGAtomRef</code>s and
* generally has no purpose of being outside of that context.</li>
* <li>The referent has no particular relationship to the referee, but one needs to explicitly
* represent a reference to an atom for the purposes automatic dereferencing, as opposed to just
* storing a handle which is a pure reference value.</li>
* <li>The reference is an atom that may carry valuable information that is accessible through
* queries and other means, and it is possible to re-establish atom references to it even after
* their removal.</li>
* </ol>
*
* The above three cases are represented by the three possible modes of an atom reference:
* <code>HARD</code>, <code>SYMBOLIC</code> and <code>FLOATING</code> respectively. The
* terms <code>HARD</code> and <code>SYMBOLIC</code> were chosen because of their familiarity
* from Unix and derivative file systems since atom references with those modes behave like
* the corresponding file links in those systems. The term <code>FLOATING</code> is specific to
* HyperGraph and it has the effect of transforming a referred to atom to a temporary, managed
* atom that gets removed if not used.
* </p>
*
* <p>
* Both a <code>HARD</code> and a <code>FLOATING</code> reference will prevent an atom from
* being removed from a HyperGraph database. That is, a call to <code>HyperGraph.remove(atomHandle)</code> will
* have no effect and return <code>false</code> whenever there's a <code>HARD</code> or a <code>FLOATING</code>
* reference to that <code>atomHandle</code>. On the other hand, <code>SYMBOLIC</code> references impose
* no such constraint. As a result, a symbolic reference may point to a non-existing atom which
* generally translates to <code>null<code>.
* </p>
*
* <code>When a mixture of both floating and hard references point to an atom, floating references take
* precedence in the management of the atom's lifetime. That is, when all hard references are deleted, but
* a floating reference remains, the atom is not going to be deleted. Also, when both all hard reference and all
* floating references are deleted, the atom is transformed into a <code>MANAGED</code> atom instead of
* being removed.
* </p>
*
* @author Borislav Iordanov
*/
public class HGAtomRef
{
public enum Mode
{
/**
* This constant define a <code>HARD</code> reference mode. This behavior of
* hard references is like the Unix file system hard links: when all hard references
* are removed from HyperGraph, the referent is removed as well.
*/
hard((byte)0),
/**
* This constant define a <code>SYMBOLIC</code> reference mode. This behavior of
* symbolic references is like the Unix file system symbolic links: they are just pointers
* to the referent without an effect on its lifetime.
*/
symbolic((byte)1),
/**
* This constant define an <code>FLOATING</code> reference mode. This behavior of
* floating references is particular to HyperGraph: when removed they will leave the
* referent as a temporary atom that will eventually be automatically removed
* from HyperGraph if not used. This behavior relies on the <code>MANAGED</code>
* system-level atom attribute. If the referent is not managed when the last floating reference
* is removed, it will be tagged as managed from then on. Thus it is still possible to
* access the atom by some other means (e.g. a handle to it is kept somewhere or through
* a query) and re-establish a <code>HGAtomRef</code> to it.
*/
floating((byte)2);
private byte code;
private Mode(byte code) { this.code = code; }
public byte getCode() { return code; }
public static Mode get(byte code)
{ if (code == 0) return hard; else if (code == 1) return symbolic; else return floating; }
}
private HGHandle referent;
private Mode mode;
/**
* <p>Construct a new <code>HGAtomRef</code> to the atom pointed by <code>reference<code>
* and with the specified <code>mode</code>.
*
* @param referent The <code>HGHandle</code> of the refered to atom.
* @param mode The atom reference mode.
* this class.
*/
public HGAtomRef(HGHandle referent, Mode mode)
{
this.referent = referent;
this.mode = mode;
}
/**
* <p>Return the atom reference mode.</p>
*/
public Mode getMode()
{
return mode;
}
/**
* <p>Return <code>true</code> if this is a hard reference and <code>false</code> otherwise.</p>
*/
public boolean isHard()
{
return mode == Mode.hard;
}
/**
* <p>Return <code>true</code> if this is a symbolic reference and <code>false</code> otherwise.</p>
*/
public boolean isSymbolic()
{
return mode == Mode.symbolic;
}
/**
* <p>Return <code>true</code> if this is a floating reference and <code>false</code> otherwise.</p>
*/
public boolean isFloating()
{
return mode == Mode.floating;
}
/**
* <p>Return the referent atom.</p>
*/
public HGHandle getReferent()
{
return referent;
}
}