File Coverage

blib/lib/RDF/Redland/DIG/KB.pm
Criterion Covered Total %
statement 58 60 96.6
branch n/a
condition n/a
subroutine 20 20 100.0
pod n/a
total 78 80 97.5


line stmt bran cond sub pod time code
1             package RDF::Redland::DIG::KB;
2              
3 1     1   7 use strict;
  1         2  
  1         37  
4 1     1   5 use warnings;
  1         2  
  1         32  
5              
6 1         83 use constant CREATE_KB => q|
7            
8             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
9 1     1   6 |;
  1         1  
10              
11             # Primitive Concept Retrieval
12              
13 1         61 use constant ASK_ALLCONCEPTNAMES => q|
14            
15             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
16             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
17             xmlns:owl="http://www.w3.org/2002/07/owl#"
18             xmlns="http://dl.kr.org/dig/2003/03/lang">
19            
20              
21            
22            
23            
24            
25            
26            
27 1     1   6 |;
  1         1  
28              
29 1         54 use constant ASK_ALLROLENAMES => q|
30            
31             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
32             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
33             xmlns:owl="http://www.w3.org/2002/07/owl#"
34             xmlns="http://dl.kr.org/dig/2003/03/lang">
35            
36              
37            
38            
39            
40            
41            
42            
43 1     1   6 |;
  1         2  
44              
45 1         64 use constant ASK_ALLINDIVIDUALS => q|
46            
47             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
48             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
49             xmlns:owl="http://www.w3.org/2002/07/owl#"
50             xmlns="http://dl.kr.org/dig/2003/03/lang">
51            
52              
53            
54            
55            
56            
57            
58            
59 1     1   5 |;
  1         2  
60              
61             # Satisfiability
62              
63 1         68 use constant ASK_SATISFIABLE => q|
64            
65             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
66             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
67             xmlns:owl="http://www.w3.org/2002/07/owl#"
68             xmlns="http://dl.kr.org/dig/2003/03/lang">
69            
70              
71            
72            
73            
74            
75            
76              
77            
78            
79            
80            
81            
82            
83            
84              
85            
86 1     1   5 |;
  1         2  
87              
88              
89             # Concept Hierarchy
90              
91 1         64 use constant ASK_PARENTS => q|
92            
93             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
94             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
95             xmlns:owl="http://www.w3.org/2002/07/owl#"
96             xmlns="http://dl.kr.org/dig/2003/03/lang">
97            
98              
99            
100            
101            
102            
103            
104              
105            
106            
107            
108            
109            
110            
111            
112              
113            
114 1     1   5 |;
  1         1  
115              
116 1         76 use constant ASK_CHILDREN => q|
117            
118             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
119             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
120             xmlns:owl="http://www.w3.org/2002/07/owl#"
121             xmlns="http://dl.kr.org/dig/2003/03/lang">
122            
123              
124            
125            
126            
127            
128            
129              
130            
131            
132            
133            
134            
135            
136            
137              
138            
139 1     1   6 |;
  1         2  
140              
141 1         125 use constant ASK_DESCENDANTS => q|
142            
143             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
144             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
145             xmlns:owl="http://www.w3.org/2002/07/owl#"
146             xmlns="http://dl.kr.org/dig/2003/03/lang">
147            
148              
149            
150            
151            
152            
153            
154              
155            
156            
157            
158            
159            
160            
161            
162              
163            
164 1     1   6 |;
  1         2  
165              
166 1         59 use constant ASK_ANCESTORS => q|
167            
168             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
169             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
170             xmlns:owl="http://www.w3.org/2002/07/owl#"
171             xmlns="http://dl.kr.org/dig/2003/03/lang">
172            
173              
174            
175            
176            
177            
178            
179              
180            
181            
182            
183            
184            
185            
186            
187              
188            
189 1     1   5 |;
  1         2  
190              
191 1         76 use constant ASK_EQUIVALENTS => q|
192            
193             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
194             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
195             xmlns:owl="http://www.w3.org/2002/07/owl#"
196             xmlns="http://dl.kr.org/dig/2003/03/lang">
197            
198              
199            
200            
201            
202            
203            
204              
205            
206            
207            
208            
209            
210            
211            
212              
213            
214 1     1   5 |;
  1         1  
215              
216 1         60 use constant ASK_RPARENTS => q|
217            
218             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
219             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
220             xmlns:owl="http://www.w3.org/2002/07/owl#"
221             xmlns="http://dl.kr.org/dig/2003/03/lang">
222            
223              
224            
225            
226            
227            
228            
229              
230            
231            
232            
233            
234            
235            
236            
237              
238            
239 1     1   6 |;
  1         1  
240              
241 1         55 use constant ASK_RCHILDREN => q|
242            
243             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
244             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
245             xmlns:owl="http://www.w3.org/2002/07/owl#"
246             xmlns="http://dl.kr.org/dig/2003/03/lang">
247            
248              
249            
250            
251            
252            
253            
254              
255            
256            
257            
258            
259            
260            
261            
262              
263            
264 1     1   5 |;
  1         1  
265              
266              
267 1         65 use constant ASK_RANCESTORS => q|
268            
269             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
270             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
271             xmlns:owl="http://www.w3.org/2002/07/owl#"
272             xmlns="http://dl.kr.org/dig/2003/03/lang">
273            
274              
275            
276            
277            
278            
279            
280              
281            
282            
283            
284            
285            
286            
287            
288              
289            
290 1     1   5 |;
  1         1  
