File Coverage

blib/lib/PFIX/Dictionary.pm
Criterion Covered Total %
statement 129 137 94.1
branch 55 68 80.8
condition 6 12 50.0
subroutine 23 26 88.4
pod 0 20 0.0
total 213 263 80.9


line stmt bran cond sub pod time code
1             package PFIX::Dictionary;
2              
3 4     4   3470 use warnings;
  4         8  
  4         144  
4 4     4   21 use strict;
  4         6  
  4         123  
5              
6             =head1 NAME
7              
8             PFIX::Dictionary - Perl FIX dictionnary methods
9              
10             =cut
11              
12 4     4   1078 use Data::Dumper;
  4         7218  
  4         7089  
13              
14             my $fixDico = {};
15              
16             sub load($) {
17 3     3 0 1275 my $ver = shift;
18              
19 3 50       17 if ( !defined $fixDico->{$ver} ) {
20              
21 3         7827 require("PFIX/$ver.pm");
22              
23 3         303 my $f = eval "PFIX::${ver}::getFix()";
24              
25             ##
26             # parse messages and build a hash for faster access
27             #
28 3         15 $f->{hMessages} = {};
29 3         8 for my $a ( @{ $f->{messages} } ) {
  3         12  
30 276         568 $f->{hMessages}->{ $a->{msgtype} } = $a;
31 276         1176 $f->{hMessages}->{ $a->{name} } = $a;
32             }
33              
34             ##
35             # parse fields and build a hash for faster access
36             #
37 3         12 $f->{hFields} = {};
38 3         5 for my $a ( @{ $f->{fields} } ) {
  3         6  
39 2742         5342 $f->{hFields}->{ $a->{name} } = $a;
40 2742         5296 $f->{hFields}->{ $a->{number} } = $a;
41             }
42              
43             ##
44             # parse components and build a hash for faster access
45             #
46 3         14 $f->{hComponents} = {};
47 3         6 for my $a ( @{ $f->{components} } ) {
  3         12  
48 72         205 $f->{hComponents}->{ $a->{name} } = $a;
49             }
50              
51 3         41 $fixDico->{$ver} = $f;
52             }
53              
54             #print Dumper($fixDico);
55              
56             }
57              
58             sub new ($) {
59 2     2 0 5 my $proto = shift;
60              
61 2   33     18 my $class = ref($proto) || $proto;
62 2         4 my $self = {};
63 2         5 bless( $self, $class );
64 2         16 $self->{_dict} = $fixDico->{FIX44};
65              
66 2         11 return $self;
67             }
68              
69             sub getMessages($) {
70 77     77 0 83 my $self = shift;
71 77         198 return $self->{_dict}->{hMessages};
72             }
73              
74             sub getMessage($$) {
75 77     77 0 86 my ( $self, $m ) = @_;
76 77         132 return $self->getMessages()->{$m};
77             }
78              
79             sub getMessageName($$) {
80 3     3 0 9 my ( $self, $m ) = @_;
81 3         7 my $mh = $self->getMessage($m);
82 3 100       41 return defined $mh ? $mh->{name} : undef;
83             }
84              
85             sub getMessageMsgType($$) {
86 3     3 0 6 my ( $self, $m ) = @_;
87 3         4 my $mh = $self->getMessage($m);
88 3 100       17 return defined $mh ? $mh->{msgtype} : undef;
89             }
90              
91             sub getMessageFields($$) {
92 63     63 0 71 my ( $self, $m ) = @_;
93 63         99 my $mh = $self->getMessage($m);
94 63 100       174 return defined $mh ? $mh->{fields} : undef;
95             }
96              
97             sub _getMessageOrder($$) {
98 247     247   318 my ( $self, $mf ) = @_;
99 247         236 my @arr;
100 247 50       423 return @arr if ! defined $mf;
101 247         433 for my $e ( @$mf ) {
102 2430 100       4366 if (!defined $e->{component}) {
103 2322         4556 push(@arr, $self->getFieldNumber($e->{name}));
104             }
105             else {
106 108         201 push(@arr, $self->_getMessageOrder($self->getComponentFields($e->{name})));
107             }
108 2430 100       5605 if (defined $e->{group}) {
109 112         434 push(@arr, $self->_getMessageOrder($e->{group}));
110             }
111             }
112 247         1706 @arr;
113             }
114            
115             sub getMessageOrder($$) {
116 9     9 0 14 my ( $self, $m ) = @_;
117 9         52 my $mf = $self->getMessageFields($m);
118 9         40 my @arr=$self->_getMessageOrder($self->{_dict}->{header});;
119 9         33 push(@arr,$self->_getMessageOrder($mf));
120 9         115 push(@arr,$self->_getMessageOrder($self->{_dict}->{trailer}));
121 9         18 my %ret;
122 9         36 for my $i ( 0..scalar(@arr)-1 ) {
123 2322         3673 $ret{$arr[$i]}=$i;
124             }
125 9         1145 %ret;
126             }
127              
128             sub getComponent($$) {
129 0     0 0 0 my ($self, $c) = @_;
130 0         0 return $self->{_dict}->{hComponents}->{$c};
131             }
132              
133             sub getComponentFields($$) {
134 220     220 0 264 my ($self, $c) = @_;
135 220         606 my $cc=$self->{_dict}->{hComponents}->{$c};
136 220 50       708 return defined $cc ? $cc->{fields} : undef;
137             }
138              
139             sub getField($$) {
140 3248     3248 0 3740 my ( $self, $f ) = @_;
141 3248         8031 return $self->{_dict}->{hFields}->{$f};
142             }
143              
144             sub getFieldName($$) {
145 596     596 0 680 my ( $self, $f ) = @_;
146 596         847 my $fh = $self->getField($f);
147 596 100       1775 return defined $fh ? $fh->{name} : undef;
148             }
149              
150             sub getFieldNumber($$) {
151 2355     2355 0 3077 my ( $self, $f ) = @_;
152 2355 100       5009 return $f if ( $f =~ /^[0-9]+$/ );
153 2335         3647 my $fh = $self->getField($f);
154 2335 50       4291 warn("getFieldNumber($f) returning undef") if !defined $fh;
155 2335 50       6719 return defined $fh ? $fh->{number} : undef;
156             }
157              
158             sub getFieldType($$) {
159 0     0 0 0 my ( $self, $f ) = @_;
160 0         0 my $fh = $self->getField($f);
161 0 0       0 return defined $fh ? $fh->{type} : undef;
162             }
163              
164              
165             ##
166             # returns true if given field is found in the structure.
167             sub _isFieldInStructure($$$);
168              
169             sub _isFieldInStructure($$$) {
170 222     222   269 my ( $self, $m, $f ) = @_;
171 222 50 33     583 return 0 if ( !defined $m || !defined $f );
172 222         363 my $fn = $self->getFieldName($f);
173 222 100       380 return 0 if !defined $fn;
174              
175 221         199 for my $f2 ( @{$m} ) {
  221         324  
176              
177             #print "checking if $fn eq " . $f2->{name} . "\n";
178             ##
179             # found the field? return 1. Beware that if the element is a component then we don't accept
180             # it as a valid field of the structure.
181 1051 100 66     2333 return 1 if ( $f2->{name} eq $fn && !defined $f2->{component} );
182              
183             ##
184             # if the field is a group then scan all elements of the group
185 1001 100       1522 if ( defined $f2->{group} ) {
186 97 100       202 return 1 if $self->_isFieldInStructure( $f2->{group}, $fn ) == 1;
187             }
188              
189             ##
190             # if the field is a component, we need to go to the component hash and check out its
191             # composition.
192 994 100       1656 if ( defined $f2->{component} ) {
193 59 100       119 return 1 if $self->_isFieldInStructure( $self->getComponentFields($f2->{name}), $fn ) == 1;
194             }
195             }
196              
197 160         434 return 0;
198             }
199              
200             sub isFieldInHeader($$) {
201 5     5 0 10 my ( $self, $f ) = @_;
202 5         6 my $s = $self->{_dict}->{header};
203 5         12 return $self->_isFieldInStructure( $s, $f );
204             }
205              
206             sub isFieldInTrailer($$) {
207 0     0 0 0 my ( $self, $f ) = @_;
208 0         0 my $s = $self->{_dict}->{trailer};
209 0         0 return $self->_isFieldInStructure( $s, $f );
210             }
211              
212             ##
213             # returns true if given field is a member of the given message
214             # $dict->isFieldInMessage('NewOrderSingle', 'Symbol') -> returns 1
215             # $dict->isFieldInMessage('NewOrderSingle', 'NoLegs') -> returns 0
216             # a recursive search into group members and components is performed.
217             sub isFieldInMessage($$$) {
218 8     8 0 22 my ( $self, $m, $f ) = @_;
219 8         15 my $s = $self->getMessage($m);
220 8 50       18 return 0 if !defined $s;
221 8         18 return $self->_isFieldInStructure( $s->{fields}, $f );
222             }
223              
224             ##
225             # returns 1 if given field is a group header field
226             # $dict->isGroup('NoAllocs') -> returns 1
227             # $dict->isGroup('Symbol') -> returns 0
228             sub isGroup($$) {
229 317     317 0 456 my ( $self, $f ) = @_;
230 317         482 my $ff = $self->getField($f);
231 317 50       1633 return defined $ff ? $ff->{type} eq 'NUMINGROUP' : 0;
232             }
233              
234             sub _getGroupInStructure($$$) {
235 208     208   237 my ($self,$s, $gn) = @_;
236            
237 208         179 my $ret;
238             ##
239             # parse each field in the structure, and ....
240 208         184 for my $e ( @{$s} ) {
  208         302  
241             # we found the group name
242 1073 100 66     2386 return $e->{group} if ($e->{name} eq $gn && defined $e->{group});
243            
244             # stop at each group header
245 1020 100       1913 if (defined $e->{group}) {
246             # and research recursively
247 102         221 $ret = $self->_getGroupInStructure($e->{group},$gn);
248 102 100       214 return $ret if defined $ret;
249             }
250            
251             # if we run into a component we need to check that out too
252 1018 100       2108 if (defined $e->{component}) {
253 53         120 $ret = $self->_getGroupInStructure($self->getComponentFields($e->{name}), $gn);
254 53 100       121 return $ret if defined $ret;
255             }
256             }
257 150         256 undef;
258             }
259              
260             ##
261             # return a ref on group of a message, this then allows us to work on the group elements.
262             # $d->getGroupInMessage('D','NoAllocs')
263             # will return a ref on the NoAllocs group allowing us to then parse it
264             #
265             # Looks recursively into groups of groups if needed.
266             sub getGroupInMessage($$$) {
267 54     54 0 67 my ( $self, $m, $g ) = @_;
268 54         94 my $s = $self->getMessageFields($m);
269 54 100       100 return undef if !defined $s;
270 53         82 my $gn = $self->getFieldName($g);
271 53 50       94 return undef if !defined($gn);
272            
273 53 50       78 return undef if ! $self->isGroup($g);
274              
275 53         115 return $self->_getGroupInStructure( $s, $gn );
276             }
277              
278              
279             ##
280             # returns true if given field is a member of the given group of given message.
281             sub isFieldInGroup($$$$) {
282 56     56 0 92 my ( $self, $m, $g, $f ) = @_;
283              
284 56         90 my $gn = $self->getFieldName($g);
285 56 100       116 return 0 if !defined $gn;
286 55 50       95 return 0 if !$self->isGroup($gn);
287 55         135 my $fn = $self->getFieldName($f);
288 55 100       101 return 0 if !defined $fn;
289              
290 54         94 my $msg = $self->getGroupInMessage( $m, $g );
291 54 100       120 return 0 if !defined $msg;
292 53         117 return $self->_isFieldInStructure($msg, $fn);
293             }
294              
295             1;
296