]> gerrit.simantics Code Review - simantics/r.git/blob - org.simantics.r.scl/src/org/rosuda/REngine/REXPReference.java
dd402683991f08a7bb78d8e3bfd935f2ee077b66
[simantics/r.git] / org.simantics.r.scl / src / org / rosuda / REngine / REXPReference.java
1 package org.rosuda.REngine;
2
3 /** this class represents a reference (proxy) to an R object.
4  <p>
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 */
8         protected REngine eng;
9         /** an opaque (optional) handle */
10         protected Object handle;
11         /** resolved (cached) object */
12         protected REXP resolvedValue;
13
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) {
16                 super();
17                 this.eng = eng;
18                 this.handle = handle;
19         }
20
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));
24         }
25
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)
29                         return resolvedValue;
30                 try {
31                         resolvedValue = eng.resolveReference(this);
32                         return resolvedValue;
33                 } catch (REXPMismatchException me) {
34                         // this should never happen since we are REXPReference
35                 } catch(REngineException ee) {
36                         // FIXME: what to we do?
37                 }
38                 return null;
39         }
40
41         /** invalidates any cached representation of the reference */
42         public void invalidate() {
43                 resolvedValue = null;
44         }
45         
46         /** finalization that notifies the engine when a reference gets collected */
47         protected void finalize() throws Throwable {
48                 try {
49                         eng.finalizeReference(this);
50                 } finally {
51                         super.finalize();
52                 }
53         }       
54         // type checks
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; }
70
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(); }
77
78         public int length() throws REXPMismatchException { return resolve().length(); }
79
80         public REXPList _attr() { return resolve()._attr(); }
81         
82         public Object getHandle() { return handle; }
83         
84         public REngine getEngine() { return eng; }
85
86         public String toString() {
87                 return super.toString()+"{eng="+eng+",h="+handle+"}";
88         }
89 }