1#!/usr/bin/env perl
2
3#This script replaces MRW attribute names with their values from the
4#MRW XML in any file.  In addition, it can evaluate mathematical
5#expressions if they are in [[ ]]s and can use variables passed in from
6#the command line in those expressions.
7#
8#For example, if the attribute FOO has a value of 50 in the MRW, and
9#the program was started with: -v "MY_VAR1=200 MY_VAR2=400"
10#
11#then the line
12#  [[(MRW_FOO * MY_VAR1) + 5]]..[[MRW_FOO * MY_VAR2]]
13#
14#would get written out as:
15#  10005..20000
16#
17
18use strict;
19use warnings;
20
21use mrw::Targets; # Set of APIs allowing access to parsed ServerWiz2 XML output
22use Getopt::Long; # For parsing command line arguments
23
24# Globals
25my $force          = 0;
26my $serverwizFile  = "";
27my $debug          = 0;
28my $outputFile     = "";
29my $settingsFile   = "";
30my $expressionVars = "";
31my %exprVars;
32
33# Command line argument parsing
34GetOptions(
35"f"   => \$force,            # numeric
36"i=s" => \$serverwizFile,    # string
37"o=s" => \$outputFile,       # string
38"s=s" => \$settingsFile,     # string
39"v=s" => \$expressionVars,   # string
40"d"   => \$debug,
41)
42or printUsage();
43
44if (($serverwizFile eq "") or ($outputFile eq "") or ($settingsFile eq "") )
45{
46    printUsage();
47}
48
49# API used to access parsed XML data
50my $targetObj = Targets->new;
51if($debug == 1)
52{
53    $targetObj->{debug} = 1;
54}
55
56if($force == 1)
57{
58    $targetObj->{force} = 1;
59}
60
61$targetObj->loadXML($serverwizFile);
62print "Loaded MRW XML: $serverwizFile \n";
63
64open(my $inFh, '<', $settingsFile) or die "Could not open file '$settingsFile' $!";
65open(my $outFh, '>', $outputFile) or die "Could not open file '$outputFile' $!";
66
67if (length($expressionVars) > 0)
68{
69    loadVars($expressionVars);
70}
71
72# Process all the targets in the XML
73foreach my $target (sort keys %{$targetObj->getAllTargets()})
74{
75    # A future improvement could be to specify the MRW target.
76    next if ("SYS" ne $targetObj->getType($target, "TYPE"));
77    # Read the settings YAML replacing any MRW_<variable name> with their
78    # MRW value
79    while (my $row = <$inFh>)
80    {
81        while ($row =~ /MRW_(.*?)\W/g)
82        {
83            my $setting = $1;
84            my $settingValue = $targetObj->getAttribute($target, $setting);
85            $row =~ s/MRW_${setting}/$settingValue/g;
86        }
87
88        #If there are [[ ]] expressions, evaluate them and replace the
89        #[[expression]] with the value
90        while ($row =~ /\[\[(.*?)\]\]/)
91        {
92            my $expr = $1;
93            my $value = evaluate($expr);
94
95            #Break the row apart, remove the [[ ]]s, and put the
96            #value in the middle when putting back together.
97            my $exprStart = index($row, $expr);
98            my $front = substr($row, 0, $exprStart - 2);
99            my $back = substr($row, $exprStart + length($expr) + 2);
100
101            $row = $front . $value . $back;
102        }
103
104        print $outFh $row;
105    }
106    last;
107    close $inFh;
108    close $outFh;
109}
110
111#Evaluate the expression passed in.  Substitute any variables with
112#their values passed in on the command line.
113sub evaluate
114{
115    my $expr = shift;
116
117    #Put in the value for the variable.
118    for my $var (keys %exprVars)
119    {
120        $expr =~ s/$var/$exprVars{$var}/;
121    }
122
123    my $value = eval($expr);
124    if (not defined $value)
125    {
126        die "Invalid expression found: $expr\n";
127    }
128
129    #round it to an integer
130    $value = sprintf("%.0f", $value);
131    return $value;
132}
133
134#Parse the variable=value string passed in from the
135#command line and load it into %exprVars.
136sub loadVars
137{
138    my $varString = shift;
139
140    #Example: "VAR1=VALUE1 VAR2=VALUE2"
141    my @entries = split(' ', $varString);
142
143    for my $entry (@entries)
144    {
145        my ($var, $value) = $entry =~ /(.+)=(.+)/;
146
147        if ((not defined $var) || (not defined $value))
148        {
149            die "Could not parse expression variable string $varString\n";
150        }
151
152        $exprVars{$var} = $value;
153    }
154}
155
156# Usage
157sub printUsage
158{
159    print "
160    $0 -i [XML filename] -s [Settings YAML] -o [Output filename] -v [expr vars] [OPTIONS]
161
162Required:
163    -i = MRW XML filename
164    -s = The Setting YAML with MRW variables in MRW_<MRW variable name> format
165    -o = YAML output filename
166Optional:
167    -v = Variables and values for any [[expression]] evaluation
168         in the form: \"VAR1=VALUE1 VAR2=VALUE2\"
169Options:
170    -f = force output file creation even when errors
171    -d = debug mode
172    \n";
173    exit(1);
174}
175