File Coverage

blib/lib/REST/Neo4p/Path.pm
Criterion Covered Total %
statement 13 87 14.9
branch 0 44 0.0
condition 0 21 0.0
subroutine 5 12 41.6
pod 3 7 42.8
total 21 171 12.2


line stmt bran cond sub pod time code
1             #$Id$
2             package REST::Neo4p::Path;
3 36     36   258 use REST::Neo4p::Exceptions;
  36         73  
  36         1268  
4 36     36   223 use Carp qw(croak carp);
  36         66  
  36         2029  
5 36     36   241 use strict;
  36         72  
  36         948  
6 36     36   196 use warnings;
  36         66  
  36         1564  
7             BEGIN {
8 36     36   35967 $REST::Neo4p::Path::VERSION = '0.4003';
9             }
10              
11             sub new {
12 0     0 0   my $class = shift;
13 0           bless { _length => 0 }, $class;
14             }
15              
16             sub new_from_json_response {
17 0     0 0   my $class = shift;
18 0           my ($decoded_resp) = @_;
19 0 0         return $class->new_from_driver_obj(@_) if (ref($decoded_resp) =~ /Neo4j::Driver/);
20 0 0 0       REST::Neo4p::LocalException->throw("Arg does not describe a Neo4j path response\n") unless $decoded_resp->{start} && $decoded_resp->{end} && $decoded_resp->{relationships} && $decoded_resp->{nodes};
      0        
      0        
21 0           my $obj = bless {}, $class;
22 0           $obj->{_length} = $decoded_resp->{length};
23 0           my @node_urls = @{$decoded_resp->{nodes}};
  0            
24 0           my @reln_urls = @{$decoded_resp->{relationships}};
  0            
25              
26 0           while (my $node_url = shift @node_urls) {
27 0           my $reln_url = shift @reln_urls;
28 0           my ($node_id) = $node_url =~ /([0-9]+)$/;
29 0 0         my ($reln_id) = $reln_url =~ /([0-9]+)$/ if $reln_url;
30 0           my ($node, $relationship);
31 0           eval {
32 0           $node = REST::Neo4p::Node->_entity_by_id($node_id);
33             };
34 0 0         if (my $e = REST::Neo4p::Exception->caught()) {
    0          
35             # TODO : handle different classes
36 0           $e->rethrow;
37             }
38             elsif ($e = Exception::Class->caught()) {
39 0 0 0       (ref $e && $e->can("rethrow")) ? $e->rethrow : die $e;
40             }
41 0           push @{$obj->{_nodes}}, $node;
  0            
42 0           eval {
43 0 0         $relationship = REST::Neo4p::Relationship->_entity_by_id($reln_id) if defined $reln_id;
44             };
45 0 0         if (my $e = REST::Neo4p::Exception->caught()) {
    0          
46             # TODO : handle different classes
47 0           $e->rethrow;
48             }
49             elsif ($e = Exception::Class->caught()) {
50 0 0 0       (ref $e && $e->can("rethrow")) ? $e->rethrow : die $e;
51             }
52 0 0         push @{$obj->{_relationships}}, $relationship if $relationship;
  0            
53             }
54 0 0         REST::Neo4p::LocalException->throw("Extra relationships in path\n") if @reln_urls;
55 0           return $obj;
56             }
57              
58             sub new_from_driver_obj {
59 0     0 0   my $class = shift;
60 0           my ($pth_obj) = @_;
61 0           my $obj = bless {}, $class;
62              
63 0           my @nodes = $pth_obj->nodes;
64 0           my @relns = $pth_obj->relationships;
65 0           $obj->{_length} = scalar @relns;
66              
67 0           while (my $n = shift @nodes) {
68 0           my $r = shift @relns;
69 0           my ($node, $relationship);
70 0           eval {
71 0           $node = REST::Neo4p::Node->_entity_by_id($n->id);
72             };
73 0 0         if (my $e = REST::Neo4p::Exception->caught()) {
    0          
74             # TODO : handle different classes
75 0           $e->rethrow;
76             }
77             elsif ($e = Exception::Class->caught()) {
78 0 0 0       (ref $e && $e->can("rethrow")) ? $e->rethrow : die $e;
79             }
80 0           push @{$obj->{_nodes}}, $node;
  0            
81 0           eval {
82 0 0         $relationship = REST::Neo4p::Relationship->_entity_by_id($r->id) if defined $r;
83             };
84 0 0         if (my $e = REST::Neo4p::Exception->caught()) {
    0          
85             # TODO : handle different classes
86 0           $e->rethrow;
87             }
88             elsif ($e = Exception::Class->caught()) {
89 0 0 0       (ref $e && $e->can("rethrow")) ? $e->rethrow : die $e;
90             }
91 0 0         push @{$obj->{_relationships}}, $relationship if $relationship;
  0            
92             }
93 0 0         REST::Neo4p::LocalException->throw("Extra relationships in path\n") if @relns;
94 0           return $obj;
95             }
96              
97             sub as_simple {
98 0     0 1   my $self = shift;
99 0           my $ret;
100 0           my @n = $self->nodes;
101 0           my @r = $self->relationships;
102 0           while (my $n = shift @n) {
103 0           push @$ret, $n->as_simple;
104 0           my $r = shift @r;
105 0 0         push @$ret, $r->as_simple if defined $r;
106             }
107 0           return $ret;
108             }
109              
110             sub simple_from_json_response {
111 0     0 0   my $class = shift;
112 0           my ($decoded_resp) = @_;
113 0           return $class->new_from_json_response($decoded_resp)->as_simple;
114             }
115              
116 0     0 1   sub nodes { @{shift->{_nodes}} }
  0            
