-
Notifications
You must be signed in to change notification settings - Fork 47
/
REXPReference.java
89 lines (77 loc) · 3.69 KB
/
REXPReference.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package org.rosuda.REngine;
/** this class represents a reference (proxy) to an R object.
<p>
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. */
public class REXPReference extends REXP {
/** engine which will be used to resolve the reference */
protected REngine eng;
/** an opaque (optional) handle */
protected Object handle;
/** resolved (cached) object */
protected REXP resolvedValue;
/** create an external REXP reference using given engine and handle. The handle value is just an (optional) identifier not used by the implementation directly. */
public REXPReference(REngine eng, Object handle) {
super();
this.eng = eng;
this.handle = handle;
}
/** shortcut for <code>REXPReference(eng, new Long(handle))</code> that is used by native code */
REXPReference(REngine eng, long handle) {
this(eng, Long.valueOf(handle));
}
/** 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. */
public REXP resolve() {
if (resolvedValue != null)
return resolvedValue;
try {
resolvedValue = eng.resolveReference(this);
return resolvedValue;
} catch (REXPMismatchException me) {
// this should never happen since we are REXPReference
} catch(REngineException ee) {
// FIXME: what to we do?
}
return null;
}
/** invalidates any cached representation of the reference */
public void invalidate() {
resolvedValue = null;
}
/** finalization that notifies the engine when a reference gets collected */
protected void finalize() throws Throwable {
try {
eng.finalizeReference(this);
} finally {
super.finalize();
}
}
// type checks
public boolean isString() { return resolve().isString(); }
public boolean isNumeric() { return resolve().isNumeric(); }
public boolean isInteger() { return resolve().isInteger(); }
public boolean isNull() { return resolve().isNull(); }
public boolean isFactor() { return resolve().isFactor(); }
public boolean isList() { return resolve().isList(); }
public boolean isLogical() { return resolve().isLogical(); }
public boolean isEnvironment() { return resolve().isEnvironment(); }
public boolean isLanguage() { return resolve().isLanguage(); }
public boolean isSymbol() { return resolve().isSymbol(); }
public boolean isVector() { return resolve().isVector(); }
public boolean isRaw() { return resolve().isRaw(); }
public boolean isComplex() { return resolve().isComplex(); }
public boolean isRecursive() { return resolve().isRecursive(); }
public boolean isReference() { return true; }
// basic accessor methods
public String[] asStrings() throws REXPMismatchException { return resolve().asStrings(); }
public int[] asIntegers() throws REXPMismatchException { return resolve().asIntegers(); }
public double[] asDoubles() throws REXPMismatchException { return resolve().asDoubles(); }
public RList asList() throws REXPMismatchException { return resolve().asList(); }
public RFactor asFactor() throws REXPMismatchException { return resolve().asFactor(); }
public int length() throws REXPMismatchException { return resolve().length(); }
public REXPList _attr() { return resolve()._attr(); }
public Object getHandle() { return handle; }
public REngine getEngine() { return eng; }
public String toString() {
return super.toString()+"{eng="+eng+",h="+handle+"}";
}
}