File Coverage

lib/UR/Object/Command/List/Style.pm
Criterion Covered Total %
statement 92 189 48.6
branch 13 32 40.6
condition 6 18 33.3
subroutine 16 28 57.1
pod 0 2 0.0
total 127 269 47.2


"; "; "; ";
line stmt bran cond sub pod time code
1             package UR::Object::Command::List::Style;
2              
3             our $VERSION = "0.46"; # UR $VERSION;
4              
5             sub new {
6 6     6 0 36 my ($class, %args) = @_;
7 6         16 foreach (qw/iterator show noheaders output/){
8 24 50       42 die "no value for $_!" unless defined $args{$_};
9             }
10 6         15 return bless(\%args, $class);
11             }
12              
13             sub _get_next_object_from_iterator {
14 18     18   17 my $self = shift;
15              
16 18         17 my $obj;
17 18         23 for (1) {
18 18         16 $obj = eval { $self->{'iterator'}->next };
  18         54  
19 18 50       44 if ($@) {
20 0         0 UR::Object::Command::List->warning_message($@);
21 0         0 redo;
22             }
23             }
24 18         45 return $obj;
25             }
26              
27             sub _object_properties_to_string {
28 12     12   17 my ($self, $o, $char) = @_;
29 12         10 my @v;
30             return join(
31             $char,
32 29 50       81 map { defined $_ ? $_ : '' }
33             map {
34 29         44 $self->_object_property_to_string($o,$_)
35 12         12 } @{$self->{show}}
  12         24  
36             );
37             }
38              
39             sub _object_property_to_string {
40 29     29   32 my ($self, $o, $property) = @_;
41              
42 29         24 my @v;
43 29 100       45 if (substr($property,0,1) eq '(') {
44 2         104 @v = eval $property;
45 2 50       19 if ($@) {
46 0         0 @v = (''); # ($@ =~ /^(.*)$/);
47             }
48             }
49             else {
50 27         29 @v = ();
51 27         54 foreach my $i ($o->__get_attr__($property)) {
52 27 50 33     153 if (! defined $i) {
    50 33        
    50 33        
53 0         0 push @v, "";
54             }
55             elsif (Scalar::Util::blessed($i) and $i->isa('UR::Value') and $i->can('create_view')) {
56             # Here we allow any UR::Values that have their own views to present themselves.
57 0         0 my $v = $i->create_view( perspective => 'default', toolkit => 'text' );
58 0         0 push @v, $v->content();
59             }
60             elsif (Scalar::Util::blessed($i) and $i->can('__display_name__')) {
61 0         0 push @v, $i->__display_name__;
62             }
63             else {
64 27         39 push @v, $i;
65             }
66             }
67             }
68              
69 29 50       42 if (@v > 1) {
70 2     2   51 no warnings;
  2         3  
  2         614  
71 0         0 return join(' ',@v);
72             }
73             else {
74 29         55 return $v[0];
75             }
76             }
77              
78             sub format_and_print{
79 0     0 0 0 my $self = shift;
80              
81 0 0       0 unless ( $self->{noheaders} ) {
82 0         0 $self->{output}->print($self->_get_header_string. "\n");
83             }
84              
85 0         0 my $count = 0;
86 0         0 while (my $object = $self->_get_next_object_from_iterator()) {
87 0         0 $self->{output}->print($self->_get_object_string($object), "\n");
88 0         0 $count++;
89             }
90              
91             }
92              
93             package UR::Object::Command::List::Html;
94 2     2   9 use base 'UR::Object::Command::List::Style';
  2         2  
  2         47  
