|
1 # Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
2 # All rights reserved. |
|
3 # This component and the accompanying materials are made available |
|
4 # under the terms of "Eclipse Public License v1.0" |
|
5 # which accompanies this distribution, and is available |
|
6 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 # |
|
8 # Initial Contributors: |
|
9 # Nokia Corporation - initial contribution. |
|
10 # |
|
11 # Contributors: |
|
12 # |
|
13 # Description: |
|
14 # Package: SysModelGen |
|
15 # Build an SVG System Model diagram |
|
16 # |
|
17 # |
|
18 |
|
19 package SysModelGen; |
|
20 |
|
21 use Cwd; |
|
22 use Cwd 'abs_path'; |
|
23 use File::Copy; |
|
24 use File::Path; |
|
25 use FindBin; |
|
26 use lib $FindBin::Bin."/../common"; |
|
27 use Getopt::Long qw(:config no_ignore_case); |
|
28 use File::Basename; |
|
29 use File::Spec; |
|
30 use Logger; |
|
31 use Env qw(@PATH); |
|
32 use Env qw(@PATHEXT); |
|
33 use Env qw(@CLASSPATH); |
|
34 use strict; |
|
35 |
|
36 my @Filters; |
|
37 |
|
38 |
|
39 use constant KSystemModelGenerator => 201; |
|
40 |
|
41 #------------------------------------------------------------------------------------------------- |
|
42 # Subroutine: new |
|
43 # Purpose: |
|
44 # Input: None (extracted from command line args) |
|
45 # Output: A reference to itself |
|
46 #------------------------------------------------------------------------------------------------- |
|
47 sub new |
|
48 { |
|
49 my $package = shift; |
|
50 my $self = {}; # Create reference to object |
|
51 bless $self, $package; # Associate a reference with class name |
|
52 |
|
53 my $dataroot =&SystemModelXmlDataDir(); |
|
54 my @yr = gmtime(); |
|
55 my %Args = ( |
|
56 'iHelp' => {'param' => "h", |
|
57 'desc' => 'Help on usage'}, |
|
58 'iIniFile' => { 'param' => "i=s", 'type'=>'file', |
|
59 'desc' => 'An INI file listing one argument per line, with the syntax: <argument> = <value>. Command line arguments will override ini file settings.' }, |
|
60 'iDiagram' => { 'param' => "output=s" , default=>"sysmodel.svg",'type'=>'outfile', |
|
61 'class' => 'Build Control', 'desc' => 'The name of the file to save the built System Model SVG. If in the format filename.svgz, it will attempt to compress the file. If compression is not supported, it will rename the output to filename.svg. Defaults to sysmodel.svg or sysmodel.svgz if -compress is set.'}, |
|
62 'iOutputCsv' => { 'param' => "csv_output=s" , 'type'=>'outfile', |
|
63 'class' => 'Build Control', 'desc' => 'The name of the file to save a CSV description of the built System Model. Only items shown on the system model will be included.'}, |
|
64 'iCsvColumns' => { 'param' => "csv_columns=s" , 'type'=>'outfile', |
|
65 'class' => 'Build Control', 'desc' => 'Comma-separated list of columns to include in the output CSV. This does nothing if -csv_output is not present. By default (if -csv_columns is not present), the columns will be a sorted list of all attributes on all items. '}, |
|
66 'iCsvLabels' => { 'param' => "csv_labels=s" , 'type'=>'outfile', |
|
67 'class' => 'Build Control', 'desc' => 'Comma-separated list of columns labels include in the output CSV. Do not use quotes or commas in label names. This does nothing if -csv_output is not present. If this list is shorter than -csv_columns, the remaining columns will use the attribute name as the label. '}, |
|
68 'iOutputXml' => { 'param' => 'xml_output=s' ,'type'=>'outfile', |
|
69 'class' => 'Build Control', 'desc' => 'The name of the file to save a combined system definition XML. Only items shown in the built system model will be included.'}, |
|
70 'iWarningLevel' => { 'param' => "w=s", 'type' => 'number', |
|
71 'class' =>'Build Control', 'desc' => 'Warning level. 1: errors only (default), 2: warnings as well as errors, 3: info messages, warnings and errors, 4: all plus deep syntax validation and reporting -- note that this can take a long time to compute so do not use this warning level by default'}, |
|
72 'iLowMem' => { 'param' => "lowmem", |
|
73 'class' =>'Build Control', 'desc' => 'Build the model storing more data in the temp directory and using less runtime memory. If building fails due to an out of memory condition, try running again with the -lowmem option.'}, |
|
74 "iClean" => { 'param' => 'clean' , |
|
75 'class' => 'Build Control', 'desc' =>'Caution: if set, it will delete the contents of the temporary directory.'}, |
|
76 'iCompress' => { 'param' => "compress", |
|
77 'class' => 'Build Control', 'desc' => 'If set, it will attempt to compress the output as an SVGZ file. In order to success gzip must be installed and in the PATH. This will also rename the output file from filename.svg to filename.svgz.'}, |
|
78 'iTemporaryDirectory' => { 'param' => "tempdir=s", 'default' => 'drawsvg_temp','type'=>'dir', |
|
79 'class' => 'Build Control', 'desc' => 'Temporary directory for build files.'}, |
|
80 'iLogFile' => { 'param' => "log=s", 'type'=>'outfile', |
|
81 'class' => 'Build Control', 'desc' => 'File in which to store output. Defaults to stdout'}, |
|
82 'iModel' => { 'param' => "model=s" ,'type'=>'file/uri', 'default' => "$dataroot/ModelTemplate.xml", |
|
83 'class' => 'Files or URIs', 'desc' => 'The location of the Model XML file to use to build the file. Content of this file will be overridden by anything set on the command line on in an ini file'}, |
|
84 'iSysDefFile' => { 'param' => "sysdef=s", 'multi' => 1,'type'=>'file/uri', 'xpath' => '/model/sysdef', |
|
85 'class' => 'Model Control', 'desc' => 'The System Definition XML file(s) used to build the model.'}, |
|
86 "iSourceRoot" => {'param'=>'srcvar=s' ,'multi' => 1, |
|
87 'class' => 'Model Control'}, |
|
88 'iPathPrefix' => {'param' => 'sysdef-prefix=s', 'multi' => 1, 'class' => 'Model Control','type'=>'file/uri',}, |
|
89 "iSysDefPath" => {'param' => "sysdef-path=s", 'multi' => 1,'type'=>'path', |
|
90 'class' => 'Model Control', 'desc' => 'The directory which the system definition file should be considered to be in when turning unit\'s relative links into absolute paths. This is only necessary to provide if the result requires the absolute paths to be meaningful. The order of this parameter must match the order of the -sysdef parameter'}, |
|
91 'iShapes' => { 'param' => "shapes=s", 'xpath' => '/model/@shapes','type'=>'file/uri', |
|
92 'class' => 'Files or URIs', 'desc' => 'The location of the Shapes XML file used to provide rules to control the display of the system model items. If not present, default behaviour (in Shapes.xml) is used. This and the default bahaviours are overrriden by using the -color, -border, -pattern, and -style options. '}, |
|
93 'iLink' => { 'param' => "link=s", 'xpath' => '/model/@link', |
|
94 'class' => 'Files or URIs', 'desc' => 'The base URL to use for all hyperlinks in the model. A base URL will be appended by the type and name (e.g. Blocks/Comms%20Services.html) of the items to create the full URL of the linked file. Window directories will be converted into file URIs.'}, |
|
95 'iLinkExpr' => { 'param' => "link-expr=s", 'multi' => 1, 'xpath' => 'model/link', |
|
96 'class' => 'Model Control', 'desc' => 'The link used on any system model item. Any values within {...} are evaluled as an expression on the item. All xpath locations in the expresion must be set otherwise the link will not be created for the item'}, |
|
97 'iName' => { 'param' => "system_name=s" , 'xpath' => '/model/@name', |
|
98 'class' => "Labels", 'desc' =>'The name of the product described in the model. It appears at the bottom right.'}, |
|
99 'iRelease' => { 'param' => "system_version=s" , 'xpath' => '/model/@ver', |
|
100 'class' =>"Labels", 'desc' =>'The version of the product described in the model. It appears at the bottom right after the name.'}, |
|
101 'iLabel' => { 'param' => "model_name=s" , 'xpath' => '/model/@label', |
|
102 'class' =>"Labels", 'desc' =>'The label for the model. It appears at the bottom right, under the name.'}, |
|
103 'iRevision' => { 'param' => "model_version=s", 'xpath' => '/model/@revision', |
|
104 'class' =>"Labels", 'desc' =>'A number which appears before the model-revision-type. If specified this overrides the build number used by depmodel. If not building depmodel, this defaults to "1"'}, |
|
105 'iRevisionType' => { 'param' => "model_version_type=s", 'xpath' => '/model/@revision-type', |
|
106 'class' =>"Labels", 'desc' =>'One of "draft", "issued", "build", "date" or free-text value. Appears below the model label. If specified this overrides the build number used by DepToolkit.If not building depmodel, this defaults to "draft"'}, |
|
107 'iCopyright' => { 'param' => "copyright=s", 'default' => (1900+$yr[5])." Nokia Corporation", 'xpath' => '/model/@copyright', |
|
108 'class' =>"Labels", 'desc' =>'The copyright to appear in the lower left. Set to empty string to leave out.'}, |
|
109 'iDistribution' => { 'param' => "distribution=s", 'xpath' => '/model/@distribution', |
|
110 'class' => "Labels", 'desc' =>'Text to appear on the bottom centre to indicate to whom the model can be shown. Informational only. Suggested values are "internal", "secret" or "unrestrictred". Not shown if not set.'}, |
|
111 'iLgdTitle' => { 'param' => "legend_title=s", 'xpath' => '/model/layout/legend/@label', |
|
112 'class' =>"Labels", 'desc' =>'The title to appear in the leftmost part of the legend.'}, |
|
113 'iLgdFloat' => { 'param' => "legend_float=s", 'xpath' => '/model/layout/legend/@float', 'type' => 'boolean', |
|
114 'class' =>"Model Control", 'desc' =>'If set, the legend will appear when the mouse hovers over the bottom of the window. The floating legend will span the full width of the window. This may not be readable, depending on the amonent of content in the legend.'}, |
|
115 'iCoreOs' => { 'param' => "coreos=s", 'type' => 'on/off/new', |
|
116 'class' =>'Model Control', 'desc' => 'Turn on or off Core OS colouring for 9.4 and later models -- For backwards compatibility only! Use "on" for Symbian OS 9.4 models and "new" for Symbian OS 9.5 and later models (non-Foundation)'}, |
|
117 |
|
118 'iExtra' => { 'multi' => 1, 'param' => "sysinfo=s",'type'=>'file/uri', info=>'extra', 'xpath' => '/model/sysdef', |
|
119 'class' => 'Files or URIs', 'desc' => 'The location of extra component information used to provided additional properies for components. By default, the provided "SystemInfo.xml" is used.'}, |
|
120 'iLocalize' => { 'multi' => 1, 'param' => "localize=s", 'xpath' => '/model/layout','type'=>'file/uri', info=>'abbrev', |
|
121 'class' => 'Files or URIs', 'desc' => 'The location of the Localization file used to provide displayable names for the model entities.'}, |
|
122 'iDict' => { 'param' => "dictionary=s", 'type'=>'file/uri', |
|
123 'class' => 'Build Control', 'desc' => 'A term dictionary file used to semi-intelligently generate the abbreviations for the names of system model entries. Anything mentioned in the Localization files overrides generated abbreviations.'}, |
|
124 'iS12' => { 'multi' => 1, 'param' => "s12=s",'type'=>'file/uri' , info=>'s12', 'xpath' => '/model/sysdef', |
|
125 'depr' => "Only works on 2.0 syntax and older models", |
|
126 'class' => 'Files or URIs', 'desc' => 'The location of the Schedule 12 XML file used to provide the border shapres of the components. If this a directory, the S12 XML file is found by appending "Symbian_OS_v[system_version]_Schedule12.xml" to the directory.'}, |
|
127 'iLevels' => { 'multi' => 1, 'param' => "levels=s",'type'=>'file/uri' , info=>'levels', 'xpath' => '/model/sysdef', |
|
128 'depr' => "Only works on 2.0 syntax and older models. Use info file instead", |
|
129 'class' =>'Files or URIs', 'desc' => 'The location of the Levels XML file used to override the stacking of collections. '}, |
|
130 'iDepsFile' => { 'multi' => 1, 'param' => "deps=s", 'xpath' => '/model/sysdef','type'=>'file/uri', info=>'extra', |
|
131 'class' => 'Files or URIs', 'desc' => 'The location of a sysinfo file containing Dependencies. If not present, dependencies will not be drawn'}, |
|
132 |
|
133 'iColor' => { 'multi' => 1, 'param' => "color=s", 'xpath' => '/model/layout','type'=>'file/uri', 'info'=>'color', |
|
134 'class' =>'Files or URIs', 'desc' => 'The location of a Values XML file used to specify per-component colours. If not present, the default colours are used.'}, |
|
135 'iBorder' => { 'multi' => 1, 'param' => "border-shape=s", 'xpath' => '/model/layout','type'=>'file/uri','info'=>'border', |
|
136 'class' =>'Files or URIs', 'desc' => 'The location of a Values XML file used to specify the shape (border) of each component. If not present, the default borders are used.'}, |
|
137 'iOverlay' => { 'multi' => 1, 'param' => "pattern=s", 'xpath' => '/model/layout','type'=>'file/uri','info'=>'overlay', |
|
138 'class' => 'Files or URIs', 'desc' => 'The location of a Values XML file used to specify per-component overlay patterns. If not present, the default patterns (for new and reference components) are used.'}, |
|
139 'iStyle' => { 'multi' => 1, 'param' => "border-style=s", 'xpath' => '/model/layout','type'=>'file/uri','info'=>'style', |
|
140 'class' => 'Files or URIs', 'desc' => 'The location of a Values XML file used to specify per-component border styles. If not present, the default border styles are used. '}, |
|
141 |
|
142 'iFilter' =>{ 'type' => 'filter-name', 'multi' => 1, 'param' => "filter=s", |
|
143 'depr' => "Only works on 2.0 syntax and older models", |
|
144 'class' =>'Model Control', 'desc' => 'The name of a filter to turn on when building the model. All filters on an item must be present in this list in order for that item to appear. Can have any number of these Defaults to "java" and "gt"'}, |
|
145 'iFilterHas' =>{ 'type' => 'filter-name', 'ordered' => 1,'param' => "filter-has=s", |
|
146 'class' => 'Model Control', 'desc' =>'Like -filter, except any filter on an item must be present in this list in order for that item to appear. Include "*" in the list in order to show items with no filters. Equivalent to "-show-attr filter xxx"'}, |
|
147 'iShow' => { 'type' => 'attr[=val]', 'ordered' => 1,'param' => "show-attr=s", |
|
148 'class' =>'Model Control', 'desc' => 'A mechanism of filtering which allows filtering based on component attribute values. If a value is set for that attribute, the component will be shown. Use in conjunction with -hide-attr for fine contol of what is shown. "class" and "filter" attribtues are handled specially -- see the documentation for details'}, |
|
149 'iHide' => { 'type' => 'attr[=val]', 'ordered' => 1,'param' => "hide-attr=s", |
|
150 'class' =>'Model Control', 'desc' => 'A mechanism of filtering which allows filtering based on component attribute values. If a value is set for that attribute, the component will not be shown on the model. Use in conjunction with -show-attr for fine contol of what is shown. "class" and "filter" attribtues are handled specially -- see the documentation for details'}, |
|
151 'iIgnore' => { 'type' => 'item', 'multi' => 1, 'param' => "ignore=s", 'xpath' => '/model/ignore', |
|
152 'class' =>'Model Control', 'desc' => 'The ID of a model entity to not draw. Any number of these can be used'}, |
|
153 'iIgnoreMeta' => { 'type' => 'item', 'multi' => 1, 'param' => "ignore-meta=s", 'xpath' => '/model/ignore', |
|
154 'class' =>'Model Control', 'desc' => 'The "rel" meta value to ignore. Takes the form of [relvalue] or [relvalue]:[type]. Any number of these can be used'}, |
|
155 |
|
156 'iNavCtrl' =>{'param' => "navctrl=s" , 'type'=>'boolean' , 'xpath' => '/model/layout/@navctrl', |
|
157 'class' =>'Model Control', 'desc' => 'If set, a navigation control widget will appear in the upper left corner of the model. The control might not work on some SVG viewers.'}, |
|
158 'iDetail' =>{'param' => "detail=s", 'type' => 'item-type' , 'xpath' => '/model/layout/@detail', |
|
159 'class' =>'Model Control', 'desc' => 'The type of the smallest System Model entity to draw. One of "layer", "package", "collection" or "component". Defaults to "component"'}, |
|
160 'iLevelDetail' =>{'param' => "level-detail=s", 'type' => 'show/hide' , 'xpath' => '/model/layout/@levels', |
|
161 'class' =>'Model Control', 'desc' => 'Toggles display of level names on packages or layers. A value of "show" will display level names inside either layers (at "layer" level of detail only) or packages (at "package" level of detail only). A value of "hide" (default) will not show any level names.'}, |
|
162 'iDetailType' => { 'param' => "detail-type=s", 'type' => 'type' , 'xpath' => '/model/layout/@detail-type', |
|
163 'class' =>'Model Control', 'desc' => 'If set to "fixed", the smallest System Model entity drawn will have a fixed with (rather then sized by their invisible components). This can be used to reduce the size and complexity of the overall model.'}, |
|
164 'iPlaceholderDetail' => { 'param' => "placeholder=s", 'type' => 'item-type' , 'xpath' => '/model/layout/@placeholder-detail', |
|
165 'class' =>'Model Control', 'desc' => 'The type of the smallest *empty* System Model entity to draw. One of "layer", "package", "collection" or "component". For example, if set to "package" empty layers and packages will be drawn, but empty collections will be ignored. If not set, no empty items will be drawn.'}, |
|
166 'iPageWidth' =>{'param' => "page-width=s", 'type' => 'length', 'xpath' => '/model/layout/@page-width', |
|
167 'depr' => "Only works on 2.0 syntax and older models", |
|
168 'class' =>'Model Control', 'desc' => 'The width of the drawn image (with units). If not specified it will fit the viewer window. Valid units: "in", "mm", "cm", "px", "pt"'}, |
|
169 'iStatic' => { 'param' => "static=s", 'type' => 'boolean', 'xpath' => '/model/layout/@static', |
|
170 'class' =>'Model Control', 'desc' => 'If present, the model will not have any mouseover effects (this is overriden by builing the depmodel).'}, |
|
171 'iPrintResolution' =>{ 'param' => "dpi=s", 'type' => 'number', 'xpath' => '/model/layout/@resolution', |
|
172 'class' =>'Model Control', 'desc' => 'The DPI to use when printing from the Adobe SVG Viewer. If not present, it will print well at A4 size. A value of 300 will look good on A3 size paper'}, |
|
173 'iModelFont' =>{'param' => "model_font=s", 'type' =>'font', 'xpath' => '/model/layout/@font', |
|
174 'class' =>'Model Control', 'desc' => 'The name of the base font to use to draw the model. This will be overriden by any custom CSS in the Shapes XML'}, |
|
175 'iVersions' => { 'param' => "version-list=s", |
|
176 'class' =>'Model Control'}, |
|
177 'iLogoSrc' =>{ 'param' => "logo=s", 'type'=>'file/uri', 'xpath' => '/model/layout/logo/@src', |
|
178 'class' => 'Model Control', 'desc' => 'If present, the logo will be drawn in the lower-left corner of the model. If the logo is an SVG file, -logo-width and -logo-height are optional, otherwise the must both be specified'}, |
|
179 'iLogoEmbed' =>{ 'xpath' => '/model/layout/logo/@embed', 'class' => 'Model Control' }, |
|
180 'iLogoHeight' => { 'param' => "logo-height=s", 'type' => 'length', 'xpath' => '/model/layout/logo/@height', |
|
181 'class' =>'Model Control', 'desc' => 'Specifies the height of the logo (if any) in mm. Width is scaled along with height unless otherwise specified. Both width and height MUST be specified if a bitmap image is used'}, |
|
182 'iLogoWidth' => { 'param' => "logo-width=s", 'type' => 'length', 'xpath' => '/model/layout/logo/@width', |
|
183 'class' =>'Model Control', 'desc' => 'Specifies the width of the logo (if any) in mm. Height is scaled along with width unless otherwise specified. Both width and height MUST be specified if a bitmap image is used'}, |
|
184 'iLegendWidth' =>{ 'param' => "legend-width=s", 'type' => '%', 'xpath' => '/model/layout/legend/@width', |
|
185 'class' => 'Model Control', 'desc' =>'The percent width of the model the legend takes up. This will scale the size of the legend and model title, but not the logo, to fill the specified space. If a logo is included, but no width specified, the legend cannot be scaled since it will not be able to determine the available space. Note that that -max-legend-scale will further limit the potential width.'}, |
|
186 'iLegendMaxScale' =>{ 'param' => "legend-max-scale=s", 'type' => 'scale', 'xpath' => '/model/layout/legend/@maxscale', |
|
187 'class' => 'Model Control', 'desc' =>'Specifies the maximum scale factor for resizing the legend. If this is present and -legend-width is not, the legend and title will scale to 100% of the available width. If both are present the scale factor will take precedent. If neither is present, the legend will not resize. Note that when this is used, the legend can shrink if it would normally be wider than the model.'}, |
|
188 'iTitleScale' => { 'param' => "title-scale=s", 'type' => 'scale', 'xpath' => '/model/layout/legend/@title-scale', |
|
189 'class' => 'Model Control', 'desc' =>'Specifies the scale factor for the size of the title font (the text in the lower right). Use this instead of CSS to control the size, since the model generator needs to explicitly know how much space to allocate for the title.'}, |
|
190 'iXsltParam' =>{ 'multi' => 2, 'param' => "xslt-param=s", |
|
191 'class' =>'Build Control', 'desc' => 'Advanced: Parameters to feed directly to the XSLT transforms'}, |
|
192 'iLegendNote' =>{ 'multi' => 1, 'param' => "note=s", 'xpath' => '/model/layout/legend/note', |
|
193 'class' => 'Labels', 'desc' => 'Free text to appear inside the legend box, on the rightmost side. If multiple ones are provided, they will appear as separate boxes from left to right. Newlines and other special characters can be entity-encoded (e.g. 
). When using entities in an INI file, you *must* quote the value, otherwise the # will be treated as a comment delimiter.',} |
|
194 ); |
|
195 |
|
196 $self->{iArgs} = \%Args; |
|
197 |
|
198 |
|
199 # basic test of command line: |
|
200 if (scalar(@ARGV) == 0) |
|
201 { |
|
202 $self->Help(); |
|
203 exit Logger::KErrorNone; # nothing to do. Leave |
|
204 } |
|
205 |
|
206 # process the input: |
|
207 $self->ParseCommandLineOptions(); |
|
208 |
|
209 $self->{iReturnCode} = Logger::KErrorNone; |
|
210 return $self; |
|
211 } |
|
212 |
|
213 |
|
214 sub ParseCommandLineOptions() |
|
215 { |
|
216 my $self = shift; |
|
217 |
|
218 my %opt; |
|
219 while(my ($n,$b) = each %{$self->{iArgs}} ) |
|
220 { |
|
221 if(!$b->{'param'}) {next} # not a command line arg |
|
222 my @ps = ($b->{'param'}); |
|
223 ($ps[1]=$ps[0]) =~ tr/_-/-_/; |
|
224 if($ps[1] eq $ps[0]) {shift(@ps)} |
|
225 foreach my $p (@ps) |
|
226 { |
|
227 if($b->{'multi'}==1) |
|
228 { |
|
229 $opt{$p} = \@{$self->{$n}}; |
|
230 } |
|
231 elsif($b->{'multi'}==2) |
|
232 { |
|
233 $opt{$p} = \%{$self->{$n}}; |
|
234 } |
|
235 elsif($b->{'ordered'}) |
|
236 { |
|
237 $opt{$p} = \&OrderedOption; |
|
238 } |
|
239 else |
|
240 { |
|
241 $opt{$p} = \$self->{$n}; |
|
242 } |
|
243 } |
|
244 } |
|
245 |
|
246 foreach (@ARGV) { |
|
247 # some MS products replace "-" with en-dash in an effort to be "intelligent". |
|
248 # This replaces all leading en-dashes in the command line with "-" |
|
249 # There is a small risk that the en-dash is intentional and this will clobber it. |
|
250 s/^\x96/-/; |
|
251 } |
|
252 |
|
253 GetOptions(%opt); |
|
254 |
|
255 if ($self->{'iHelp'}) |
|
256 { |
|
257 $self->Help(); |
|
258 exit Logger::KErrorNone; |
|
259 } |
|
260 |
|
261 # set read files to absolute paths |
|
262 my $dir = cwd; |
|
263 |
|
264 while(my ($n,$b) = each %{$self->{iArgs}} ) |
|
265 { |
|
266 my $type =$b->{'type'}; |
|
267 if( $type eq 'file' or $type eq 'dir' or $type eq 'file/uri') |
|
268 { |
|
269 if($self->{$n} eq '') {next} # no value, so do nothing |
|
270 if ($b->{'multi'} == 1) |
|
271 { |
|
272 foreach my $v (@{$self->{$n}}) |
|
273 { |
|
274 $v =&fixFile($type,$dir,$v); |
|
275 } |
|
276 } |
|
277 elsif ($b->{'multi'} == 2) |
|
278 { |
|
279 while(my ($var,$val)=each (%{$self->{$n}})) |
|
280 { |
|
281 $self->{$n}->{$var}=&fixFile($type,$dir,$val); |
|
282 } |
|
283 } |
|
284 else |
|
285 { |
|
286 $self->{$n} = &fixFile($type,$dir,$self->{$n} ); |
|
287 } |
|
288 } |
|
289 } |
|
290 |
|
291 |
|
292 @{$self->{'iFiltering'}} = @Filters; |
|
293 @Filters=(); |
|
294 my $i=0; |
|
295 for($i=0;$i<=$#ARGV;$i++) |
|
296 { # check remaining args to ensure they are valid |
|
297 if($ARGV[$i]=~/^(http|file):\/\//) { # assume URLs are correct |
|
298 next; |
|
299 } |
|
300 if($ARGV[$i] eq "-" || $ARGV[$i] eq "") |
|
301 { #special values to use nothing or use the tmp file, but only valid for odd numbered args |
|
302 if($i%2==1) {next} |
|
303 $self->HelpBase(); |
|
304 &Logger::LogFatal("Invalid syntax", KSystemModelGenerator, 0,Logger::KIncorrectSyntax); |
|
305 } |
|
306 if(!(-e $ARGV[$i])) { |
|
307 $self->HelpBase(); |
|
308 &Logger::LogFatal("file $ARGV[$i] does not exist", KSystemModelGenerator, 0,Logger::KFileDoesNotExist); |
|
309 } |
|
310 } |
|
311 $self->ReadIniFile(); |
|
312 |
|
313 if($self->{'iDetail'}) |
|
314 { # for ease of BC with ini files |
|
315 $self->{'iDetail'} =~ s/^(block|subblock|logical(sub)?set)$/package/ || |
|
316 $self->{'iDetail'} =~ s/^(module)$/collection/; |
|
317 } |
|
318 |
|
319 |
|
320 while(my ($n,$b) = each %{$self->{iArgs}} ) # set defaults |
|
321 { |
|
322 if($b->{'default'} and !defined $self->{$n}) |
|
323 { |
|
324 $self->{$n} =$b->{'default'}; |
|
325 } |
|
326 if($b->{'type'} eq 'boolean' and (defined $self->{$n})) |
|
327 { #set booleans to true/false |
|
328 if($self->{$n} == 1 or $self->{$n} =~/^(yes|on|true|y)$/i) |
|
329 { |
|
330 $self->{$n} = 'true'; |
|
331 } |
|
332 else |
|
333 { |
|
334 $self->{$n} = 'false'; |
|
335 } |
|
336 } |
|
337 } |
|
338 |
|
339 # computed defaults: |
|
340 |
|
341 # if saving to .svgz, try to compress |
|
342 $self->{iCompress} = $self->{iCompress} || ( $self->{iDiagram} =~ /\.svgz$/i ); |
|
343 |
|
344 if($self->{'iLogoSrc'} =~ /\.svg$/i) # embed SVG logos only |
|
345 { |
|
346 $self->{'iLogoEmbed'}= "yes"; |
|
347 } |
|
348 |
|
349 if(defined $self->{iCoreOs} and ($self->{'iModel'} eq $self->{'iArgs'}->{'iModel'}->{'default'})) |
|
350 { |
|
351 my $dataroot =&SystemModelXmlDataDir(); |
|
352 if($self->{iCoreOs}=~/(on|yes|true)$/i ) |
|
353 { |
|
354 $self->{'iModel'} = "$dataroot/ModelTemplate.94.xml", |
|
355 } |
|
356 elsif($self->{iCoreOs}=~/(off|no|false)$/i ) |
|
357 { |
|
358 $self->{'iModel'} = "$dataroot/ModelTemplate.xml", |
|
359 } |
|
360 elsif(! ($self->{iCoreOs}=~/^[0-9]+$/ )) # any other non-number |
|
361 { |
|
362 $self->{'iModel'} = "$dataroot/ModelTemplate.95.xml", |
|
363 } |
|
364 } |
|
365 |
|
366 |
|
367 $self->{iTemporaryDirectory} = &fixFile('dir', cwd,$self->{iTemporaryDirectory} ); # now gives the full path name $self->{iTemporaryDirectory} |
|
368 |
|
369 mkpath $self->{iTemporaryDirectory} if ! -d $self->{iTemporaryDirectory}; |
|
370 |
|
371 # set the log file if needed: |
|
372 $Logger::LOGFILE = $self->{iLogFile} if $self->{iLogFile}; |
|
373 |
|
374 # set the correct warning level: |
|
375 # -w=1: errors only (default) |
|
376 # -w=2: warnings as well as errors |
|
377 # -w=3: info messages, warnings and errors. |
|
378 if (defined $self->{iWarningLevel} and $self->{iWarningLevel} > 1) |
|
379 { |
|
380 if ($self->{iWarningLevel} == 2) |
|
381 { |
|
382 $self->{iWarningLevel} = LogItem::WARNING; |
|
383 } |
|
384 elsif ($self->{iWarningLevel} == 3) |
|
385 { |
|
386 $self->{iWarningLevel} = LogItem::INFO; |
|
387 } |
|
388 else # for anything higher than set it to LogItem::VERBOSE |
|
389 { |
|
390 $self->{iWarningLevel} = LogItem::VERBOSE; |
|
391 } |
|
392 } |
|
393 else |
|
394 { |
|
395 $self->{iWarningLevel} = LogItem::ERROR; |
|
396 } |
|
397 # set the logger up: |
|
398 $Logger::SEVERITY = $self->{iWarningLevel}; |
|
399 |
|
400 #determine the XSLT Processor we need to use |
|
401 $self->{'iXslt'} = XsltProcessor(); |
|
402 |
|
403 } |
|
404 |
|
405 sub OrderedOption() { |
|
406 my $var = shift; |
|
407 my $val = shift; |
|
408 if($var=~/^(show|hide)-attr$/) { |
|
409 my $f = "<filter xmlns='' display='$1' "; |
|
410 if($val=~s/^([^=]+)=//) {$f.="select='$1' value='$val'/>"} |
|
411 else {$f.="select='$val'/>"} |
|
412 push(@Filters,$f); |
|
413 } elsif($var eq 'filter-has' && $val eq '*') { |
|
414 push(@Filters,"<filter xmlns='' display='show' select='*'/>"); |
|
415 }elsif($var eq 'filter-has') { |
|
416 if(!scalar(@Filters)) { # if the 1st is showing a filter than that implies everythig without a filter is turned off |
|
417 push(@Filters,'<filter xmlns="" select="*" display="hide"/>'); |
|
418 } |
|
419 foreach my $v (split(/,/,$val)) { |
|
420 push(@Filters,"<filter xmlns='' display='show' select='filter' value='$v'/>"); |
|
421 } |
|
422 } |
|
423 } |
|
424 |
|
425 |
|
426 sub fixFile { |
|
427 my $type = shift; |
|
428 my $dir = shift; |
|
429 my $val = shift; |
|
430 if($val eq '') {return} |
|
431 $val = &FullPath("$dir/", $val ); |
|
432 if($type eq 'file/uri') { $val =&FileAsUrl($val)} |
|
433 return $val; |
|
434 } |
|
435 |
|
436 |
|
437 sub FullPath { |
|
438 my $root = shift; |
|
439 my $file = shift; |
|
440 |
|
441 # If the file is not specified then return null |
|
442 if (!$file) { |
|
443 return; |
|
444 } |
|
445 |
|
446 |
|
447 # If the file is a URL or Windows path then return it as is |
|
448 if ($file =~ /:/) { |
|
449 return $file; |
|
450 } |
|
451 |
|
452 # If the file is a windows remote path then return it as is |
|
453 if ($file =~ /\\\\/ || $file =~ /\/\//) { |
|
454 return $file; |
|
455 } |
|
456 |
|
457 if ($root && !-e $root) { |
|
458 &Logger::LogFatal("root$root does not exist"); |
|
459 } |
|
460 |
|
461 if (-f $root) { |
|
462 $root = File::Basename::dirname($root) |
|
463 } |
|
464 |
|
465 # if root is empty or the same dir, then file is relative |
|
466 if($root eq '' or $root eq '.') { |
|
467 return $file; |
|
468 } |
|
469 |
|
470 # If the file is relative from the root then we want to add the drive letter to the file (if one exists) |
|
471 if ($file =~ s/^[\\\/]// ) { |
|
472 if ($root =~ /^([a-z]:)/i) { |
|
473 return File::Spec->catdir($1, $file); |
|
474 } else { # it's a unix path, put the / back on |
|
475 return "/$file"; |
|
476 } |
|
477 } |
|
478 |
|
479 # Return the concatenated root and filename |
|
480 return File::Spec->catdir($root, $file); |
|
481 } |
|
482 |
|
483 |
|
484 sub ReadIniFile() |
|
485 { |
|
486 my $self = shift; |
|
487 my %setHere; |
|
488 return if ! defined $self->{iIniFile}; |
|
489 |
|
490 # Log a fatal error if the ini file is defined but doesn't exist: |
|
491 &Logger::LogFatal("ini file does not exist\"$self->{iIniFile}\": $!", KSystemModelGenerator) if ! -e $self->{iIniFile}; |
|
492 |
|
493 open(INI, $self->{iIniFile}) or |
|
494 &Logger::LogFatal("Could not open the ini file \"$self->{iIniFile}\": $!", KSystemModelGenerator); |
|
495 |
|
496 &Logger::LogInfo("Reading ini file \"$self->{iIniFile}...", KSystemModelGenerator); |
|
497 |
|
498 |
|
499 my %IniMap; # map from ini var to internal var |
|
500 foreach my $a (keys %{$self->{'iArgs'}}) { |
|
501 my $v = $self->{'iArgs'}->{$a}->{'param'}; |
|
502 $v=~s/=.*//; |
|
503 $IniMap{$v}=$a; |
|
504 $v=~tr/-_/_-/; # allow both model_name and model-name |
|
505 $IniMap{$v}=$a; |
|
506 } |
|
507 |
|
508 my $iniDir = $self->{iIniFile}; |
|
509 $iniDir =~ s,[^\\//]+$,,; |
|
510 #$iniDir .= '\\'; |
|
511 |
|
512 foreach my $line (<INI>) |
|
513 { |
|
514 $line =~ s/^\s*//; # remove spaces |
|
515 $line =~ s/\s*$//; # a/a |
|
516 $line =~ s/\n$//; # remove new line |
|
517 if($line =~/"/) { |
|
518 $line =~ s/^(([^"#]*"[^"]*")+)#.*$/$1/; # remove comments indicated by # (to the end of the line) |
|
519 } else { |
|
520 $line =~ s/#.*$//; # remove comments indicated by # (to the end of the line) |
|
521 } |
|
522 next if $line eq ""; # ignore blank lines |
|
523 if ($line =~ m/([^=]+)\s*=\s*(.*)/) |
|
524 { |
|
525 my $argType = lc $1; # case-insensitive |
|
526 my $argValue = $2; # case-sensitive as it can have strings intended for html output |
|
527 |
|
528 $argType =~ s/^\s*//; # remove spaces on either end (Cannot use s/\s+// as this will not be suitable for html text) |
|
529 $argType =~ s/\s*$//; |
|
530 $argValue =~ s/^\s*//; |
|
531 $argValue =~ s/\s*$//; |
|
532 |
|
533 $argValue =~ s/^'//; # no need for quotes around the values |
|
534 $argValue =~ s/'$//; |
|
535 $argValue =~ s/^"//; |
|
536 $argValue =~ s/"$//; |
|
537 |
|
538 if(!defined $IniMap{$argType}) {next} |
|
539 my $param = $IniMap{$argType}; |
|
540 if($self->{'iArgs'}->{$param}->{'ordered'}) { |
|
541 &OrderedOption($argType, $argValue); |
|
542 } else { |
|
543 my $type = $self->{'iArgs'}->{$param}->{'type'}; |
|
544 # make sure all files mentioned are taken relative to the ini file |
|
545 if($type eq 'file' or $type eq 'outfile' or $type eq 'dir' or $type eq 'file/uri') |
|
546 { |
|
547 $argValue =&fixFile($type,$iniDir,$argValue); |
|
548 } |
|
549 |
|
550 # do not override! Only set values that have not been set on command line already |
|
551 |
|
552 if ($self->{'iArgs'}->{$param}->{'multi'} == 1) { |
|
553 if(scalar(@{$self->{$param}})==0 || $setHere{$param}) { |
|
554 push(@{$self->{$param}}, $argValue) ; |
|
555 $setHere{$param}=1; |
|
556 } |
|
557 } elsif ($self->{'iArgs'}->{$param}->{'multi'} == 2) { |
|
558 $argValue=~s/^([^=]+)=//; |
|
559 if(scalar(%{$self->{$param}})==0 || $setHere{$param}) { |
|
560 $self->{$param}->{$1}=$argValue; |
|
561 $setHere{$param} = 1; |
|
562 } |
|
563 } else |
|
564 { |
|
565 $self->{$param} = $argValue if ! $self->{$param}; |
|
566 } |
|
567 } |
|
568 } |
|
569 } |
|
570 |
|
571 close(INI); |
|
572 @{$self->{'iFiltering'}} = @Filters if ! @{$self->{'iFiltering'}}; |
|
573 @Filters=(); |
|
574 } |
|
575 |
|
576 sub getModel() |
|
577 { |
|
578 my $self = shift; |
|
579 |
|
580 my $tempDirectoryPathname = $self->{iTemporaryDirectory}; |
|
581 my $modelXml = "$tempDirectoryPathname/Model.xml"; |
|
582 |
|
583 if(defined $self->{'iModelCreated'}) {return $modelXml} |
|
584 |
|
585 my $needsMod=0; |
|
586 # the following needs a bit of work |
|
587 foreach my $param (keys %{$self->{'iArgs'}}) { |
|
588 if (! ($self->{'iArgs'}->{$param}->{'class'} =~ /^(Build Control|)$/ )) |
|
589 { |
|
590 if ($self->IsSet($param)) {$needsMod=1; last} |
|
591 } |
|
592 } |
|
593 # if no parameters are set that would impact the model, just use the raw Model XML provided |
|
594 if(!$needsMod) {return $self->{iModel}} |
|
595 |
|
596 my $dir = $self->{iModel}; |
|
597 $dir=~s,[^/\\]+$,,; |
|
598 |
|
599 my $command = $self->XsltTransformCmd("-",$self->{'iModel'},$modelXml,1); # does not take any params |
|
600 |
|
601 open XSLT, "|$command" |
|
602 #open XSLT, ">$tempDirectoryPathname/xslt.xsl" |
|
603 || &Logger::LogFatal("error in running $command", KSystemModelGenerator); |
|
604 my $basedir = &FileAsUrl($dir); |
|
605 $basedir=~s,/$,,; # make sure no // |
|
606 print XSLT '<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform"> |
|
607 <variable name="fullpath">',$basedir,'/</variable> |
|
608 <template match="@*" priority="-2"><copy-of select="."/></template> |
|
609 <template match="@href|model/@shapes|logo/@src|legend/@use[not(starts-with(.,'@') or starts-with(.,'#'))]" priority="-1"> |
|
610 <choose> |
|
611 <when test="$fullpath!='' and not(contains(.,':') or starts-with(.,'/'))"> |
|
612 <attribute name="{name()}"><value-of select="concat($fullpath,.)"/></attribute> |
|
613 </when> |
|
614 <otherwise><copy-of select="."/></otherwise> |
|
615 </choose> |
|
616 </template> |
|
617 <template match="*" mode="attr"><apply-templates select="@*"/></template> |
|
618 <template match="*" mode="content" priority="-1"><apply-templates select="*"/></template> |
|
619 <template match="*" mode="legend"><copy-of select="."/></template> |
|
620 <template match="note" mode="legend"><copy><copy-of select="@*"/><apply-templates select="." mode="content"/></copy></template> |
|
621 <template match="model" mode="content"> |
|
622 <call-template name="sysdef"/> |
|
623 <call-template name="filter"/> |
|
624 <apply-templates select="*"/> |
|
625 </template> |
|
626 <template match="/shapes/*"><param name="m"/> |
|
627 <if test="not(preceding-sibling::*[name()=name(current())] or $m//legend[@use=concat(\'@shapes#\',name(current()))])"> |
|
628 <element name="legend" namespace=""> |
|
629 <attribute name="use">@shapes#<value-of select="name()"/></attribute> |
|
630 </element></if> |
|
631 </template> |
|
632 <template match="/shapes/*[namespace-uri(.)!=',"''",']"/> |
|
633 <template match="note" mode="content" priority="-1"><apply-templates select="node()"/></template> |
|
634 <template match="*"> |
|
635 <copy><apply-templates select="." mode="attr"/><apply-templates select="." mode="content"/></copy> |
|
636 </template> |
|
637 '; |
|
638 |
|
639 my %at; |
|
640 my %info=''; |
|
641 foreach my $param (keys %{$self->{'iArgs'}}) { |
|
642 my $cur = $self->{'iArgs'}->{$param}; |
|
643 if (! ($cur->{'class'} =~ /^(Build Control|)$/) && $self->IsSet($param) ) { |
|
644 if($cur->{'xpath'}) { |
|
645 my $x = $cur->{'xpath'}; |
|
646 my $match = $x; |
|
647 $x=~s,/([^/]+)$,,; |
|
648 my $item = $1; |
|
649 if($item=~s/^@//) { |
|
650 if($self->{$param} ne '') { |
|
651 if($self->{'iArgs'}->{$param}->{'type'} ne 'boolean' || $self->{$param} eq 'true') { # if boolean and false, don't set attribute in XML |
|
652 $at{$x}.="\t<attribute name=\"$item\">".&SafeXml($self->{$param})."</attribute>\n"; |
|
653 } |
|
654 } |
|
655 print XSLT "<template match=\"$match\"/>\n"; |
|
656 } elsif($item eq 'note') { # just in case there's other things that can take plan text later, can add them here |
|
657 if($cur->{'multi'}==1) { |
|
658 my $count =0; |
|
659 foreach my $n (@{$self->{$param}}) { |
|
660 print XSLT "<template match=\"$item\[count(preceding::$item)=$count\]\" mode=\"content\">",&SafeXml($n),"</template>\n"; |
|
661 $count++; |
|
662 } |
|
663 } elsif(!$cur->{'multi'}) { |
|
664 my $n =$self->{$param}; |
|
665 print XSLT "<template match=\"$match\" mode=\"content\">&SafeXml($n)</template>\n"; |
|
666 } |
|
667 } elsif($cur->{'info'}) { |
|
668 my $t = $cur->{'info'}; |
|
669 if( ! ($self->{'iArgs'}->{$param}->{'dontclear'} )) { # can force it to be included anyway if necessary |
|
670 print XSLT "<template match=\"$match/info\[\@type='$t'\]\"/>\n"; # remove from doc, add explicitly |
|
671 } |
|
672 if($cur->{'multi'}==1){ |
|
673 foreach my $n (@{$self->{$param}}) { |
|
674 if($n ne '') { |
|
675 $info{$match}.="\t<info xmlns='' type='$t' href='$n'/>\n"; |
|
676 } |
|
677 } |
|
678 } elsif(!$cur->{'multi'}){ |
|
679 $info{$match}.="\t<info xmlns='' type='$t' href='",$self->{$param},"'/>\n"; |
|
680 } |
|
681 } elsif($param eq 'iIgnore' or $param eq 'iIgnoreMeta' or $param eq 'iLinkExpr' or $param eq 'iSysDefFile') { |
|
682 print XSLT "<template match='",$cur->{'xpath'},"'/>\n" # ignore any already present if set |
|
683 } |
|
684 } elsif($param eq 'iModel' || $param eq 'iSysDefPath' || $param eq 'iPathPrefix' || $param eq 'iSourceRoot') { |
|
685 } else { |
|
686 print STDERR "$param ",$self->{$param},"\n"; # should not get here |
|
687 } |
|
688 } |
|
689 } |
|
690 if(scalar @{$self->{'iFiltering'}}) { |
|
691 print XSLT "<template match='filter'/>\n" # ignore all already present if set |
|
692 } |
|
693 while (my ($a,$b) = each(%at) ){ |
|
694 print XSLT "<template match=\"$a\" mode=\"attr\">\n\t<apply-templates select=\"@*\"/>\n$b</template>\n"; |
|
695 } |
|
696 print XSLT '<template name="sysdef">'; |
|
697 my $count=0; |
|
698 foreach my $sys (@{$self->{'iSysDefFile'}}) { |
|
699 $count++; |
|
700 print XSLT "\n\t<element name='sysdef' namespace=''>\n"; |
|
701 print XSLT "\t\t<attribute name='href'>$sys</attribute>\n"; |
|
702 my $src=$count; |
|
703 if(scalar(@{$self->{'iSourceRoot'}}) == 1) {$src=0} |
|
704 if($self->{'iSourceRoot'}->[$src]) { |
|
705 print XSLT "\t\t<attribute name='root'>",$self->{'iSourceRoot'}->[$src],"</attribute>\n"; |
|
706 } |
|
707 $src=$count; |
|
708 if(scalar(@{$self->{'iPathPrefix'}}) == 1) {$src=0} |
|
709 if($self->{'iPathPrefix'}->[$src]) { |
|
710 print XSLT "\t\t<attribute name='path-prefix'>",$self->{'iPathPrefix'}->[$src],"</attribute>\n"; |
|
711 } |
|
712 $src=$count; |
|
713 if(scalar(@{$self->{'iSysDefPath'}}) == 1) {$src=0} |
|
714 if($self->{'iSysDefPath'}->[$src]) { |
|
715 print XSLT "\t\t<attribute name='path'>",$self->{'iSysDefPath'}->[$src],"</attribute>\n"; |
|
716 } |
|
717 print XSLT $info{'/model/sysdef'}, |
|
718 "<apply-templates select=\"/model/sysdef/info\"/>\n\t</element>\n"; |
|
719 $count++; |
|
720 } |
|
721 foreach my $link (@{$self->{'iLinkExpr'}}) { |
|
722 print XSLT "\t<element name='link' namespace=''><attribute name='expr'>",&SafeXml($link),"</attribute></element>\n"; |
|
723 } |
|
724 print XSLT "</template>\n", |
|
725 "<template name=\"filter\">\n"; |
|
726 foreach my $ig (@{$self->{'iIgnore'}}) { |
|
727 print XSLT "\t<ignore xmlns='' "; |
|
728 if($ig=~/^(layer|package|block|logicalset|logicalsubset|subblock|collection|module|component):(.*)$/) {print XSLT "type='$1' name='$2'/>\n"} |
|
729 elsif($ig=~/:.*\//) {print XSLT "namespace='$ig'/>\n"} # assume it's a namespace if it has a colon and a slash |
|
730 else {print XSLT "ref='$ig'/>\n"} |
|
731 } |
|
732 foreach my $ig (@{$self->{'iIgnoreMeta'}}) { |
|
733 print XSLT "\t<ignore xmlns='' "; |
|
734 if($ig=~/^(.*):(.*)$/) {print XSLT "meta-type='$2' meta='$1'/>\n"} |
|
735 else {print XSLT "meta='$ig'/>\n"} |
|
736 } |
|
737 print XSLT join("\n\t",@{$self->{'iFiltering'}}), |
|
738 "</template>\n"; |
|
739 |
|
740 print XSLT '<template match="layout/legend" mode="content">',"\n"; |
|
741 if($self->{'iShapes'}) {print XSLT ' <apply-templates select="document(\'',$self->{'iShapes'},'\',.)/shapes/*|*"><with-param name="m" select="current()"/></apply-templates>',"\n";} |
|
742 foreach my $link ('iColor','iBorder','iOverlay' , 'iStyle') { |
|
743 my $type=$self->{'iArgs'}->{$link}->{'info'}; |
|
744 if(scalar @{$self->{$link}}) { |
|
745 my $use ="#$type"; |
|
746 print XSLT "\t<if test=\"not(//legend[\@use='$use'])\">"; |
|
747 } else { |
|
748 print XSLT "\t<if test=\"../info[\@type='$type']\">"; |
|
749 } |
|
750 print XSLT "<legend xmlns=\"\" use=\"#$type\"/></if>\n"; |
|
751 } |
|
752 $count =1; |
|
753 my $notes=''; |
|
754 foreach my $n (@{$self->{'iLegendNote'}}) { |
|
755 $notes.="\t<if test='count(//note) < $count'><note xmlns='' width='auto'>".&SafeXml($n)."</note></if>\n"; |
|
756 } |
|
757 print XSLT "$notes</template>\n", |
|
758 '<template match="layout/legend[legend]" mode="content">', |
|
759 "\n\t<apply-templates select='*' mode='legend'/>\n$notes</template>\n", |
|
760 '<template match="layout" mode="content">',"\n",$info{'/model/layout'}; |
|
761 if($self->{'iLogoSrc'}) { |
|
762 print XSLT "\t<if test='not(//logo)'><element name='logo' namespace=''>\n",$at{'/model/layout/logo'},"\t</element></if>\n"; |
|
763 } |
|
764 print XSLT "\t<apply-templates select='*'/></template>\n"; |
|
765 print XSLT "</stylesheet>\n"; |
|
766 close XSLT; |
|
767 $self->{'iModelCreated'}=1; |
|
768 return $modelXml; |
|
769 } |
|
770 |
|
771 |
|
772 sub GetXsltDir() |
|
773 { |
|
774 my $self = shift; |
|
775 my $xsltDir = $FindBin::Bin."/core"; # calcluated w.r.t root of Dep directory |
|
776 return $xsltDir; |
|
777 } |
|
778 |
|
779 |
|
780 sub GetExtrasDir() |
|
781 { |
|
782 my $self = shift; |
|
783 my $dir = $FindBin::Bin."/extra"; # calcluated w.r.t root of Dep directory |
|
784 return $dir; |
|
785 } |
|
786 |
|
787 |
|
788 |
|
789 sub FileAsUrl() |
|
790 { |
|
791 my $file = $_[0]; |
|
792 if($file=~/^..+:/){ return $file} # already a URL |
|
793 if(-f $file) |
|
794 { # abs_path only works on dirs, so strip off file name and put it back when done |
|
795 if(! ($file=~/^[a-z]:[\\\/][^\\\/]+$/i)) |
|
796 { # if it's in the root dir, do nothing |
|
797 my $tail = "/$file"; |
|
798 # if it's just a file name, need to find cwd; |
|
799 if($file =~ s,([\\/][^\\/]+)$,,) |
|
800 { |
|
801 $tail = $1; |
|
802 } |
|
803 else {$file = "."} |
|
804 $file = abs_path($file)."$tail"; |
|
805 } |
|
806 } |
|
807 elsif (-d $file) |
|
808 { |
|
809 $file = abs_path($file); |
|
810 } # else does not exist, so just convert to unix-style path |
|
811 $file=~tr/\\/\//; |
|
812 return "file:///$file"; |
|
813 } |
|
814 |
|
815 |
|
816 sub RunCmd() { |
|
817 my $command = shift; |
|
818 open(EXE,"$command 2>&1|"); |
|
819 while(<EXE>){ |
|
820 chomp; |
|
821 s/^XSLT Message: //; |
|
822 s/\.Source tree node:.*$//; |
|
823 if($_ ne '') { |
|
824 if(s/^note: //i) { |
|
825 &Logger::LogInfo($_, KSystemModelGenerator,2, 100); |
|
826 } elsif(s/^Warning: //) { |
|
827 &Logger::LogWarning($_, KSystemModelGenerator,2, 600); |
|
828 } elsif(s/^Error: //i) { |
|
829 &Logger::LogError($_, KSystemModelGenerator,2, 400); |
|
830 } else { |
|
831 print STDERR "$_\n"; |
|
832 } |
|
833 } |
|
834 } |
|
835 close(EXE); |
|
836 return $?; |
|
837 } |
|
838 |
|
839 sub ShouldCreateDepmodel() |
|
840 { |
|
841 my $self = shift; |
|
842 if (@{$self->{iDepsFile}}) |
|
843 { |
|
844 return 1; |
|
845 } |
|
846 my $should = 0; |
|
847 my $model = $self->getModel(); |
|
848 my $t = $/; |
|
849 $/='>'; |
|
850 open(M,$model); |
|
851 while(<M>) |
|
852 { |
|
853 if(/<model\s.*deps=/){$should=1;last;} |
|
854 if(/<info\s.*data-type="Dependencies"/){$should=1;last;} |
|
855 } |
|
856 close M; |
|
857 $/ = $t; |
|
858 return $should |
|
859 } |
|
860 |
|
861 |
|
862 sub XsltTransformCmd() |
|
863 { |
|
864 my $self = shift; |
|
865 my $command = $self->{'iXslt'} . ' ' ; |
|
866 |
|
867 if(join('',@PATH)=~/\\/) { |
|
868 # use windows path |
|
869 $command =~ s#\/#\\#g; |
|
870 } |
|
871 |
|
872 if($command =~ /xalan\.jar/i) { |
|
873 return $command. XalanJTransformCmd(@_); |
|
874 } |
|
875 if($command =~ /xsltproc/i) { |
|
876 return $command. XsltprocTransformCmd(@_); |
|
877 } |
|
878 |
|
879 return $command. XalanTransformCmd(@_); |
|
880 } |
|
881 |
|
882 sub XalanTransformCmd() |
|
883 { |
|
884 my $xslt = shift; |
|
885 my $from = shift; |
|
886 my $to = shift; |
|
887 my $indent = shift; |
|
888 my %params = (scalar @_) ? %{$_[0]} : (); |
|
889 |
|
890 if($from=~/ /) {$from= "\"$from\""} |
|
891 if($to=~/ /) {$to= "\"$to\""} |
|
892 if($xslt=~/ /) {$xslt= "\"$xslt\""} |
|
893 |
|
894 my $command; |
|
895 while (my($p,$v) = each(%{$_[0]})) |
|
896 { |
|
897 $v =~ s/"/"/g; # replace quotes with entities |
|
898 $command.= " -p $p \"$v\""; |
|
899 } |
|
900 |
|
901 if($indent >=0) { |
|
902 $command .= " -i $indent"; |
|
903 } |
|
904 if($to ne '') { |
|
905 $command .= " -o $to"; |
|
906 } |
|
907 return "$command $from $xslt"; |
|
908 } |
|
909 |
|
910 |
|
911 sub XalanJTransformCmd() |
|
912 { |
|
913 my $xslt = shift; |
|
914 my $from = shift; |
|
915 my $to = shift; |
|
916 my $indent = shift; # not used in versions of xalan.jar we expect to see |
|
917 my %params = (scalar @_) ? %{$_[0]} : (); |
|
918 |
|
919 if($from=~/ /) {$from= "\"$from\""} |
|
920 if($to=~/ /) {$to= "\"$to\""} |
|
921 if($xslt=~/ /) {$xslt= "\"$xslt\""} |
|
922 |
|
923 my $command; |
|
924 while (my($p,$v) = each(%{$_[0]})) |
|
925 { |
|
926 $v =~ s/"/"/g; # replace quotes with entities |
|
927 $command.= " -param $p \"$v\""; |
|
928 } |
|
929 |
|
930 if($to ne '') { |
|
931 $command .= " -out $to"; |
|
932 } |
|
933 |
|
934 die &Logger::LogError("Model transforms are not supported using Xalan-J", KSystemModelGenerator, 1) if ($xslt eq '-'); |
|
935 |
|
936 $command .= " -xsl $xslt"; |
|
937 $command .= " -in $from"; |
|
938 return $command; |
|
939 } |
|
940 |
|
941 sub XsltTransform() |
|
942 { |
|
943 my $self = shift; |
|
944 my $to=$_[2]; |
|
945 my $command = $self->XsltTransformCmd(@_); |
|
946 &Logger::LogInfo("System Call: $command", KSystemModelGenerator,3,800); |
|
947 if($to eq '') {return `$command`} |
|
948 return &RunCmd($command); |
|
949 } |
|
950 |
|
951 sub XsltprocTransformCmd() |
|
952 { |
|
953 my $xslt = shift; |
|
954 my $from = shift; |
|
955 my $to = shift; |
|
956 my $indent = shift; |
|
957 my %params = (scalar @_) ? %{$_[0]} : (); |
|
958 my $command; |
|
959 |
|
960 if($from=~/ /) {$from= "\"$from\""} |
|
961 if($to=~/ /) {$to= "\"$to\""} |
|
962 if($xslt=~/ /) {$xslt= "\"$xslt\""} |
|
963 |
|
964 while (my($p,$v) = each(%{$_[0]})) |
|
965 { |
|
966 $v =~ s/"/"/g; |
|
967 $command.= " --param $p \"$v\""; |
|
968 } |
|
969 |
|
970 if($to ne '') { |
|
971 $command .= " -o $to"; |
|
972 } |
|
973 return "$command $xslt $from"; |
|
974 } |
|
975 |
|
976 |
|
977 sub makeAbbrev |
|
978 { |
|
979 my $self = shift; |
|
980 my $xsltDir = $self->GetExtrasDir(); |
|
981 my %params = ( |
|
982 'dict' => "'".$self->{'iDict'}."'" |
|
983 ); |
|
984 if(scalar @{$self->{'iSysDefFile'}}) |
|
985 { # if sysdefs provided, create one abbrev file for each |
|
986 my $count = 1; |
|
987 if(! (scalar @{$self->{'iLocalize'}})) |
|
988 { # do not fitler out any abbrev already in the model template |
|
989 $self->{'iArgs'}->{'iLocalize'}->{'dontclear'}=1; |
|
990 } |
|
991 foreach my $sysdef (@{$self->{'iSysDefFile'}}) |
|
992 { |
|
993 my $afile = $self->{'iTemporaryDirectory'} . "/abbrev$count.xml"; |
|
994 my $error = $self->XsltTransform("$xsltDir/makeabbrev.xsl",$sysdef,$afile,1,\%params); |
|
995 &Logger::LogError("Xalan error ($error) occured in creating abbrev file", KSystemModelGenerator, 1) if $error; |
|
996 # prepend generated file to the list (order does not matter since the same name appearing twice will have the same abbreviation) |
|
997 unshift(@{$self->{'iLocalize'}}, &FileAsUrl($afile)); |
|
998 $count++; |
|
999 } |
|
1000 } |
|
1001 else |
|
1002 { # no sysdefs provided, run against template model xml |
|
1003 if(scalar @{$self->{'iLocalize'}}) |
|
1004 {# if localize files provided, include = 0, which means it will ignore any localize files in the model template |
|
1005 # if there are none provided, then any in the model template will be appended to the generated file |
|
1006 # this is only needed for the case where it's run on the model. When run on the sysdef, inclusion has no meaning |
|
1007 $params{'include'} = 0; |
|
1008 } |
|
1009 my $afile = $self->{'iTemporaryDirectory'} . "/abbrev.xml"; |
|
1010 my $error = $self->XsltTransform("$xsltDir/makeabbrev.xsl",$self->{'iModel'},$afile,1,\%params); |
|
1011 &Logger::LogError("Xalan error ($error) occured in creating abbrev file", KSystemModelGenerator, 1) if $error; |
|
1012 # prepend generated file to the list |
|
1013 unshift(@{$self->{'iLocalize'}}, &FileAsUrl($afile)); |
|
1014 } |
|
1015 } |
|
1016 |
|
1017 sub Draw() |
|
1018 { |
|
1019 my $self = shift; |
|
1020 my $genSvg = $self->{'iDiagram'} ne ''; |
|
1021 my $genCsv = $self->{'iOutputCsv'} ne ''; |
|
1022 my $genXml = $self->{'iOutputXml'} ne ''; |
|
1023 my $error; |
|
1024 |
|
1025 if(!$genSvg && !$genCsv && !$genXml) |
|
1026 { |
|
1027 &Logger::LogFatal("Must specify at least one type of output file. Cannot continue...", KSystemModelGenerator, 0,Logger::KNothingToDo); |
|
1028 } |
|
1029 |
|
1030 # Step 0: |
|
1031 # Prepare some file names and create output directory: |
|
1032 |
|
1033 # construct full path name: |
|
1034 |
|
1035 my $xsltDir = $self->GetXsltDir(); |
|
1036 my $extraDir = $self->GetExtrasDir(); |
|
1037 my $tempDirectoryPathname = $self->{'iTemporaryDirectory'}; |
|
1038 my $tempStuctureFile = "$tempDirectoryPathname/system_definition_tmp.xml"; |
|
1039 my $tempXslFile = "$tempDirectoryPathname/styling_tmp.xsl"; |
|
1040 my $tempModelFile = "$tempDirectoryPathname/model_tmp.svg"; |
|
1041 my $tempModelFile2 = "$tempDirectoryPathname/model_tmp2.svg"; |
|
1042 my $modelXsl = $xsltDir."/layoutsysdef.xsl"; |
|
1043 |
|
1044 if($self->{'iDict'}) |
|
1045 { |
|
1046 &Logger::LogInfo("Create an abbreviation file...", KSystemModelGenerator, 0); |
|
1047 $self->makeAbbrev(); |
|
1048 } |
|
1049 |
|
1050 &Logger::LogInfo("Generating Model XML...", KSystemModelGenerator, 0); |
|
1051 my $modelXml = $self->getModel(); |
|
1052 |
|
1053 # Step 2 - |
|
1054 &Logger::LogInfo("Generating merged sysdef XML...", KSystemModelGenerator, 0); |
|
1055 $error = $self->XsltTransform($modelXsl,$modelXml,$tempStuctureFile,1); # does not take any params |
|
1056 |
|
1057 &Logger::LogError("Xalan error ($error) occured in combining sysdefs", KSystemModelGenerator, 1) if $error; |
|
1058 |
|
1059 # Step 3 - validation |
|
1060 if($self->{iWarningLevel} == LogItem::VERBOSE ) |
|
1061 { |
|
1062 &Logger::LogInfo("Validating merged XML...", KSystemModelGenerator, 0); |
|
1063 my $errors = $self->XsltTransform($extraDir."/validate.xsl",$tempStuctureFile,'',-1); |
|
1064 &Logger::LogList(split(/\n/,$errors)); |
|
1065 } |
|
1066 |
|
1067 if($genSvg) |
|
1068 { # only needed for model building |
|
1069 &Logger::LogInfo("Generating Model Diagram...", KSystemModelGenerator, 0); |
|
1070 |
|
1071 # Step 4 |
|
1072 &Logger::LogInfo("Creating styling XSLT...", KSystemModelGenerator, 1); |
|
1073 $error = $self->XsltTransform("$xsltDir/shapes.xsl",$modelXml,$tempXslFile,1, |
|
1074 {%{$self->{'iXsltParam'}},'Model-Transform' => "'".&FileAsUrl("$xsltDir/draw.xsl")."'" }); |
|
1075 &Logger::LogError("Xalan error ($error) occured generating Styling transform", KSystemModelGenerator, 2) if $error; |
|
1076 |
|
1077 if($self->{iLowMem}) |
|
1078 { # split step 5 into parts so we don't use as much runtime memory |
|
1079 # Step 5a |
|
1080 my $tempDetailsFile = "$tempDirectoryPathname/system_definition_draw.xml"; |
|
1081 &Logger::LogInfo("Generating temp details XML", KSystemModelGenerator, 1); |
|
1082 $error = $self->XsltTransform($tempXslFile,$tempStuctureFile,$tempDetailsFile,1, |
|
1083 {%{$self->{'iXsltParam'}},'Run' => "'calc'" } ); |
|
1084 &Logger::LogError("Xalan error ($error) occured in building temp datafile", KSystemModelGenerator, 2) if $error; |
|
1085 # Step 5b |
|
1086 &Logger::LogInfo("Generating SVG model...", KSystemModelGenerator, 1); |
|
1087 $error = $self->XsltTransform($tempXslFile,$tempDetailsFile,$tempModelFile,1, |
|
1088 {%{$self->{'iXsltParam'}},'Run' => "'draw'" } ); |
|
1089 &Logger::LogError("Xalan error ($error) occured in building SVG", KSystemModelGenerator, 2) if $error; |
|
1090 } |
|
1091 else |
|
1092 { |
|
1093 # Step 5 |
|
1094 &Logger::LogInfo("Generating SVG model...", KSystemModelGenerator, 1); |
|
1095 $error = $self->XsltTransform($tempXslFile,$tempStuctureFile,$tempModelFile,1,$self->{'iXsltParam'}); |
|
1096 &Logger::LogError("Xalan error ($error) occured in building SVG", KSystemModelGenerator, 2) if $error; |
|
1097 } |
|
1098 if ($self->ShouldCreateDepmodel()) { # insert as 1st transform |
|
1099 @ARGV=( $extraDir."/dependencies.xsl",'-',@ARGV) |
|
1100 } |
|
1101 |
|
1102 my $tmpsvg = $tempModelFile; |
|
1103 while(scalar(@ARGV)) { |
|
1104 my $transform = shift(@ARGV); |
|
1105 my $datafile = shift(@ARGV); |
|
1106 if($datafile eq '-') {$datafile = &FileAsUrl($tempStuctureFile)} |
|
1107 elsif($datafile ne '') {$datafile = &FileAsUrl($datafile)} |
|
1108 # save to the output if this is the last transform |
|
1109 # otherwise save to tempModelFile2 if reading from tempModelFile, and vis versa |
|
1110 my $saveto = $self->{'iDiagram'}; |
|
1111 if(scalar(@ARGV)) { |
|
1112 $saveto = ($tmpsvg eq $tempModelFile) ? $tempModelFile2 : $tempModelFile; |
|
1113 } |
|
1114 # Step 6 |
|
1115 &Logger::LogInfo("Applying post-processing transformation...", KSystemModelGenerator,1); |
|
1116 my %p = %{$self->{'iXsltParam'}}; |
|
1117 if($datafile ne '') { |
|
1118 $p{'Data'}="'$datafile'"; # optional -- only if needed for transform |
|
1119 } |
|
1120 $error = $self->XsltTransform($transform,$tmpsvg,$saveto,1,\%p); |
|
1121 &Logger::LogError("Xalan error ($error) occured in post-processing SVG file", KSystemModelGenerator, 2) if $error; |
|
1122 $tmpsvg = $saveto; # read from this next time. |
|
1123 } |
|
1124 if ($tmpsvg ne $self->{'iDiagram'}) { |
|
1125 open(OUT,">".$self->{iDiagram}); |
|
1126 open(IN,$tmpsvg); |
|
1127 print OUT <IN>; |
|
1128 close OUT; |
|
1129 close IN; |
|
1130 } |
|
1131 |
|
1132 my $zipname = $self->{iDiagram}; |
|
1133 my $unzipname = $zipname; |
|
1134 $zipname =~ s/\.svg$/.svgz/i; |
|
1135 $unzipname =~ s/\.svgz$/.svg/i; |
|
1136 my $compressed = 0; |
|
1137 if($self->{iCompress}) |
|
1138 { |
|
1139 my $gzip = &GzipCommand(); |
|
1140 if($gzip) |
|
1141 { |
|
1142 &Logger::LogInfo("Compressing output model", KSystemModelGenerator,1); |
|
1143 my $command = "$gzip ".$self->{iDiagram}; |
|
1144 &Logger::LogInfo("System Call: $command", KSystemModelGenerator,2); |
|
1145 $error = &RunCmd($command);# this should generate the sysmodel.svg in the output directory |
|
1146 &Logger::LogError("Gzip error ($error) occured when comrpessing SVG", KSystemModelGenerator, 2) if $error; |
|
1147 &Logger::LogInfo("Renaming output to : $zipname", KSystemModelGenerator,2); |
|
1148 rename $self->{iDiagram}.".gz", $zipname; |
|
1149 $compressed = 1; |
|
1150 } |
|
1151 } |
|
1152 if(!$compressed && $unzipname ne $self->{iDiagram}) |
|
1153 { |
|
1154 &Logger::LogInfo("Renaming output to : $unzipname", KSystemModelGenerator,1); |
|
1155 rename $self->{iDiagram}, $unzipname; |
|
1156 } |
|
1157 } |
|
1158 # create CSV if desired |
|
1159 if($genCsv) |
|
1160 { |
|
1161 &Logger::LogInfo("Generating CSV output", KSystemModelGenerator, 0); |
|
1162 my %p; |
|
1163 if($self->{iCsvColumns}) |
|
1164 { |
|
1165 $p{'atts'}="'".$self->{iCsvColumns}."'"; |
|
1166 } |
|
1167 if($self->{iCsvLabels}) |
|
1168 { |
|
1169 $p{'labels'}="'".$self->{iCsvLabels}."'"; |
|
1170 } |
|
1171 $error = $self->XsltTransform($extraDir."/output-csv.xsl",$tempStuctureFile,$self->{iOutputCsv},-1,\%p); |
|
1172 &Logger::LogError("Xalan error ($error) occured in CSV output...", KSystemModelGenerator, 1) if $error; |
|
1173 } |
|
1174 |
|
1175 # create sysdef XML if desired |
|
1176 |
|
1177 if($genXml) |
|
1178 { |
|
1179 &Logger::LogInfo("Generating XML output", KSystemModelGenerator, 0); |
|
1180 $error = $self->XsltTransform($extraDir."/output-sysdef.xsl",$tempStuctureFile,$self->{iOutputXml},1,$self->{'iXsltParam'}); |
|
1181 &Logger::LogError("Xalan error ($error) occured in Sysdef output...", KSystemModelGenerator, 1) if $error; |
|
1182 } |
|
1183 |
|
1184 # delete the contents of the temp directory if -clean is specified by the user: |
|
1185 if ($self->{iClean}) |
|
1186 { |
|
1187 &Logger::LogInfo("Deleting contents of the temp directory $self->{iTemporaryDirectory}...", KSystemModelGenerator,0); |
|
1188 $self->DeleteTempDirectory(); |
|
1189 } |
|
1190 } |
|
1191 |
|
1192 |
|
1193 |
|
1194 sub SafeXml { |
|
1195 my $txt = shift; |
|
1196 if(!($txt=~/&#?[0-9a-z]+;/i)) |
|
1197 { # if not entity-encoded, entity encode the stuff |
|
1198 $txt=~ s/([&<>\x7f-\xff])/"&#".ord($1).";"/eg; |
|
1199 } |
|
1200 return $txt; |
|
1201 } |
|
1202 |
|
1203 sub IsSet() |
|
1204 { |
|
1205 my $self = shift; |
|
1206 my $param = shift; |
|
1207 if ($self->{'iArgs'}->{$param}->{'multi'} == 1) |
|
1208 { |
|
1209 if (scalar @{$self->{$param}} ) {return 1} |
|
1210 } |
|
1211 elsif ($self->{'iArgs'}->{$param}->{'multi'} == 2) |
|
1212 { |
|
1213 if (scalar %{$self->{$param}} ) {return 1} |
|
1214 } |
|
1215 elsif (defined $self->{$param}){return 1} |
|
1216 return 0; |
|
1217 } |
|
1218 |
|
1219 |
|
1220 sub SystemModelXmlDataDir() |
|
1221 { |
|
1222 my $file =$FindBin::Bin."/rsc"; |
|
1223 return $file; |
|
1224 } |
|
1225 |
|
1226 |
|
1227 #----------------------------------------------------------------------------- |
|
1228 # Xalan |
|
1229 #----------------------------------------------------------------------------- |
|
1230 my $KXalanDirectory = $FindBin::Bin."/rsc/installed/Xalan"; |
|
1231 my $KXalan = $KXalanDirectory."/xalan.exe"; |
|
1232 sub Xalan() |
|
1233 { |
|
1234 my $xalan = &FindInPath("xalan"); |
|
1235 if($xalan ne '') { |
|
1236 if($xalan=~/ /) {return "\"$xalan\""} |
|
1237 return $xalan |
|
1238 } |
|
1239 # not found, use windows built-in version |
|
1240 $xalan = $KXalan; |
|
1241 return $xalan; |
|
1242 } |
|
1243 |
|
1244 sub XsltProcessor() |
|
1245 { |
|
1246 #first try xalan-c |
|
1247 my $proc = &FindInPath("xalan"); |
|
1248 if($proc ne '') { |
|
1249 if($proc=~/ /) {return "\"$proc\""} |
|
1250 return $proc |
|
1251 } |
|
1252 # now try xsltproc |
|
1253 my $proc = &FindInPath("xsltproc"); |
|
1254 if($proc ne '') |
|
1255 { |
|
1256 if($proc=~/ /) {return "\"$proc\""} |
|
1257 return $proc |
|
1258 } |
|
1259 # now try xalan-j |
|
1260 foreach my $dir(@CLASSPATH) |
|
1261 { |
|
1262 my $file = "$dir/xalan.jar"; |
|
1263 if(-e $file) |
|
1264 { |
|
1265 if($file=~/ /) {$file="\"$file\""} |
|
1266 return "java -jar $file"; # assume java is installed. Why would ever have a CLASSPATH and not have java? |
|
1267 } |
|
1268 } |
|
1269 # not found, use windows built-in version. If we're not in windows this will fail, but since we have no other options we may as well try it. |
|
1270 $proc = $KXalan; |
|
1271 $proc = $FindBin::Bin."/../../resources/installed/Xalan/xalan.exe" if ! -e $proc; |
|
1272 if($proc=~/ /) {return "\"$proc\""} |
|
1273 return $proc; |
|
1274 } |
|
1275 |
|
1276 |
|
1277 #----------------------------------------------------------------------------- |
|
1278 # Gzip |
|
1279 #----------------------------------------------------------------------------- |
|
1280 sub GzipCommand |
|
1281 { # returns empty if gzip not in path |
|
1282 my $dir = &FindInPath("gzip"); |
|
1283 if($dir ne '') {return "gzip -9"} |
|
1284 return ""; |
|
1285 } |
|
1286 |
|
1287 sub FindInPath |
|
1288 { |
|
1289 my $exe = shift; |
|
1290 foreach my $d (@PATH) |
|
1291 { |
|
1292 my $dir = $d; |
|
1293 $dir=~s,[\\\/]$,,; # remove trailing slash |
|
1294 $dir.="/$exe"; # try w/o extension |
|
1295 foreach my $ext ('',@PATHEXT) { |
|
1296 if(-f "$dir$ext" && -x "$dir$ext") {return "$dir$ext"} # must be a file and must be executable |
|
1297 } |
|
1298 } |
|
1299 return ""; |
|
1300 } |
|
1301 |
|
1302 |
|
1303 #------------------- |
|
1304 |
|
1305 |
|
1306 sub DeleteTempDirectory() |
|
1307 { |
|
1308 my $self = shift; |
|
1309 # This will delete all files in the $self->{iTemporaryDirectory} |
|
1310 rmtree $self->{iTemporaryDirectory}; |
|
1311 } |
|
1312 |
|
1313 sub Help() |
|
1314 { |
|
1315 my $self = shift; |
|
1316 my ($param,$text); |
|
1317 |
|
1318 my @helporder = ('','', 'Build Control', '','Files or URIs',"All of these take a file name (relative or absolute path) or URI of a data source", |
|
1319 "Labels","All of these take a plain text value which is displayed on the model",'Model Control',''); |
|
1320 |
|
1321 format STDERR = |
|
1322 @<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
|
1323 $param, $text, |
|
1324 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~ |
|
1325 $text |
|
1326 . |
|
1327 |
|
1328 |
|
1329 my @list =( |
|
1330 'Switch', 'Explanation' ); |
|
1331 |
|
1332 for(my $i=0;$i<=$#helporder;$i+=2) { |
|
1333 my $item=$helporder[$i]; |
|
1334 my $next = $helporder[$i+1]; |
|
1335 if($next ne '') {$next="\n$next"} |
|
1336 if($item ne '') { |
|
1337 push (@list,"==== $item ====$next"); |
|
1338 } |
|
1339 foreach my $b (sort values %{$self->{'iArgs'}}) { |
|
1340 if(!$b->{'param'}) {next} # not an arg |
|
1341 my $a = $b->{'param'}; |
|
1342 if ($b->{'class'} eq $item) { |
|
1343 if ($a=~s/=.*// && $b->{'type'} ne '') { |
|
1344 $a .= ' ['.$b->{'type'}.']'; |
|
1345 } |
|
1346 my $ex = $b->{'desc'}; |
|
1347 if($b->{'default'}) { $ex.= ($ex=~/./ ? '. ' : '' ). 'Defaults to "'.$b->{'default'}.'"'} |
|
1348 if($b->{'multi'}) { $ex.= ($ex=~/./ ? '. ' : '' ). "Can specify multiple times."} |
|
1349 if($b->{'depr'}) { $ex.= ($ex=~/./ ? '. ' : '' ). "DEPRECATED: ".$b->{'depr'}} |
|
1350 push(@list,'-'.$a,$ex); |
|
1351 } |
|
1352 } |
|
1353 } |
|
1354 |
|
1355 $self->HelpBase(); |
|
1356 print STDERR "\nArguments:\n"; |
|
1357 my $head=2; |
|
1358 while(@list) { |
|
1359 $param = shift(@list); |
|
1360 if($head<=0 and !($param=~/^-/)){print STDERR "\n$param\n";next;} |
|
1361 $text = shift(@list); |
|
1362 write STDERR ; |
|
1363 $head--; |
|
1364 } |
|
1365 return; |
|
1366 } |
|
1367 |
|
1368 sub HelpBase() |
|
1369 { |
|
1370 print STDERR "Usage: $0 [Arguments] [Transform Data-file] ...\n"; |
|
1371 } |
|
1372 1; |