ruby_kpi 0.0.1

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.
data/lib/ruby_kpi.rb ADDED
@@ -0,0 +1,723 @@
1
+ # requirements
2
+ require "xml"
3
+ require "uuid"
4
+ require "socket"
5
+ require "logger"
6
+ require "ReplyMessage"
7
+ require "TCPConnection"
8
+ require "DataStructures"
9
+ require "SSAP_templates"
10
+ require "ruby_kpi/version"
11
+
12
+
13
+ module RubyKpi
14
+
15
+ ##################################################
16
+ #
17
+ # The Handler class
18
+ #
19
+ ##################################################
20
+
21
+ class Handler
22
+
23
+ # initializer
24
+ def initialize()
25
+ # nothing to do
26
+ end
27
+
28
+ # handle method
29
+ def handle(added, removed)
30
+
31
+ # print added triples
32
+ puts "Added:"
33
+ added.each do |a|
34
+ if a.class == "Triple"
35
+ puts a.to_str()
36
+ else
37
+ puts a.join(", ")
38
+ end
39
+ end
40
+
41
+ # print removed triples
42
+ puts "Removed:"
43
+ removed.each do |r|
44
+ if r.class == "Triple"
45
+ puts r.to_str()
46
+ else
47
+ puts r.join(", ")
48
+ end
49
+ end
50
+
51
+ return
52
+
53
+ end
54
+
55
+ end
56
+
57
+
58
+ ##################################################
59
+ #
60
+ # The Exceptions classes
61
+ #
62
+ ##################################################
63
+
64
+ class SIBError < StandardError
65
+
66
+ end
67
+
68
+
69
+ ##################################################
70
+ #
71
+ # The KP class
72
+ #
73
+ ##################################################
74
+
75
+ class KP
76
+
77
+ # accessors
78
+ attr_reader :last_request, :last_reply, :active_subscriptions, :node_id, :ip, :port, :ss
79
+
80
+
81
+ ####################################################
82
+ #
83
+ # constructor
84
+ #
85
+ ####################################################
86
+
87
+ def initialize(ip, port, smart_space, debug = false)
88
+
89
+ # debug object
90
+ @debug = debug
91
+ if @debug
92
+ @logger = Logger.new(STDOUT)
93
+ @logger.debug("KP:initialize")
94
+ end
95
+
96
+ # instance variables
97
+ @ip = ip
98
+ @port = port
99
+ @ss = smart_space
100
+ @transaction_id = 1
101
+ @node_id = UUID.new().generate()
102
+ @last_request = nil
103
+ @last_reply = nil
104
+ @active_subscriptions = {}
105
+
106
+ end
107
+
108
+
109
+ ####################################################
110
+ #
111
+ # join
112
+ #
113
+ ####################################################
114
+
115
+ def join_sib()
116
+
117
+ # debug print
118
+ if @debug
119
+ @logger.debug("KP:join_sib")
120
+ end
121
+
122
+ # building and storing the SSAP JOIN REQUEST
123
+ msg = JOIN_REQUEST_TEMPLATE % [ @node_id, @ss, @transaction_id ]
124
+ @last_request = msg
125
+
126
+ # connecting to the SIB
127
+ tcpc = TCPConnection.new(@ip, @port)
128
+
129
+ # sending the request message
130
+ tcpc.send_request(msg)
131
+
132
+ # waiting for a reply
133
+ rmsg = tcpc.receive_reply()
134
+
135
+ # closing the socket
136
+ tcpc.close()
137
+
138
+ # storing last reply
139
+ @last_reply = rmsg
140
+
141
+ # reading message
142
+ r = ReplyMessage.new(rmsg)
143
+
144
+ # increment transaction id
145
+ @transaction_id += 1
146
+
147
+ # return
148
+ return r.success?()
149
+
150
+ end
151
+
152
+
153
+ ####################################################
154
+ #
155
+ # LEAVE
156
+ #
157
+ ####################################################
158
+
159
+ def leave_sib()
160
+
161
+ # debug print
162
+ if @debug
163
+ @logger.debug("KP:leave_sib")
164
+ end
165
+
166
+ # building and storing the SSAP LEAVE REQUEST
167
+ msg = LEAVE_REQUEST_TEMPLATE % [ @node_id, @ss, @transaction_id ]
168
+ @last_request = msg
169
+
170
+ # connecting to the SIB
171
+ tcpc = TCPConnection.new(@ip, @port)
172
+
173
+ # sendind the request
174
+ tcpc.send_request(msg)
175
+
176
+ # waiting a reply
177
+ rmsg = tcpc.receive_reply()
178
+
179
+ ## instantiate a new ReplyMessage
180
+ r = ReplyMessage.new(rmsg)
181
+
182
+ # closing the socket
183
+ tcpc.close()
184
+
185
+ # storing last reply
186
+ @last_reply = rmsg
187
+
188
+ # increment transaction id
189
+ @transaction_id += 1
190
+
191
+ # return
192
+ return r.success?()
193
+
194
+ end
195
+
196
+
197
+
198
+ ####################################################
199
+ #
200
+ # INSERT
201
+ #
202
+ ####################################################
203
+
204
+ def insert(triple_list)
205
+
206
+ # debug print
207
+ if @debug
208
+ @logger.debug("KP:insert")
209
+ end
210
+
211
+ # build the triple_string
212
+ triple_string = ""
213
+ triple_list.each do |triple|
214
+ triple_string += TRIPLE_TEMPLATE % [triple.subject.class.to_s.downcase, triple.subject.value, triple.predicate.value, triple.object.class.to_s.downcase, triple.object.value]
215
+ end
216
+
217
+ # build the SSAP INSERT REQUEST
218
+ msg = INSERT_REQUEST_TEMPLATE % [ @node_id, @ss, @transaction_id, triple_string ]
219
+
220
+ # connecting to the SIB
221
+ tcpc = TCPConnection.new(@ip, @port)
222
+
223
+ # sendind the request
224
+ tcpc.send_request(msg)
225
+
226
+ # waiting a reply
227
+ rmsg = tcpc.receive_reply()
228
+
229
+ # closing the socket
230
+ tcpc.close()
231
+
232
+ # storing last reply
233
+ @last_reply = rmsg
234
+
235
+ # storing last request and last reply
236
+ @last_request = msg
237
+ @last_reply = rmsg
238
+
239
+ # read the reply
240
+ r = ReplyMessage.new(rmsg)
241
+
242
+ # increment transaction id
243
+ @transaction_id += 1
244
+
245
+ # return
246
+ return r.success?()
247
+
248
+ end
249
+
250
+
251
+ ####################################################
252
+ #
253
+ # REMOVE
254
+ #
255
+ ####################################################
256
+
257
+ def remove(triple_list)
258
+
259
+ # debug print
260
+ if @debug
261
+ @logger.debug("KP:remove")
262
+ end
263
+
264
+ # build the triple string
265
+ triple_string = ""
266
+ triple_list.each do |triple|
267
+ triple_string += TRIPLE_TEMPLATE % [triple.subject.class, triple.subject.value, triple.predicate.value, triple.object.class, triple.object.value]
268
+ end
269
+
270
+ # building and storing the SSAP REMOVE REQUEST
271
+ msg = REMOVE_REQUEST_TEMPLATE % [ @node_id, @ss, @transaction_id, triple_string ]
272
+ @last_request = msg
273
+
274
+ # connecting to the SIB
275
+ tcpc = TCPConnection.new(@ip, @port)
276
+
277
+ # sendind the request
278
+ tcpc.send_request(msg)
279
+
280
+ # waiting a reply
281
+ rmsg = tcpc.receive_reply()
282
+
283
+ # closing the socket
284
+ tcpc.close()
285
+
286
+ # storing last reply
287
+ @last_reply = rmsg
288
+
289
+ # increment transaction id
290
+ @transaction_id += 1
291
+
292
+ # parsing the message to get the return value
293
+ r = ReplyMessage.new(rmsg)
294
+ return r.success?()
295
+
296
+ end
297
+
298
+
299
+ ####################################################
300
+ #
301
+ # UPDATE
302
+ #
303
+ ####################################################
304
+
305
+ def update(new_triple_list, old_triple_list)
306
+
307
+ # debug print
308
+ if @debug
309
+ @logger.debug("KP:update")
310
+ end
311
+
312
+ # build the triple strings
313
+ old_triple_string = ""
314
+ old_triple_list.each do |triple|
315
+ old_triple_string += TRIPLE_TEMPLATE % [triple.subject.class, triple.subject.value, triple.predicate.value, triple.object.class, triple.object.value]
316
+ end
317
+ new_triple_string = ""
318
+ new_triple_list.each do |triple|
319
+ new_triple_string += TRIPLE_TEMPLATE % [triple.subject.class, triple.subject.value, triple.predicate.value, triple.object.class, triple.object.value]
320
+ end
321
+
322
+ # building and storing the SSAP REMOVE REQUEST
323
+ msg = UPDATE_REQUEST_TEMPLATE % [ @node_id, @ss, @transaction_id, new_triple_string, old_triple_string ]
324
+ @last_request = msg
325
+
326
+ # connecting to the SIB
327
+ tcpc = TCPConnection.new(@ip, @port)
328
+
329
+ # sendind the request
330
+ tcpc.send_request(msg)
331
+
332
+ # waiting a reply
333
+ rmsg = tcpc.receive_reply()
334
+
335
+ # closing the socket
336
+ tcpc.close()
337
+
338
+ # storing last reply
339
+ @last_reply = rmsg
340
+
341
+ # increment transaction id
342
+ @transaction_id += 1
343
+
344
+ # parsing the message to get the return value
345
+ r = ReplyMessage.new(rmsg)
346
+ return r.success?()
347
+
348
+ end
349
+
350
+
351
+ ####################################################
352
+ #
353
+ # RDF QUERY
354
+ #
355
+ ####################################################
356
+
357
+ def rdf_query(triple)
358
+
359
+ # debug print
360
+ if @debug
361
+ @logger.debug("KP:rdf_query")
362
+ end
363
+
364
+ # build the triple
365
+ triple_string = TRIPLE_TEMPLATE % [triple.subject.class, triple.subject.value, triple.predicate.value, triple.object.class, triple.object.value]
366
+
367
+ # build and store the SSAP QUERY REQUEST
368
+ msg = RDF_QUERY_REQUEST_TEMPLATE % [ @node_id, @ss, @transaction_id, triple_string ]
369
+ @last_request = msg
370
+
371
+ # connecting to the SIB
372
+ tcpc = TCPConnection.new(@ip, @port)
373
+
374
+ # sendind the request
375
+ tcpc.send_request(msg)
376
+
377
+ # waiting a reply
378
+ rmsg = tcpc.receive_reply()
379
+
380
+ # storing and reading the reply
381
+ @last_reply = rmsg
382
+ r = ReplyMessage.new(rmsg)
383
+
384
+ # closing the socket
385
+ tcpc.close()
386
+
387
+ # increment transaction id
388
+ @transaction_id += 1
389
+
390
+ # return
391
+ return r.success?(), r.get_rdf_triples()
392
+
393
+ end
394
+
395
+
396
+ ####################################################
397
+ #
398
+ # SPARQL QUERY
399
+ #
400
+ ####################################################
401
+
402
+ def sparql_query(q)
403
+
404
+ # debug print
405
+ if @debug
406
+ @logger.debug("KP:sparql_query")
407
+ end
408
+
409
+ # build and store the SSAP SPARQL QUERY REQUEST
410
+ q = q.gsub("<", "&lt;").gsub(">", "&gt;")
411
+ msg = SPARQL_QUERY_REQUEST_TEMPLATE % [ @node_id, @ss, @transaction_id, q ]
412
+ @last_request = msg
413
+
414
+ # connecting to the SIB
415
+ tcpc = TCPConnection.new(@ip, @port)
416
+
417
+ # sendind the request
418
+ tcpc.send_request(msg)
419
+
420
+ # waiting a reply
421
+ rmsg = tcpc.receive_reply()
422
+
423
+ # closing the socket
424
+ tcpc.close()
425
+
426
+ # storing last reply
427
+ @last_reply = rmsg
428
+
429
+ # increment transaction id
430
+ @transaction_id += 1
431
+
432
+ # reading the reply
433
+ r = ReplyMessage.new(rmsg)
434
+
435
+ # return
436
+ return r.success?(), r.get_sparql_results()
437
+
438
+ end
439
+
440
+
441
+ ####################################################
442
+ #
443
+ # RDF Subscription
444
+ #
445
+ ####################################################
446
+
447
+ def rdf_subscribe(triple, myHandlerClass)
448
+
449
+ # debug print
450
+ if @debug
451
+ @logger.debug("KP:rdf_subscribe")
452
+ end
453
+
454
+ # build the triple
455
+ triple_string = TRIPLE_TEMPLATE % [triple.subject.class, triple.subject.value, triple.predicate.value, triple.object.class, triple.object.value]
456
+
457
+ # build and store the SSAP QUERY REQUEST
458
+ msg = RDF_SUBSCRIBE_REQUEST_TEMPLATE % [ @node_id, @ss, @transaction_id, triple_string ]
459
+ @last_request = msg
460
+
461
+ # connecting to the SIB
462
+ tcpc = TCPConnection.new(@ip, @port)
463
+
464
+ # sendind the request
465
+ tcpc.send_request(msg)
466
+
467
+ # waiting a reply
468
+ rmsg = tcpc.receive_reply()
469
+
470
+ # storing and reading the last reply
471
+ @last_reply = rmsg
472
+ r = ReplyMessage.new(rmsg)
473
+
474
+ # increment transaction id
475
+ @transaction_id += 1
476
+
477
+ # get the subscription id
478
+ subscription_id = r.get_subscription_id()
479
+
480
+ # Get the initial results
481
+ triple_list = r.get_rdf_triples()
482
+
483
+ # instantiate the handler class
484
+ h = myHandlerClass.new()
485
+
486
+ # start the thread
487
+ t = Thread.new{rdf_indication_receiver(tcpc, subscription_id, h)}
488
+
489
+ # store the subscription id, its socket and its thread
490
+ @active_subscriptions[subscription_id] = {}
491
+ @active_subscriptions[subscription_id]["socket"] = tcpc
492
+ @active_subscriptions[subscription_id]["thread"] = t
493
+
494
+ # return
495
+ return r.success?(), subscription_id, triple_list
496
+
497
+ end
498
+
499
+
500
+ ####################################################
501
+ #
502
+ # SPARQL Subscription
503
+ #
504
+ ####################################################
505
+
506
+ def sparql_subscribe(pattern, myHandlerClass = nil)
507
+
508
+ # debug print
509
+ if @debug
510
+ @logger.debug("KP:rdf_subscribe")
511
+ end
512
+
513
+ # build and store the SSAP QUERY REQUEST
514
+ msg = SPARQL_SUBSCRIBE_REQUEST_TEMPLATE % [ @node_id, @ss, @transaction_id, pattern ]
515
+ @last_request = msg
516
+
517
+ # connecting to the SIB
518
+ tcpc = TCPConnection.new(@ip, @port)
519
+
520
+ # sendind the request
521
+ tcpc.send_request(msg)
522
+
523
+ # waiting a reply
524
+ rmsg = tcpc.receive_reply()
525
+
526
+ # storing and reading the last reply
527
+ @last_reply = rmsg
528
+ r = ReplyMessage.new(rmsg)
529
+
530
+ # increment transaction id
531
+ @transaction_id += 1
532
+
533
+ # get the subscription id
534
+ subscription_id = r.get_subscription_id()
535
+
536
+ # Get the initial results
537
+ initial_results = r.get_sparql_results()
538
+
539
+ # start the indication receiver
540
+ if myHandlerClass
541
+ # TODO check if myHandlerClass is a Handler,
542
+ # otherwise raise an exception
543
+ h = myHandlerClass.new()
544
+ else
545
+ h = nil
546
+ end
547
+ t = Thread.new{sparql_indication_receiver(tcpc, subscription_id, h)}
548
+
549
+ # store the subscription id and its socket
550
+ @active_subscriptions[subscription_id] = {}
551
+ @active_subscriptions[subscription_id]["socket"] = tcpc
552
+ @active_subscriptions[subscription_id]["thread"] = t
553
+
554
+ # return
555
+ return r.success?(), subscription_id, initial_results
556
+
557
+ end
558
+
559
+
560
+ ####################################################
561
+ #
562
+ # unsubscribe
563
+ #
564
+ ####################################################
565
+
566
+ def unsubscribe(sub_id)
567
+
568
+ # debug print
569
+ if @debug
570
+ @logger.debug("KP:unsubscribe")
571
+ end
572
+
573
+ # building and storing the SSAP UNSUBSCRIBE REQUEST
574
+ msg = UNSUBSCRIBE_REQUEST_TEMPLATE % [ @node_id, @ss, @transaction_id, sub_id ]
575
+ @last_request = msg
576
+
577
+ # connecting to the SIB
578
+ tcpc = TCPConnection.new(@ip, @port)
579
+
580
+ # sending the request message
581
+ tcpc.send_request(msg)
582
+
583
+ # closing the socket
584
+ tcpc.close()
585
+
586
+ # increment transaction id
587
+ @transaction_id += 1
588
+
589
+ # get the thread and return
590
+ return @active_subscriptions[sub_id]["thread"].value
591
+
592
+ end
593
+
594
+
595
+ ####################################################
596
+ #
597
+ # rdf indication receiver
598
+ #
599
+ ####################################################
600
+
601
+ def rdf_indication_receiver(tcpc, subscription_id, handler)
602
+
603
+ # debug print
604
+ if @debug
605
+ @logger.debug("KP:rdf_indication_receiver")
606
+ end
607
+
608
+ # Endless loop
609
+ while true
610
+
611
+ # receive
612
+ rmsg = tcpc.receive_reply()
613
+ r = ReplyMessage.new(rmsg)
614
+
615
+ # is it an indication?
616
+ if r.get_message_type() == "INDICATION"
617
+
618
+ # debug print
619
+ if @debug
620
+ @logger.debug("KP:rdf_indication_receiver -- INDICATION")
621
+ end
622
+
623
+ # call the handler
624
+ added, removed = r.get_rdf_triples_from_indication()
625
+ handler.handle(added, removed)
626
+
627
+ # it is an unsubscribe confirm
628
+ else
629
+
630
+ # close subscription
631
+ if r.success?()
632
+
633
+ # debug print
634
+ if @debug
635
+ @logger.debug("KP:rdf_indication_receiver -- UNSUBSCRIBE CONFIRM")
636
+ end
637
+
638
+ # save the reply
639
+ @last_reply = rmsg
640
+
641
+ # close subscription
642
+ @active_subscriptions[subscription_id]["socket"].close()
643
+ t = @active_subscriptions[subscription_id]["thread"]
644
+ @active_subscriptions.delete(subscription_id)
645
+
646
+ # return
647
+ r = ReplyMessage.new(rmsg)
648
+ return r.success?()
649
+
650
+ end
651
+ end
652
+ end
653
+ end
654
+
655
+
656
+ ####################################################
657
+ #
658
+ # sparql indication receiver
659
+ #
660
+ ####################################################
661
+
662
+ def sparql_indication_receiver(tcpc, subscription_id, handler)
663
+
664
+ # debug print
665
+ if @debug
666
+ @logger.debug("KP:sparql_indication_receiver")
667
+ end
668
+
669
+ # Endless loop
670
+ while true
671
+
672
+ # receive
673
+ rmsg = tcpc.receive_reply()
674
+ r = ReplyMessage.new(rmsg)
675
+
676
+ # parse the message
677
+ content = XML::Parser.string(rmsg).parse
678
+
679
+ # is it an indication?
680
+ if r.get_message_type() == "INDICATION"
681
+
682
+ # debug print
683
+ if @debug
684
+ @logger.debug("KP:sparql_indication_receiver -- INDICATION")
685
+ end
686
+
687
+ # extract triples from the indication and launch the handler
688
+ added, removed = r.get_sparql_results_from_indication()
689
+ handler.handle(added, removed)
690
+
691
+ # it is an unsubscribe confirm
692
+ else
693
+
694
+ # close subscription
695
+ if r.success?()
696
+
697
+ # debug print
698
+ if @debug
699
+ @logger.debug("KP:sparql_indication_receiver -- UNSUBSCRIBE CONFIRM")
700
+ end
701
+
702
+ # save the reply
703
+ @last_reply = rmsg
704
+
705
+ # close subscription
706
+ @active_subscriptions[subscription_id]["socket"].close()
707
+ t = @active_subscriptions[subscription_id]["thread"]
708
+ @active_subscriptions.delete(subscription_id)
709
+
710
+ # return
711
+ r = ReplyMessage.new(rmsg)
712
+ return r.success?()
713
+
714
+ end
715
+ end
716
+ end
717
+ end
718
+
719
+ # end of the class
720
+ end
721
+
722
+ # end of the module
723
+ end