117 0     0 1   sub relationships { @{shift->{_relationships}} }
  0            
118              
119             =head1 NAME
120              
121             REST::Neo4p::Path - Container for Neo4j path elements
122              
123             =head1 SYNOPSIS
124              
125             use REST::Neo4p::Query;
126             $query = REST::Neo4p::Query->new(
127             'START n=node(0), m=node(1) MATCH p=(n)-[*..3]->(m) RETURN p'
128             );
129             $query->execute;
130             $path = $query->fetch->[0];
131             @nodes = $path->nodes;
132             @relns = $path->relationships;
133             while ($n = shift @nodes) {
134             my $r = shift @relns;
135             print $r ? $n->id."-".$r->id."->" : $n->id."\n";
136             }
137              
138             =head1 DESCRIPTION
139              
140             REST::Neo4p::Path provides a simple container for Neo4j paths as returned
141             by Cypher queries. Nodes and relationships are stored in path order.
142              
143             Creating de novo instances of this class is really the job of L.
144              
145             =head1 METHODS
146              
147             =over
148              
149             =item nodes()
150              
151             @nodes = $path->nodes;
152              
153             Get the nodes in path order.
154              
155             =item relationships()
156              
157             @relationships = $path->relationships;
158              
159             Get the relationships in path order.
160              
161             =item as_simple()
162              
163             $a = $path->as_simple;
164             @simple_nodes = grep { $_->{_node} } @$a;
165             @simple_relns = grep { $_->{_relationship} } @$a;
166              
167             Get the path as an array of simple node and relationship hashes (see
168             L,
169             L).
170              
171             =back
172              
173             =head1 SEE ALSO
174              
175             L, L, L,
176             L.
177              
178             =head1 AUTHOR
179              
180             Mark A. Jensen
181             CPAN ID: MAJENSEN
182             majensen -at- cpan -dot- org
183              
184             =head1 LICENSE
185              
186             Copyright (c) 2012-2022 Mark A. Jensen. This program is free software; you
187             can redistribute it and/or modify it under the same terms as Perl
188             itself.
189              
190             =cut
191              
192             1;