1 package org.rosuda.REngine;
3 /** this class represents a reference (proxy) to an R object.
5 The reference semantics works by calling {@link #resolve()} (which in turn uses {@link REngine#resolveReference(REXP)} on itself) whenever any methods are accessed. The implementation is not finalized yat and may change as we approach the JRI interface which is more ameanable to reference-style access. Subclasses are free to implement more efficient implementations. */
6 public class REXPReference extends REXP {
7 /** engine which will be used to resolve the reference */
9 /** an opaque (optional) handle */
10 protected Object handle;
11 /** resolved (cached) object */
12 protected REXP resolvedValue;
14 /** create an external REXP reference using given engine and handle. The handle value is just an (optional) identifier not used by the implementation directly. */
15 public REXPReference(REngine eng, Object handle) {
21 /** shortcut for <code>REXPReference(eng, new Long(handle))</code> that is used by native code */
22 REXPReference(REngine eng, long handle) {
23 this(eng, new Long(handle));
26 /** resolve the external REXP reference into an actual REXP object. In addition, the value (if not <code>null</code>) will be cached for subsequent calls to <code>resolve</code> until <code>invalidate</code> is called. */
27 public REXP resolve() {
28 if (resolvedValue != null)
31 resolvedValue = eng.resolveReference(this);
33 } catch (REXPMismatchException me) {
34 // this should never happen since we are REXPReference
35 } catch(REngineException ee) {
36 // FIXME: what to we do?
41 /** invalidates any cached representation of the reference */
42 public void invalidate() {
46 /** finalization that notifies the engine when a reference gets collected */
47 protected void finalize() throws Throwable {
49 eng.finalizeReference(this);
55 public boolean isString() { return resolve().isString(); }
56 public boolean isNumeric() { return resolve().isNumeric(); }
57 public boolean isInteger() { return resolve().isInteger(); }
58 public boolean isNull() { return resolve().isNull(); }
59 public boolean isFactor() { return resolve().isFactor(); }
60 public boolean isList() { return resolve().isList(); }
61 public boolean isLogical() { return resolve().isLogical(); }
62 public boolean isEnvironment() { return resolve().isEnvironment(); }
63 public boolean isLanguage() { return resolve().isLanguage(); }
64 public boolean isSymbol() { return resolve().isSymbol(); }
65 public boolean isVector() { return resolve().isVector(); }
66 public boolean isRaw() { return resolve().isRaw(); }
67 public boolean isComplex() { return resolve().isComplex(); }
68 public boolean isRecursive() { return resolve().isRecursive(); }
69 public boolean isReference() { return true; }
71 // basic accessor methods
72 public String[] asStrings() throws REXPMismatchException { return resolve().asStrings(); }
73 public int[] asIntegers() throws REXPMismatchException { return resolve().asIntegers(); }
74 public double[] asDoubles() throws REXPMismatchException { return resolve().asDoubles(); }
75 public RList asList() throws REXPMismatchException { return resolve().asList(); }
76 public RFactor asFactor() throws REXPMismatchException { return resolve().asFactor(); }
78 public int length() throws REXPMismatchException { return resolve().length(); }
80 public REXPList _attr() { return resolve()._attr(); }
82 public Object getHandle() { return handle; }
84 public REngine getEngine() { return eng; }
86 public String toString() {
87 return super.toString()+"{eng="+eng+",h="+handle+"}";