File Coverage

blib/lib/Net/Rexster/Client.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Net::Rexster::Client;
2              
3 1     1   24131 use warnings;
  1         2  
  1         61  
4 1     1   7 use strict;
  1         2  
  1         37  
5 1     1   7 use Carp;
  1         7  
  1         95  
6              
7 1     1   516 use Moose;
  0            
  0            
8             use Net::Rexster::Request;
9              
10             use version;
11             our $VERSION = qv('0.0.5');
12              
13             has 'server' => (is => 'rw', isa => 'Str', default => 'http://localhost:8182');
14             has 'graph' => (is => 'rw', isa => 'Str', required => 1);
15             has 'request' => (is => 'ro', isa => 'Net::Rexster::Request', default => sub { new Net::Rexster::Request } );
16              
17             __PACKAGE__->meta->make_immutable;
18             no Moose;
19              
20             # /graphs
21             sub get_graphs {
22             my ($self) = @_;
23             my $uri = $self->server . "/graphs";
24             return $self->request->get($uri)->get_graphs;
25             }
26              
27             # /graphs/<graph>
28             sub get_graph {
29             my ($self) = @_;
30             my $uri = $self->server . "/graphs/" . $self->graph;
31             return $self->request->get($uri);
32             }
33              
34             # /graphs/<graph>/vertices
35             sub get_all_vertices {
36             my ($self) = @_;
37             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices";
38             return $self->request->get($uri)->get_results();
39             }
40              
41             #/graphs/<graph>/vertices?key=<key>&value=<value>
42             sub lookup_vertex {
43             my ($self, $key, $value) = @_;
44             die "key and value are needed\n" if (! defined $key || ! defined $value);
45             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices?key=$key&value=$value";
46             return $self->request->get($uri)->get_results();
47             }
48              
49             #/graphs/<graph>/vertices/<id>
50             sub get_vertex {
51             my ($self, $id) = @_;
52             die "id is needed\n" if (! defined $id);
53             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id;
54             return $self->request->get($uri)->get_results();
55             }
56              
57             #/graphs/<graph>/vertices/<id>/out
58             sub outV {
59             my ($self, $id) = @_;
60             die "id is needed\n" if (! defined $id);
61             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id . "/out";
62             return $self->request->get($uri)->get_results();
63             }
64              
65             #/graphs/<graph>/vertices/<id>/in
66             sub inV {
67             my ($self, $id) = @_;
68             die "id is needed\n" if (! defined $id);
69             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id . "/in";
70             return $self->request->get($uri)->get_results();
71             }
72              
73             #/graphs/<graph>/vertices/<id>/both
74             sub bothV {
75             my ($self, $id) = @_;
76             die "id is needed\n" if (! defined $id);
77             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id . "/both";
78             return $self->request->get($uri)->get_results();
79             }
80              
81             # /graphs/<graph>/vertices/<id>/outCount
82             sub outVcount {
83             my ($self, $id) = @_;
84             die "id is needed\n" if (! defined $id);
85             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id . "/outCount";
86             return $self->request->get($uri)->get_totalSize();
87             }
88              
89             # /graphs/<graph>/vertices/<id>/inCount
90             sub inVcount {
91             my ($self, $id) = @_;
92             die "id is needed\n" if (! defined $id);
93             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id . "/inCount";
94             return $self->request->get($uri)->get_totalSize();
95             }
96              
97             # /graphs/<graph>/vertices/<id>/bothCount
98             sub bothVcount {
99             my ($self, $id) = @_;
100             die "id is needed\n" if (! defined $id);
101             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id . "/bothCount";
102             return $self->request->get($uri)->get_totalSize();
103             }
104              
105             #/graphs/<graph>/vertices/<id>/outIds
106             sub outIds{
107             my ($self, $id) = @_;
108             die "id is needed\n" if (! defined $id);
109             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id . "/outIds";
110             return $self->request->get($uri)->get_results();
111             }
112              
113             #/graphs/<graph>/vertices/<id>/inIds
114             sub inIds{
115             my ($self, $id) = @_;
116             die "id is needed\n" if (! defined $id);
117             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id . "/inIds";
118             return $self->request->get($uri)->get_results();
119             }
120             #/graphs/<graph>/vertices/<id>/bothIds
121             sub bothIds{
122             my ($self, $id) = @_;
123             die "id is needed\n" if (! defined $id);
124             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id . "/bothIds";
125             return $self->request->get($uri)->get_results();
126             }
127              
128             #/graphs/<graph>/edges
129             sub get_all_edges {
130             my ($self) = @_;
131             my $uri = $self->server . "/graphs/" . $self->graph . "/edges";
132             return $self->request->get($uri)->get_results();
133             }
134              
135             #/graphs/<graph>/edges?key=<key>&value=<value>
136             sub lookup_edges {
137             my ($self, $key, $value) = @_;
138             die "key and value are needed\n" if (! defined $key || ! defined $value);
139             my $uri = $self->server . "/graphs/" . $self->graph . "/edges?key=$key&value=$value";
140             return $self->request->get($uri)->get_results();
141             }
142             #/graphs/<graph>/edges/<id>
143             sub get_edge {
144             my ($self, $id) = @_;
145             die "id is needed\n" if (! defined $id);
146             my $uri = $self->server . "/graphs/" . $self->graph . "/edges/". $id;
147             return $self->request->get($uri)->get_results();
148             }
149             #/graphs/<graph>/vertices/<id>/outE
150             sub outE {
151             my ($self, $id) = @_;
152             die "id is needed\n" if (! defined $id);
153             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id . "/outE";
154             return $self->request->get($uri)->get_results();
155             }
156             #/graphs/<graph>/vertices/<id>/inE
157             sub inE {
158             my ($self, $id) = @_;
159             die "id is needed\n" if (! defined $id);
160             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id . "/inE";
161             return $self->request->get($uri)->get_results();
162             }
163             #/graphs/<graph>/vertices/<id>/bothE
164             sub bothE {
165             my ($self, $id) = @_;
166             die "id is needed\n" if (! defined $id);
167             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/". $id . "/bothE";
168             return $self->request->get($uri)->get_results();
169             }
170              
171             #/graphs/<graph>/indices
172             sub get_indices {
173             my ($self) = @_;
174             my $uri = $self->server . "/graphs/" . $self->graph . "/indices";
175             return $self->request->get($uri)->get_results();
176             }
177             #/graphs/<graph>/indices/index?key=<key>&value=<value>
178             sub lookup_index {
179             my ($self, $index, $key, $value) = @_;
180             die "index, key and value are needed\n" if (! defined $key || ! defined $value || ! defined $index);
181             my $uri = $self->server . "/graphs/" . $self->graph . "/indices/$index?key=$key&value=$value";
182             return $self->request->get($uri)->get_results();
183             }
184              
185             #/graphs/<graph>/indices/index/count?key=<key>&value=<value>
186             sub index_count {
187             my ($self, $key, $value) = @_;
188             die "key and value are needed\n" if (! defined $key || ! defined $value);
189             my $uri = $self->server . "/graphs/" . $self->graph . "/indices/index/count?key=$key&value=$value";
190             return $self->request->get($uri)->get_totalSize();
191             }
192              
193             # Comment out until I figure out how kyeindices is used.
194             ##/graphs/<graph>/keyindices/
195             #sub index_keys {
196             # my ($self) = @_;
197             # my $uri = $self->server . "/graphs/" . $self->graph . "/keyindices";
198             # #return $self->request->get($uri)->get_results();
199             # return $self->request->get($uri)->get_keys();
200             #}
201             #
202             ##/graphs/<graph>/keyindices/vertex
203             #sub get_vertex_indices {
204             # my ($self) = @_;
205             # my $uri = $self->server . "/graphs/" . $self->graph . "/keyindices/vertex";
206             # return $self->request->get($uri)->get_results();
207             #}
208             #
209             ##/graphs/<graph>/keyindices/edge
210             #sub get_edge_indices {
211             # my ($self) = @_;
212             # my $uri = $self->server . "/graphs/" . $self->graph . "/keyindices/edge";
213             # print $uri;
214             # return $self->request->get($uri)->get_results();
215             #}
216             #
217             #/graphs/<graph>/prefixes - only SailGraph. No need to support
218             #/graphs/<graph>/prefixes/prefix - only SailGraph. No need to support
219              
220             #======================================================================================
221             # POST
222             #======================================================================================
223             #/graphs/<graph>/vertices
224             #/graphs/<graph>/vertices/<id> # <id> may not work.
225             sub create_vertex {
226             my ($self, $id) = @_;
227             $id = "" unless ( defined $id );
228             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/$id";
229             return $self->request->post($uri)->get_results();
230             }
231              
232             #/graphs/<graph>/vertices/<id>?<key>=<value>&<key'>=<value'>
233             sub create_vertex_property {
234             my ($self, $id, $params) = @_;
235              
236             die "id and parameters are needed\n" if (! defined $id || ! defined $params);
237             # $params = { 'age' => 30, 'sex' => 'male'}
238             my $uri_param = $self->_params_to_string($params);
239            
240             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/$id?$uri_param";
241             return $self->request->post($uri)->get_results();
242             }
243              
244             #/graphs/<graph>/edges?_outV=<id>&_label=friend&_inV=2&<key>=<key'>
245             #/graphs/<graph>/edges/3?_outV=<id>&_label=friend&_inV=2&<key>=<key'>
246             sub create_edge {
247             my ( $self, $outId, $label, $inId, $params) = @_;
248             #param = { name => key, name2 => key2 }
249             die "out-id, label and in-id are needed\n" if (! defined $outId || ! defined $label || ! defined $inId );
250             my $uri_param = $self->_params_to_string($params);
251             my $uri = $self->server . "/graphs/" . $self->graph . "/edges?_outV=$outId&_label=$label&_inV=$inId&$uri_param";
252             return $self->request->post($uri)->get_results();
253             }
254              
255             #/graphs/<graph>/edges/3?<key>=<key'>
256             sub create_edge_property {
257             my ($self, $id, $params) = @_;
258             die "id and parameters are needed\n" if (! defined $id || ! defined $params);
259             # $params = { 'age' => 30, 'sex' => 'male'}
260             my $uri_param = $self->_params_to_string($params);
261             my $uri = $self->server . "/graphs/" . $self->graph . "/edges/$id?$uri_param";
262             return $self->request->post($uri)->get_results();
263             }
264              
265             #/graphs/<graph>/indices/index?class=vertex
266             sub create_index {
267             my ($self, $index) = @_;
268             die "index is needed" if ( ! defined $index );
269             my $uri = $self->server . "/graphs/" . $self->graph . "/indices/$index?class=vertex";
270             return $self->request->post($uri)->get_results();
271             }
272              
273             #
274             # TODO Comment out keyindeces as it's not clear about how it's used
275             ##/graphs/<graph>/keyindices/vertex/<key>
276             #sub create_vertex_index {
277             # my ($self, $key) = @_;
278             # my $uri = $self->server . "/graphs/" . $self->graph . "/keyindices/vertex/$key";
279             # return $self->request->post($uri)->get_contents;
280             #}
281             ##/graphs/<graph>/keyindices/edge/<key>
282             #sub create_edge_index {
283             # my ($self, $key) = @_;
284             # my $uri = $self->server . "/graphs/" . $self->graph . "/keyindices/edge/$key";
285             # return $self->request->post($uri)->get_contents;
286             #}
287              
288             #======================================================================================
289             # PUT
290             #======================================================================================
291              
292             #/graphs/<graph>/vertices/<id>?<key>=<value>&<key'>=<value'>
293             sub replace_vertex_property {
294             my ($self, $id, $params) = @_;
295             die "id and parameters are needed\n" if (! defined $id || ! defined $params);
296             my $uri_param = $self->_params_to_string($params);
297             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/$id?$uri_param";
298             return $self->request->put($uri)->get_results();
299             }
300             #/graphs/<graph>/edges/<id>?<key>=<value>&<key'>=<value'>
301             sub replace_edge_property {
302             my ($self, $id, $params) = @_;
303             die "id and parameters are needed\n" if (! defined $id || ! defined $params);
304             my $uri_param = $self->_params_to_string($params);
305             my $uri = $self->server . "/graphs/" . $self->graph . "/edges/$id?$uri_param";
306             return $self->request->put($uri)->get_results();
307             }
308             #/graphs/<graph>/indices/index?key=<key>&value=<value>&id=<id>
309             sub put_vertex_to_index {
310             my ($self, $id, $index, $key, $value) = @_;
311             die "id, index, key and value are needed\n" if (! defined $id || ! defined $key || ! defined $value || ! defined $index);
312             my $uri = $self->server . "/graphs/"
313             . $self->graph . "/indices/$index?key=$key&value=$value&id=$id";
314             return $self->request->put($uri);
315             }
316              
317             #======================================================================================
318             # DELETE : return of each funtion is void
319             #======================================================================================
320             #/graphs/<graph>/vertices/<id>
321             sub delete_vertex {
322             my ($self, $id) = @_;
323             die "id is needed\n" if (! defined $id);
324             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/$id";
325             return $self->request->delete($uri);
326             }
327             #/graphs/<graph>/vertices/<id>?<key>&<key'>
328             sub delete_vertex_property {
329             my ($self, $id, $params) = @_;
330             die "id and parameters are needed\n" if (! defined $id || ! defined $params);
331             my $uri_param = $self->_array_params_to_string($params);
332             my $uri = $self->server . "/graphs/" . $self->graph . "/vertices/$id?$uri_param";
333             return $self->request->delete($uri);
334             }
335             #/graphs/<graph>/edges/<id>
336             sub delete_edge {
337             my ($self, $id) = @_;
338             die "id is needed\n" if (! defined $id);
339             my $uri = $self->server . "/graphs/" . $self->graph . "/edges/$id";
340             return $self->request->delete($uri);
341             }
342             #/graphs/<graph>/edges/3?<key>&<key'>
343             sub delete_edge_property{
344             my ($self, $id, $params) = @_;
345             die "id and parameters are needed\n" if (! defined $id || ! defined $params);
346             my $uri_param = $self->_array_params_to_string($params);
347             my $uri = $self->server . "/graphs/" . $self->graph . "/edges/$id?$uri_param";
348             return $self->request->delete($uri);
349             }
350             #/graphs/<graph>/indices/index
351             sub delete_index {
352             my ($self, $index) = @_;
353             die "index is needed\n" if (! defined $index);
354             my $uri = $self->server . "/graphs/" . $self->graph . "/indices/$index";
355             return $self->request->delete($uri);
356             }
357             #/graphs/<graph>/indices/index?key=<key>&value=<value>&class=vertex&id=<id>
358             sub delete_vertex_from_index {
359             my ($self, $id, $index, $key, $value) = @_;
360             die "id, index, key and value are needed\n" if (! defined $id || ! defined $key || ! defined $value || ! defined $index);
361             my $uri = $self->server . "/graphs/" . $self->graph . "/indices/$index?key=$key&value=$value&class=vertex&id=$id";
362             return $self->request->delete($uri);
363             }
364              
365             #======================================================================================
366              
367             # Create a string from hash parameter
368             sub _params_to_string {
369             my ( $self, $params ) = @_;
370             my @uri_params;
371             for my $param (keys %$params) {
372             push @uri_params, $param . "=" . $params->{ $param };
373             }
374             return join '&', sort @uri_params;
375             }
376              
377             # [ 1 2 3 ] to '1&2&3'
378             sub _array_params_to_string {
379             my ( $self, $array_ref ) = @_;
380             return join '&', @$array_ref;
381             }
382              
383             # The below yet to be installed
384             #/graphs/<graph>/indices/index?key=<key>&value=<value>
385             #/graphs/<graph>/indices/index/count?key=<key>&value=<value>
386             #/graphs/<graph>/keyindices/
387             #/graphs/<graph>/keyindices/vertex
388             #/graphs/<graph>/keyindices/edge
389             #/graphs/<graph>/prefixes
390             #/graphs/<graph>/prefixes/prefix
391              
392              
393             1; # Magic true value required at end of module
394              
395             __END__
396              
397             =head1 NAME
398              
399             Net::Rexster::Client - Handle Rexster REST request and response
400              
401             =head1 VERSION
402              
403             This document describes Net::Rexster version 0.0.5
404              
405             =head1 SYNOPSIS
406              
407             use Net::Rexster::Client;
408             use Data::Dumper;
409            
410             my $c = new Net::Rexster::Client(graph => "testdb", server => 'http://localhost:8182');
411            
412             # Create vertices and get the id
413             $id1 = $c->create_vertex->{_id};
414             $id2 = $c->create_vertex->{_id};
415            
416             # Add property.
417             $c->create_vertex_property($id1, { 'dateOfBirth' => 'Dec 26' });
418            
419             # Create edge with label, friend
420             $c->create_edge($id1, "friend", $id2);
421            
422             # See edge and vertices
423             print Dumper $c->get_all_edges;
424             print Dumper $c->get_all_vertices;
425            
426             # Delete the vertices
427             $c->delete_vertex($id1);
428             $c->delete_vertex($id2);
429              
430              
431             =head1 DESCRIPTION
432              
433             Rexster(https://github.com/tinkerpop/rexster/wiki) provides REST API for Blueprint graph(e.g. Neo4j, OrientDB..)
434             This module covers the most of REST in hhttps://github.com/tinkerpop/rexster/wiki/Basic-REST-API
435             so that REST can be called from Perl. GraphDB server as well as Rexter server need to be up to use this API.
436              
437             =head1 INTERFACE
438              
439             All of the methods defined here return hash reference which converted form JSON response.
440             As Net::Rexster::Client provides low level interface, please use Data::Dumper to check the contect of data.
441              
442             =head2 get_graphs()
443              
444             get all the graphs
445              
446             =head2 get_graph($graph_name)
447              
448             get the graph named
449              
450             =head2 get_all_vertices()
451              
452             get all vertices
453              
454             =head2 lookup_vertex($key, $value)
455              
456             get all vertices for a key index given the specified
457              
458             =head2 get_vertex($id)
459              
460             get vertex with id
461              
462             =head2 outV($id)
463              
464             get the adjacent out vertices of vertex
465              
466             =head2 inV($id)
467              
468             get the adjacent in vertices of vertex
469              
470             =head2 bothV()
471              
472             get the both adjacent in and out vertices of vertex
473              
474             =head2 outVcount($id)
475              
476             get the number of out vertices of vertex
477              
478             =head2 inVcount($id)
479              
480             get the number of in vertices of vertex
481              
482             =head2 bothVcount($id)
483              
484             get the number of adjacent in and out vertices of vertex
485              
486             =head2 outIds($id)
487              
488             get the identifiers of out vertices of vertex
489              
490             =head2 inIds($id)
491              
492             get the identifiers of in vertices of vertex
493              
494             =head2 bothIds($id)
495              
496             get the identifiers of adjacent in and out vertices of vertex
497              
498             =head2 get_all_edges()
499              
500             get all edges
501              
502             =head2 lookup_edges($key, $value)
503              
504             get all edges for a key index given the specified
505              
506             =head2 get_edge($id)
507              
508             get edge with id
509              
510             =head2 outE($id)
511              
512             get the out edges of vertex
513              
514             =head2 inE($id)
515              
516             get the in edges of vertex
517              
518             =head2 bothE($id)
519              
520             get the both in and out edges of vertex
521              
522             =head2 get_indices()
523              
524             get all the indices associated with the graph
525              
526             =head2 lookup_index($index, $key, $value)
527              
528             get all elements with $key property equal to $value in $index
529              
530             =head2 index_count($key, $value)
531              
532             get a count of all elements with $key property equal to $value in index
533              
534             =head2 create_vertex($id)
535              
536             create a vertex with no specified identifier. Note some graphDB doesn't support the arrument $id.
537             If it's not supported, the new $id is created automatically by DB server.
538              
539             =head2 create_vertex_property($id, { $key1 => $value1,,, })
540              
541             create a vertex with $id and the provided properties (or update vertex properties if vertex already exists).
542              
543             =head2 create_edge($id1, $label, $id2)
544              
545             create an out edge with no specified identifier from vertex <id> to vertex 2 labeled “friend” with provided properties.
546              
547             =head2 create_edge_property($id, {$key1 => $value1,,,})
548              
549             create the properties of the edge with id
550              
551             =head2 create_index($index)
552              
553             create a new manual index named $index
554              
555             =head2 replace_vertex_property($id, {$key1 => $value1,,,})
556              
557             replaces the all existing properties of the vertex $id with those specified
558              
559             =head2 replace_edge_property($id, {$key1 => $value1,,,})
560              
561             replaces the all existing properties of the edge $id with those specified
562              
563             =head2 put_vertex_to_index($vertex_id, $index, $key, $value)
564              
565             put vertex with $id into index at $key/$value
566              
567             =head2 delete_vertex($id)
568              
569             remove vertex $id
570              
571             =head2 delete_vertex_property($id, [$key1,$key2,,,])
572              
573             remove properties keys from vertex $id
574              
575             =head2 delete_edge($id)
576              
577             remove the edge with $id
578              
579             =head2 delete_edge_property($id, [$key1,$key2,,,])
580              
581             remove properties keys from edge
582              
583             =head2 delete_index($index)
584              
585             drop the index named $index
586              
587             =head2 delete_vertex_from_index($id, $index, $key, $value)
588              
589             remove the vertex $id from $index at $key/$value
590              
591             =for author to fill in:
592             Write a separate section listing the public components of the modules
593             interface. These normally consist of either subroutines that may be
594             exported, or methods that may be called on objects belonging to the
595             classes provided by the module.
596              
597              
598             =head1 CONFIGURATION AND ENVIRONMENT
599              
600             Net::Rexster requires no configuration files or environment variables.
601              
602             =head1 BUGS AND LIMITATIONS
603              
604             No bugs have been reported.
605              
606             =head1 AUTHOR
607              
608             Shohei Kameda C<< <shoheik@cpan.org> >>
609              
610              
611             =head1 LICENCE AND COPYRIGHT
612              
613             Copyright (c) 2012, Shohei Kameda C<< <shoheik@cpan.org> >>. All rights reserved.
614              
615             This module is free software; you can redistribute it and/or
616             modify it under the same terms as Perl itself. See L<perlartistic>.
617              
618              
619             =head1 DISCLAIMER OF WARRANTY
620              
621             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
622             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
623             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
624             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
625             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
626             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
627             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
628             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
629             NECESSARY SERVICING, REPAIR, OR CORRECTION.
630              
631             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
632             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
633             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
634             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
635             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
636             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
637             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
638             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
639             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
640             SUCH DAMAGES.