diametric 0.1.1-java → 0.1.2-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +627 -179
- data/ext/diametric/DiametricCollection.java +696 -66
- data/ext/diametric/DiametricCommon.java +165 -0
- data/ext/diametric/DiametricDatabase.java +10 -3
- data/ext/diametric/DiametricPeer.java +12 -4
- data/ext/diametric/DiametricService.java +35 -2
- data/ext/diametric/DiametricSet.java +270 -0
- data/ext/diametric/DiametricUtils.java +52 -10
- data/lib/diametric/entity.rb +7 -5
- data/lib/diametric/persistence/common.rb +3 -3
- data/lib/diametric/persistence/peer.rb +3 -12
- data/lib/diametric/persistence/rest.rb +1 -1
- data/lib/diametric/query.rb +26 -14
- data/lib/diametric/version.rb +1 -1
- data/lib/diametric_service.jar +0 -0
- data/spec/developer_query_spec.rb +3 -3
- data/spec/diametric/peer_api_spec.rb +425 -8
- data/spec/diametric/persistence/peer_many2many_spec.rb +10 -9
- data/spec/parent_child_sample.rb +21 -16
- data/spec/peer_integration_spec.rb +43 -9
- data/spec/support/entities.rb +2 -0
- metadata +24 -22
@@ -1,147 +1,777 @@
|
|
1
1
|
package diametric;
|
2
2
|
|
3
|
-
import java.util.Collection;
|
4
3
|
import java.util.Iterator;
|
4
|
+
import java.util.List;
|
5
5
|
|
6
6
|
import org.jruby.Ruby;
|
7
|
+
import org.jruby.RubyArray;
|
8
|
+
import org.jruby.RubyBoolean;
|
7
9
|
import org.jruby.RubyClass;
|
10
|
+
import org.jruby.RubyFixnum;
|
8
11
|
import org.jruby.RubyObject;
|
12
|
+
import org.jruby.RubyRange;
|
13
|
+
import org.jruby.RubyString;
|
9
14
|
import org.jruby.anno.JRubyClass;
|
10
15
|
import org.jruby.anno.JRubyMethod;
|
11
16
|
import org.jruby.javasupport.JavaUtil;
|
17
|
+
import org.jruby.runtime.Arity;
|
12
18
|
import org.jruby.runtime.Block;
|
13
19
|
import org.jruby.runtime.ThreadContext;
|
14
20
|
import org.jruby.runtime.builtin.IRubyObject;
|
15
21
|
|
22
|
+
import clojure.lang.APersistentVector;
|
23
|
+
import clojure.lang.LazySeq;
|
24
|
+
import clojure.lang.PersistentVector;
|
25
|
+
import clojure.lang.Var;
|
26
|
+
|
16
27
|
@JRubyClass(name = "Diametric::Persistence::Collection")
|
17
28
|
public class DiametricCollection extends RubyObject {
|
18
29
|
// should be a Ruby's Enumerable
|
19
30
|
private static final long serialVersionUID = 7656855654760249694L;
|
20
|
-
private
|
31
|
+
private List vector_or_seq = null;
|
32
|
+
private Integer count = null; // unable to count the vector size that exceeds Integer
|
33
|
+
private DiametricCommon common = null;
|
21
34
|
|
22
35
|
public DiametricCollection(Ruby runtime, RubyClass klazz) {
|
23
36
|
super(runtime, klazz);
|
24
37
|
}
|
25
|
-
|
26
|
-
void init(Object
|
27
|
-
if (
|
28
|
-
|
38
|
+
|
39
|
+
void init(Object obj) {
|
40
|
+
if ((obj instanceof APersistentVector) ||
|
41
|
+
(obj instanceof LazySeq) ||
|
42
|
+
(obj instanceof PersistentVector.ChunkedSeq)) {
|
43
|
+
this.vector_or_seq = (List)obj;
|
29
44
|
} else {
|
30
45
|
throw new RuntimeException("Wrong type of query result");
|
31
46
|
}
|
47
|
+
common = new DiametricCommon();
|
32
48
|
}
|
33
49
|
|
34
50
|
Object toJava() {
|
35
|
-
return
|
51
|
+
return vector_or_seq;
|
52
|
+
}
|
53
|
+
|
54
|
+
@JRubyMethod(meta=true)
|
55
|
+
public static IRubyObject wrap(ThreadContext context, IRubyObject klazz, IRubyObject arg) {
|
56
|
+
try {
|
57
|
+
clojure.lang.PersistentVector value =
|
58
|
+
(clojure.lang.PersistentVector)arg.toJava(clojure.lang.PersistentVector.class);
|
59
|
+
return DiametricUtils.getDiametricCollection(context, (List)value);
|
60
|
+
} catch (Throwable t) {
|
61
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
@JRubyMethod(meta=true)
|
66
|
+
public static IRubyObject be_lazy(ThreadContext context, IRubyObject klazz, IRubyObject arg) {
|
67
|
+
try {
|
68
|
+
clojure.lang.PersistentVector v =
|
69
|
+
(clojure.lang.PersistentVector)arg.toJava(clojure.lang.PersistentVector.class);
|
70
|
+
Var var = DiametricService.getFn("clojure.core", "take");
|
71
|
+
Object value = var.invoke(100, v);
|
72
|
+
return DiametricUtils.getDiametricCollection(context, (List)value);
|
73
|
+
} catch (Throwable t) {
|
74
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
75
|
+
}
|
36
76
|
}
|
37
77
|
|
38
78
|
@JRubyMethod
|
39
79
|
public IRubyObject to_java(ThreadContext context) {
|
40
|
-
return JavaUtil.convertJavaToUsableRubyObject(context.getRuntime(),
|
80
|
+
return JavaUtil.convertJavaToUsableRubyObject(context.getRuntime(), vector_or_seq);
|
41
81
|
}
|
42
|
-
|
43
|
-
@JRubyMethod(name="
|
44
|
-
public IRubyObject
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
82
|
+
|
83
|
+
@JRubyMethod(name="&")
|
84
|
+
public IRubyObject op_and(ThreadContext context, IRubyObject arg) {
|
85
|
+
throw context.getRuntime().newRuntimeError("Not supported. Perhaps, doesn't make sense for query result.");
|
86
|
+
}
|
87
|
+
|
88
|
+
@JRubyMethod(name="-")
|
89
|
+
public IRubyObject op_diff(ThreadContext context, IRubyObject arg) {
|
90
|
+
if (!(arg instanceof List)) {
|
91
|
+
throw context.getRuntime().newRuntimeError("argument should be array");
|
92
|
+
}
|
93
|
+
List other = (List)arg;
|
94
|
+
Var two_arrays_diff_fn = null;
|
95
|
+
if (DiametricService.fnMap.containsKey("two-arrays-diff")) {
|
96
|
+
two_arrays_diff_fn = DiametricService.fnMap.get("two-arrays-diff");
|
97
|
+
} else {
|
98
|
+
Var var = DiametricService.getFn("clojure.core", "load-string");
|
99
|
+
String fn =
|
100
|
+
"(defn two-arrays-diff [this other]\n" +
|
101
|
+
" (let [f (fn [ary n] (remove (partial = n) ary))]\n"+
|
102
|
+
" (reduce f this other)))";
|
103
|
+
two_arrays_diff_fn = (Var)var.invoke(fn);
|
104
|
+
DiametricService.fnMap.put("two-arrays-diff", two_arrays_diff_fn);
|
105
|
+
}
|
106
|
+
try {
|
107
|
+
Object value = two_arrays_diff_fn.invoke(vector_or_seq, other);
|
108
|
+
return DiametricUtils.getDiametricCollection(context, (List)value);
|
109
|
+
} catch (Throwable t) {
|
110
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
@JRubyMethod(name="*")
|
115
|
+
public IRubyObject op_times(ThreadContext context, IRubyObject arg) {
|
116
|
+
if (arg instanceof RubyFixnum) {
|
117
|
+
Var append_n_times_fn = null;
|
118
|
+
if (DiametricService.fnMap.containsKey("append-n-times")) {
|
119
|
+
append_n_times_fn = DiametricService.fnMap.get("append-n-times");
|
120
|
+
} else {
|
121
|
+
Var var = DiametricService.getFn("clojure.core", "load-string");
|
122
|
+
append_n_times_fn = (Var)var.invoke("(defn append-n-times [n array] (reduce concat (replicate n array)))");
|
123
|
+
DiametricService.fnMap.put("append-n-times", append_n_times_fn);
|
124
|
+
}
|
125
|
+
Integer n = (Integer)arg.toJava(Integer.class);
|
126
|
+
try {
|
127
|
+
Object value = append_n_times_fn.invoke(n, vector_or_seq);
|
128
|
+
return DiametricUtils.getDiametricCollection(context, (List)value);
|
129
|
+
} catch (Throwable t) {
|
130
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
131
|
+
}
|
132
|
+
} else if (arg instanceof RubyString) {
|
133
|
+
return join(context, arg);
|
134
|
+
} else {
|
135
|
+
throw context.getRuntime().newArgumentError("argument should be either String or Fixnum");
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
@JRubyMethod(name="+")
|
140
|
+
public IRubyObject op_plus(ThreadContext context, IRubyObject arg) {
|
141
|
+
if (!(arg instanceof List)) {
|
142
|
+
throw context.getRuntime().newRuntimeError("argument should be array");
|
143
|
+
}
|
144
|
+
List other = (List)arg;
|
145
|
+
try {
|
146
|
+
Var var = DiametricService.getFn("clojure.core", "concat");
|
147
|
+
Object value = var.invoke(vector_or_seq, other);
|
148
|
+
return DiametricUtils.getDiametricCollection(context, (List)value);
|
149
|
+
} catch (Throwable t) {
|
150
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
@JRubyMethod(name="<<")
|
155
|
+
public IRubyObject op_append(ThreadContext context) {
|
156
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
157
|
+
}
|
158
|
+
|
159
|
+
@JRubyMethod(name="<=>")
|
160
|
+
public IRubyObject op_cmp(ThreadContext context, IRubyObject arg) {
|
161
|
+
if (!(arg instanceof List)) return context.getRuntime().getNil();
|
162
|
+
List other = (List)arg;
|
163
|
+
try {
|
164
|
+
Var var = DiametricService.getFn("clojure.core", "compare");
|
165
|
+
Integer value = (Integer)var.invoke(vector_or_seq, other);
|
166
|
+
return context.getRuntime().newFixnum(value);
|
167
|
+
} catch (Throwable t) {
|
168
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
@JRubyMethod(name={"[]", "slice"}, required=1, optional=1)
|
173
|
+
public IRubyObject aref(ThreadContext context, IRubyObject[] args) {
|
174
|
+
/*
|
175
|
+
* ary[index] -> obj or nil
|
176
|
+
* ary[start, length] -> new_ary or nil
|
177
|
+
* ary[range] -> new_ary or nil
|
178
|
+
* slice(index) -> obj or nil
|
179
|
+
* slice(start,length) -> new_ary or_nil
|
180
|
+
* slice(range) -> new_ary or nil
|
181
|
+
*/
|
182
|
+
switch(args.length) {
|
183
|
+
case 1:
|
184
|
+
return aref(context, args[0]);
|
185
|
+
case 2:
|
186
|
+
return aref(context, args[0], args[1]);
|
187
|
+
default:
|
188
|
+
Arity.raiseArgumentError(getRuntime(), args.length, 1, 2);
|
189
|
+
}
|
190
|
+
return context.getRuntime().getNil();
|
191
|
+
}
|
192
|
+
|
193
|
+
private IRubyObject aref(ThreadContext context, IRubyObject index_or_range) {
|
194
|
+
if (index_or_range instanceof RubyFixnum) {
|
195
|
+
Long index = (Long)index_or_range.toJava(Long.class);
|
196
|
+
return commonArefIndex(context, index);
|
197
|
+
} else if (index_or_range instanceof RubyRange) {
|
198
|
+
RubyRange range = (RubyRange)index_or_range;
|
199
|
+
Long start = (Long)range.first().toJava(Long.class);
|
200
|
+
Long last = (Long)range.last().toJava(Long.class);
|
201
|
+
// subvec returns from 'start' to element (- end 1)
|
202
|
+
if (range.exclude_end_p().isTrue()) {
|
203
|
+
return commonAref(context, start, null, last);
|
204
|
+
} else {
|
205
|
+
return commonAref(context, start, null, last + 1);
|
206
|
+
}
|
207
|
+
} else {
|
208
|
+
throw context.getRuntime().newArgumentError("wrong argument");
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
private IRubyObject aref(ThreadContext context, IRubyObject arg0, IRubyObject arg1) {
|
213
|
+
Long start = (Long)arg0.toJava(Long.class);
|
214
|
+
Long length = (Long)arg1.toJava(Long.class);
|
215
|
+
if (length < 0L) return context.getRuntime().getNil();
|
216
|
+
try {
|
217
|
+
return commonAref(context, start, length, null);
|
218
|
+
} catch (Throwable t) {
|
219
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
private IRubyObject commonArefIndex(ThreadContext context, Long index) {
|
224
|
+
try {
|
225
|
+
Var var = DiametricService.getFn("clojure.core", "nth");
|
226
|
+
Object value = var.invoke(vector_or_seq, index);
|
227
|
+
return DiametricUtils.convertJavaToRuby(context, value);
|
228
|
+
} catch (Throwable t) {
|
229
|
+
if (t instanceof IndexOutOfBoundsException) {
|
230
|
+
// raised only from [index] when index is greater than the last index or negative
|
231
|
+
if (index >= (long)getCount()) return context.getRuntime().getNil();
|
232
|
+
if (index < 0L) index += (long)getCount();
|
233
|
+
if (index < 0L) return context.getRuntime().getNil();
|
234
|
+
return commonArefIndex(context, index);
|
235
|
+
}
|
236
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
237
|
+
}
|
238
|
+
}
|
239
|
+
|
240
|
+
private IRubyObject commonAref(ThreadContext context, Long start, Long length, Long last) {
|
241
|
+
try {
|
242
|
+
Object value = null;
|
243
|
+
if (vector_or_seq instanceof APersistentVector) {
|
244
|
+
long end = length != null ? (start + length) : last;
|
245
|
+
// checking a vector's length may be a costly operation.
|
246
|
+
// allows to raise exception for the first time
|
247
|
+
value = commonArefBySubvec(start, end);
|
248
|
+
} else {
|
249
|
+
// negative drop doesn't raise exception
|
250
|
+
// too big number for take doesn't raise exception
|
251
|
+
if (start > (long)getCount()) return context.getRuntime().getNil();
|
252
|
+
if (start == (long)getCount()) return context.getRuntime().newEmptyArray();
|
253
|
+
if (start < 0L) start += (long)getCount();
|
254
|
+
if (start < 0L) return context.getRuntime().getNil();
|
255
|
+
if (length == null) length = last - start;
|
256
|
+
value = commonArefByDropTake(start, length);
|
257
|
+
}
|
258
|
+
return DiametricUtils.getDiametricCollection(context, (List)value);
|
259
|
+
} catch (Throwable t) {
|
260
|
+
if (t instanceof IndexOutOfBoundsException) {
|
261
|
+
return retryAref(context, start, length, last);
|
262
|
+
}
|
263
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
264
|
+
}
|
265
|
+
}
|
266
|
+
|
267
|
+
private Object commonArefBySubvec(Long start, Long end) {
|
268
|
+
Var var = DiametricService.getFn("clojure.core", "subvec");
|
269
|
+
// subvec returns from 'start' to element (- end 1)
|
270
|
+
return var.invoke(vector_or_seq, start, end);
|
271
|
+
}
|
272
|
+
|
273
|
+
private Object commonArefByDropTake(Long start, Long length) {
|
274
|
+
Var seq_subvec_fn = null;
|
275
|
+
if (DiametricService.fnMap.containsKey("seq-subvec")) {
|
276
|
+
seq_subvec_fn = DiametricService.fnMap.get("seq-subvec");
|
277
|
+
} else {
|
278
|
+
Var var = DiametricService.getFn("clojure.core", "load-string");
|
279
|
+
seq_subvec_fn = (Var)var.invoke("(defn seq-subvec [seq start length] (take length (drop start seq)))");
|
280
|
+
DiametricService.fnMap.put("seq-subvec", seq_subvec_fn);
|
281
|
+
}
|
282
|
+
return seq_subvec_fn.invoke(vector_or_seq, start, length);
|
283
|
+
}
|
284
|
+
|
285
|
+
private IRubyObject retryAref(ThreadContext context, Long start, Long length, Long last) {
|
286
|
+
// now, check the vector's length
|
287
|
+
if (start > (long)getCount()) return context.getRuntime().getNil();
|
288
|
+
if (start == (long)getCount()) return context.getRuntime().newEmptyArray();
|
289
|
+
if (start < 0L) start += (long)getCount();
|
290
|
+
if (start < 0L) return context.getRuntime().getNil();
|
291
|
+
|
292
|
+
long end = length != null ? (start + length) : last;
|
293
|
+
end = (end <= (long)getCount()) ? end : (long)getCount();
|
294
|
+
return commonAref(context, start, null, end);
|
295
|
+
}
|
296
|
+
|
297
|
+
@JRubyMethod
|
298
|
+
public IRubyObject assoc(ThreadContext context, IRubyObject arg) {
|
299
|
+
throw context.getRuntime().newRuntimeError("Not yet supported. Might be implented later depends on datomic queries.");
|
300
|
+
}
|
301
|
+
|
302
|
+
@JRubyMethod
|
303
|
+
public IRubyObject at(ThreadContext context, IRubyObject arg) {
|
304
|
+
Long index = null;
|
305
|
+
try {
|
306
|
+
if (arg instanceof RubyFixnum) {
|
307
|
+
index = (Long)arg.toJava(Long.class);
|
308
|
+
return commonArefIndex(context, index);
|
50
309
|
} else {
|
51
|
-
|
310
|
+
throw context.getRuntime().newArgumentError("argument should be fixnum");
|
52
311
|
}
|
312
|
+
} catch (Throwable t) {
|
313
|
+
if (t instanceof IndexOutOfBoundsException) {
|
314
|
+
// raised only when index is greater than the last index or negative
|
315
|
+
if (index >= (long)getCount()) return context.getRuntime().getNil();
|
316
|
+
if (index < 0L) index += (long)getCount();
|
317
|
+
if (index < 0L) return context.getRuntime().getNil();
|
318
|
+
return commonArefIndex(context, index);
|
319
|
+
}
|
320
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
@JRubyMethod
|
325
|
+
public IRubyObject bsearch(ThreadContext context, Block block) {
|
326
|
+
throw context.getRuntime().newRuntimeError("bsearch is not supported.");
|
327
|
+
}
|
328
|
+
|
329
|
+
@JRubyMethod
|
330
|
+
public IRubyObject clear(ThreadContext context) {
|
331
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
332
|
+
}
|
333
|
+
|
334
|
+
@JRubyMethod(name={"collect", "map"})
|
335
|
+
public IRubyObject collect(ThreadContext context, Block block) {
|
336
|
+
if (block.isGiven()) {
|
337
|
+
return common.collect(context, block, vector_or_seq.iterator());
|
53
338
|
} else {
|
54
|
-
return
|
339
|
+
return this;
|
55
340
|
}
|
56
341
|
}
|
57
342
|
|
343
|
+
@JRubyMethod(name={"collect!", "map!"})
|
344
|
+
public IRubyObject collect_bang(ThreadContext context, Block block) {
|
345
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
346
|
+
}
|
347
|
+
|
58
348
|
@JRubyMethod
|
59
|
-
public IRubyObject
|
60
|
-
|
349
|
+
public IRubyObject combination(ThreadContext context, IRubyObject arg, Block block) {
|
350
|
+
throw context.getRuntime().newRuntimeError("Not supported yet. Perhaps, doesn't make sense for query result.");
|
351
|
+
}
|
352
|
+
|
353
|
+
@JRubyMethod
|
354
|
+
public IRubyObject compact(ThreadContext context) {
|
355
|
+
try {
|
356
|
+
Var var = DiametricService.getFn("clojure.core", "remove");
|
357
|
+
Var nil_p = DiametricService.getFn("clojure.core", "nil?");
|
358
|
+
LazySeq value = (LazySeq) var.invoke(nil_p, vector_or_seq);
|
359
|
+
Iterator itr = value.iterator();
|
360
|
+
RubyArray result = context.getRuntime().newArray();
|
361
|
+
while (itr.hasNext()) {
|
362
|
+
Object obj = itr.next();
|
363
|
+
result.callMethod("<<", DiametricUtils.convertJavaToRuby(context, obj));
|
364
|
+
}
|
365
|
+
return result;
|
366
|
+
} catch (Throwable t) {
|
367
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
368
|
+
}
|
369
|
+
}
|
370
|
+
|
371
|
+
@JRubyMethod(name="compact!")
|
372
|
+
public IRubyObject compact_bang(ThreadContext context) {
|
373
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
374
|
+
}
|
375
|
+
|
376
|
+
@JRubyMethod
|
377
|
+
public IRubyObject concat(ThreadContext context, IRubyObject arg) {
|
378
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
379
|
+
}
|
380
|
+
|
381
|
+
@JRubyMethod
|
382
|
+
public IRubyObject count(ThreadContext context, Block block) {
|
383
|
+
if (block.isGiven()) {
|
384
|
+
return common.count(context, block, vector_or_seq.iterator());
|
385
|
+
} else {
|
386
|
+
return context.getRuntime().newFixnum(getCount());
|
387
|
+
}
|
388
|
+
}
|
389
|
+
|
390
|
+
@JRubyMethod(required = 1)
|
391
|
+
public IRubyObject count(ThreadContext context, IRubyObject arg, Block block) {
|
392
|
+
if (block.isGiven()) {
|
393
|
+
throw context.getRuntime().newArgumentError("given block not used");
|
394
|
+
} else {
|
395
|
+
return common.count(context, arg, vector_or_seq);
|
396
|
+
}
|
397
|
+
}
|
398
|
+
|
399
|
+
@JRubyMethod
|
400
|
+
public IRubyObject cycle(ThreadContext context, Block block) {
|
401
|
+
throw context.getRuntime().newRuntimeError("Not supported yet. Perhaps, doesn't make sense for query result.");
|
402
|
+
}
|
403
|
+
|
404
|
+
@JRubyMethod
|
405
|
+
public IRubyObject cycle(ThreadContext context, IRubyObject arg, Block block) {
|
406
|
+
throw context.getRuntime().newRuntimeError("Not supported yet. Perhaps, doesn't make sense for query result.");
|
407
|
+
}
|
408
|
+
|
409
|
+
@JRubyMethod
|
410
|
+
public IRubyObject delete(ThreadContext context, IRubyObject arg, Block block) {
|
411
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
412
|
+
}
|
413
|
+
|
414
|
+
@JRubyMethod(name={"delete_at", "slice!"}, required=1, optional=1)
|
415
|
+
public IRubyObject delete_at(ThreadContext context, IRubyObject arg[]) {
|
416
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
417
|
+
}
|
418
|
+
|
419
|
+
@JRubyMethod(name={"delete_if", "reject!"})
|
420
|
+
public IRubyObject delete_if(ThreadContext context, Block block) {
|
421
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
422
|
+
}
|
423
|
+
|
424
|
+
@JRubyMethod(name={"drop", "take"})
|
425
|
+
public IRubyObject drop(ThreadContext context, IRubyObject arg) {
|
426
|
+
if (!(arg instanceof RubyFixnum)) {
|
427
|
+
throw context.getRuntime().newArgumentError("argument should be Fixnum");
|
428
|
+
}
|
429
|
+
Long n = (Long)arg.toJava(Long.class);
|
430
|
+
if (n < 0) {
|
431
|
+
throw context.getRuntime().newArgumentError("negative drop size");
|
432
|
+
}
|
433
|
+
if (n == 0) return this;
|
434
|
+
return common.drop_or_take(context, n, vector_or_seq);
|
435
|
+
}
|
436
|
+
|
437
|
+
@JRubyMethod(name={"drop_while", "take_while"})
|
438
|
+
public IRubyObject drop_while(ThreadContext context, Block block) {
|
439
|
+
if (block.isGiven()) {
|
440
|
+
return common.drop_while(context, block, vector_or_seq.iterator());
|
441
|
+
} else {
|
442
|
+
return this;
|
443
|
+
}
|
444
|
+
}
|
445
|
+
|
446
|
+
@JRubyMethod
|
447
|
+
public IRubyObject each(ThreadContext context, Block block) {
|
448
|
+
if (block.isGiven()) {
|
449
|
+
common.each(context, block, vector_or_seq.iterator());
|
450
|
+
}
|
451
|
+
return this;
|
452
|
+
}
|
453
|
+
|
454
|
+
@JRubyMethod
|
455
|
+
public IRubyObject each_index(ThreadContext context, Block block) {
|
456
|
+
if (block.isGiven()) {
|
457
|
+
Iterator<Object> itr = vector_or_seq.iterator();
|
458
|
+
Long index = 0L;
|
459
|
+
while (itr.hasNext()) {
|
460
|
+
itr.next();
|
461
|
+
block.yield(context, context.getRuntime().newFixnum(index));
|
462
|
+
index++;
|
463
|
+
}
|
464
|
+
}
|
465
|
+
return this;
|
466
|
+
}
|
467
|
+
|
468
|
+
@JRubyMethod(name="empty?")
|
469
|
+
public IRubyObject empty_p(ThreadContext context) {
|
470
|
+
return common.empty_p(context, vector_or_seq);
|
471
|
+
}
|
472
|
+
|
473
|
+
@JRubyMethod(name={"eql?", "=="})
|
474
|
+
public IRubyObject equal_p(ThreadContext context, IRubyObject arg) {
|
475
|
+
if (arg.isNil()) return context.getRuntime().getFalse();
|
476
|
+
Object other_vector = null;
|
477
|
+
if (arg instanceof DiametricCollection) {
|
478
|
+
other_vector = ((DiametricCollection)arg).toJava();
|
479
|
+
} else if ((arg instanceof List) || (arg instanceof RubyArray)) {
|
480
|
+
other_vector = arg;
|
481
|
+
} else {
|
482
|
+
return context.getRuntime().getFalse();
|
483
|
+
}
|
484
|
+
try {
|
485
|
+
Var var = DiametricService.getFn("clojure.core", "=");
|
486
|
+
if ((Boolean)var.invoke(vector_or_seq, other_vector)) {
|
487
|
+
return context.getRuntime().getTrue();
|
488
|
+
} else {
|
489
|
+
return context.getRuntime().getFalse();
|
490
|
+
}
|
491
|
+
} catch (Throwable t) {
|
492
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
493
|
+
}
|
61
494
|
}
|
62
495
|
|
63
|
-
@JRubyMethod(
|
64
|
-
public
|
65
|
-
|
496
|
+
@JRubyMethod(required=1, optional=1)
|
497
|
+
public IRubyObject fetch(ThreadContext context, IRubyObject args[], Block block) {
|
498
|
+
Long index = (Long)args[0].toJava(Long.class);
|
499
|
+
try {
|
500
|
+
Var var = DiametricService.getFn("clojure.core", "nth");
|
501
|
+
// counting vector size will be costly when the vector is way huge.
|
502
|
+
// allows to raise exception for negative or too big index
|
503
|
+
Object value = var.invoke(vector_or_seq, index);
|
504
|
+
return DiametricUtils.convertJavaToRuby(context, value);
|
505
|
+
} catch (Throwable t) {
|
506
|
+
if (t instanceof IndexOutOfBoundsException) {
|
507
|
+
return retryFetch(context, args, block, index);
|
508
|
+
}
|
509
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
510
|
+
}
|
66
511
|
}
|
512
|
+
|
513
|
+
private IRubyObject retryFetch(ThreadContext context, IRubyObject[] args, Block block, Long index) {
|
514
|
+
// now, counts vector size and adjust the index
|
515
|
+
if (index > (long)getCount()) return handleError(context, args, block);
|
516
|
+
if (index < 0L) index += (long)getCount();
|
517
|
+
if (index < 0L) return handleError(context, args, block);
|
67
518
|
|
68
|
-
|
69
|
-
|
70
|
-
|
519
|
+
try {
|
520
|
+
Var var = DiametricService.getFn("clojure.core", "nth");
|
521
|
+
Object value = var.invoke(vector_or_seq, index);
|
522
|
+
return DiametricUtils.convertJavaToRuby(context, value);
|
523
|
+
} catch (Throwable t) {
|
524
|
+
if (t instanceof IndexOutOfBoundsException) {
|
525
|
+
return handleError(context, args, block);
|
526
|
+
}
|
527
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
528
|
+
}
|
71
529
|
}
|
72
530
|
|
73
|
-
|
74
|
-
|
75
|
-
|
531
|
+
private IRubyObject handleError(ThreadContext context, IRubyObject[] args, Block block) {
|
532
|
+
if (block.isGiven()) {
|
533
|
+
return block.yield(context, args[0]);
|
534
|
+
} else if (args.length == 2) {
|
535
|
+
return args[1];
|
536
|
+
} else {
|
537
|
+
throw context.getRuntime().newIndexError("Given index is out of vector size");
|
538
|
+
}
|
76
539
|
}
|
77
540
|
|
78
541
|
@JRubyMethod
|
79
|
-
public
|
80
|
-
|
542
|
+
public IRubyObject fill(ThreadContext context, Block block) {
|
543
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is a query result.");
|
81
544
|
}
|
82
545
|
|
83
|
-
@JRubyMethod
|
84
|
-
public
|
85
|
-
|
546
|
+
@JRubyMethod(required=1, optional=2)
|
547
|
+
public IRubyObject fill(ThreadContext context, IRubyObject args[], Block block) {
|
548
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is a query result.");
|
549
|
+
}
|
550
|
+
|
551
|
+
@JRubyMethod(name={"find_index", "index"})
|
552
|
+
public IRubyObject find_index(ThreadContext context, IRubyObject arg, Block unsed) {
|
553
|
+
Object java_obj = DiametricUtils.convertRubyToJava(context, arg);
|
554
|
+
int index = vector_or_seq.indexOf(java_obj);
|
555
|
+
if (index >= 0) {
|
556
|
+
return context.getRuntime().newFixnum(index);
|
557
|
+
} else {
|
558
|
+
return context.getRuntime().getNil();
|
559
|
+
}
|
86
560
|
}
|
87
561
|
|
562
|
+
@JRubyMethod(name={"find_index", "index"})
|
563
|
+
public IRubyObject find_index(ThreadContext context, Block block) {
|
564
|
+
if (block.isGiven()) {
|
565
|
+
Iterator<Object> itr = vector_or_seq.iterator();
|
566
|
+
int index = 0;
|
567
|
+
while (itr.hasNext()) {
|
568
|
+
IRubyObject value = DiametricUtils.convertJavaToRuby(context, itr.next());
|
569
|
+
if (block.yield(context, value).isTrue()) {
|
570
|
+
return context.getRuntime().newFixnum(index);
|
571
|
+
}
|
572
|
+
index++;
|
573
|
+
}
|
574
|
+
return context.getRuntime().getNil();
|
575
|
+
} else {
|
576
|
+
return this;
|
577
|
+
}
|
578
|
+
}
|
579
|
+
|
88
580
|
@JRubyMethod
|
89
|
-
public
|
90
|
-
return
|
581
|
+
public IRubyObject first(ThreadContext context) {
|
582
|
+
return common.first(context, vector_or_seq);
|
91
583
|
}
|
92
584
|
|
93
585
|
@JRubyMethod
|
94
|
-
public
|
95
|
-
|
586
|
+
public IRubyObject first(ThreadContext context, IRubyObject arg) {
|
587
|
+
if (!(arg instanceof RubyFixnum)) throw context.getRuntime().newArgumentError("argument should be a Fixnum");
|
588
|
+
Long n = (Long)arg.toJava(Long.class);
|
589
|
+
return common.first(context, n, vector_or_seq);
|
96
590
|
}
|
97
591
|
|
98
592
|
@JRubyMethod
|
99
|
-
public
|
100
|
-
|
593
|
+
public IRubyObject flatten(ThreadContext context) {
|
594
|
+
throw context.getRuntime().newRuntimeError("Not yet supported. Might be implented later depends on datomic queries.");
|
101
595
|
}
|
102
596
|
|
103
597
|
@JRubyMethod
|
104
|
-
public
|
105
|
-
|
598
|
+
public IRubyObject flatten(ThreadContext context, IRubyObject arg) {
|
599
|
+
throw context.getRuntime().newRuntimeError("Not yet supported. Might be implented later depends on datomic queries.");
|
106
600
|
}
|
107
|
-
|
601
|
+
|
602
|
+
@JRubyMethod(name="flatten!")
|
603
|
+
public IRubyObject flatten_bang(ThreadContext context) {
|
604
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
605
|
+
}
|
606
|
+
|
607
|
+
@JRubyMethod(name="flatten!")
|
608
|
+
public IRubyObject flatten_bang(ThreadContext context, IRubyObject arg) {
|
609
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
610
|
+
}
|
611
|
+
|
612
|
+
@JRubyMethod(name="frozen?")
|
613
|
+
public RubyBoolean frozen_p(ThreadContext context) {
|
614
|
+
return (RubyBoolean)context.getRuntime().getTrue();
|
615
|
+
}
|
616
|
+
|
108
617
|
@JRubyMethod
|
109
|
-
public
|
110
|
-
return
|
618
|
+
public IRubyObject hash(ThreadContext context) {
|
619
|
+
return common.hash(context, vector_or_seq);
|
111
620
|
}
|
112
|
-
|
621
|
+
|
622
|
+
@JRubyMethod(name="include?")
|
623
|
+
public IRubyObject include_p(ThreadContext context, IRubyObject arg) {
|
624
|
+
Var include_p_fn = null;
|
625
|
+
if (DiametricService.fnMap.containsKey("include?")) {
|
626
|
+
include_p_fn = DiametricService.fnMap.get("include?");
|
627
|
+
} else {
|
628
|
+
Var var = DiametricService.getFn("clojure.core", "load-string");
|
629
|
+
include_p_fn = (Var)var.invoke("(defn include? [v array] (some (partial = v) array))");
|
630
|
+
DiametricService.fnMap.put("include?", include_p_fn);
|
631
|
+
}
|
632
|
+
Object java_object = DiametricUtils.convertRubyToJava(context, arg);
|
633
|
+
try {
|
634
|
+
Object result = include_p_fn.invoke(java_object, vector_or_seq);
|
635
|
+
if ((result instanceof Boolean) && (Boolean)result) {
|
636
|
+
return context.getRuntime().getTrue();
|
637
|
+
} else {
|
638
|
+
return context.getRuntime().getFalse();
|
639
|
+
}
|
640
|
+
} catch (Throwable t) {
|
641
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
642
|
+
}
|
643
|
+
}
|
644
|
+
|
645
|
+
@JRubyMethod(required=2, rest=true)
|
646
|
+
public IRubyObject insert(ThreadContext context, IRubyObject[] args) {
|
647
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
648
|
+
}
|
649
|
+
|
113
650
|
@JRubyMethod
|
114
|
-
public
|
115
|
-
|
651
|
+
public IRubyObject join(ThreadContext context) {
|
652
|
+
try {
|
653
|
+
Var var = DiametricService.getFn("clojure.string", "join");
|
654
|
+
return context.getRuntime().newString((String)var.invoke(vector_or_seq));
|
655
|
+
} catch (Throwable t) {
|
656
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
657
|
+
}
|
116
658
|
}
|
117
|
-
|
659
|
+
|
118
660
|
@JRubyMethod
|
119
|
-
public
|
120
|
-
|
661
|
+
public IRubyObject join(ThreadContext context, IRubyObject arg) {
|
662
|
+
if (arg.isNil()) {
|
663
|
+
return join(context);
|
664
|
+
} else if (arg instanceof RubyString) {
|
665
|
+
try {
|
666
|
+
String separator = (String)arg.toJava(String.class);
|
667
|
+
Var var = DiametricService.getFn("clojure.string", "join");
|
668
|
+
return context.getRuntime().newString((String)var.invoke(separator, vector_or_seq));
|
669
|
+
} catch (Throwable t) {
|
670
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
671
|
+
}
|
672
|
+
}
|
673
|
+
return context.getRuntime().getNil();
|
121
674
|
}
|
122
|
-
|
675
|
+
|
676
|
+
@JRubyMethod(name={"keep_if", "select!"})
|
677
|
+
public IRubyObject keep_if(ThreadContext context, Block block) {
|
678
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
679
|
+
}
|
680
|
+
|
123
681
|
@JRubyMethod
|
124
|
-
public
|
125
|
-
|
682
|
+
public IRubyObject last(ThreadContext context) {
|
683
|
+
try {
|
684
|
+
Var var = DiametricService.getFn("clojure.core", "last");
|
685
|
+
return DiametricUtils.convertJavaToRuby(context, var.invoke(vector_or_seq));
|
686
|
+
} catch (Throwable t) {
|
687
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
688
|
+
}
|
126
689
|
}
|
127
|
-
|
690
|
+
|
128
691
|
@JRubyMethod
|
129
|
-
public
|
130
|
-
|
692
|
+
public IRubyObject last(ThreadContext context, IRubyObject arg) {
|
693
|
+
if (!(arg instanceof RubyFixnum)) {
|
694
|
+
throw context.getRuntime().newArgumentError("Argument should be a Fixnum");
|
695
|
+
}
|
696
|
+
if (vector_or_seq.isEmpty()) return context.getRuntime().newEmptyArray();
|
697
|
+
Long n = (Long)arg.toJava(Long.class);
|
698
|
+
try {
|
699
|
+
Var var = DiametricService.getFn("clojure.core", "take-last");
|
700
|
+
return DiametricUtils.convertJavaToRuby(context, var.invoke(n, vector_or_seq));
|
701
|
+
} catch (Throwable t) {
|
702
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
703
|
+
}
|
131
704
|
}
|
132
|
-
|
705
|
+
|
133
706
|
@JRubyMethod
|
134
|
-
public
|
135
|
-
|
707
|
+
public IRubyObject pack(ThreadContext context, IRubyObject arg) {
|
708
|
+
throw context.getRuntime().newRuntimeError("Not supported. Perhaps, doesn't make sense for query result.");
|
136
709
|
}
|
137
|
-
|
710
|
+
|
711
|
+
@JRubyMethod
|
712
|
+
public IRubyObject permutation(ThreadContext context, IRubyObject arg, Block block) {
|
713
|
+
throw context.getRuntime().newRuntimeError("Not supported. Perhaps, doesn't make sense for query result.");
|
714
|
+
}
|
715
|
+
|
716
|
+
@JRubyMethod
|
717
|
+
public IRubyObject permutation(ThreadContext context, Block block) {
|
718
|
+
throw context.getRuntime().newRuntimeError("Not supported. Perhaps, doesn't make sense for query result.");
|
719
|
+
}
|
720
|
+
|
721
|
+
@JRubyMethod
|
722
|
+
public IRubyObject pop(ThreadContext context) {
|
723
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
724
|
+
}
|
725
|
+
|
726
|
+
@JRubyMethod
|
727
|
+
public IRubyObject pop(ThreadContext context, IRubyObject arg) {
|
728
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
729
|
+
}
|
730
|
+
|
138
731
|
@JRubyMethod(rest = true)
|
139
|
-
public
|
140
|
-
|
732
|
+
public IRubyObject product(ThreadContext context, IRubyObject[] args, Block block) {
|
733
|
+
throw context.getRuntime().newRuntimeError("Not supported. Perhaps, doesn't make sense for query result.");
|
141
734
|
}
|
142
|
-
|
735
|
+
|
143
736
|
@JRubyMethod
|
144
|
-
public
|
145
|
-
|
737
|
+
public IRubyObject replace(ThreadContext context, IRubyObject arg) {
|
738
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
739
|
+
}
|
740
|
+
|
741
|
+
@JRubyMethod(rest = true)
|
742
|
+
public IRubyObject push(ThreadContext context, IRubyObject[] arg) {
|
743
|
+
throw context.getRuntime().newRuntimeError("Not supported. Data is immutable.");
|
744
|
+
}
|
745
|
+
|
746
|
+
@JRubyMethod
|
747
|
+
public IRubyObject rassoc(ThreadContext context, IRubyObject arg) {
|
748
|
+
throw context.getRuntime().newRuntimeError("Not yet supported. Might be implented later depends on datomic queries.");
|
749
|
+
}
|
750
|
+
|
751
|
+
private int getCount() {
|
752
|
+
if (count == null) {
|
753
|
+
Var var = DiametricService.getFn("clojure.core", "count");
|
754
|
+
count = (Integer)var.invoke(vector_or_seq);
|
755
|
+
}
|
756
|
+
return count;
|
757
|
+
}
|
758
|
+
|
759
|
+
@JRubyMethod(name={"length", "size"})
|
760
|
+
public IRubyObject size(ThreadContext context) {
|
761
|
+
try {
|
762
|
+
return context.getRuntime().newFixnum(getCount());
|
763
|
+
} catch (Throwable t) {
|
764
|
+
throw context.getRuntime().newRuntimeError(t.getMessage());
|
765
|
+
}
|
766
|
+
}
|
767
|
+
|
768
|
+
@JRubyMethod(name={"to_a", "to_ary"})
|
769
|
+
public IRubyObject to_a(ThreadContext context) {
|
770
|
+
return this;
|
771
|
+
}
|
772
|
+
|
773
|
+
@JRubyMethod(name={"to_s", "inspect"})
|
774
|
+
public IRubyObject to_s(ThreadContext context) {
|
775
|
+
return common.to_s(context, vector_or_seq);
|
146
776
|
}
|
147
777
|
}
|