File Coverage

lib/XML/XMetaL/Utilities.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package XML::XMetaL::Utilities;
2            
3 3     3   4991 use strict;
  3         6  
  3         491  
4 3     3   19 use warnings;
  3         6  
  3         85  
5 3     3   20 use Carp;
  3         6  
  3         244  
6 3     3   19 use Hash::Util qw(lock_keys);
  3         7  
  3         37  
7 3     3   8339 use Win32;
  0            
  0            
8            
9             # DOM node types
10             use constant DOMELEMENT => 1;
11             use constant DOMATTR => 2;
12             use constant DOMTEXT => 3;
13             use constant DOMCDATASECTION => 4;
14             use constant DOMENTITYREFERENCE => 5;
15             use constant DOMENTITY => 6;
16             use constant DOMPROCESSINGINSTRUCTION => 7;
17             use constant DOMCOMMENT => 8;
18             use constant DOMDOCUMENT => 9;
19             use constant DOMDOCUMENTTYPE => 10;
20             use constant DOMDOCUMENTFRAGMENT => 11;
21             use constant DOMNOTATION => 12;
22             use constant DOMCHARACTERREFERENCE => 505; # Extension to DOM
23            
24             # Attribute types
25             use constant UNKNOWN => -1;
26             use constant CDATA => 0;
27             use constant ID => 1;
28             use constant IDREF => 2;
29             use constant IDREFS => 3;
30             use constant ENTITY => 4;
31             use constant ENTITIES => 5;
32             use constant NMTOKEN => 6;
33             use constant NMTOKENS => 7;
34             use constant NOTATION => 8;
35             use constant NAMETOKENGROUP => 9;
36            
37            
38            
39             require Exporter;
40            
41             our @ISA = qw(Exporter);
42            
43             our @dom_type_names = qw(
44             DOMELEMENT DOMATTR DOMTEXT
45             DOMCDATASECTION DOMENTITYREFERENCE DOMENTITY
46             DOMPROCESSINGINSTRUCTION DOMCOMMENT DOMDOCUMENT
47             DOMDOCUMENTTYPE DOMDOCUMENTFRAGMENT DOMNOTATION
48             DOMCHARACTERREFERENCE
49             );
50            
51             our @attribute_type_names = qw(
52             UNKNOWN CDATA ID
53             IDREF IDREFS ENTITY
54             ENTITIES NMTOKEN NMTOKENS
55             NOTATION NAMETOKENGROUP
56             );
57            
58             our %EXPORT_TAGS = (
59             all => [@dom_type_names, @attribute_type_names],
60             dom_node_types => [@dom_type_names],
61             attribute_types => [@attribute_type_names],
62             );
63            
64             our @EXPORT_OK = (@{$EXPORT_TAGS{all}});
65            
66             # Variables used by the generate_id() method
67             our $count = 0;
68             our $user = Win32::LoginName();
69             our $time = time();
70            
71            
72            
73             sub new {
74             my ($class, %args) = @_;
75             my $self;
76             eval {
77             lock_keys(%args, qw(-application));
78             $self = bless {
79             _application => $args{-application} || croak("-application parameter missing or undefined"),
80             }, ref($class) || $class;
81             lock_keys(%$self, keys %$self);
82             };
83             croak $@ if $@;
84             return $self;
85             }
86            
87             sub get_application {
88             my ($self) = @_;
89             return $self->{_application};
90             }
91            
92             sub get_active_document {
93             my ($self) = @_;
94             return $self->get_application()->{ActiveDocument};
95             }
96            
97             sub get_selection {
98             my ($self) = @_;
99             my $application = $self->get_application();
100             return $application->{Selection};
101             }
102            
103             sub insert_element_with_id {
104             my ($self, $generic_identifier) = @_;
105             my $inserted_node = undef;
106             eval {
107             my $active_document = $self->get_active_document();
108             my $initial_position_range = $active_document->{Range};
109             my $final_position_range;
110             my $selection = $self->get_selection();
111             if ($selection->CanInsert($generic_identifier)) {
112             $selection->InsertElementWithRequired($generic_identifier);
113             $final_position_range = $active_document->{Range};
114             $initial_position_range->Select();
115             $selection->MoveRight(0);
116             $inserted_node = $selection->{ContainerNode};
117             $self->populate_element_with_id($inserted_node);
118             $final_position_range->Select();
119             }
120             };
121             croak $@ if $@;
122             return $inserted_node;
123             }
124            
125             sub generate_id {
126             $count++;
127             my $id = sprintf "%s%u%04u",$user,$time,$count;
128             return $id;
129             }
130            
131             sub get_id_attribute_name {
132             my ($self, $generic_identifier) = @_;
133             my $id_attribute_name;
134             eval {
135             my $active_document = $self->get_active_document();
136             my $doctype = $active_document->{doctype};
137             my $count = 0;
138             while ($id_attribute_name = $doctype->elementAttribute($generic_identifier, $count)) {
139             $count++;
140             last if $doctype->attributeType($generic_identifier,$id_attribute_name) == ID;
141             }
142             };
143             croak $@ if $@;
144             return $id_attribute_name || undef;
145             }
146            
147             sub populate_id_attributes {
148             my ($self, $generic_identifier) = @_;
149             eval {
150             my $active_document = $self->get_active_document();
151             my $element_node_list = $active_document->getElementsByTagName($generic_identifier);
152             my $element;
153             for (my $count = 0; $count < $element_node_list->{length}; $count++) {
154             $element = $element_node_list->item($count);
155             $self->populate_element_with_id($element);
156             }
157             };
158             croak $@ if $@;
159             }
160            
161             sub populate_element_with_id {
162             my ($self, $element_node) = @_;
163             eval {
164             my $generic_identifier = $element_node->{tagName};
165             my $attribute_name = $self->get_id_attribute_name($generic_identifier);
166             if ($attribute_name) {
167             unless ($element_node->hasAttribute($attribute_name)) {
168             my $id_value = $self->generate_id();
169             $element_node->setAttribute($attribute_name, $id_value);
170             }
171             }
172             };
173             croak $@ if $@;
174             }
175            
176             sub word_count {
177             my ($self, $argument) = @_;
178             my $word_count;
179             eval {
180             $word_count = ref($argument) ?
181             $self->_count_words_in_element($argument):
182             $self->_count_words_in_string($argument);
183            
184             };
185             croak($@) if $@;
186             return $word_count;
187             }
188            
189             sub _count_words_in_string {
190             my ($self, $string) = @_;
191             my $word_count;
192             eval {
193             my @words = split /[\s\:\-\;\,]+/, $string;
194             @words = grep {$_} @words; # Filter out empty strings
195             $word_count = @words;
196             };
197             croak $@ if $@;
198             return $word_count;
199             }
200            
201             sub _count_words_in_element {
202             my ($self, $element) = @_;
203             my $word_count = 0;
204             eval {
205             my $child_nodes = $element->{childNodes};
206             my ($child, $node_type);
207             for (my $count = 0; $count < $child_nodes->{length};$count++) {
208             $child = $child_nodes->item($count);
209             $node_type = $child->{nodeType};
210             foreach ($node_type) {
211             $node_type == DOMELEMENT && do {
212             $word_count += $self->_count_words_in_element($child);
213             last;
214             };
215             $node_type == DOMTEXT && do {
216             $word_count += $self->_count_words_in_string($child->{data});
217             last;
218             };
219             $node_type == DOMCDATASECTION && do {
220             $word_count += $self->_count_words_in_string($child->{data});
221             last;
222             };
223             }
224             }
225             };
226             croak $@ if $@;
227             return $word_count;
228             }
229            
230             1;
231            
232             __END__