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.
@@ -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 Collection query_result = null;
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 result) {
27
- if (result instanceof Collection) {
28
- this.query_result = (Collection)result;
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 query_result;
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(), query_result);
80
+ return JavaUtil.convertJavaToUsableRubyObject(context.getRuntime(), vector_or_seq);
41
81
  }
42
-
43
- @JRubyMethod(name="==", required=1)
44
- public IRubyObject op_equal(ThreadContext context, IRubyObject arg) {
45
- Ruby runtime = context.getRuntime();
46
- if (arg instanceof DiametricCollection) {
47
- DiametricCollection other = (DiametricCollection)arg;
48
- if (query_result.toString().equals(other.toJava().toString())) {
49
- return runtime.getTrue();
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
- return runtime.getFalse();
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 runtime.getFalse();
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 to_s(ThreadContext context) {
60
- return context.getRuntime().newString(query_result.toString());
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(name = "all?")
64
- public static IRubyObject all_p(ThreadContext context, IRubyObject self, final Block block) {
65
- return context.getRuntime().getNil();
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
- @JRubyMethod(name = "any?")
69
- public static IRubyObject any_p(ThreadContext context, IRubyObject self, final Block block) {
70
- return context.getRuntime().getNil();
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
- @JRubyMethod
74
- public static IRubyObject chunk(ThreadContext context, IRubyObject self, final Block block) {
75
- return context.getRuntime().getNil();
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 static IRubyObject chunk(ThreadContext context, IRubyObject self, final IRubyObject initialState, final Block block) {
80
- return context.getRuntime().getNil();
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 static IRubyObject collect(ThreadContext context, IRubyObject self, final Block block) {
85
- return context.getRuntime().getNil();
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 static IRubyObject collect_concat(ThreadContext context, IRubyObject self, final Block block) {
90
- return context.getRuntime().getNil();
581
+ public IRubyObject first(ThreadContext context) {
582
+ return common.first(context, vector_or_seq);
91
583
  }
92
584
 
93
585
  @JRubyMethod
94
- public static IRubyObject count(ThreadContext context, IRubyObject self, final Block block) {
95
- return context.getRuntime().getNil();
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 static IRubyObject count(ThreadContext context, IRubyObject self, final IRubyObject methodArg, final Block block) {
100
- return context.getRuntime().getNil();
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 static IRubyObject cycle(ThreadContext context, IRubyObject self, final Block block) {
105
- return context.getRuntime().getNil();
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 static IRubyObject cycle(ThreadContext context, IRubyObject self, IRubyObject arg, final Block block) {
110
- return context.getRuntime().getNil();
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 static IRubyObject detect(ThreadContext context, IRubyObject self, final Block block) {
115
- return context.getRuntime().getNil();
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 static IRubyObject detect(ThreadContext context, IRubyObject self, IRubyObject ifnone, final Block block) {
120
- return context.getRuntime().getNil();
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 static IRubyObject drop(ThreadContext context, IRubyObject self, IRubyObject n, final Block block) {
125
- return context.getRuntime().getNil();
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 static IRubyObject drop_while(ThreadContext context, IRubyObject self, final Block block) {
130
- return context.getRuntime().getNil();
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 static IRubyObject each_cons(ThreadContext context, IRubyObject self, IRubyObject arg, final Block block) {
135
- return context.getRuntime().getNil();
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 static IRubyObject each_entry(ThreadContext context, final IRubyObject self, final IRubyObject[] args, final Block block) {
140
- return context.getRuntime().getNil();
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 static IRubyObject each_slice(ThreadContext context, IRubyObject self, IRubyObject arg, final Block block) {
145
- return context.getRuntime().getNil();
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
  }