File Coverage

blib/lib/Devel/ModInfo.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             # This code is a part of ModInfo, and is released under the Perl Artistic
2             # License.
3             # Copyright 2002 by James Tillman and Todd Cushard. See README and COPYING
4             # for more information, or see
5             # http://www.perl.com/pub/a/language/misc/Artistic.html.
6             # $Id: ModInfo.pm,v 1.6 2002/08/17 23:23:46 jtillman Exp $
7              
8             #TODO
9             #check that RETVAL is getting processed when doing reading in XML for functions
10             #
11              
12             $| = 1;
13              
14             # MODINFO module Devel::ModInfo
15             package Devel::ModInfo;
16              
17 3     3   30206 use 5.006;
  3         9  
  3         149  
18             # MODINFO dependency module File::Spec::Functions
19 3     3   2690 use File::Spec::Functions;
  3         3123  
  3         310  
20             # MODINFO dependency module XML::DOM
21 3     3   4985 use XML::DOM;
  0            
  0            
22             # MODINFO dependency module Data::Dumper
23             use Data::Dumper;
24              
25             # MODINFO dependency module strict
26             use strict;
27             # MODINFO dependency module warnings
28             use warnings;
29              
30             # MODINFO dependency module Devel::ModInfo::Method
31             use Devel::ModInfo::Method;
32             # MODINFO dependency module Devel::ModInfo::Constructor
33             use Devel::ModInfo::Constructor;
34             # MODINFO dependency module Devel::ModInfo::Parameter
35             use Devel::ModInfo::Parameter;
36             # MODINFO dependency module Devel::ModInfo::Function
37             use Devel::ModInfo::Function;
38             # MODINFO dependency module Devel::ModInfo::Property
39             use Devel::ModInfo::Property;
40             # MODINFO dependency module Devel::ModInfo::Module
41             use Devel::ModInfo::Module;
42             # MODINFO dependency module Devel::ModInfo::Dependency
43             use Devel::ModInfo::Dependency;
44             # MODINFO dependency module Devel::ModInfo::ParentClass
45             use Devel::ModInfo::ParentClass;
46             # MODINFO dependency module Devel::ModInfo::ParamHash::Key
47             use Devel::ModInfo::ParamHash::Key;
48             # MODINFO dependency module Devel::ModInfo::ParamHash
49             use Devel::ModInfo::ParamHash;
50             # MODINFO dependency module Devel::ModInfo::ParamHash
51             use Devel::ModInfo::ParamHashRef;
52             # MODINFO dependency module Devel::ModInfo::ParamArray
53             use Devel::ModInfo::ParamArray;
54             # MODINFO dependency module Devel::ModInfo::DataType
55             use Devel::ModInfo::DataType 'String2DataType';
56              
57             # MODINFO dependency module Exporter
58             require Exporter;
59              
60             # MODINFO parent_class AutoLoader
61             our @ISA = qw(Exporter AutoLoader);
62             our @EXPORT = qw();
63              
64             # MODINFO version 2.04
65             our $VERSION = '2.04';
66              
67              
68             # Preloaded methods go here.
69             # MODINFO constructor new
70             # MODINFO param module STRING Package name of the module to get info for
71             sub new{
72             my ($class, $module) = @_;
73              
74             #
75             #Translate module and find ModInfo metadata file
76             #
77             my $mod_info_file = $module;
78             $mod_info_file =~ s|::|/|g;
79             $mod_info_file .= ".mfo";
80             $mod_info_file = canonpath(_findINC($mod_info_file));
81             if ($mod_info_file eq '') {
82             die "Couldn't locate mfo file for $module in @INC path";
83             }
84             my $parser = XML::DOM::Parser->new();
85             my $xml_doc;
86             eval {
87             $xml_doc = $parser->parsefile($mod_info_file);
88             };
89             if ($@) {
90             warn "Error parsing mfo file $mod_info_file: $@";
91             return undef;
92             }
93             my(@methods, @constructors, @functions, @properties);
94              
95              
96             #
97             #Get methods
98             #
99             foreach my $item ($xml_doc->getElementsByTagName('method')) {
100             my $item_obj = Devel::ModInfo::Method->new(
101             _extract_function_data($item, $class)
102             );
103             push(@methods, $item_obj);
104             }
105              
106             #
107             #Get constructors
108             #
109             foreach my $item ($xml_doc->getElementsByTagName('constructor')) {
110             my $item_obj = Devel::ModInfo::Constructor->new(_extract_function_data($item, $class));
111             push(@constructors, $item_obj);
112             }
113              
114             #
115             #Get functions
116             #
117             foreach my $item ($xml_doc->getElementsByTagName('function')) {
118             my $item_obj = Devel::ModInfo::Function->new(_extract_function_data($item, $class));
119             push(@functions, $item_obj);
120             }
121              
122             #
123             #Get properties
124             #
125             foreach my $item ($xml_doc->getElementsByTagName('property')) {
126             my $item_obj = Devel::ModInfo::Property->new(
127             name => $item->getAttribute('name'),
128             display_name => $item->getAttribute('display_name'),
129             short_description => $item->getAttribute('short_description'),
130             read_method => $item->getAttribute('read_method'),
131             write_method => $item->getAttribute('write_method'),
132             data_type => _get_datatype(class_name=>$class, data_type=>$item->getAttribute('data_type')),
133             );
134             push(@properties, $item_obj);
135             }
136            
137              
138             #
139             # Get module-level info
140             #
141             my $mod_node = $xml_doc->getElementsByTagName('module')->[0];
142              
143             return undef if !$mod_node;
144              
145             my @deps;
146             foreach my $dep_node ($mod_node->getElementsByTagName('dependency')) {
147             my $dep_obj = Devel::ModInfo::Dependency->new(
148             type => $dep_node->getAttribute('type'),
149             target => $dep_node->getAttribute('target'),
150             );
151             push(@deps, $dep_obj);
152             }
153              
154             my @parents;
155             foreach my $parent ($mod_node->getElementsByTagName('parent_class')) {
156             my $parent_obj = Devel::ModInfo::ParentClass->new(
157             name => $parent->getAttribute('name'),
158             );
159             push(@parents, $parent_obj);
160             }
161              
162              
163             my $mod_obj = Devel::ModInfo::Module->new(
164             name => $mod_node->getAttribute('name'),
165             display_name => $mod_node->getAttribute('display_name'),
166             short_description => $mod_node->getAttribute('short_description'),
167             version => $mod_node->getAttribute('version'),
168             class => $module,
169             dependencies => \@deps,
170             parent_classes => \@parents,
171             );
172            
173             #
174             # Assign collections and other attributes to $self
175             #
176             my $self = {
177             module_name => $module,
178             mod_info_file => $mod_info_file,
179             methods => \@methods,
180             constructors => \@constructors,
181             functions => \@functions,
182             properties => \@properties,
183             module => $mod_obj,
184             };
185              
186             #print Dumper $self;
187            
188             #
189             # Return object
190             #
191             return bless $self => $class;
192             }
193              
194             # MODINFO function properties
195             # MODINFO retval ARRAYREF
196             sub properties{$_[0]->{properties}}
197              
198             # MODINFO function methods
199             # MODINFO retval ARRAYREF
200             sub methods{$_[0]->{methods}}
201              
202             # MODINFO function functions
203             # MODINFO retval ARRAYREF
204             sub functions{$_[0]->{functions}}
205              
206             # MODINFO function constructors
207             # MODINFO retval ARRAYREF
208             sub constructors{$_[0]->{constructors}}
209              
210             # MODINFO function module Returns the Module object for this Package
211             # MODINFO retval Devel::ModInfo::Module
212             sub module{$_[0]->{module}}
213              
214             # MODINFO function is_oo Returns 1 if this is an object-oriented package, 0 if not
215             # MODINFO retval INTEGER
216             sub is_oo{
217             my($self) = @_;
218             if ($self->constructors) {return 1}
219             else {return 0}
220             }
221              
222             # MODINFO function icon Returns the path to an icon for this module (relative to the module file itself)
223             # MODINFO retval STRING
224             sub icon{$_[0]->{icon}}
225              
226             sub _findINC {
227             my $file = join('/',@_);
228             my $dir;
229             $file =~ s,::,/,g;
230             foreach $dir (@INC) {
231             my $path;
232             return $path if (-e ($path = "$dir/$file"));
233             }
234             return undef;
235             }
236              
237             #sub _check_module_version {
238             # my($version, $module) = @_;
239             # my $module_file = $module . ".pm";
240             # $module_file =~ s/::/\//g;
241             # open(MOD, _findINC($module_file)) or warn "Couldn't open $module_file for verification of version: $!";
242             # while(my $line = ) {
243             # if($line =~ /^package\s+(.);/ && $1 eq $module)
244             # }
245             #
246             # print "Version for $module is: $module_version\n";
247             # return $module_version;
248             #
249             #}
250              
251             sub _extract_function_data {
252             my($function_node, $class) = @_;
253             #my $function_node = $params{function_node};
254            
255             my $name = $function_node->getAttribute('name');
256             my $display_name = $function_node->getAttribute('display_name');
257             my $short_description = $function_node->getAttribute('short_description');
258             my @ret_val = $function_node->getElementsByTagName('retval');
259             my $data_type;
260             if (@ret_val) {
261             $data_type = $ret_val[0]->getAttribute('data_type');
262             }
263             else {
264             $data_type = String2DataType('VOID');
265             }
266              
267             # Get parameters
268             my @params;
269             foreach my $param ($function_node->getElementsByTagName('param')) {
270             my $name = $param->getAttribute('name');
271             my $data_type = _get_datatype(class_name=>$class, data_type=>$param->getAttribute('data_type'));
272             my $short_description = $param->getAttribute('short_description');
273             my $display_name = $param->getAttribute('display_name');
274            
275             my $param_obj = Devel::ModInfo::Parameter->new(
276             name => $name,
277             display_name => $display_name,
278             data_type => $data_type,
279             short_description => $short_description,
280             );
281            
282             push(@params, $param_obj);
283             }
284              
285             #
286             # Check for paramhash(ref) at end of param list. Paramhashes must be
287             # last item in parameter list, anyway
288             #
289             my(@keys);
290             my $param_hash;
291             if ($param_hash = $function_node->getElementsByTagName('paramhash')->[0] or
292             $param_hash = $function_node->getElementsByTagName('paramhashref')->[0]) {
293             my $name = $param_hash->getAttribute('name');
294             my $data_type = $param_hash->getAttribute('data_type');
295             my $short_description = $param_hash->getAttribute('short_description');
296             my $display_name = $param_hash->getAttribute('display_name');
297            
298             foreach my $key ($param_hash->getElementsByTagName('key')) {
299             my $name = $key->getAttribute('name');
300             my $data_type = _get_datatype(class_name=>$class, data_type=>$key->getAttribute('data_type'));
301             my $short_description = $key->getAttribute('short_description');
302             my $display_name = $key->getAttribute('display_name');
303             my $key_obj = Devel::ModInfo::ParamHash::Key->new(
304             name => $name,
305             display_name => $display_name,
306             data_type => $data_type,
307             short_description => $short_description,
308             );
309            
310             push(@keys, $key_obj);
311             }
312             my $param_hash_obj;
313             if ($data_type eq 'paramhash') {
314             $param_hash_obj = Devel::ModInfo::ParamHash->new(
315             name => $name,
316             display_name => $display_name,
317             data_type => $data_type,
318             short_description => $short_description,
319             keys => \@keys,
320             );
321             }
322             else {
323             $param_hash_obj = Devel::ModInfo::ParamHashRef->new(
324             name => $name,
325             display_name => $display_name,
326             data_type => $data_type,
327             short_description => $short_description,
328             keys => \@keys,
329             );
330             }
331            
332             push(@params, $param_hash_obj);
333             }
334              
335             #
336             # Check for paramarray at end of parameter list. Paramarrays must be
337             # last item in parameter list, anyway
338             #
339             if (my $param_array = $function_node->getElementsByTagName('paramarray')->[0]) {
340             my $name = $param_array->getAttribute('name');
341             my $data_type = _get_datatype(class_name=>$class, data_type=>$param_array->getAttribute('data_type'));
342             my $short_description = $param_array->getAttribute('short_description');
343             my $display_name = $param_array->getAttribute('display_name');
344            
345             my $param_array_obj = Devel::ModInfo::ParamArray->new(
346             name => $name,
347             display_name => $display_name,
348             data_type => $data_type,
349             short_description => $short_description,
350             keys => \@keys,
351             );
352            
353             push(@params, $param_array_obj);
354              
355             }
356              
357             my %data = (
358             name => $name,
359             display_name => $display_name,
360             short_description => $short_description,
361             data_type => $data_type,
362             parameters => \@params,
363             );
364              
365             return %data;
366             }
367              
368             sub _get_datatype {
369             my(%params) = @_;
370             #print "Converting $params{data_type}\n";
371             my $data_type = String2DataType($params{'data_type'});
372             if (!$data_type) {
373             my $file_path = $params{'class_name'};
374             $file_path =~ s|::|/|g;
375             $file_path = _findINC("$file_path.pm");
376             if (-f $file_path) {
377             $data_type = $params{'data_type'};
378             }
379             else {
380             warn "Could not resolve data type " . $params{'data_type'} . " while processing " . $params{'class_name'} . "\n";
381             }
382             }
383            
384             return $data_type;
385             };
386              
387             1;
388             __END__