ruby_kpi 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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