File Coverage

blib/lib/StateML/Object.pm
Criterion Covered Total %
statement 55 71 77.4
branch 17 32 53.1
condition 1 6 16.6
subroutine 11 13 84.6
pod 9 9 100.0
total 93 131 70.9


line stmt bran cond sub pod time code
1             package StateML::Object ;
2              
3 4     4   22 use strict ;
  4         6  
  4         124  
4 4     4   19 use Carp qw( confess );
  4         6  
  4         605  
5              
6             =head1 METHODS
7              
8             =over
9              
10             =cut
11              
12             =item new
13              
14             $self->new( attr => "val", ... ) ;
15              
16             Create a new object.
17              
18             =cut
19              
20             sub new {
21 16     16 1 37 my $proto = shift ;
22 16   33     70 my $class = ref $proto || $proto ;
23 16         105 my $self = bless {
24             @_,
25             }, $class ;
26 16         101 return $self ;
27             }
28              
29              
30             =item type
31              
32             $obj->type ;
33              
34             Returns "MACHINE", "STATE", "ARC", "EVENT".
35              
36             =cut
37              
38              
39             sub type {
40 11     11 1 15 my $self = shift ;
41              
42 11         27 my $type = uc ref $self ;
43 11         51 $type =~ s/.*:// ;
44 11         37 return $type ;
45             }
46              
47              
48             sub _generate_id {
49 1     1   2 my $self = shift ;
50 1         2 my $class = ref $self ;
51 4     4   16 no strict 'refs' ;
  4         10  
  4         2617  
52 1         3 $self->id( $self->type . " " . ++${"$class\::ID_COUNTER"} ) ;
  1         12  
53             }
54              
55              
56             =item class_ids
57              
58             A list of class ids this class inherits from.
59              
60             To set the list, this method takes a list of strings, each of which should
61             be one or more class_ids separated by a comma. Trailing commas are allowed.
62              
63             =cut
64              
65             sub class_ids {
66 10     10 1 217 my $self = shift;
67 10 100       31 $self->{CLASS_IDS} = [ grep length, map split( /,/ ), @_ ] if @_;
68 10 100       45 return unless $self->{CLASS_IDS};
69 4         5 return @{$self->{CLASS_IDS}};
  4         13  
70             }
71              
72              
73             =item id
74              
75             $obj->id( "foo" ) ;
76             $id = $obj->id ;
77              
78             Returns the id string. Creates a new unique one if not defined.
79              
80             The id "" is not valid.
81              
82             =cut
83              
84             sub id {
85 32     32 1 37 my $self = shift ;
86 32 100       77 $self->{ID} = shift if @_ ;
87 32 100       67 return unless defined wantarray;
88 31 100       97 $self->_generate_id unless defined $self->{ID} ;
89 31 50       65 confess "invalid id ''" unless length $self->{ID};
90 31         98 return $self->{ID} ;
91             }
92              
93              
94             =item name
95              
96             $obj->name( "foo" ) ;
97             $id = $obj->name ;
98              
99             Returns the name string or the id string if the name is unset.
100             The name "" is valid.
101              
102             The name is used for human readable documentation purposes, the id is
103             used for internal linking and for generated code. The name is merely
104             a comment with semantic value.
105              
106             =cut
107              
108             sub name {
109 0     0 1 0 my $self = shift ;
110 0 0       0 $self->{NAME} = shift if @_ ;
111 0 0       0 return defined $self->{NAME}
112             ? $self->{NAME}
113             : $self->id;
114             }
115              
116              
117             =item enum_id
118              
119             $enum_id = $obj->enum_id ;
120              
121             Returns the same string as $obj->id, but cleaned up sufficiently to be
122             used in a C "enum" statement.
123              
124             =cut
125              
126             sub enum_id {
127 6     6 1 11 my $self = shift ;
128 6         29 my $oid = $self->id ;
129 6         16 for ( $oid ) {
130 6 50       36 $_ = "_$_" if /^[^a-zA-Z_]/ ;
131 6         39 s/[^a-zA-Z0-9_]+/_/g ;
132             }
133 6         41 return $oid ;
134             }
135              
136              
137             =item machine
138              
139             $obj->machine( $machine ) ;
140             $m = $obj->machine ;
141              
142             Sets/gets the StateML::Machine object this object is a part of.
143              
144             =cut
145              
146             sub machine {
147 22     22 1 29 my $self = shift ;
148 22 100       72 $self->{MACHINE} = shift if @_ ;
149 22         78 return $self->{MACHINE} ;
150             }
151              
152              
153             =item attribute
154              
155             $attr = $obj->attribute( $namespace_uri, $name ) ;
156              
157             Returns the attribute identified by the XML namespace prefix and name.
158              
159             $attr = $obj->attribute( $namespace_uri, $name, $value ) ;
160              
161             The namespace_uri is the XML concept of namespace identifier.
162              
163             Checks up the class hierarchy if an attribute is not defined.
164              
165             =cut
166              
167             #If there is no attribute named "{$namespace_uri}$name", returns
168             #an attribute named $name if that exists. Returns undef otherwise.
169              
170             sub attribute {
171 0     0 1 0 my $self = shift ;
172 0         0 my ( $namespace_uri, $name, $value ) = @_ ;
173              
174 0         0 my $key = "{$namespace_uri}$name" ;
175 0         0 my $a = $self->{ATTRS} ;
176 0 0       0 if ( @_ == 3 ) {
177 0 0       0 if ( defined $value ) {
178 0         0 $a->{$key} = $value ;
179             }
180             else {
181 0         0 delete $a->{$key} ;
182             }
183             }
184 0 0 0     0 return $a->{$key} if exists $a->{$key} && defined $a->{$key} ;
185              
186 0         0 for ( $self->class_ids ) {
187 0         0 my $attr = $self->machine->object_by_id( $_ )->attribute( @_[0,1] );
188 0 0       0 return $attr if defined $attr;
189             }
190              
191 0         0 return undef ;
192             }
193              
194             =item attributes
195              
196             %attrs = $obj->attributes( $namespace_uri );
197             %attrs = $obj->attributes;
198              
199             If a namespace URI is passed, returns attributes in that namespace and
200             no others with the localname of the attribute as the key (ie without the
201             namespace URI).
202              
203             If no namespace URI is passed, returns all attributes with the URI encoded
204             in jclark notation.
205              
206             Compiles a list of all attributes from the class hierarchy.
207              
208             =cut
209              
210             sub attributes {
211 9     9 1 1034 my $self = shift ;
212 9         13 my ( $namespace_uri ) = @_ ;
213 9         14 my $a = $self->{ATTRS} ;
214              
215 3         22 my %inherited_attrs = map {
216 9         20 my $base_class = $self->machine->object_by_id( $_ );
217 3 50       12 confess "base class $_ not found ", $self->{LOCATION}
218             unless $base_class;
219 3         10 $base_class->attributes( @_ );
220             } $self->class_ids;
221              
222 9 100       20 if ( ! defined $namespace_uri ) {
223 3         19 return ( %inherited_attrs, %$a );
224             }
225              
226 6         13 $namespace_uri = "{$namespace_uri}" ;
227 6         12 my $l = length $namespace_uri;
228             return (
229 3         9 %inherited_attrs,
230             (
231             map {
232 6         37 my $name = substr( $_, $l ) ;
233 3         22 ( $name => $a->{$_} ) ;
234             } grep 0 == index( $_, $namespace_uri ), keys %$a
235             ),
236             );
237             }
238              
239             =back
240              
241             =cut
242              
243              
244             1 ;