291              
292              
293 1         60 use constant ASK_RDESCENDANTS => q|
294            
295             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
296             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
297             xmlns:owl="http://www.w3.org/2002/07/owl#"
298             xmlns="http://dl.kr.org/dig/2003/03/lang">
299            
300              
301            
302            
303            
304            
305            
306              
307            
308            
309            
310            
311            
312            
313            
314              
315            
316 1     1   5 |;
  1         2  
317              
318 1         73 use constant ASK_INSTANCES => q|
319            
320             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
321             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
322             xmlns:owl="http://www.w3.org/2002/07/owl#"
323             xmlns="http://dl.kr.org/dig/2003/03/lang">
324            
325              
326            
327            
328            
329            
330            
331              
332            
333            
334            
335            
336            
337            
338            
339              
340            
341 1     1   10 |;
  1         2  
342              
343 1         159 use constant ASK_TYPES => q|
344            
345             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
346             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
347             xmlns:owl="http://www.w3.org/2002/07/owl#"
348             xmlns="http://dl.kr.org/dig/2003/03/lang">
349            
350              
351            
352            
353            
354            
355            
356              
357            
358            
359            
360            
361            
362            
363            
364            
365            
366            
367            
368            
369            
370            
371            
372            
373            
374            
375            
376            
377            
378            
379            
380            
381            
382            
383            
384            
385            
386              
387            
388 1     1   6 |;
  1         1  
389              
390 1         47 use constant TELLS => q|
391            
392             xmlns:fo="http://www.w3.org/1999/XSL/Format"
393             xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
394             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
395             xmlns:owl="http://www.w3.org/2002/07/owl#"
396             xmlns:ns0="http://www.owl-ontologies.com/Ontology1206537648.owl#"
397             xmlns="http://dl.kr.org/dig/2003/03/lang">
398            
399              
400            
401            
402            
403            
404            
405            
406            
407            
408            
409            
410            
411              
412            
413            
414            
415            
416            
417            
418            
419            
420            
421            
422            
423            
424            
425            
426            
427            
428            
429            
430            
431            
432            
433            
434            
435            
436            
437            
438            
439            
440            
441            
442            
443            
444            
445            
446            
447            
448            
449            
450            
451            
452            
453            
454            
455            
456            
457            
458            
459            
460            
461            
462            
463            
464              
465            
466            
467            
468            
469            
470            
471            
472            
473            
474            
475            
476            
477            
478            
479            
480            
481            
482            
483            
484            
485              
486            
487            
488            
489            
490            
491            
492            
493            
494            
495            
496            
497            
498            
499            
500            
501            
502            
503            
504            
505            
506            
507            
508            
509            
510            
511            
512            
513            
514            
515            
516            
517            
518            
519            
520            
521            
522            
523              
524            
525            
526            
527            
528            
529            
530            
531            
532            
533            
534            
535            
536            
537            
538              
539            
540            
541            
542            
543            
544            
545            
546            
547            
548            
549            
550              
551            
552            
553            
554            
555            
556            
557            
558            
559            
560            
561            
562              
563            
564            
565            
566            
567            
568            
569            
570            
571            
572            
573            
574              
575            
576            
577            
578            
579            
580            
581            
582            
583            
584            
585            
586              
587            
588            
589            
590            
591            
592            
593            
594            
595            
596            
597            
598              
599            
600 1     1   7 |;
  1         1  
