File Coverage

blib/lib/DS/TypeSpec.pm
Criterion Covered Total %
statement 67 112 59.8
branch 18 40 45.0
condition 2 2 100.0
subroutine 12 18 66.6
pod 0 11 0.0
total 99 183 54.1


line stmt bran cond sub pod time code
1             #!perl
2            
3             # ########################################################################## #
4             # Title: Type specification
5             # Creation date: 2007-03-05
6             # Author: Michael Zedeler
7             # Description: Class holding type specifications for data streams
8             # File: $Source: /data/cvs/lib/DSlib/lib/DS/TypeSpec.pm,v $
9             # Repository: kronhjorten
10             # State: $State: Exp $
11             # Documentation: inline
12             # Recepient: -
13             # ########################################################################## #
14            
15             package DS::TypeSpec;
16            
17 12     12   169927 use base qw{ Clone };
  12         30  
  12         10529  
18            
19 12     12   56965 use strict;
  12         26  
  12         328  
20 12     12   63 use Carp;
  12         26  
  12         1021  
21 12     12   7764 use Carp::Assert;
  12         10902  
  12         80  
22 12     12   14392 use List::MoreUtils qw{ any all };
  12         17014  
  12         1091  
23 12     12   7246 use DS::TypeSpec::Field;
  12         29  
  12         15408  
