Stderr to a file - avoid xml problems in error messages.
#
# Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
# This component and the accompanying materials are made available
# under the terms of the License "Eclipse Public License v1.0"
# which accompanies this distribution, and is available
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
#
# Initial Contributors:
# Nokia Corporation - initial contribution.
#
# Contributors:
#
# Description:
#
# This package contains routines to read the information from the Feature List XML file.
package featureparser; # Base class implementation of feature list xml parser
# Include the genericparser to use API to read from XML file.
use genericparser;
use strict;
#
# Class constructor
#
sub new {
my $class = shift;
my $object = {};
# Class members
$object->{_DEFAULT_RANGE} = []; # Array of default ranges
$object->{_DEFAULT_INCLUDE_COUNT} = 0; # Default include range count
$object->{_DEFAULT_EXCLUDE_COUNT} = 0; # Default exclude range count
$object->{_FILENAME} = undef; # Current xml file parsing
$object->{_ROOT_ELEMENT} = undef; # Root element pointer of current xml file
bless($object, $class);
return $object;
}
#
# Public methods
#
# Get/Set the _DEFAULT_RANGE member value of this class
# @param : array of default ranges (optional for GET)
#
sub defaultRangeList
{
my $object = shift;
return 0 if(!&ISREF($object,qw(defaultRangeList)));
if (@_)
{
$object->{_DEFAULT_RANGE} = shift;
}
return $object->{_DEFAULT_RANGE};
}
# Get/Set the _DEFAULT_INCLUDE_COUNT member value of this class
# @param : default include feature count (optional for GET)
#
sub defaultIncludeCount
{
my $object = shift;
return 0 if(!&ISREF($object,qw(defaultIncludeCount)));
if (@_)
{
$object->{_DEFAULT_INCLUDE_COUNT} = shift;
}
return $object->{_DEFAULT_INCLUDE_COUNT};
}
# Get/Set the _DEFAULT_EXCLUDE_COUNT member value of this class
# @param : default exclude feature count (optional for GET)
#
sub defaultExcludeCount
{
my $object = shift;
return 0 if(!&ISREF($object,qw(defaultExcludeCount)));
if (@_)
{
$object->{_DEFAULT_EXCLUDE_COUNT} = shift;
}
return $object->{_DEFAULT_EXCLUDE_COUNT};
}
# Get/Set the _FILENAME member value of this class
# @param : xml file name (optional for GET)
#
sub fileName
{
my $object = shift;
return 0 if(!&ISREF($object,qw(fileName)));
if (@_)
{
$object->{_FILENAME} = shift;
}
return $object->{_FILENAME};
}
# Get/Set the _ROOT_ELEMENT member value of this class
# @param : root element document pointer (optional for GET)
#
sub rootElement
{
my $object = shift;
return 0 if(!&ISREF($object,qw(rootElement)));
if (@_)
{
$object->{_ROOT_ELEMENT} = shift;
}
return $object->{_ROOT_ELEMENT};
}
# Parse the feature xml file
# @param : xml file name to parse
#
sub parseXMLFile
{
my $object = shift;
return 0 if(!&ISREF($object,qw(parseXMLFile)));
my $file = shift; # Get the featuredatabase XML filename
$object->fileName($file);
# Check for the existence of xml file
if(!(-e $file))
{
ERROR($file." doesn\'t exist");
return 0;
}
#Parse the file and Get root Element
my $root = &genericparser::getRootElement($file);
$object->rootElement($root);
if($root)
{
#Read the <featureset>/<feature> elements
if( !($object->createFeatureMap()) )
{
return 0;
}
#Read the <defaultfeaturerange> elements
if( !($object->createDefaultRangeMap()) )
{
return 0;
}
return 1;
}
return -1;
}
# Read the <defaultfeaturerange> elements
# @param - input range attribute set
#
sub createDefaultRangeMap
{
my ($object, @attrSet) = @_;
return 0 if(!&ISREF($object,"createDefaultRangeMap"));
# Get the reference to the default feature range list from the object
my $rangeList = $object->defaultRangeList();
foreach my $currNode (@attrSet)
{
my ($min, $max);
my %attrHashMap = ();
# Get the range attributes
$object->readRangeAttributes($currNode, \%attrHashMap);
#Get the lower and higher uids
$min = $attrHashMap{min};
$max = $attrHashMap{max};
#Validate it
if((!&IsValidNum($min)) or (!&IsValidNum($max))) {
&ERROR("Valid hexadecimal or decimal value expected in default range");
return 0;
}
#Convert it to decimal
$attrHashMap{min} = &ConvertHexToDecimal($min);
$attrHashMap{max} = &ConvertHexToDecimal($max);
if( $attrHashMap{min} > $attrHashMap{max} ) {
&ERROR("Mininum/Lower UID value ".$min." is greater than Maximum/Higher UID value ".$max);
return 0;
}
#Add it to the existing range list
my $include = 1;
foreach my $node (@$rangeList) { #Check the range already exists
if(($node->{min} == $attrHashMap{min}) && ($node->{max} == $attrHashMap{max})
&& ($node->{support} eq $attrHashMap{support})) {
$include = 0;
}
}
if($include) { # If it is a new range attribute then add it to the list
push @$rangeList, \%attrHashMap;
$object->defaultIncludeCount($object->defaultIncludeCount()+1) if(lc($attrHashMap{support}) eq "include");
$object->defaultExcludeCount($object->defaultExcludeCount()+1) if(lc($attrHashMap{support}) eq "exclude");
}
}
return 1;
}
# Get the default include ranges of min and max values in 2dimensional array
#
sub getDefaultIncludeInfo()
{
my $object = shift;
return 0 if(!&ISREF($object,qw(getDefaultIncludeInfo)));
my @result;
my %tempHash=();
my $rangeList = $object->defaultRangeList();
foreach my $range (@$rangeList)
{
if(lc($range->{"support"}) eq "include" )
{
my $min_value=$range->{"min"};
my $max_value=$range->{"max"};
$tempHash{$min_value} = $max_value;
}
}
my $index = 0;
my @sortedHash = sort keys %tempHash;
foreach my $key (@sortedHash)
{
push @{$result[$index]},$key;
push @{$result[$index]},$tempHash{$key};
$index++;
}
return @result;
}
# Get the default exclude ranges of min and max values in 2dimensional array
#
sub getDefaultExcludeInfo()
{
my $object = shift;
return 0 if(!&ISREF($object,qw(getDefaultExcludeInfo)));
my @result;
my %tempHash=();
my $rangeList = $object->defaultRangeList();
foreach my $range (@$rangeList)
{
if(lc($range->{"support"}) eq "exclude" )
{
my $min_value=$range->{"min"};
my $max_value=$range->{"max"};
$tempHash{$min_value} = $max_value;
}
}
my $index = 0;
my @sortedHash = sort {$a <=> $b}(keys %tempHash);
foreach my $key (@sortedHash){
push @{$result[$index]},$key;
push @{$result[$index]},$tempHash{$key};
$index++;
}
return @result;
}
# Get the count of total number of ranges that are either included or excluded on the device as default
#
sub getDefaultTotalCount()
{
my $object = shift;
return 0 if(!&ISREF($object,qw(getDefaultTotalCount)));
return ($object->defaultIncludeCount() + $object->defaultExcludeCount());
}
# For a given uid value, this function checks if the given uid is within the default=present range.
# @param : UID to check
#
sub getRangeEntry
{
my $object = shift;
return 0 if(!&ISREF($object,qw(getRangeEntry)));
my $aUid = shift;
my $length = $object->getDefaultTotalCount();
my $pos = 0;
my $rangeRef;
my $rangeList = $object->defaultRangeList();
foreach my $range (@$rangeList)
{
if ( (lc($range->{"support"}) eq "include") and ($range->{"min"} <= $aUid) and ($range->{"max"} >= $aUid) )
{
return $range;
}
}
return undef;
}
# Get the list of features
#
sub getFeatures($$)
{
my ($includeFeatureRef, $excludeFeatureRef) = @_;
my %FeatureMap = ();
my @FeatList = ();
my $featRef;
my $uid;
foreach my $feat (@$excludeFeatureRef)
{
$uid = $feat->{uid};
$featRef = $FeatureMap{$uid};
if( $featRef->{include} == 1 )
{
&ERROR("The feature $feat->{name} was added into the exclude as well as include list");
return 0;
}
elsif($featRef->{exclude} == 1)
{
# Already added to the final feature list
next;
}
else
{
$FeatureMap{$uid} = $feat;
push @FeatList, $feat;
}
}
foreach my $feat (@$includeFeatureRef)
{
$uid = $feat->{uid};
$featRef = $FeatureMap{$uid};
if( $featRef->{exclude} == 1 )
{
&ERROR("The feature $feat->{name} was added into the exclude as well as include list");
return 0;
}
elsif($featRef->{include} == 1)
{
# Already added to the final feature list
next;
}
else
{
$FeatureMap{$uid} = $feat;
push @FeatList, $feat;
}
}
return \@FeatList;
}
# ========================================================================
# Wrappers for generic xml parser
# ========================================================================
sub featureparser::getnodefromTree
{
&genericparser::getNodeFromTree(@_);
}
sub getattrValue
{
&genericparser::getAttrValue(@_);
}
sub getelementValue
{
&genericparser::getElementValue(@_);
}
# ========================================================================
# Utility sub routines
# ========================================================================
# Check whether the object is reference type
# @param : the object reference
#
sub ISREF
{
my ($object, $method) = @_;
if(!ref($object))
{
&ERROR("**Object is not reference-type for the method($method)");
return 0;
}
return 1;
}
# Parser debugging routines
#
sub WARN
{
print "WARNING: ".$_[0]."\n";
}
sub ERROR
{
print "ERROR: ".$_[0]."\n";
}
# Return Decimal value for the given Hexadecimal number.
# @param : HexaDecimal Value
#
sub ConvertHexToDecimal
{
my $val = shift;
if(grep /^0x/i, $val)
{
# Input is Hexadecimal value, convert to Decimal
return hex($val);
}
else
{
# Decimal value
return $val;
}
}
# Validate if the given value is a valid number
#
sub IsValidNum
{
my $num = shift;
return 1 if($num =~ /^\d+$|^0[x][\da-f]+/i);
return 0;
}
# Validate if the given UID value is a valid number (either decimal or hexadecimal number)
#
sub ValidateUIDValue
{
my $fuid = shift;
# check to ensure that uid value contains only valid digits (decimal/hexadecimal)
if(IsValidNum $fuid)
{
return 1;
}
else
{
&ERROR("Invalid UID value".$fuid."\n");
return 0;
}
}
1;