|
1 # |
|
2 # Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 # All rights reserved. |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of the License "Eclipse Public License v1.0" |
|
6 # which accompanies this distribution, and is available |
|
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 # |
|
9 # Initial Contributors: |
|
10 # Nokia Corporation - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # |
|
16 |
|
17 # This package contains routines to read the information from the Feature List XML file. |
|
18 package featureparser; # Base class implementation of feature list xml parser |
|
19 |
|
20 # Include the genericparser to use API to read from XML file. |
|
21 use genericparser; |
|
22 use strict; |
|
23 |
|
24 # |
|
25 # Class constructor |
|
26 # |
|
27 sub new { |
|
28 my $class = shift; |
|
29 |
|
30 my $object = {}; |
|
31 |
|
32 # Class members |
|
33 $object->{_DEFAULT_RANGE} = []; # Array of default ranges |
|
34 $object->{_DEFAULT_INCLUDE_COUNT} = 0; # Default include range count |
|
35 $object->{_DEFAULT_EXCLUDE_COUNT} = 0; # Default exclude range count |
|
36 |
|
37 $object->{_FILENAME} = undef; # Current xml file parsing |
|
38 $object->{_ROOT_ELEMENT} = undef; # Root element pointer of current xml file |
|
39 |
|
40 bless($object, $class); |
|
41 return $object; |
|
42 } |
|
43 |
|
44 # |
|
45 # Public methods |
|
46 # |
|
47 |
|
48 # Get/Set the _DEFAULT_RANGE member value of this class |
|
49 # @param : array of default ranges (optional for GET) |
|
50 # |
|
51 sub defaultRangeList |
|
52 { |
|
53 my $object = shift; |
|
54 return 0 if(!&ISREF($object,qw(defaultRangeList))); |
|
55 |
|
56 if (@_) |
|
57 { |
|
58 $object->{_DEFAULT_RANGE} = shift; |
|
59 } |
|
60 return $object->{_DEFAULT_RANGE}; |
|
61 } |
|
62 |
|
63 # Get/Set the _DEFAULT_INCLUDE_COUNT member value of this class |
|
64 # @param : default include feature count (optional for GET) |
|
65 # |
|
66 sub defaultIncludeCount |
|
67 { |
|
68 my $object = shift; |
|
69 return 0 if(!&ISREF($object,qw(defaultIncludeCount))); |
|
70 |
|
71 if (@_) |
|
72 { |
|
73 $object->{_DEFAULT_INCLUDE_COUNT} = shift; |
|
74 } |
|
75 return $object->{_DEFAULT_INCLUDE_COUNT}; |
|
76 } |
|
77 |
|
78 # Get/Set the _DEFAULT_EXCLUDE_COUNT member value of this class |
|
79 # @param : default exclude feature count (optional for GET) |
|
80 # |
|
81 sub defaultExcludeCount |
|
82 { |
|
83 my $object = shift; |
|
84 return 0 if(!&ISREF($object,qw(defaultExcludeCount))); |
|
85 |
|
86 if (@_) |
|
87 { |
|
88 $object->{_DEFAULT_EXCLUDE_COUNT} = shift; |
|
89 } |
|
90 return $object->{_DEFAULT_EXCLUDE_COUNT}; |
|
91 } |
|
92 |
|
93 # Get/Set the _FILENAME member value of this class |
|
94 # @param : xml file name (optional for GET) |
|
95 # |
|
96 sub fileName |
|
97 { |
|
98 my $object = shift; |
|
99 return 0 if(!&ISREF($object,qw(fileName))); |
|
100 |
|
101 if (@_) |
|
102 { |
|
103 $object->{_FILENAME} = shift; |
|
104 } |
|
105 return $object->{_FILENAME}; |
|
106 } |
|
107 |
|
108 # Get/Set the _ROOT_ELEMENT member value of this class |
|
109 # @param : root element document pointer (optional for GET) |
|
110 # |
|
111 sub rootElement |
|
112 { |
|
113 my $object = shift; |
|
114 return 0 if(!&ISREF($object,qw(rootElement))); |
|
115 |
|
116 if (@_) |
|
117 { |
|
118 $object->{_ROOT_ELEMENT} = shift; |
|
119 } |
|
120 return $object->{_ROOT_ELEMENT}; |
|
121 } |
|
122 |
|
123 # Parse the feature xml file |
|
124 # @param : xml file name to parse |
|
125 # |
|
126 sub parseXMLFile |
|
127 { |
|
128 my $object = shift; |
|
129 return 0 if(!&ISREF($object,qw(parseXMLFile))); |
|
130 |
|
131 my $file = shift; # Get the featuredatabase XML filename |
|
132 $object->fileName($file); |
|
133 |
|
134 # Check for the existence of xml file |
|
135 if(!(-e $file)) |
|
136 { |
|
137 ERROR($file." doesn\'t exist"); |
|
138 return 0; |
|
139 } |
|
140 |
|
141 #Parse the file and Get root Element |
|
142 my $root = &genericparser::getRootElement($file); |
|
143 $object->rootElement($root); |
|
144 |
|
145 if($root) |
|
146 { |
|
147 #Read the <featureset>/<feature> elements |
|
148 if( !($object->createFeatureMap()) ) |
|
149 { |
|
150 return 0; |
|
151 } |
|
152 #Read the <defaultfeaturerange> elements |
|
153 if( !($object->createDefaultRangeMap()) ) |
|
154 { |
|
155 return 0; |
|
156 } |
|
157 |
|
158 return 1; |
|
159 } |
|
160 |
|
161 return -1; |
|
162 } |
|
163 |
|
164 # Read the <defaultfeaturerange> elements |
|
165 # @param - input range attribute set |
|
166 # |
|
167 sub createDefaultRangeMap |
|
168 { |
|
169 my ($object, @attrSet) = @_; |
|
170 return 0 if(!&ISREF($object,"createDefaultRangeMap")); |
|
171 |
|
172 # Get the reference to the default feature range list from the object |
|
173 my $rangeList = $object->defaultRangeList(); |
|
174 foreach my $currNode (@attrSet) |
|
175 { |
|
176 my ($min, $max); |
|
177 my %attrHashMap = (); |
|
178 |
|
179 # Get the range attributes |
|
180 $object->readRangeAttributes($currNode, \%attrHashMap); |
|
181 |
|
182 #Get the lower and higher uids |
|
183 $min = $attrHashMap{min}; |
|
184 $max = $attrHashMap{max}; |
|
185 |
|
186 #Validate it |
|
187 if((!&IsValidNum($min)) or (!&IsValidNum($max))) { |
|
188 &ERROR("Valid hexadecimal or decimal value expected in default range"); |
|
189 return 0; |
|
190 } |
|
191 |
|
192 #Convert it to decimal |
|
193 $attrHashMap{min} = &ConvertHexToDecimal($min); |
|
194 $attrHashMap{max} = &ConvertHexToDecimal($max); |
|
195 if( $attrHashMap{min} > $attrHashMap{max} ) { |
|
196 &ERROR("Mininum/Lower UID value ".$min." is greater than Maximum/Higher UID value ".$max); |
|
197 return 0; |
|
198 } |
|
199 |
|
200 #Add it to the existing range list |
|
201 my $include = 1; |
|
202 foreach my $node (@$rangeList) { #Check the range already exists |
|
203 if(($node->{min} == $attrHashMap{min}) && ($node->{max} == $attrHashMap{max}) |
|
204 && ($node->{support} eq $attrHashMap{support})) { |
|
205 $include = 0; |
|
206 } |
|
207 } |
|
208 if($include) { # If it is a new range attribute then add it to the list |
|
209 push @$rangeList, \%attrHashMap; |
|
210 $object->defaultIncludeCount($object->defaultIncludeCount()+1) if(lc($attrHashMap{support}) eq "include"); |
|
211 $object->defaultExcludeCount($object->defaultExcludeCount()+1) if(lc($attrHashMap{support}) eq "exclude"); |
|
212 } |
|
213 } |
|
214 |
|
215 return 1; |
|
216 } |
|
217 |
|
218 # Get the default include ranges of min and max values in 2dimensional array |
|
219 # |
|
220 sub getDefaultIncludeInfo() |
|
221 { |
|
222 my $object = shift; |
|
223 return 0 if(!&ISREF($object,qw(getDefaultIncludeInfo))); |
|
224 |
|
225 my @result; |
|
226 my %tempHash=(); |
|
227 |
|
228 my $rangeList = $object->defaultRangeList(); |
|
229 foreach my $range (@$rangeList) |
|
230 { |
|
231 if(lc($range->{"support"}) eq "include" ) |
|
232 { |
|
233 my $min_value=$range->{"min"}; |
|
234 my $max_value=$range->{"max"}; |
|
235 $tempHash{$min_value} = $max_value; |
|
236 } |
|
237 } |
|
238 |
|
239 my $index = 0; |
|
240 my @sortedHash = sort keys %tempHash; |
|
241 |
|
242 foreach my $key (@sortedHash) |
|
243 { |
|
244 push @{$result[$index]},$key; |
|
245 push @{$result[$index]},$tempHash{$key}; |
|
246 $index++; |
|
247 } |
|
248 return @result; |
|
249 } |
|
250 |
|
251 # Get the default exclude ranges of min and max values in 2dimensional array |
|
252 # |
|
253 sub getDefaultExcludeInfo() |
|
254 { |
|
255 my $object = shift; |
|
256 return 0 if(!&ISREF($object,qw(getDefaultExcludeInfo))); |
|
257 |
|
258 my @result; |
|
259 my %tempHash=(); |
|
260 |
|
261 my $rangeList = $object->defaultRangeList(); |
|
262 foreach my $range (@$rangeList) |
|
263 { |
|
264 if(lc($range->{"support"}) eq "exclude" ) |
|
265 { |
|
266 my $min_value=$range->{"min"}; |
|
267 my $max_value=$range->{"max"}; |
|
268 $tempHash{$min_value} = $max_value; |
|
269 } |
|
270 } |
|
271 |
|
272 my $index = 0; |
|
273 my @sortedHash = sort {$a <=> $b}(keys %tempHash); |
|
274 foreach my $key (@sortedHash){ |
|
275 push @{$result[$index]},$key; |
|
276 push @{$result[$index]},$tempHash{$key}; |
|
277 $index++; |
|
278 } |
|
279 return @result; |
|
280 } |
|
281 |
|
282 # Get the count of total number of ranges that are either included or excluded on the device as default |
|
283 # |
|
284 sub getDefaultTotalCount() |
|
285 { |
|
286 my $object = shift; |
|
287 return 0 if(!&ISREF($object,qw(getDefaultTotalCount))); |
|
288 |
|
289 return ($object->defaultIncludeCount() + $object->defaultExcludeCount()); |
|
290 } |
|
291 |
|
292 # For a given uid value, this function checks if the given uid is within the default=present range. |
|
293 # @param : UID to check |
|
294 # |
|
295 sub getRangeEntry |
|
296 { |
|
297 my $object = shift; |
|
298 return 0 if(!&ISREF($object,qw(getRangeEntry))); |
|
299 |
|
300 my $aUid = shift; |
|
301 my $length = $object->getDefaultTotalCount(); |
|
302 my $pos = 0; |
|
303 my $rangeRef; |
|
304 |
|
305 my $rangeList = $object->defaultRangeList(); |
|
306 foreach my $range (@$rangeList) |
|
307 { |
|
308 if ( (lc($range->{"support"}) eq "include") and ($range->{"min"} <= $aUid) and ($range->{"max"} >= $aUid) ) |
|
309 { |
|
310 return $range; |
|
311 } |
|
312 } |
|
313 return undef; |
|
314 } |
|
315 |
|
316 # Get the list of features |
|
317 # |
|
318 sub getFeatures($$) |
|
319 { |
|
320 my ($includeFeatureRef, $excludeFeatureRef) = @_; |
|
321 my %FeatureMap = (); |
|
322 my @FeatList = (); |
|
323 my $featRef; |
|
324 my $uid; |
|
325 |
|
326 foreach my $feat (@$excludeFeatureRef) |
|
327 { |
|
328 $uid = $feat->{uid}; |
|
329 |
|
330 $featRef = $FeatureMap{$uid}; |
|
331 |
|
332 if( $featRef->{include} == 1 ) |
|
333 { |
|
334 &ERROR("The feature $feat->{name} was added into the exclude as well as include list"); |
|
335 return 0; |
|
336 } |
|
337 elsif($featRef->{exclude} == 1) |
|
338 { |
|
339 # Already added to the final feature list |
|
340 next; |
|
341 } |
|
342 else |
|
343 { |
|
344 $FeatureMap{$uid} = $feat; |
|
345 push @FeatList, $feat; |
|
346 } |
|
347 } |
|
348 |
|
349 foreach my $feat (@$includeFeatureRef) |
|
350 { |
|
351 $uid = $feat->{uid}; |
|
352 |
|
353 $featRef = $FeatureMap{$uid}; |
|
354 |
|
355 if( $featRef->{exclude} == 1 ) |
|
356 { |
|
357 &ERROR("The feature $feat->{name} was added into the exclude as well as include list"); |
|
358 return 0; |
|
359 } |
|
360 elsif($featRef->{include} == 1) |
|
361 { |
|
362 # Already added to the final feature list |
|
363 next; |
|
364 } |
|
365 else |
|
366 { |
|
367 $FeatureMap{$uid} = $feat; |
|
368 push @FeatList, $feat; |
|
369 } |
|
370 } |
|
371 |
|
372 return \@FeatList; |
|
373 } |
|
374 |
|
375 # ======================================================================== |
|
376 # Wrappers for generic xml parser |
|
377 # ======================================================================== |
|
378 sub featureparser::getnodefromTree |
|
379 { |
|
380 &genericparser::getNodeFromTree(@_); |
|
381 } |
|
382 |
|
383 sub getattrValue |
|
384 { |
|
385 &genericparser::getAttrValue(@_); |
|
386 } |
|
387 |
|
388 sub getelementValue |
|
389 { |
|
390 &genericparser::getElementValue(@_); |
|
391 } |
|
392 |
|
393 # ======================================================================== |
|
394 # Utility sub routines |
|
395 # ======================================================================== |
|
396 # Check whether the object is reference type |
|
397 # @param : the object reference |
|
398 # |
|
399 sub ISREF |
|
400 { |
|
401 my ($object, $method) = @_; |
|
402 if(!ref($object)) |
|
403 { |
|
404 &ERROR("**Object is not reference-type for the method($method)"); |
|
405 return 0; |
|
406 } |
|
407 return 1; |
|
408 } |
|
409 |
|
410 # Parser debugging routines |
|
411 # |
|
412 sub WARN |
|
413 { |
|
414 print "WARNING: ".$_[0]."\n"; |
|
415 } |
|
416 sub ERROR |
|
417 { |
|
418 print "ERROR: ".$_[0]."\n"; |
|
419 } |
|
420 |
|
421 # Return Decimal value for the given Hexadecimal number. |
|
422 # @param : HexaDecimal Value |
|
423 # |
|
424 sub ConvertHexToDecimal |
|
425 { |
|
426 my $val = shift; |
|
427 if(grep /^0x/i, $val) |
|
428 { |
|
429 # Input is Hexadecimal value, convert to Decimal |
|
430 return hex($val); |
|
431 } |
|
432 else |
|
433 { |
|
434 # Decimal value |
|
435 return $val; |
|
436 } |
|
437 } |
|
438 |
|
439 # Validate if the given value is a valid number |
|
440 # |
|
441 sub IsValidNum |
|
442 { |
|
443 my $num = shift; |
|
444 return 1 if($num =~ /^\d+$|^0[x][\da-f]+/i); |
|
445 return 0; |
|
446 } |
|
447 |
|
448 # Validate if the given UID value is a valid number (either decimal or hexadecimal number) |
|
449 # |
|
450 sub ValidateUIDValue |
|
451 { |
|
452 my $fuid = shift; |
|
453 # check to ensure that uid value contains only valid digits (decimal/hexadecimal) |
|
454 if(IsValidNum $fuid) |
|
455 { |
|
456 return 1; |
|
457 } |
|
458 else |
|
459 { |
|
460 &ERROR("Invalid UID value".$fuid."\n"); |
|
461 return 0; |
|
462 } |
|
463 } |
|
464 |
|
465 1; |