24            
25             our ($VERSION) = $DS::VERSION;
26             our ($REVISION) = '$Revision: 1.2 $' =~ /(\d+\.\d+)/;
27            
28            
29             sub new {
30 29     29 0 68 my( $class, $arg1, $arg2 ) = @_;
31            
32 29         49 my $name;
33             my $fields;
34 29 100       106 if( $arg1 ) {
35 23 50       77 if( ref( $arg1 ) eq '' ) {
36 23         35 $name = $arg1;
37 23 100       77 if( $arg2 ) {
38 19         35 $fields = $arg2;
39             }
40             } else {
41 0         0 $fields = $arg1;
42             }
43 23 100       89 if( $fields ) {
44 19         118 should(ref($fields) , 'ARRAY');
45             }
46             }
47            
48 29   100     276 my $self = bless {
49             name => $name || '',
50             fields => {}
51             }, $class;
52            
53 29 100       99 if( $fields ) {
54 19         67 $self->add_fields( $fields );
55             }
56            
57 29         351 return $self;
58             }
59            
60             sub add_fields {
61 19     19 0 38 my( $self, $fields ) = @_;
62            
63 19         39 foreach my $field (@$fields) {
64 50         133 $self->add_field( $field );
65             }
66             }
67            
68             sub add_field {
69 57     57 0 81 my( $self, $field ) = @_;
70            
71 57 50       205 if( ref( $field ) eq '' ) {
72 0         0 $field = new DS::TypeSpec::Field( $field );
73             }
74 57         415 assert($field->isa('DS::TypeSpec::Field'));
75 57 50       510 if( $self->{fields}->{ $field->{name} } ) {
76 0         0 croak("Can't add field to data stream type spec, since another field with the same name already exists");
77             } else {
78 57         224 $self->{fields}->{ $field->{name} } = $field;
79             }
80             }
81            
82             sub remove_fields {
83 0     0 0 0 my( $self, $fields ) = @_;
84            
85 0         0 foreach my $field (@$fields) {
86 0         0 $self->remove_field( $field );
87             }
88             }
89            
90             sub remove_field {
91 0     0 0 0 my( $self, $field ) = @_;
92            
93 0         0 my $field_name;
94 0 0       0 if( not ref($field) eq '' ) {
95 0         0 should($field->isa, 'DS::TypeSpec::Field');
96 0         0 $field_name = $field->{name};
97             } else {
98 0         0 $field_name = $field;
99             }
100 0 0       0 if( not $self->{fields}->{ $field->{name} } ) {
101 0         0 croak("Can't remove field from data stream type spec - name not recognized. The name is $field_name, but I only have " . join(", ", keys %{$self->{fields}}));
  0         0  
102             } else {
103 0         0 delete $self->{fields}->{ $field->{name} };
104             }
105             }
106            
107             sub fields {
108 0     0 0 0 my( $self, $fields ) = @_;
109            
110 0         0 my $result = 1;
111 0 0       0 if( $fields ) {
112 0         0 should(ref($fields), 'ARRAY');
113 0         0 my %remove_fields = ( %{$self->{fields}} );
  0         0  
114 0         0 foreach my $field ( @$fields ) {
115 0 0       0 if( $self->{fields}->{$field} ) {
116 0         0 $self->add_field( $field );
117 0         0 delete $remove_fields{ $field };
118             }
119             }
120 0         0 $self->{fields} = $fields;
121             } else {
122 0         0 $result = $self->{fields};
123             }
124 0         0 return $result;
125             }
126            
127             sub field_names {
128 0     0 0 0 my( $self, $fields ) = @_;
129 0         0 return keys %{$self->{fields}};
  0         0  
130             }
131            
132             sub keys_locked {
133 0     0 0 0 my( $self, $keys_locked ) = @_;
134            
135 0         0 my $result = 1;
136 0 0       0 if( $keys_locked ) {
137 0 0       0 $self->{keys_locked} = $keys_locked ? 1 : 0;
138             } else {
139 0         0 $keys_locked = $self->{keys_locked};
140             }
141 0         0 return $result;
142             }
143            
144             sub values_readonly {
145 0     0 0 0 my( $self, $values_readonly ) = @_;
146            
147 0         0 my $result = 1;
148 0 0       0 if( $values_readonly ) {
149 0 0       0 $self->{values_readonly} = $values_readonly ? 1 : 0;
150             } else {
151 0         0 $values_readonly = $self->{values_readonly};
152             }
153 0         0 return $result;
154             }
155            
156             sub contains {
157 23     23 0 57 my( $self, $other ) = @_;
158            
159 23         32 my $result;
160            
161 23 100       137 if( $other->isa('DS::TypeSpec::Any') ) {
162 2         12 $result = 1;
163             } else {
164             # This is equivalent to the subset operator in mathematics
165             # For all of the $other fields
166             $result = all {
167 49     49   114 my $other = $_;
168             # There must be one key with the same name
169 49         141 any { $_ eq $other } keys %{$self->{fields}};
  98         154  
  49         206  
170 21         97 } keys %{$other->{fields}};
  21         152  
171             }
172            
173 23         151 return $result;
174             }
175            
176             sub project {
177 4     4 0 3526 my( $self, $arg1, $arg2 ) = @_;
178            
179 4         6 my $name = '';
180 4         4 my $new_fields;
181 4 50       9 if( $arg1 ) {
182 4 50       11 if( ref( $arg1 ) eq '' ) {
183 4         5 $name = $arg1;
184 4 50       6 if( $arg2 ) {
185 4         7 $new_fields = $arg2;
186             }
187             } else {
188 0         0 $new_fields = $arg1;
189             }
190             }
191            
192             # if( ref( $fields ) eq 'ARRAY' ) {
193             # my $new_fields = {};
194             # foreach my $field ( @$fields ) {
195             # $new_fields->{$field} = 1;
196             # }
197             # $fields = $new_fields;
198             # }
199 4         13 should(ref($new_fields), 'HASH');
200            
201 4         19 my $new_spec = new DS::TypeSpec( $name );
202            
203 4         11 foreach my $new_field (keys %$new_fields) {
204 9 100       27 if( my $field = $self->{fields}->{ $new_fields->{$new_field} } ) {
205 7         54 my $new_field_obj = $field->clone();
206 7         13 $new_field_obj->{name} = $new_field;
207 7         13 $new_spec->add_field( $new_field_obj );
208             } else {
209 2         379 croak("Can't limit to field $new_field since it is not in the original type");
210             }
211             }
212 2         5 return $new_spec;
213             }
214            
215             1;
216            
217             #TODO Add sorting and unique constraints. Possibly also field order (or maybe not?!?)