diff options
Diffstat (limited to 'lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java')
-rw-r--r-- | lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java new file mode 100644 index 0000000000..8056439962 --- /dev/null +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java @@ -0,0 +1,264 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2000-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +package com.ericsson.otp.erlang; + +import java.io.Serializable; + +/** + * Provides a Java representation of Erlang refs. There are two styles of Erlang + * refs, old style (one id value) and new style (array of id values). This class + * manages both types. + */ +public class OtpErlangRef extends OtpErlangObject implements Serializable, + Cloneable { + // don't change this! + static final long serialVersionUID = -7022666480768586521L; + + private final String node; + private final int creation; + + // old style refs have one 18-bit id + // r6 "new" refs have array of ids, first one is only 18 bits however + private int ids[] = null; + + /** + * Create a unique Erlang ref belonging to the local node. + * + * @param self + * the local node. + * + * @deprecated use OtpLocalNode:createRef() instead + */ + @Deprecated + public OtpErlangRef(final OtpLocalNode self) { + final OtpErlangRef r = self.createRef(); + + ids = r.ids; + creation = r.creation; + node = r.node; + } + + /** + * Create an Erlang ref from a stream containing a ref encoded in Erlang + * external format. + * + * @param buf + * the stream containing the encoded ref. + * + * @exception OtpErlangDecodeException + * if the buffer does not contain a valid external + * representation of an Erlang ref. + */ + public OtpErlangRef(final OtpInputStream buf) + throws OtpErlangDecodeException { + final OtpErlangRef r = buf.read_ref(); + + node = r.node(); + creation = r.creation(); + + ids = r.ids(); + } + + /** + * Create an old style Erlang ref from its components. + * + * @param node + * the nodename. + * + * @param id + * an arbitrary number. Only the low order 18 bits will be + * used. + * + * @param creation + * another arbitrary number. Only the low order 2 bits will + * be used. + */ + public OtpErlangRef(final String node, final int id, final int creation) { + this.node = node; + ids = new int[1]; + ids[0] = id & 0x3ffff; // 18 bits + this.creation = creation & 0x03; // 2 bits + } + + /** + * Create a new style Erlang ref from its components. + * + * @param node + * the nodename. + * + * @param ids + * an array of arbitrary numbers. Only the low order 18 bits + * of the first number will be used. If the array contains + * only one number, an old style ref will be written instead. + * At most three numbers will be read from the array. + * + * @param creation + * another arbitrary number. Only the low order 2 bits will + * be used. + */ + public OtpErlangRef(final String node, final int[] ids, final int creation) { + this.node = node; + this.creation = creation & 0x03; // 2 bits + + // use at most 82 bits (18 + 32 + 32) + int len = ids.length; + this.ids = new int[3]; + this.ids[0] = 0; + this.ids[1] = 0; + this.ids[2] = 0; + + if (len > 3) { + len = 3; + } + System.arraycopy(ids, 0, this.ids, 0, len); + this.ids[0] &= 0x3ffff; // only 18 significant bits in first number + } + + /** + * Get the id number from the ref. Old style refs have only one id number. + * If this is a new style ref, the first id number is returned. + * + * @return the id number from the ref. + */ + public int id() { + return ids[0]; + } + + /** + * Get the array of id numbers from the ref. If this is an old style ref, + * the array is of length 1. If this is a new style ref, the array has + * length 3. + * + * @return the array of id numbers from the ref. + */ + public int[] ids() { + return ids; + } + + /** + * Determine whether this is a new style ref. + * + * @return true if this ref is a new style ref, false otherwise. + */ + public boolean isNewRef() { + return ids.length > 1; + } + + /** + * Get the creation number from the ref. + * + * @return the creation number from the ref. + */ + public int creation() { + return creation; + } + + /** + * Get the node name from the ref. + * + * @return the node name from the ref. + */ + public String node() { + return node; + } + + /** + * Get the string representation of the ref. Erlang refs are printed as + * #Ref<node.id> + * + * @return the string representation of the ref. + */ + @Override + public String toString() { + String s = "#Ref<" + node; + + for (int i = 0; i < ids.length; i++) { + s += "." + ids[i]; + } + + s += ">"; + + return s; + } + + /** + * Convert this ref to the equivalent Erlang external representation. + * + * @param buf + * an output stream to which the encoded ref should be + * written. + */ + @Override + public void encode(final OtpOutputStream buf) { + buf.write_ref(node, ids, creation); + } + + /** + * Determine if two refs are equal. Refs are equal if their components are + * equal. New refs and old refs are considered equal if the node, creation + * and first id numnber are equal. + * + * @param o + * the other ref to compare to. + * + * @return true if the refs are equal, false otherwise. + */ + @Override + public boolean equals(final Object o) { + if (!(o instanceof OtpErlangRef)) { + return false; + } + + final OtpErlangRef ref = (OtpErlangRef) o; + + if (!(node.equals(ref.node()) && creation == ref.creation())) { + return false; + } + + if (isNewRef() && ref.isNewRef()) { + return ids[0] == ref.ids[0] && ids[1] == ref.ids[1] + && ids[2] == ref.ids[2]; + } + return ids[0] == ref.ids[0]; + } + + /** + * Compute the hashCode value for a given ref. This function is compatible + * with equal. + * + * @return the hashCode of the node. + **/ + + @Override + protected int doHashCode() { + OtpErlangObject.Hash hash = new OtpErlangObject.Hash(7); + hash.combine(creation, ids[0]); + if (isNewRef()) { + hash.combine(ids[1], ids[2]); + } + return hash.valueOf(); + } + + @Override + public Object clone() { + final OtpErlangRef newRef = (OtpErlangRef) super.clone(); + newRef.ids = ids.clone(); + return newRef; + } +} |