95              
96             sub _get_header_string{
97 0     0   0 my $self = shift;
98 0         0 return "
". join("", map { uc } @{$self->{show}}) ."
  0         0  
  0         0  
99             }
100              
101             sub _get_object_string{
102 0     0   0 my ($self, $object) = @_;
103            
104 0         0 my $out = "
105 0         0 for my $property ( @{$self->{show}} ){
  0         0  
106 0         0 $out .= "" . $object->$property . "
107             }
108            
109 0         0 return $out . "
110             }
111              
112             sub format_and_print{
113 0     0   0 my $self = shift;
114            
115 0         0 $self->{output}->print("");
116            
117             #cannot use super because \n screws up javascript
118 0 0       0 unless ( $self->{noheaders} ) {
119 0         0 $self->{output}->print($self->_get_header_string);
120             }
121              
122 0         0 my $count = 0;
123 0         0 while (my $object = $self->_get_next_object_from_iterator()) {
124 0         0 $self->{output}->print($self->_get_object_string($object));
125 0         0 $count++;
126             }
127            
128 0         0 $self->{output}->print("
");
129             }
130              
131             package UR::Object::Command::List::Csv;
132 2     2   611 use base 'UR::Object::Command::List::Style';
  2         4  
  2         25  
133              
134             sub _get_header_string{
135 0     0   0 my $self = shift;
136              
137 0         0 my $delimiter = $self->{'csv_delimiter'};
138 0         0 return join($delimiter, map { lc } @{$self->{show}});
  0         0  
  0         0  
139             }
140              
141             sub _get_object_string {
142 0     0   0 my ($self, $object) = @_;
143              
144 0         0 return $self->_object_properties_to_string($object, $self->{'csv_delimiter'});
145             }
146              
147             package UR::Object::Command::List::Tsv;
148 2     2   351 use base 'UR::Object::Command::List::Csv';
  2         2  
  2         25  
149              
150             sub _get_header_string{
151 0     0   0 my $self = shift;
152              
153 0         0 my $delimiter = "\t";
154 0         0 return join($delimiter, map { lc } @{$self->{show}});
  0         0  
  0         0  
155             }
156              
157             sub _get_object_string {
158 0     0   0 my ($self, $object) = @_;
159              
160 0         0 return $self->_object_properties_to_string($object, "\t");
161             }
162              
163              
164             package UR::Object::Command::List::Pretty;
165 2     2   714 use base 'UR::Object::Command::List::Style';
  2         3  
  2         20  
166              
167             sub _get_header_string{
168 0     0   0 return '';
169             }
170              
171             sub _get_object_string{
172 0     0   0 my ($self, $object) = @_;
173              
174 0         0 my $out;
175 0         0 for my $property ( @{$self->{show}} )
  0         0  
176             {
177 0         0 my $value = join(', ', $self->_object_property_to_string($object,$property));
178 0         0 $out .= sprintf(
179             "%s: %s\n",
180             Term::ANSIColor::colored($property, 'red'),
181             Term::ANSIColor::colored($value, 'cyan'),
182             );
183             }
184              
185 0         0 return $out;
186             }
187              
188             package UR::Object::Command::List::Xml;
189 2     2   435 use base 'UR::Object::Command::List::Style';
  2         4  
  2         22  
190              
191             sub format_and_print{
192 0     0   0 my $self = shift;
193 0         0 my $out;
194              
195 0         0 eval "use XML::LibXML";
196 0 0       0 if ($@) {
197 0         0 die "Please install XML::LibXML (run sudo cpanm XML::LibXML) to use this tool!";
198             }
199              
200 0         0 my $doc = XML::LibXML->createDocument();
201 0         0 my $results_node = $doc->createElement("results");
202 0         0 $results_node->addChild( $doc->createAttribute("generated-at",$UR::Context::current->now()) );
203              
204 0         0 $doc->setDocumentElement($results_node);
205              
206 0         0 my $count = 0;
207 0         0 while (my $object = $self->_get_next_object_from_iterator()) {
208 0         0 my $object_node = $results_node->addChild( $doc->createElement("object") );
209              
210 0         0 my $object_reftype = ref $object;
211 0         0 $object_node->addChild( $doc->createAttribute("type",$object_reftype) );
212 0         0 $object_node->addChild( $doc->createAttribute("id",$object->id) );
213              
214 0         0 for my $property ( @{$self->{show}} ) {
  0         0  
215              
216 0         0 my $property_node = $object_node->addChild ($doc->createElement($property));
217              
218 0         0 my @items = $self->_object_property_to_string($object, $property);
219              
220 0         0 my $reftype = ref $items[0];
221              
222 0 0 0     0 if ($reftype && $reftype ne 'ARRAY' && $reftype ne 'HASH') {
      0        
223 0         0 foreach (@items) {
224 0         0 my $subobject_node = $property_node->addChild( $doc->createElement("object") );
225 0         0 $subobject_node->addChild( $doc->createAttribute("type",$reftype) );
226 0         0 $subobject_node->addChild( $doc->createAttribute("id",$_->id) );
227             #$subobject_node->addChild( $doc->createTextNode($_->id) );
228             #xIF
229             }
230             } else {
231 0         0 foreach (@items) {
232 0         0 $property_node->addChild( $doc->createTextNode($_) );
233             }
234             }
235              
236             }
237 0         0 $count++;
238             }
239 0         0 $self->{output}->print($doc->toString(1));
240             }
241              
242             package UR::Object::Command::List::Text;
243 2     2   670 use base 'UR::Object::Command::List::Style';
  2         4  
  2         21  
244              
245             sub _get_header_string{
246 6     6   10 my $self = shift;
247             return join (
248             "\n",
249 14         34 join("\t", map { uc } @{$self->{show}}),
  6         11  
250 6         11 join("\t", map { '-' x length } @{$self->{show}}),
  14         55  
  6         11  
251             );
252             }
253              
254             sub _get_object_string{
255 12     12   21 my ($self, $object) = @_;
256 12         29 $self->_object_properties_to_string($object, "\t");
257             }
258              
259             sub format_and_print{
260 6     6   7 my $self = shift;
261 6         8 my $tab_delimited;
262 6 50       21 unless ($self->{noheaders}){
263 6         21 $tab_delimited .= $self->_get_header_string."\n";
264             }
265              
266 6         8 my $count = 0;
267 6         21 while (my $object = $self->_get_next_object_from_iterator()) {
268 12         27 $tab_delimited .= $self->_get_object_string($object)."\n";
269 12         21 $count++;
270             }
271              
272 6         25 $self->{output}->print($self->tab2col($tab_delimited));
273             }
274              
275             sub tab2col{
276 6     6   12 my ($self, $data) = @_;
277              
278             #turn string into 2d array of arrayrefs ($array[$rownum][$colnum])
279 6         29 my @rows = split("\n", $data);
280 6         10 @rows = map { [split("\t", $_)] } @rows;
  24         54  
281              
282 6         13 my $output;
283             my @width;
284              
285             #generate array of max widths per column
286 6         11 foreach my $row_ref (@rows) {
287 24         34 my @cols = @$row_ref;
288 24         24 my $index = $#cols;
289 24         38 for (my $i = 0; $i <= $index; $i++) {
290 57         70 my $l = (length $cols[$i]) + 3; #TODO test if we need this buffer space
291 57 100 100     185 $width[$i] = $l if ! defined $width[$i] or $l > $width[$i];
292             }
293             }
294            
295             #create a array of blanks to use as a templatel
296 6         11 my @column_template = map { ' ' x $_ } @width;
  14         29  
297              
298             #iterate through rows and cols, substituting in the row entry in your template
299 6         11 foreach my $row_ref (@rows) {
300 24         29 my @cols = @$row_ref;
301 24         19 my $index = $#cols;
302             #only apply template for all but the last entry in a row
303 24         46 for (my $i = 0; $i < $index; $i++) {
304 33         26 my $entry = $cols[$i];
305 33         26 my $template = $column_template[$i];
306 33         31 substr($template, 0, length $entry, $entry);
307 33         50 $output.=$template;
308             }
309 24         39 $output.=$cols[$index]."\n"; #Don't need traling spaces on the last entry
310             }
311 6         61 return $output;
312             }
313              
314             package UR::Object::Command::List::Newtext;
315 2     2   953 use base 'UR::Object::Command::List::Text';
  2         4  
  2         21  
316              
317             sub format_and_print{
318 0     0     my $self = shift;
319 0           my $tab_delimited;
320              
321 0 0         unless ($self->{noheaders}){
322 0           $tab_delimited .= $self->_get_header_string."\n";
323             }
324              
325             my $view = UR::Object::View->create(
326             subject_class_name => 'UR::Object',
327             perspective => 'lister',
328             toolkit => 'text',
329 0           aspects => [ @{$self->{'show'}} ],
  0            
330             );
331              
332 0           my $count = 0;
333 0           while (my $object = $self->_get_next_object_from_iterator()) {
334 0           $view->subject($object);
335 0           $tab_delimited .= $view->content() . "\n";
336 0           $count++;
337             }
338              
339 0           $self->{output}->print($self->tab2col($tab_delimited));
340             }
341              
342             1;
343             =pod
344              
345             =head1 NAME
346              
347             UR::Object::Command::List - Fetches and lists objects in different styles.
348              
349             =head1 SYNOPSIS
350              
351             package MyLister;
352              
353             use strict;
354             use warnings;
355              
356             use above "UR";
357              
358             class MyLister {
359             is => 'UR::Object::Command::List',
360             has => [
361             # add/modify properties
362             ],
363             };
364              
365             1;
366              
367             =head1 Provided by the Developer
368              
369             =head2 subject_class_name (optional)
370              
371             The subject_class_name is the class for which the objects will be fetched. It can be specified one of two main ways:
372              
373             =over
374              
375             =item I
376              
377             For this do nothing, the end user will have to provide it when the command is run.
378              
379             =item I
380              
381             For this, in the class declaration, add a has key w/ arrayref of hashrefs. One of the hashrefs needs to be subject_class_name. Give it this declaration:
382              
383             class MyFetchAndDo {
384             is => 'UR::Object::Command::FetchAndDo',
385             has => [
386             subject_class_name => {
387             value => ,
388             is_constant => 1,
389             },
390             ],
391             };
392              
393             =back
394              
395             =head2 show (optional)
396              
397             Add defaults to the show property:
398              
399             class MyFetchAndDo {
400             is => 'UR::Object::Command::FetchAndDo',
401             has => [
402             show => {
403             default_value => 'name,age',
404             },
405             ],
406             };
407              
408             =head2 helps (optional)
409              
410             Overwrite the help_brief, help_synopsis and help_detail methods to provide specific help. If overwiting the help_detail method, use call '_filter_doc' to get the filter documentation and usage to combine with your specific help.
411              
412             =head1 List Styles
413              
414             text, csv, html, xml, pretty (inprogress)
415              
416             =cut
417              
418              
419             #$HeadURL: svn+ssh://svn/srv/svn/gscpan/perl_modules/trunk/UR/Object/Command/List.pm $
420             #$Id: List.pm 50329 2009-08-25 20:10:00Z abrummet $