Updates:
[bioperl-live.git] / Bio / Tools / EUtilities / Summary / Item.pm
blob017330277d201c6ccc00e8e746fc1a84b51d4a9d
1 # $Id$
3 # BioPerl module for Bio::DB::EUtilities::Summary::Item
5 # Cared for by Chris Fields
7 # Copyright Chris Fields
9 # You may distribute this module under the same terms as perl itself
11 # POD documentation - main docs before the code
13 # Part of the EUtilities BioPerl package
15 =head1 NAME
17 Bio::DB::EUtilities::Summary::Item - simple layered object for DocSum item data
19 =head1 SYNOPSIS
21 # Items can be nested up to three levels at this time. These levels can be
22 # accessed via Item, ListItem, or StructureItem methods:
24 while (my $item = $docsum->next_Item) {
25 print "Name: ",$item->get_name,"\n";
26 print "Data: ",$item->get_content,"\n";
27 print "Type: ",$item->get_type,"\n";
28 while (my $ls = $item->next_ListItem) {
29 # do same here
30 while (my $struct = $ls->next_StructureItem) {
31 # do more stuff here
37 =head1 DESCRIPTION
39 DocSum data, as returned from esummary, normally is a simple list of
40 item-content-content_type groups. However, items can also contain nested data to
41 represent more complex data (such as structural data). Up to three nested layers
42 may appear in any document summary.
44 This class contains methods to access data that can appear in a docsum for any
45 individual item as well as describes methods to traverse the hierarchy of items
46 present in a document summary.
48 The unique name for items are accessed via get_name(), the content by
49 get_content() (if present), and the data type by get_type(). Items can have
50 ListItems (Item objects with a datatype() 'list'), which in turn can have
51 StructureItems (Item objects with a datatype of 'structure'). Items are
52 initially traversed via a DocSum object using next_Item() or obtained all at
53 once with get_Items(). Similarly, nested Items can be accessed by using
54 next_ListItem/get_ListItems and next_StructureItem/get_StructureItem. A
55 flattened list of items can be accessed with get_all_Items().
57 =head1 FEEDBACK
59 =head2 Mailing Lists
61 User feedback is an integral part of the
62 evolution of this and other Bioperl modules. Send
63 your comments and suggestions preferably to one
64 of the Bioperl mailing lists. Your participation
65 is much appreciated.
67 bioperl-l@lists.open-bio.org - General discussion
68 http://www.bioperl.org/wiki/Mailing_lists - About the mailing lists
70 =head2 Reporting Bugs
72 Report bugs to the Bioperl bug tracking system to
73 help us keep track the bugs and their resolution.
74 Bug reports can be submitted via the web.
76 http://bugzilla.open-bio.org/
78 =head1 AUTHOR Chris Fields
80 Email cjfields at uiuc dot edu
82 =head1 APPENDIX
84 The rest of the documentation details each of the
85 object methods. Internal methods are usually
86 preceded with a _
88 =cut
90 # Let the code begin...
92 package Bio::Tools::EUtilities::Summary::Item;
93 use strict;
94 use warnings;
96 use base qw(Bio::Root::Root Bio::Tools::EUtilities::EUtilDataI);
98 =head2 new
100 Title : new
101 Usage :
102 Function :
103 Returns :
104 Args :
106 =cut
108 sub new {
109 my ($class, @args) = @_;
110 my $self = $class->SUPER::new(@args);
111 my ($type) = $self->_rearrange(['DATATYPE'],@args);
112 $type ||= 'item';
113 $self->datatype($type);
114 $self->eutil('esummary');
115 $self->rewind('recursive');
116 return $self;
119 =head2 get_ids
121 Title : get_ids
122 Usage : my ($id) = $item->get_ids;
123 Function : returns array or array ref with id
124 Returns : array or array ref
125 Args : none
126 Note : the behavior of this method is to remain consistent with other
127 implementations of get_ids(). To retrieve the single DocSum ID use
128 get_id()
130 =cut
132 sub get_ids {
133 my $self = shift;
134 return ($self->{'_id'});
137 =head2 get_id
139 Title : get_id
140 Usage : my ($id) = $item->get_id;
141 Function : returns UID of record
142 Returns : integer
143 Args : none
145 =cut
147 sub get_id {
148 my $self = shift;
149 return $self->{'_id'};
152 =head2 next_ListItem
154 Title : next_ListItem
155 Usage : while (my $ls = $item->next_ListItem) {...}
156 Function : iterates through ListItems (nested layer of Item)
157 Returns : single ListItem
158 Args : none
160 =cut
162 sub next_ListItem {
163 my $self = shift;
164 unless ($self->{'_lists_it'}) {
165 my @lists = $self->get_ListItems;
166 # reset the structure iterator (required!)
167 delete $self->{'_structures_it'} if $self->{'_structures_it'};
168 $self->{'_lists_it'} = sub {return shift @lists}
170 return $self->{'_lists_it'}->();
173 =head2 get_ListItems
175 Title : get_ListItems
176 Usage : my @ls = $item->get_ListItems
177 Function : returns list of, well, List Items
178 Returns : array of List Items
179 Args : none
181 =cut
183 sub get_ListItems {
184 my $self = shift;
185 my @items = $self->get_type eq 'List' ? $self->get_subItems : ();
186 return @items;
189 =head2 next_StructureItem
191 Title : next_StructureItem
192 Usage : while (my $struc = $ls->next_StructureItem) {...}
193 Function : iterates through StructureItems (nested layer of ListItem)
194 Returns : single StructureItems
195 Args : none
197 =cut
199 sub next_StructureItem {
200 my $self = shift;
201 unless ($self->{'_structures_it'}) {
202 my @structs = $self->get_StructureItems;
203 $self->{'_structures_it'} = sub {return shift @structs}
205 return $self->{'_structures_it'}->();
208 =head2 get_StructureItems
210 Title : get_StructureItems
211 Usage : my @structs = $ls->get_StructureItems
212 Function : returns list of Structure Items
213 Returns : array of StructureItems
214 Args : none
216 =cut
218 sub get_StructureItems {
219 my $self = shift;
220 my @items = $self->get_type eq 'Structure' ? $self->get_subItems : ();
221 return @items;
224 =head2 next_subItem
226 Title : next_subItem
227 Usage : while (my $it = $ls->next_subItem) {...}
228 Function : iterates through the next layer of Items
229 Returns : single Item
230 Args : none
231 Notes : unlike next_ListItem and next_Structureitem, this generically
232 accesses any sub Items (useful for recursive calls, for example)
234 =cut
236 sub next_subItem {
237 my $self = shift;
238 unless ($self->{'_subitem_it'}) {
239 my @structs = $self->get_subItems;
240 $self->{'_subitem_it'} = sub {return shift @structs}
242 return $self->{'_subitem_it'}->();
245 =head2 get_subItems
247 Title : get_subItems
248 Usage : my @items = $ls->get_subItems
249 Function : returns list of sub Items
250 Returns : array of Items
251 Args : none
252 Notes : unlike get_ListItems and get_StructureItems, this generically
253 accesses any sub Items (useful for recursive calls, for example)
255 =cut
257 sub get_subItems {
258 my $self = shift;
259 ref $self->{'_items'} ? return @{ $self->{'_items'} } : return ();
262 =head2 get_name
264 Title : get_name
265 Usage : my $nm = $ls->get_name
266 Function : retrieves Item/ListItem/StructureItem name
267 Returns : string
268 Args : none
270 =cut
272 sub get_name {
273 my $self = shift;
274 return $self->{'_itemname'};
277 =head2 get_type
279 Title : get_type
280 Usage : my $type = $ls->get_type
281 Function : retrieves Item/ListItem/StructureItem type
282 Returns : string
283 Args : none
284 Note : this is not the same as the datatype(), which describes the
285 group this Item object belongs to
287 =cut
289 sub get_type {
290 my $self = shift;
291 return $self->{'_itemtype'};
294 =head2 get_content
296 Title : get_content
297 Usage : my $data = $ls->get_content
298 Function : retrieves Item/ListItem/StructureItem content (if any)
299 Returns : string
300 Args : none
302 =cut
304 sub get_content {
305 my $self = shift;
306 return $self->{'_itemcontent'};
309 =head2 rewind
311 Title : rewind
312 Usage : $item->rewind()
313 Function : rewinds iterators
314 Returns : none
315 Args : [optional] No arg - only rewinds current layer
316 'all' - rewind all DocSum object layers
317 (Items, ListItems, StructureItems)
319 =cut
321 sub rewind {
322 my ($self, $request) = @_;
323 if ($request && $request eq 'all') {
324 map {$_->rewind()} $self->get_ListItems;
326 delete $self->{"_lists_it"} if $self->{"_lists_it"};
327 delete $self->{"_structures_it"} if $self->{"_structures_it"};
330 # private data method
332 sub _add_data {
333 my ($self, $data) = @_;
334 if ($data->{Item}) {
335 my $objtype = lc $data->{Type}.'_item';
336 $self->{'_id'} = $data->{Id} if exists $data->{Id};
337 for my $sd (@{ $data->{Item} } ) {
338 $sd->{Id} = $data->{Id} if exists $data->{Id};
339 my $subdoc = Bio::Tools::EUtilities::Summary::Item->new(
340 -datatype => $objtype,
341 -verbose => $self->verbose);
342 $subdoc->_add_data($sd);
343 push @{ $self->{'_items'} }, $subdoc;
346 for my $nm (qw(Type content Name)) {
347 $self->{'_item'.lc $nm} = $data->{$nm} if defined $data->{$nm};
349 $self->{'_id'} = $data->{Id} if exists $data->{Id};
352 =head2 to_string
354 Title : to_string
355 Usage : $foo->to_string()
356 Function : converts current object to string
357 Returns : none
358 Args : (optional) simple data for text formatting. This implementation
359 passes an argument for layering Items/subItems
360 Note : Used generically for debugging and print_DocSums methods
362 =cut
364 # recursively called to grab subitems, then layer
366 sub to_string {
367 my $self = shift;
368 my $level = shift || 0;
369 # this is the field length for the initial data (spaces are padded in front)
370 my $pad = 20 - $level;
371 my $content = $self->get_content || '';
372 my $string .= sprintf("%-*s%-*s%s\n",
373 $level, '',
374 $pad, $self->get_name(),
375 $self->_text_wrap(':',
376 ' ' x ($pad).':',
377 $content));
378 for my $sub ($self->get_subItems) {
379 $string .= $sub->to_string(4 + $level);
381 return $string;