601              
602             =pod
603              
604             =head1 NAME
605              
606             RDF::Redland::DIG::KB - DIG extension for Redland RDF (Knowledge Base)
607              
608             =head1 SYNOPSIS
609              
610             my $model = new RDF::Redland::Model ....
611              
612             use RDF::Redland::DIG;
613             my $r = new RDF::Redland::DIG (url => http://localhost:8081/);
614              
615             use RDF::Redland::DIG::KB;
616             my $kb = $r->kb; # create an empty knowledge base there
617              
618             eval {
619             $kb->tell ($model);
620             }; die $@ if $@;
621              
622             my %children = $kb->children ('urn:pizza', 'urn:topping');
623              
624             my %all_children = $kb->children ();
625              
626             my %parents = $kb->parents ....
627             my %descendants = $kb->descendants ...
628              
629             my @equivs = $kb->equivalents ('urn:pizza');
630              
631              
632             my @unsatisfiable = $kb->unsatisfiable; # returns all
633              
634             my %relatedIndividuals = $kb->relatedIndividuals ...
635              
636             =head1 DESCRIPTION
637              
638             Objects of this class represent knowledge bases in the sense of DIG. Any DIG reasoner can host a
639             number of such knowledge bases.
640              
641             =cut
642              
643 1     1   489 use XML::LibXML;
  0            
  0            
644             use XML::LibXML::XPathContext;
645             use XML::LibXSLT;
646             my $xpc = XML::LibXML::XPathContext->new;
647             $xpc->registerNs('x','http://dl.kr.org/dig/2003/02/lang');
648              
649             =pod
650              
651             =head1 INTERFACE
652              
653             =head2 Constructor
654              
655             You will create knowledge bases by using an existing reasoner object (see L).
656             Alternatively, this constructor clones one knowledge base. The only mandatory parameter is the
657             reasoner.
658              
659             my $kb = new RDF::Redland::DIG::KB ($r);
660              
661             You can have any number of knowledge bases for one reasoner.
662              
663             =cut
664              
665             sub new {
666             my $class = shift;
667             my $reasoner = shift;
668            
669             my $dig_answer = _get_response(CREATE_KB, $reasoner);
670             my $uri = $xpc->findvalue('/x:response/x:kb/@uri',$dig_answer);
671            
672             return bless { reasoner => $reasoner, uri => $uri }, $class;
673             }
674              
675             sub DESTROY{
676             my $self = shift;
677             my $release = qq|
678            
679             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
680             uri="$self->{uri}" />|;
681            
682             my $dig_answer = _get_response ($release, $self->{reasoner});
683             }
684              
685             =pod
686              
687             =head2 Methods
688              
689             =over
690              
691             =item B
692              
693             This method stores data from the given model in the knowledge base. The only mandatory parameter is
694             an L. The last provided model is the actual model.
695              
696             =cut
697              
698             sub tell {
699             my $self = shift;
700             my $model = shift;
701             $self->{last_model} = $model or die 'no model provided';
702            
703             # create RDF/XML-scheme from $model
704             my $dig_question = $self->_create_digxml (TELLS);
705             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
706            
707             # find all error codes ->
708             my @error_nodes;
709            
710             foreach my $node ( $xpc->findnodes('x:error', $dig_answer) ) {
711             push(@error_nodes, $node->findvalue('@code'));
712             }
713            
714             #use Data::Dumper;
715             #warn Dumper \@error_nodes;
716            
717             die "errors occurred during tell" unless (! @error_nodes);
718             }
719              
720             =pod
721              
722             =item B
723              
724             Returns an array that contains all concepts from the knowledge base based on the actual model.
725              
726             =cut
727              
728             sub allConceptNames {
729             my $self = shift;
730            
731             # create RDF/XML-scheme from $model
732             my $dig_question = $self->_create_digxml (ASK_ALLCONCEPTNAMES);
733             my $dig_answer = _get_response($dig_question, $self->{reasoner});
734            
735             # find all classes ->
736             #
737             my @result;
738            
739             foreach my $node ( $xpc->findnodes('x:conceptSet', $dig_answer) ) {
740             foreach my $conceptnode( $xpc->findnodes('x:synonyms/x:catom', $node) ){
741             push(@result, $conceptnode->findvalue('@name'));
742             }
743             }
744              
745             return @result;
746             }
747              
748             =pod
749              
750             =item B
751              
752             Returns an array that contains all roles from the knowledge base based on the actual model.
753              
754             =cut
755              
756             sub allRoleNames {
757             my $self = shift;
758            
759             # create RDF/XML-scheme from $model
760             my $dig_question = $self->_create_digxml (ASK_ALLROLENAMES);
761             my $dig_answer = _get_response($dig_question, $self->{reasoner});
762              
763            
764             # find all classes ->
765             #
766             my @result;
767            
768             foreach my $node ( $xpc->findnodes('x:roleSet', $dig_answer) ) {
769             foreach my $rolenode($xpc->findnodes('x:synonyms/x:ratom', $node)){
770             push(@result, $rolenode->findvalue('@name'));
771             }
772             }
773              
774             return @result;
775             }
776              
777             =pod
778              
779             =item B
780              
781             Returns an array that contains all individuals from the knowledge base based on the actual model.
782              
783             =cut
784              
785             sub allIndividuals {
786             my $self = shift;
787            
788             # create RDF/XML-scheme from $model
789             my $dig_question = $self->_create_digxml (ASK_ALLINDIVIDUALS);
790             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
791             # find all classes ->
792             #
793             my @result;
794            
795             foreach my $node ( $xpc->findnodes('x:individualSet', $dig_answer) ) {
796             foreach my $individualnode($xpc->findnodes('x:individual', $node)){
797             push(@result, $individualnode->findvalue('@name'));
798             }
799             }
800              
801             return @result;
802             }
803              
804             =pod
805              
806             =item B
807              
808             Returns an array that contains all unsatisfied concept-elements from the knowledge base based on the
809             actual model.
810              
811             =cut
812              
813             sub unsatisfiable {
814             my $self = shift;
815            
816             # create RDF/XML-scheme from $model
817             my $dig_question = $self->_create_digxml (ASK_SATISFIABLE);
818             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
819             # find all classes that are unsatisfied ->
820             my @result;
821            
822             foreach my $node ( $xpc->findnodes('x:false', $dig_answer) ) {
823             push(@result, $node->findvalue('@id'));
824             }
825            
826             return @result;
827             }
828              
829             =pod
830              
831             =item B
832              
833             This method checks whether or not one concept subsumes another. The only mandatory parameter is a
834             hash that contains the main concept as a key and the questioned concepts as an array reference as
835             value. Returns the hash without the concepts that do not subsume the main concept.
836              
837             =cut
838              
839             sub subsumes {
840             my $self = shift;
841             my $dref = shift or die 'no data provided';
842             my %data = %{ ($dref) };
843            
844             my $dig_question = $self->_create_digxml2("subsumes", "catom", "catom", \%data);
845             my $dig_answer = _get_response($dig_question, $self->{reasoner});
846              
847             foreach my $key ( keys( %data ) ){
848             my $i = 0;
849            
850             foreach my $node ( $xpc->findnodes("x:*[\@id='$key']", $dig_answer) ){
851             if ( $node->nodeName eq "false" ) {
852             splice( @{ $data { $key } } , $i, 1);
853             } else {
854             $i++;
855             }
856             }
857             }
858             return %data;
859             }
860              
861             =pod
862              
863             =item B
864              
865             This method checks whether or not once concept is disjoint with another. The only mandatory
866             parameter is a hash that contains the main concept as a key and the questioned concepts as an array
867             reference as value. Returns the hash without the concepts that are not disjoint with the main
868             concept.
869              
870             =cut
871              
872             sub disjoint {
873             my $self = shift;
874             my $dref = shift or die 'no data provided';
875             my %data = %{ ($dref) };
876            
877            
878             my $dig_question = $self->_create_digxml2("disjoint", "catom", "catom", \%data);
879             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
880             foreach my $key ( keys( %data ) ){
881            
882             my $i = 0;
883            
884             foreach my $node ( $xpc->findnodes("x:*[\@id='$key']", $dig_answer) ){
885             if ( $node->nodeName eq "false" ) {
886             splice( @{ $data { $key } } , $i, 1);
887             } else {
888             $i++;
889             }
890             }
891             }
892            
893             return %data;
894             }
895              
896             =pod
897              
898             =item B
899              
900             This method returns a hash with concepts as key and their parents as value. You can either provide
901             an array as parameter (if you want the parents from specific concepts) or otherwise all parents from
902             all concepts will be returned.
903              
904             =cut
905              
906             sub parents {
907             my $self = shift;
908             my @classes = @_;
909            
910             my $dig_question;
911             if (@classes) {
912             $dig_question = $self->_create_digxml3("parents", "catom", \ @classes);
913             } else {
914             # look for all classes
915             $dig_question = $self->_create_digxml (ASK_PARENTS);
916             }
917            
918             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
919            
920             # find parents of all classes ->
921             #
922            
923             # stores child and the list of parents
924             my %result = ();
925            
926             foreach my $node ( $xpc->findnodes('x:conceptSet', $dig_answer) ) {
927             my @parentnodes;
928            
929             foreach my $parentnode( $xpc->findnodes('x:synonyms/x:catom', $node) ){
930             push(@parentnodes, $parentnode->findvalue('@name'));
931             }
932            
933             $result { $node->findvalue('@id') } = \ @parentnodes;
934             }
935              
936             return %result;
937             }
938              
939             =pod
940              
941             =item B
942            
943             This method returns a hash with concepts as key and their children as value. You can either provide
944             an array as parameter (if you want the children from specific concepts) or otherwise all children
945             from all concepts will be returned.
946              
947             =cut
948              
949             sub children {
950             my $self = shift;
951             my @classes = @_;
952            
953             my $dig_question;
954             if (@classes) {
955             $dig_question = $self->_create_digxml3("children", "catom", \ @classes);
956             } else {
957             # look for all classes
958             $dig_question = $self->_create_digxml (ASK_CHILDREN);
959             }
960              
961             # create RDF/XML-scheme from $model
962             my $dig_answer = _get_response ($dig_question, $self->{reasoner} );
963            
964             # find parents of all classes ->
965             #
966            
967             # stores parent and the list of children
968             my %result = ();
969            
970             foreach my $node ( $xpc->findnodes('x:conceptSet', $dig_answer) ) {
971             my @childnodes;
972            
973             foreach my $childnode( $xpc->findnodes('x:synonyms/x:catom', $node) ){
974             push(@childnodes, $childnode->findvalue('@name') );
975             }
976            
977             $result { $node->findvalue('@id') } = \ @childnodes;
978             }
979             return %result;
980             }
981              
982             =pod
983              
984             =item B
985            
986             This method returns a hash with concepts as key and their descendants as value. You can either
987             provide an array as parameter (if you want the descendants from specific concepts) or otherwise all
988             descendants from all concepts will be returned.
989              
990             =cut
991              
992             sub descendants {
993             my $self = shift;
994             my @classes = @_;
995            
996             # create RDF/XML-scheme from $model
997            
998             my $dig_question;
999             if (@classes) {
1000             $dig_question = $self->_create_digxml3("descendants", "catom", \ @classes);
1001             } else {
1002             # look for all classes
1003             $dig_question = $self->_create_digxml (ASK_DESCENDANTS);
1004             }
1005              
1006             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
1007            
1008             # find descendants for all classes ->
1009             #
1010            
1011             # stores class and the list of descendants
1012             my %result = ();
1013            
1014             foreach my $node ( $xpc->findnodes('x:conceptSet', $dig_answer) ) {
1015             my @descendantnodes;
1016            
1017             foreach my $descendantnode( $xpc->findnodes('x:synonyms/x:catom', $node) ){
1018             push(@descendantnodes, $descendantnode->findvalue('@name'));
1019             }
1020            
1021             $result { $node->findvalue('@id') } = \ @descendantnodes;
1022             }
1023              
1024             return %result;
1025             }
1026              
1027             =pod
1028              
1029             =item B
1030            
1031             This method returns a hash with concepts as key and their ancestors as value. You can either provide
1032             an array as parameter (if you want the ancestors from specific concepts) or otherwise all ancestors
1033             from all concepts will be returned.
1034              
1035             =cut
1036              
1037             sub ancestors {
1038             my $self = shift;
1039             my @classes = @_;
1040            
1041             my $dig_question;
1042             if (@classes) {
1043             $dig_question = $self->_create_digxml3("ancestors", "catom", \ @classes);
1044             } else {
1045             # look for all classes
1046             $dig_question = $self->_create_digxml (ASK_ANCESTORS);
1047             }
1048              
1049             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
1050             # find ancestors for all classes ->
1051             #
1052            
1053             # stores node and the list of ancestors
1054             my %result = ();
1055            
1056             foreach my $node ( $xpc->findnodes('x:conceptSet', $dig_answer) ) {
1057             my @ancestornodes;
1058            
1059             foreach my $ancestornode( $xpc->findnodes('x:synonyms/x:catom', $node) ){
1060             push(@ancestornodes, $ancestornode->findvalue('@name'));
1061             }
1062            
1063             $result { $node->findvalue('@id') } = \ @ancestornodes;
1064             }
1065              
1066             return %result;
1067             }
1068              
1069             =pod
1070              
1071             =item B
1072            
1073             This method returns a hash with concepts as key and their equivalents as value. You can either
1074             provide an array as parameter (if you want the equivalents from specific concepts) or otherwise all
1075             equivalents from all concepts will be returned.
1076              
1077             =cut
1078              
1079             sub equivalents {
1080             my $self = shift;
1081             my @classes = @_;
1082            
1083             my $dig_question;
1084             if (@classes) {
1085             $dig_question = $self->_create_digxml3("equivalents", "catom", \ @classes);
1086             } else {
1087             # look for all classes
1088             $dig_question = $self->_create_digxml (ASK_EQUIVALENTS);
1089             }
1090              
1091             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
1092              
1093             # find equivalents of all classes ->
1094             #
1095            
1096             # stores class and equivalents in hash
1097             my %result = ();
1098            
1099             foreach my $node ( $xpc->findnodes('x:conceptSet', $dig_answer) ) {
1100             my @equivalentnodes;
1101             foreach my $equivalentnode( $xpc->findnodes('x:synonyms/x:catom', $node) ){
1102             push(@equivalentnodes, $equivalentnode->findvalue('@name'));
1103             }
1104            
1105             $result { $node->findvalue('@id') } = \ @equivalentnodes;
1106             }
1107              
1108             return %result;
1109             }
1110              
1111             =pod
1112              
1113             =item B
1114            
1115             This method returns a hash with roles as key and their parents as value. You can either provide an
1116             array as parameter (if you want the parents from specific roles) or otherwise all parents from all
1117             roles will be returned.
1118              
1119             =cut
1120              
1121             sub rparents {
1122             my $self = shift;
1123             my @roles = @_;
1124            
1125             # create RDF/XML-scheme from $model
1126            
1127             my $dig_question;
1128             if (@roles) {
1129             $dig_question = $self->_create_digxml3("rparents", "ratom", \ @roles);
1130             } else {
1131             # look for all classes
1132             $dig_question = $self->_create_digxml (ASK_RPARENTS);
1133             }
1134              
1135             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
1136            
1137             # find parents of all classes ->
1138             #
1139            
1140             # a child can have one or more parents
1141             my @parents;
1142            
1143             # stores child and the list of parents
1144             my %result = ();
1145             foreach my $node ( $xpc->findnodes('x:roleSet', $dig_answer) ) {
1146             my @parentnodes;
1147             foreach my $parentnode( $xpc->findnodes('x:synonyms/x:ratom', $node) ){
1148             push(@parentnodes, $parentnode->findvalue('@name'));
1149             }
1150            
1151             $result { $node->findvalue('@id') } = \ @parentnodes;
1152             }
1153             return %result;
1154             }
1155              
1156             =pod
1157              
1158             =item B
1159            
1160             This method returns a hash with roles as key and their children as value. You can either provide an
1161             array as parameter (if you want the children from specific roles) or otherwise all children from all
1162             roles will be returned.
1163              
1164             =cut
1165              
1166             sub rchildren {
1167             my $self = shift;
1168             my @roles = @_;
1169            
1170             # create RDF/XML-scheme from $model
1171            
1172             my $dig_question;
1173             if (@roles) {
1174             $dig_question = $self->_create_digxml3("rchildren", "ratom", \ @roles);
1175             } else {
1176             # look for all classes
1177             $dig_question = $self->_create_digxml (ASK_RCHILDREN);
1178             }
1179             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
1180            
1181             # find parents for all roles ->
1182             #
1183            
1184             # stores parent and the list of children
1185             my %result = ();
1186             foreach my $node ( $xpc->findnodes('x:roleSet', $dig_answer) ) {
1187             my @childnodes;
1188            
1189             foreach my $childnode( $xpc->findnodes('x:synonyms/x:ratom', $node) ){
1190             push(@childnodes, $childnode->findvalue('@name'));
1191             }
1192            
1193             $result { $node->findvalue('@id') } = \ @childnodes;
1194             }
1195             return %result;
1196             }
1197              
1198             =pod
1199              
1200             =item B
1201            
1202             This method returns a hash with roles as key and their descendants as value. You can either provide
1203             an array as parameter (if you want the descendants from specific roles) or otherwise all descendants
1204             from all roles will be returned.
1205              
1206             =cut
1207              
1208             sub rdescendants {
1209             my $self = shift;
1210             my @roles = @_;
1211            
1212             # create RDF/XML-scheme from $model
1213            
1214             my $dig_question;
1215             if (@roles) {
1216             $dig_question = $self->_create_digxml3("rdescendants", "ratom", \ @roles);
1217             } else {
1218             # look for all classes
1219             $dig_question = $self->_create_digxml (ASK_RDESCENDANTS);
1220             }
1221             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
1222            
1223             # find descendants for all roles ->
1224             #
1225            
1226             # stores class and the list of descendants
1227             my %result = ();
1228             foreach my $node ( $xpc->findnodes('x:roleSet', $dig_answer) ) {
1229             my @descendantnodes;
1230            
1231             foreach my $descendantnode( $xpc->findnodes('x:synonyms/x:ratom', $node) ){
1232             push(@descendantnodes, $descendantnode->findvalue('@name'));
1233             }
1234            
1235             $result { $node->findvalue('@id') } = \ @descendantnodes;
1236             }
1237             return %result;
1238             }
1239              
1240             =pod
1241              
1242             =item B
1243            
1244             This method returns a hash with roles as key and their ancestors as value. You can either provide an
1245             array as parameter (if you want the ancestors from specific roles) or otherwise all ancestors from
1246             all roles will be returned.
1247              
1248             =cut
1249              
1250             sub rancestors {
1251             my $self = shift;
1252             my @roles = @_;
1253            
1254             # create RDF/XML-scheme from $model
1255            
1256             my $dig_question;
1257             if (@roles) {
1258             $dig_question = $self->_create_digxml3("rancestors", "ratom", \ @roles);
1259             } else {
1260             # look for all classes
1261             $dig_question = $self->_create_digxml (ASK_RANCESTORS);
1262             }
1263             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
1264              
1265             # find ancestors for all roles ->
1266             #
1267            
1268             # stores node and the list of ancestors
1269             my %result = ();
1270             foreach my $node ( $xpc->findnodes('x:roleSet', $dig_answer) ) {
1271             my @ancestornodes;
1272            
1273             foreach my $ancestornode( $xpc->findnodes('x:synonyms/x:ratom', $node) ){
1274             push(@ancestornodes, $ancestornode->findvalue('@name'));
1275             }
1276            
1277             $result { $node->findvalue('@id') } = \ @ancestornodes;
1278             }
1279             return %result;
1280             }
1281              
1282             =pod
1283              
1284             =item B
1285            
1286             This method returns a hash with concepts as key and their instances as value. You can either provide
1287             an array as parameter (if you want the instances from specific concepts) or otherwise all instances
1288             from all concepts will be returned.
1289              
1290             =cut
1291              
1292             sub instances {
1293             my $self = shift;
1294             my @classes = @_;
1295            
1296             my $dig_question;
1297             if (@classes) {
1298             $dig_question = $self->_create_digxml3("instances", "catom", \ @classes);
1299             } else {
1300             # look for all classes
1301             $dig_question = $self->_create_digxml (ASK_INSTANCES);
1302             }
1303              
1304             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
1305            
1306             # find instances for all classes ->
1307             #
1308            
1309             # stores node and the list of instances
1310             my %result = ();
1311            
1312             foreach my $node ( $xpc->findnodes('x:individualSet', $dig_answer) ) {
1313             my @instances;
1314            
1315             foreach my $instancenode( $xpc->findnodes('x:individual', $node) ){
1316             push(@instances, $instancenode->findvalue('@name'));
1317             }
1318            
1319             $result { $node->findvalue('@id') } = \ @instances;
1320             }
1321              
1322             return %result;
1323             }
1324              
1325             =pod
1326              
1327             =item B
1328            
1329             This method returns a hash with individuals as key and their concepts as value. You can either
1330             provide an array as parameter (if you want the concepts from specific individuals) or otherwise all
1331             concepts from all individuals will be returned.
1332              
1333             =cut
1334              
1335             sub types {
1336             my $self = shift;
1337             my @individuals = @_;
1338            
1339             my $dig_question;
1340             if (@individuals) {
1341             $dig_question = $self->_create_digxml3("types", "individual", \ @individuals);
1342             } else {
1343             # look for all classes
1344             $dig_question = $self->_create_digxml (ASK_TYPES);
1345             }
1346              
1347             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
1348            
1349             # find classes for all instances ->
1350             #
1351            
1352             # stores node and the list of classes
1353             my %result = ();
1354             foreach my $node ( $xpc->findnodes('x:conceptSet', $dig_answer) ) {
1355             my @types;
1356            
1357             foreach my $typenode( $xpc->findnodes('x:synonyms/x:catom', $node) ){
1358             push(@types, $typenode->findvalue('@name'));
1359             }
1360            
1361             $result { $node->findvalue('@id') } = \ @types;
1362             }
1363             return %result;
1364             }
1365              
1366             =pod
1367              
1368             =item B
1369              
1370             This method checks whether or not an individual is an instance from a specified concept. The only
1371             mandatory parameter is a hash that contains the individual as a key and the questioned concepts as
1372             an array reference as value. Returns the hash without the concepts that are not disjoint with the
1373             main concept.
1374              
1375             =cut
1376              
1377             sub instance {
1378             my $self = shift;
1379             my $dref = shift or die 'no data provided';
1380             my %data = %{ ($dref) };
1381            
1382            
1383             my $dig_question = $self->_create_digxml2("instance", "individual", "catom", \%data);
1384             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
1385            
1386            
1387             foreach my $key ( keys( %data ) ){
1388            
1389             my $i = 0;
1390            
1391             foreach my $node ( $xpc->findnodes("x:*[\@id='$key']", $dig_answer) ){
1392             if ( $node->nodeName eq "false" ) {
1393             splice( @{ $data { $key } } , $i, 1);
1394             } else {
1395             $i++;
1396             }
1397             }
1398             }
1399            
1400             return %data;
1401             }
1402              
1403             =pod
1404              
1405             =item B
1406              
1407             This method checks which individuals are asserted to a specified (individual,role)-pair. The
1408             mandatory parameters are the name of the main individual and the name of the role. Returns the
1409             asserted individuals to this pair as an array.
1410              
1411             =cut
1412              
1413             sub roleFillers {
1414             my $self = shift;
1415             my $individual = shift or die 'no data provided';
1416             my $role = shift or die 'no data provided';
1417            
1418             my $dig_question = $self->_create_digxml4("roleFillers", "individual", "ratom", $individual, $role);
1419             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
1420            
1421             # find roleFillers for individuals ->
1422             #
1423             #
1424            
1425             # stores node and the list of ancestors
1426             my @result;
1427             foreach my $node ( $xpc->findnodes('x:individualSet', $dig_answer) ) {
1428             foreach my $relatednode( $xpc->findnodes('x:individual', $node) ){
1429             push(@result, $relatednode->findvalue('@name'));
1430             }
1431             }
1432             return @result;
1433             }
1434              
1435             =pod
1436              
1437             =item B
1438              
1439             This method returns an array with pairs of individuals that are asserted to a specified role. The
1440             only mandatory parameter is the role.
1441              
1442             =cut
1443              
1444             sub relatedIndividuals {
1445             my $self = shift;
1446             my $role = shift or die 'no data provided';
1447            
1448             my $dig_question = $self->_create_digxml5("relatedIndividuals", "ratom", $role);
1449             my $dig_answer = _get_response ($dig_question, $self->{reasoner});
1450            
1451             # find related individuals for all individuals ->
1452             #
1453             #
1454              
1455             # stores relatedIndividuals
1456             my @result;
1457             foreach my $node ( $xpc->findnodes('x:individualPairSet/x:individualPair', $dig_answer) ) {
1458             my @relatednodes;
1459            
1460             foreach my $relatednode( $xpc->findnodes('x:individual', $node) ){
1461             push(@relatednodes, $relatednode->findvalue('@name'));
1462             }
1463             push(@result, \ @relatednodes);
1464             }
1465             return @result;
1466             }
1467              
1468             =pod
1469              
1470             =back
1471              
1472             =cut
1473              
1474             #-- aux functions ---------------------------------------------------------------
1475             sub _create_digxml {
1476             my $self = shift;
1477             my $stylesheet = shift;
1478            
1479             # create RDF/XML-File from model
1480             use RDF::Redland;
1481             my $serializer = new RDF::Redland::Serializer("rdfxml")
1482             or die "Failed to find serializer";
1483              
1484             my $uri = new RDF::Redland::URI($self->{uri});
1485             # serialize model to string
1486             my $ser_model = $serializer->serialize_model_to_string ($uri, $self->{last_model});
1487            
1488             $serializer = undef;
1489            
1490             my $parser = XML::LibXML->new();
1491             my $xslt = XML::LibXSLT->new();
1492            
1493             # parse rdf/xml-string
1494             my $source = $parser->parse_string($ser_model);
1495            
1496             # define xslt-stylesheet
1497             my $style_doc = $parser->parse_string($stylesheet);
1498             my $xml = $xslt->parse_stylesheet($style_doc);
1499            
1500             # define uri in $tell_result
1501             my $result = $xml->transform($source, XML::LibXSLT::xpath_to_string(
1502             param => "$self->{uri}"
1503             ));
1504            
1505             #my $out = "OUTPUT_TELL.xml";
1506             #open OUT, ">$out" or die "Cannot open $out for write";
1507             #print OUT $xml->output_string($result);
1508            
1509             return ($xml->output_string($result));
1510             }
1511              
1512             sub _create_digxml2 {
1513             my $self = shift;
1514             my $tag = shift;
1515             my $attribute1 = shift;
1516             my $attribute2 = shift;
1517             my $dataref = shift;
1518            
1519             my %data = % {$dataref};
1520            
1521            
1522             # create XML-File
1523             my $xml = XML::LibXML::Document->new("1.0","UTF-8");
1524             my $rootnode = XML::LibXML::Element->new("asks");
1525             $rootnode->setAttribute("xmlns","http://dl.kr.org/dig/2003/03/lang");
1526             $rootnode->setAttribute("xmlns:fo", "http://www.w3.org/1999/XSL/Format");
1527             $rootnode->setAttribute("xmlns:rdfs", "http://www.w3.org/2000/01/rdf-schema#");
1528             $rootnode->setAttribute("xmlns:rdf","http://www.w3.org/1999/02/22-rdf-syntax-ns#");
1529             $rootnode->setAttribute("xmlns:owl","http://www.w3.org/2002/07/owl#");
1530             $rootnode->setAttribute("uri","$self->{uri}");
1531            
1532             while ( my ($key, $value) = each(%data) ) {
1533            
1534             my @listvalues = @{($value)};
1535            
1536             foreach my $lvalue ( @listvalues ) {
1537            
1538             my $node = XML::LibXML::Element->new($tag);
1539             $node->setAttribute("id", "$key");
1540            
1541             my $childnode1 = XML::LibXML::Element->new($attribute1);
1542             $childnode1->setAttribute("name","$key");
1543            
1544             $node->appendChild($childnode1);
1545            
1546             my $childnode2 = XML::LibXML::Element->new($attribute2);
1547             $childnode2->setAttribute("name","$lvalue");
1548             $node->appendChild($childnode2);
1549            
1550             $rootnode->appendChild($node);
1551            
1552             }
1553             }
1554             $xml->setDocumentElement($rootnode);
1555            
1556             return $xml->toString();
1557             }
1558              
1559             sub _create_digxml3 {
1560             my $self = shift;
1561             my $tag = shift;
1562             my $attribute = shift;
1563             my $dataref = shift;
1564            
1565             my @data = @{$dataref};
1566            
1567             # create XML-File
1568             my $xml = XML::LibXML::Document->new("1.0","UTF-8");
1569             my $rootnode = XML::LibXML::Element->new("asks");
1570             $rootnode->setAttribute("xmlns","http://dl.kr.org/dig/2003/03/lang");
1571             $rootnode->setAttribute("xmlns:fo", "http://www.w3.org/1999/XSL/Format");
1572             $rootnode->setAttribute("xmlns:rdfs", "http://www.w3.org/2000/01/rdf-schema#");
1573             $rootnode->setAttribute("xmlns:rdf","http://www.w3.org/1999/02/22-rdf-syntax-ns#");
1574             $rootnode->setAttribute("xmlns:owl","http://www.w3.org/2002/07/owl#");
1575             $rootnode->setAttribute("uri","$self->{uri}");
1576            
1577             my $element;
1578             foreach $element ( @data ) {
1579             my $node = XML::LibXML::Element->new($tag);
1580             $node->setAttribute("id", "$element");
1581            
1582             my $childnode = XML::LibXML::Element->new($attribute);
1583             $childnode->setAttribute("name","$element");
1584            
1585             $node->appendChild($childnode);
1586             $rootnode->appendChild($node);
1587             }
1588             $xml->setDocumentElement($rootnode);
1589            
1590             return $xml->toString();
1591             }
1592              
1593             sub _create_digxml4 {
1594             my $self = shift;
1595             my $tag = shift;
1596             my $attribute1 = shift;
1597             my $attribute2 = shift;
1598             my $data1 = shift;
1599             my $data2 = shift;
1600            
1601             # create XML-File
1602             my $xml = XML::LibXML::Document->new("1.0","UTF-8");
1603             my $rootnode = XML::LibXML::Element->new("asks");
1604             $rootnode->setAttribute("xmlns","http://dl.kr.org/dig/2003/03/lang");
1605             $rootnode->setAttribute("xmlns:fo", "http://www.w3.org/1999/XSL/Format");
1606             $rootnode->setAttribute("xmlns:rdfs", "http://www.w3.org/2000/01/rdf-schema#");
1607             $rootnode->setAttribute("xmlns:rdf","http://www.w3.org/1999/02/22-rdf-syntax-ns#");
1608             $rootnode->setAttribute("xmlns:owl","http://www.w3.org/2002/07/owl#");
1609             $rootnode->setAttribute("uri","$self->{uri}");
1610            
1611             my $node = XML::LibXML::Element->new($tag);
1612             $node->setAttribute("id", "$data1");
1613            
1614             my $childnode1 = XML::LibXML::Element->new($attribute1);
1615             $childnode1->setAttribute("name","$data1");
1616             $node->appendChild($childnode1);
1617            
1618             my $childnode2 = XML::LibXML::Element->new($attribute2);
1619             $childnode2->setAttribute("name","$data2");
1620             $node->appendChild($childnode2);
1621            
1622             $rootnode->appendChild($node);
1623             $xml->setDocumentElement($rootnode);
1624            
1625             return $xml->toString();
1626             }
1627              
1628             sub _create_digxml5 {
1629             my $self = shift;
1630             my $tag = shift;
1631             my $attribute = shift;
1632             my $data = shift;
1633            
1634             # create XML-File
1635             my $xml = XML::LibXML::Document->new("1.0","UTF-8");
1636             my $rootnode = XML::LibXML::Element->new("asks");
1637             $rootnode->setAttribute("xmlns","http://dl.kr.org/dig/2003/03/lang");
1638             $rootnode->setAttribute("xmlns:fo", "http://www.w3.org/1999/XSL/Format");
1639             $rootnode->setAttribute("xmlns:rdfs", "http://www.w3.org/2000/01/rdf-schema#");
1640             $rootnode->setAttribute("xmlns:rdf","http://www.w3.org/1999/02/22-rdf-syntax-ns#");
1641             $rootnode->setAttribute("xmlns:owl","http://www.w3.org/2002/07/owl#");
1642             $rootnode->setAttribute("uri","$self->{uri}");
1643            
1644             my $node = XML::LibXML::Element->new($tag);
1645             $node->setAttribute("id", "$data");
1646            
1647             my $childnode = XML::LibXML::Element->new($attribute);
1648             $childnode->setAttribute("name","$data");
1649            
1650             $node->appendChild($childnode);
1651             $rootnode->appendChild($node);
1652             $xml->setDocumentElement($rootnode);
1653            
1654             return $xml->toString();
1655             }
1656              
1657             sub _get_response {
1658             my $dig_question = shift;
1659             my $reasoner = shift;
1660            
1661             my $req = HTTP::Request->new(POST => $reasoner->{url});
1662             $req->content_type('text/xml');
1663             use Encode;
1664             $req->content(encode("iso-8859-1", $dig_question));
1665            
1666             # Pass request to the user agent and get a response back
1667             my $res = $reasoner->{ua}->request ($req);
1668            
1669             # Check the outcome of the response
1670             die "reasoner could not be contacted at $reasoner->{url}" unless $res->is_success;
1671              
1672             my $parser = XML::LibXML->new();
1673             # parse content
1674             my $tree = $parser->parse_string($res->content);
1675             my $root = $tree->getDocumentElement;
1676              
1677             return $root;
1678             }
1679              
1680             =pod
1681              
1682             =head1 COPYRIGHT AND LICENCE
1683              
1684             Copyright 2008 by Lara Spendier and Robert Barta
1685              
1686             This library is free software; you can redistribute it and/or modify it under the same terms as Perl
1687             itself.
1688              
1689             Work supported by the Austrian Research Centers Seibersdorf (Smart Systems).
1690              
1691             =cut
1692              
1693             our $VERSION = 0.02;
1694              
1695             1;