File Coverage

blib/lib/perfSONAR_PS/Topology/ID.pm
Criterion Covered Total %
statement 108 231 46.7
branch 54 194 27.8
condition 10 99 10.1
subroutine 11 14 78.5
pod 9 11 81.8
total 192 549 34.9


line stmt bran cond sub pod time code
1             package perfSONAR_PS::Topology::ID;
2              
3 1     1   21000 use strict;
  1         2  
  1         38  
4 1     1   6 use warnings;
  1         2  
  1         28  
5 1     1   6 use base 'Exporter';
  1         7  
  1         2890  
6              
7             our $VERSION = 0.09;
8              
9             our @EXPORT = ('idConstruct', 'idIsFQ', 'idAddLevel', 'idRemoveLevel', 'idBaseLevel', 'idEncode', 'idDecode', 'idSplit', 'idCompare', 'idMatch', 'idIsAmbiguous');
10              
11             sub idConstruct {
12 8     8 1 2264 my ($type1, $field1, $type2, $field2, $type3, $field3, $type4, $field4) = @_;
13              
14 8         10 my $id = "";
15              
16 8         14 $id .= "urn:ogf:network";
17              
18 8 50 33     68 return $id if ($type1 eq "" or $field1 eq "");
19              
20 8         19 $id .= ":".$type1."=".idEncode($field1);
21              
22 8 100 66     42 return $id if ($type2 eq "" or $field2 eq "");
23              
24 6         16 $id .= ":".$type2."=".idEncode($field2);
25              
26 6 100 66     32 return $id if ($type3 eq "" or $field3 eq "");
27              
28 4         10 $id .= ":".$type3."=".idEncode($field3);
29              
30 4 100 66     23 return $id if ($type4 eq "" or $field4 eq "");
31              
32 2         5 $id .= ":".$type4."=".idEncode($field4);
33              
34 2         8 return $id;
35             }
36              
37             sub idIsFQ {
38 3     3 1 4 my ($id, $type) = @_;
39              
40 3         24 my ($new_type, $value);
41              
42 3 50       14 return 0 if (!($id =~ /^urn:ogf:network:(.*)$/));
43              
44 3 50       14 return 1 if ($type eq "");
45              
46 0         0 my @fields = split(':', $id);
47              
48 0 0 0     0 if ($type eq "domain") {
    0          
    0          
    0          
    0          
49 0         0 ($new_type, $value) = split("=", $fields[3]);
50              
51 0 0 0     0 return -1 if ($new_type ne "domain" or not defined $value);
52              
53 0         0 return 1;
54             } elsif ($type eq "path" or $type eq "network") {
55 0 0       0 if ($#fields == 3) {
    0          
56 0         0 ($new_type, $value) = split("=", $fields[3]);
57              
58 0 0 0     0 return -1 if ($new_type ne $type or not defined $value);
59              
60 0         0 return 1;
61             } elsif ($#fields == 4) {
62 0         0 ($new_type, $value) = split("=", $fields[3]);
63              
64 0 0 0     0 return -1 if ($new_type ne "domain" or not defined $value);
65              
66 0         0 ($new_type, $value) = split("=", $fields[4]);
67              
68 0 0 0     0 return -1 if ($new_type ne $type or not defined $value);
69              
70 0         0 return 1;
71             } else {
72 0         0 return -1;
73             }
74             } elsif ($type eq "node") {
75 0 0       0 return -1 if ($#fields != 4);
76              
77 0         0 ($type, $value) = split("=", $fields[3]);
78              
79 0 0 0     0 return -1 if ($type ne "domain" or not defined $value);
80              
81 0         0 ($type, $value) = split("=", $fields[4]);
82              
83 0 0 0     0 return -1 if ($type ne "node" or not defined $value);
84              
85 0         0 return 1;
86             } elsif ($type eq "port") {
87 0 0       0 return -1 if ($#fields != 5);
88              
89 0         0 ($type, $value) = split("=", $fields[3]);
90              
91 0 0 0     0 return -1 if ($type ne "domain" or not defined $value);
92              
93 0         0 ($type, $value) = split("=", $fields[4]);
94              
95 0 0 0     0 return -1 if ($type ne "node" or not defined $value);
96              
97 0         0 ($type, $value) = split("=", $fields[5]);
98              
99 0 0 0     0 return -1 if ($type ne "port" or not defined $value);
100              
101 0         0 return 1;
102             } elsif ($type eq "link") {
103 0 0       0 if ($#fields == 4) {
    0          
104 0         0 ($type, $value) = split("=", $fields[3]);
105              
106 0 0 0     0 return -1 if ($type ne "domain" or not defined $value);
107              
108 0         0 ($type, $value) = split("=", $fields[4]);
109              
110 0 0 0     0 return -1 if ($type ne "link" or not defined $value);
111              
112 0         0 return 1;
113             } elsif ($#fields == 6) {
114 0         0 ($type, $value) = split("=", $fields[3]);
115              
116 0 0 0     0 return -1 if ($type ne "domain" or not defined $value);
117              
118 0         0 ($type, $value) = split("=", $fields[4]);
119              
120 0 0 0     0 return -1 if ($type ne "node" or not defined $value);
121              
122 0         0 ($type, $value) = split("=", $fields[5]);
123              
124 0 0 0     0 return -1 if ($type ne "port" or not defined $value);
125              
126 0         0 ($type, $value) = split("=", $fields[6]);
127              
128 0 0 0     0 return -1 if ($type ne "link" or not defined $value);
129              
130 0         0 return 1;
131             } else {
132 0         0 return -1;
133             }
134             } else {
135 0         0 return -1;
136             }
137             }
138              
139             sub idAddLevel {
140 1     1 1 235 my ($id, $new_type, $new_level) = @_;
141              
142 1         2 $new_level = idEncode($new_level);
143              
144 1 50       5 if ($id =~ /^urn:ogf:network:$/) {
145 0         0 $id .= $new_type."=".$new_level;
146             } else {
147 1         3 $id .= ":".$new_type."=".$new_level;
148             }
149              
150 1         4 return $id;
151             }
152              
153             sub idRemoveLevel {
154 1     1 1 213 my ($id, $ret_type) = @_;
155              
156 1         2 my $ret_id;
157              
158 1 50       13 if ($id =~ /(^urn:ogf:network.*):[^:]+$/) {
159 1 50       5 if ($1 eq "urn:ogf:network") {
160 0         0 $ret_id = "";
161             } else {
162 1         3 $ret_id = $1;
163             }
164             } else {
165 0         0 $ret_id = $id;
166             }
167              
168 1 50 33     8 if (defined $ret_type and $ret_type ne "") {
169 1 50       4 if ($ret_id ne "") {
170 1         2 my $type;
171              
172 1         3 my $value = idBaseLevel($ret_id, \$type);
173              
174 1         13 $$ret_type = $type;
175             } else {
176 0         0 $$ret_type = "";
177             }
178             }
179              
180 1         3 return $ret_id;
181             }
182              
183             sub idBaseLevel {
184 2     2 1 488 my ($id, $ret_type) = @_;
185              
186 2         3 my $ret_id;
187              
188 2 50       8 if (!($id =~ /^urn:ogf:network/)) {
189 0 0 0     0 $$ret_type = "" if (defined $ret_type and $ret_type ne "");
190 0         0 return $id;
191             }
192              
193 2 50       6 if ($id =~ /^urn:ogf:network$/) {
194 0 0 0     0 $$ret_type = "" if (defined $ret_type and $ret_type ne "");
195 0         0 return "";
196             };
197              
198 2 50       10 if ($id =~ /^urn:ogf:network.*:([^:]+)$/) {
199 2         10 $ret_id = $1;
200             }
201              
202 2         8 my ($type, $value) = split('=', $ret_id);
203              
204 2 50 33     11 if (defined $ret_type and $ret_type ne "") {
205 2         4 $$ret_type = $type;
206             }
207              
208 2         5 return idDecode($value);
209             }
210              
211             sub idEncode {
212 22     22 1 32 my ($id) = @_;
213              
214 22         31 $id =~ s/%/%25/g;
215 22         27 $id =~ s/:/%3A/g;
216 22         26 $id =~ s/#/%23/g;
217 22         27 $id =~ s/\//%2F/g;
218 22         23 $id =~ s/\?/%3F/g;
219              
220 22         50 return $id;
221             }
222              
223             sub idDecode {
224 11     11 1 226 my ($id) = @_;
225              
226 11         16 $id =~ s/%3A/:/g;
227 11         42 $id =~ s/%23/#/g;
228 11         16 $id =~ s/%2F/\//g;
229 11         13 $id =~ s/%3F/?/g;
230 11         16 $id =~ s/%25/%/g;
231              
232 11         22 return $id;
233             }
234              
235             sub idCompare {
236 0     0 1 0 my ($id1, $id2, $compare_to) = @_;
237              
238 0         0 my @results_id1 = idSplit($id1, 0, 1);
239 0 0       0 if ($results_id1[0] == -1) {
240 0         0 my $msg = "ID \"$id1\" is not properly qualified";
241 0         0 return (-1, $msg);
242             }
243              
244 0         0 my @results_id2 = idSplit($id2, 0, 1);
245 0 0       0 if ($results_id2[0] == -1) {
246 0         0 my $msg = "ID \"$id2\" is not properly qualified";
247 0         0 return (-1, $msg);
248             }
249              
250 0         0 for(my $i = 2; $i <= $#results_id1; $i += 2) {
251 0 0       0 if (not defined $results_id2[$i]) {
252 0         0 return (-1, "ID element $compare_to not found");
253             }
254              
255 0 0 0     0 if ($results_id1[$i] ne $results_id2[$i] or $results_id1[$i + 1] ne $results_id2[$i + 1]) {
256 0         0 return (-1, $results_id1[$i]."=".$results_id1[$i + 1] . " != " . $results_id2[$i] . "=" . $results_id2[$i + 1]);
257             }
258              
259 0 0       0 return (0, "") if ($results_id1[$i] eq $compare_to);
260             }
261              
262 0         0 return (-1, "ID element $compare_to not found");
263             }
264              
265             sub idIsAmbiguous {
266 0     0 0 0 my ($id) = @_;
267              
268 0         0 return ($id =~ /(=\*:|:\*$|=\*$)/);
269             }
270              
271             sub idMatch {
272 0     0 0 0 my ($ids, $idExp) = @_;
273              
274 0         0 my @idExpFields = split(/:/, $idExp);
275              
276 0         0 my @fields = ();
277 0         0 my $finished = 0;
278 0         0 for(my $i = 0; $i <= $#idExpFields; $i++) {
279 0 0       0 if ($finished) {
280 0         0 return;
281             }
282              
283 0 0       0 if ($idExpFields[$i] =~ /([^=]*)=(.*)/) {
    0          
284 0         0 $fields[$i][0] = $1;
285 0         0 $fields[$i][1] = $2;
286             } elsif ($idExpFields[$i] eq "*") {
287 0         0 $fields[$i][0] = '*';
288 0         0 $finished = 1;
289             }
290             }
291              
292 0         0 my @matchingIds = ();
293 0         0 foreach my $id (@{ $ids }) {
  0         0  
294 0         0 my @idFields = split(/:/, $id);
295 0         0 for(my $i = 3; $i <= $#idFields; $i++) {
296             # if we get here, we're being asked to match a value,
297             # we haven't encountered a ":*" and we've hit the end
298             # of the id expression so we've got a mismatch.
299 0 0       0 last if ($i > $#fields);
300              
301 0 0       0 if ($idFields[$i] =~ /([^=]*)=(.*)/) {
302             # if we've hit a :* portion of the id, then the
303             # rest of the id matches.
304 0 0       0 if ($fields[$i][0] eq "*") {
305 0         0 push @matchingIds, $id;
306 0         0 last;
307             }
308              
309             # if the field name of the id doesn't match the
310             # field name in the id expression.
311 0 0       0 if ($fields[$i][0] ne $1) {
312 0         0 last;
313             }
314              
315             # if the expression field value isn't the 'any
316             # value' and it's not what the user specified,
317             # quit checking.
318 0 0 0     0 if ($fields[$i][1] ne "*" and $fields[$i][1] ne $2) {
319 0         0 last;
320             }
321              
322             # if we've hit the end of both sets of fields
323             # and we haven't had an error, its a match.
324 0 0 0     0 if ($i == $#idFields and $i == $#fields) {
325 0         0 push @matchingIds, $id;
326             }
327             }
328             }
329             }
330              
331 0         0 return \@matchingIds;
332             }
333              
334             sub idSplit {
335 3     3 1 5145 my ($id, $fq, $top_down) = @_;
336              
337 3 50       10 if (idIsFQ($id, "") == 0) {
338 0         0 my $msg = "ID \"$id\" is not fully qualified";
339 0         0 return (-1, $msg);
340             }
341              
342 3         14 my @fields = split(':', $id);
343              
344 3 50 33     19 if ($#fields > 6 or $#fields < 3) {
345 0         0 my $msg = "ID \"$id\" has an invalid number of fields: $#fields";
346 0         0 return (-1, $msg);
347             }
348              
349 3         5 my ($type1, $field1);
350 0         0 my ($type2, $field2);
351 0         0 my ($type3, $field3);
352 0         0 my ($type4, $field4);
353              
354 3 50       12 ($type1, $field1) = split('=', $fields[3]) if defined $fields[3];
355 3 50       19 ($type2, $field2) = split('=', $fields[4]) if defined $fields[4];
356 3 50       12 ($type3, $field3) = split('=', $fields[5]) if defined $fields[5];
357 3 50       11 ($type4, $field4) = split('=', $fields[6]) if defined $fields[6];
358              
359 3         3 my $id_type;
360              
361 3 50       8 if (defined $type4) {
    0          
    0          
    0          
362 3 50       13 if ($type4 eq "link") {
363 3         4 $id_type = $type4;
364             } else {
365 0         0 my $msg = "Fourth field of ID is of unknown type \"$type4\"";
366 0         0 return (-1, $msg);
367             }
368             } elsif (defined $type3) {
369 0 0       0 if ($type3 eq "port") {
370 0         0 $id_type = $type3;
371             } else {
372 0         0 my $msg = "Third field of ID is of unknown type \"$type3\"";
373 0         0 return (-1, $msg);
374             }
375             } elsif (defined $type2) {
376 0 0 0     0 if ($type2 eq "node" or $type2 eq "link" or $type2 eq "path" or $type2 eq "network") {
      0        
      0        
377 0         0 $id_type = $type2;
378             } else {
379 0         0 my $msg = "Second field of ID is of unknown type \"$type2\"";
380 0         0 return (-1, $msg);
381             }
382             } elsif (defined $type1) {
383 0 0 0     0 if ($type1 eq "domain" or $type1 eq "path" or $type1 eq "network") {
      0        
384 0         0 $id_type = $type1;
385             } else {
386 0         0 my $msg = "First field of ID is of unknown type \"$type1\"";
387 0         0 return (-1, $msg);
388             }
389             } else {
390 0         0 $id_type = "";
391             }
392              
393 3 100       12 if ($fq) {
394 1 50       5 $field1 = "urn:ogf:network:".$fields[3] if defined $fields[3];
395 1 50       5 $field2 = $field1.":".$fields[4] if defined $fields[4];
396 1 50       4 $field3 = $field2.":".$fields[5] if defined $fields[5];
397 1 50       4 $field4 = $field3.":".$fields[6] if defined $fields[6];
398             } else {
399 2 50       558 $field1 = idDecode($field1) if defined $field1;
400 2 50       8 $field2 = idDecode($field2) if defined $field2;
401 2 50       8 $field3 = idDecode($field3) if defined $field3;
402 2 50       8 $field4 = idDecode($field4) if defined $field4;
403             }
404              
405 3         3 my @res;
406 3         4 push @res, 0;
407 3         6 push @res, $id_type;
408 3 100       5 if ($top_down) {
409 2 50       5 push @res, $type1 if defined $type1;
410 2 50       5 push @res, $field1 if defined $field1;
411 2 50       6 push @res, $type2 if defined $type2;
412 2 50       4 push @res, $field2 if defined $field2;
413 2 50       5 push @res, $type3 if defined $type3;
414 2 50       5 push @res, $field3 if defined $field3;
415 2 50       5 push @res, $type4 if defined $type4;
416 2 50       5 push @res, $field4 if defined $field4;
417             } else {
418 1 50       4 push @res, $type4 if defined $type4;
419 1 50       3 push @res, $field4 if defined $field4;
420 1 50       4 push @res, $type3 if defined $type3;
421 1 50       3 push @res, $field3 if defined $field3;
422 1 50       4 push @res, $type2 if defined $type2;
423 1 50       3 push @res, $field2 if defined $field2;
424 1 50       4 push @res, $type1 if defined $type1;
425 1 50       3 push @res, $field1 if defined $field1;
426             }
427              
428 3         27 return @res;
429             }
430              
431             1;
432              
433             __END__