xref: /AOO41X/main/solenv/bin/modules/installer/windows/feature.pm (revision ff0525f24f03981d56b7579b645949f111420994)
1#**************************************************************
2#
3#  Licensed to the Apache Software Foundation (ASF) under one
4#  or more contributor license agreements.  See the NOTICE file
5#  distributed with this work for additional information
6#  regarding copyright ownership.  The ASF licenses this file
7#  to you under the Apache License, Version 2.0 (the
8#  "License"); you may not use this file except in compliance
9#  with the License.  You may obtain a copy of the License at
10#
11#    http://www.apache.org/licenses/LICENSE-2.0
12#
13#  Unless required by applicable law or agreed to in writing,
14#  software distributed under the License is distributed on an
15#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16#  KIND, either express or implied.  See the License for the
17#  specific language governing permissions and limitations
18#  under the License.
19#
20#**************************************************************
21
22
23
24package installer::windows::feature;
25
26use installer::existence;
27use installer::exiter;
28use installer::files;
29use installer::globals;
30use installer::sorter;
31use installer::worker;
32use installer::windows::idtglobal;
33use installer::windows::language;
34
35##############################################################
36# Returning the gid for a feature.
37# Attention: Maximum length
38##############################################################
39
40sub get_feature_gid
41{
42    my ($onefeature) = @_;
43
44    my $gid = "";
45
46    if ( $onefeature->{'gid'} ) { $gid = $onefeature->{'gid'}; }
47
48    # Attention: Maximum feature length is 38!
49    installer::windows::idtglobal::shorten_feature_gid(\$gid);
50
51    return $gid
52}
53
54##############################################################
55# Returning the gid of the parent.
56# Attention: Maximum length
57##############################################################
58
59sub get_feature_parent
60{
61    my ($onefeature) = @_;
62
63    my $parentgid = "";
64
65    if ( $onefeature->{'ParentID'} ) { $parentgid = $onefeature->{'ParentID'}; }
66
67    # The modules, hanging directly below the root, have to be root modules.
68    # Only then it is possible to make the "real" root module invisible by
69    # setting the display to "0".
70
71    if ( $parentgid eq $installer::globals::rootmodulegid ) { $parentgid = ""; }
72
73    # Attention: Maximum feature length is 38!
74    installer::windows::idtglobal::shorten_feature_gid(\$parentgid);
75
76    return $parentgid
77}
78
79##############################################################
80# Returning the display for a feature.
81# 0: Feature is not shown
82# odd: subfeatures are shown
83# even:  subfeatures are not shown
84##############################################################
85
86sub get_feature_display
87{
88    my ($onefeature) = @_;
89
90    my $display;
91    my $parentid = "";
92
93    if ( $onefeature->{'ParentID'} ) { $parentid = $onefeature->{'ParentID'}; }
94
95    if ( $parentid eq "" )
96    {
97        $display = "0";                                 # root module is not visible
98    }
99    elsif ( $onefeature->{'gid'} eq "gid_Module_Prg")   # program module shows subfeatures
100    {
101        $display = "1";                                 # root module shows subfeatures
102    }
103    else
104    {
105        $display = "2";                                 # all other modules do not show subfeatures
106    }
107
108    # special case: Feature has flag "HIDDEN_ROOT" -> $display is 0
109    my $styles = "";
110    if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
111    if ( $styles =~ /\bHIDDEN_ROOT\b/ ) { $display = "0"; }
112
113    # Special handling for language modules. Only visible in multilingual installation set
114    if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && ( ! $installer::globals::ismultilingual )) { $display = "0"; }
115
116    # Special handling for c05office. No program module visible.
117    if (( $onefeature->{'gid'} eq "gid_Module_Prg" ) && ( $installer::globals::product =~ /c05office/i )) { $display = "0"; }
118
119    # making all feature invisible in Language packs!
120    if ( $installer::globals::languagepack ) { $display = "0"; }
121
122    return $display
123}
124
125##############################################################
126# Returning the level for a feature.
127##############################################################
128
129sub get_feature_level
130{
131    my ($onefeature) = @_;
132
133    my $level = "20";   # the default
134
135    my $localdefault = "";
136
137    if ( $onefeature->{'Default'} ) { $localdefault = $onefeature->{'Default'}; }
138
139    if ( $localdefault eq "NO" )    # explicitely set Default = "NO"
140    {
141        $level = "200";             # deselected in default installation, base is 100
142        if ( $installer::globals::patch ) { $level = "20"; }
143    }
144
145    # special handling for Java and Ada
146    if ( $onefeature->{'Name'} )
147    {
148        if ( $onefeature->{'Name'} =~ /java/i ) { $level = $level + 40; }
149    }
150
151    # if FeatureLevel is defined in scp, this will be used
152
153    if ( $onefeature->{'FeatureLevel'} ) { $level = $onefeature->{'FeatureLevel'}; }
154
155    return $level
156}
157
158##############################################################
159# Returning the directory for a feature.
160##############################################################
161
162sub get_feature_directory
163{
164    my ($onefeature) = @_;
165
166    my $directory;
167
168    $directory = "INSTALLLOCATION";
169
170    return $directory
171}
172
173##############################################################
174# Returning the directory for a feature.
175##############################################################
176
177sub get_feature_attributes
178{
179    my ($onefeature) = @_;
180
181    my $attributes;
182
183    # No advertising of features and no leaving on network.
184    # Feature without parent must not have the "2"
185
186    my $parentgid = "";
187    if ( $onefeature->{'ParentID'} ) { $parentgid = $onefeature->{'ParentID'}; }
188
189    if (( $parentgid eq "" ) || ( $parentgid eq $installer::globals::rootmodulegid )) { $attributes = "8"; }
190    else { $attributes = "10"; }
191
192    return $attributes
193}
194
195#################################################################################
196# Replacing one variable in one files
197#################################################################################
198
199sub replace_one_variable
200{
201    my ($translationfile, $variable, $searchstring) = @_;
202
203    for ( my $i = 0; $i <= $#{$translationfile}; $i++ )
204    {
205        ${$translationfile}[$i] =~ s/\%$searchstring/$variable/g;
206    }
207}
208
209#################################################################################
210# Replacing the variables in the feature names and descriptions
211#################################################################################
212
213sub replace_variables
214{
215    my ($translationfile, $variableshashref) = @_;
216
217    foreach $key (keys %{$variableshashref})
218    {
219        my $value = $variableshashref->{$key};
220        replace_one_variable($translationfile, $value, $key);
221    }
222}
223
224#################################################################################
225# Collecting the feature recursively.
226#################################################################################
227
228sub collect_modules_recursive
229{
230    my ($modulesref, $parentid, $feature, $directaccess, $directgid, $directparent, $directsortkey, $sorted) = @_;
231
232    my @allchildren = ();
233    my $childrenexist = 0;
234
235    # Collecting children from Module $parentid
236
237    my $modulegid;
238    foreach $modulegid ( keys %{$directparent})
239    {
240        if ( $directparent->{$modulegid} eq $parentid )
241        {
242            my %childhash = ( "gid" => "$modulegid", "Sortkey" => "$directsortkey->{$modulegid}");
243            push(@allchildren, \%childhash);
244            $childrenexist = 1;
245        }
246    }
247
248    # Sorting children
249
250    if ( $childrenexist )
251    {
252        # Sort children
253        installer::sorter::sort_array_of_hashes_numerically(\@allchildren, "Sortkey");
254
255        # Adding children to new array
256        my $childhashref;
257        foreach $childhashref ( @allchildren )
258        {
259            my $gid = $childhashref->{'gid'};
260
261            # Saving all lines, that have this 'gid'
262
263            my $unique;
264            foreach $unique ( keys %{$directgid} )
265            {
266                if ( $directgid->{$unique} eq $gid )
267                {
268                    push(@{$feature}, ${$modulesref}[$directaccess->{$unique}]);
269                    if ( $sorted->{$unique} == 1 ) { installer::exiter::exit_program("ERROR: Sorting feature failed! \"$unique\" already sorted.", "sort_feature"); }
270                    $sorted->{$unique} = 1;
271                }
272            }
273
274            collect_modules_recursive($modulesref, $gid, $feature, $directaccess, $directgid, $directparent, $directsortkey, $sorted);
275        }
276    }
277}
278
279#################################################################################
280# Sorting the feature in specified order. Evaluated is the key "Sortkey", that
281# is set in scp2 projects.
282# The display order of modules in Windows Installer is dependent from the order
283# in the idt file. Therefore the order of the modules array has to be adapted
284# to the Sortkey order, before the idt file is created.
285#################################################################################
286
287sub sort_feature
288{
289    my ($modulesref) = @_;
290
291    my @feature = ();
292
293    my %directaccess = ();
294    my %directparent = ();
295    my %directgid = ();
296    my %directsortkey = ();
297    my %sorted = ();
298
299    for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
300    {
301        my $onefeature = ${$modulesref}[$i];
302
303        my $uniquekey = $onefeature->{'uniquekey'};
304        my $modulegid = $onefeature->{'gid'};
305
306        $directaccess{$uniquekey} = $i;
307
308        $directgid{$uniquekey} = $onefeature->{'gid'};
309
310        # ParentID and Sortkey are not saved for the 'uniquekey', but only for the 'gid'
311
312        if ( $onefeature->{'ParentID'} ) { $directparent{$modulegid} = $onefeature->{'ParentID'}; }
313        else { $directparent{$modulegid} = ""; }
314
315        if ( $onefeature->{'Sortkey'} ) { $directsortkey{$modulegid} = $onefeature->{'Sortkey'}; }
316        else { $directsortkey{$modulegid} = "9999"; }
317
318        # Bookkeeping:
319        $sorted{$uniquekey} = 0;
320    }
321
322    # Searching all feature recursively, beginning with ParentID = ""
323    my $parentid = "";
324    collect_modules_recursive($modulesref, $parentid, \@feature, \%directaccess, \%directgid, \%directparent, \%directsortkey, \%sorted);
325
326    # Bookkeeping
327    my $modulekey;
328    foreach $modulekey ( keys %sorted )
329    {
330        if ( $sorted{$modulekey} == 0 )
331        {
332            my $infoline = "Warning: Module \"$modulekey\" could not be sorted. Added to the end of the module array.\n";
333            push(@installer::globals::logfileinfo, $infoline);
334            push(@feature, ${$modulesref}[$directaccess{$modulekey}]);
335        }
336    }
337
338    return \@feature;
339}
340
341#################################################################################
342# Adding a unique key to the modules array. The gid is not unique for
343# multilingual modules. Only the combination from gid and specific language
344# is unique. Uniqueness is required for sorting mechanism.
345#################################################################################
346
347sub add_uniquekey
348{
349    my ( $modulesref ) = @_;
350
351    for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
352    {
353        my $uniquekey = ${$modulesref}[$i]->{'gid'};
354        if ( ${$modulesref}[$i]->{'specificlanguage'} ) { $uniquekey = $uniquekey . "_" . ${$modulesref}[$i]->{'specificlanguage'}; }
355        ${$modulesref}[$i]->{'uniquekey'} = $uniquekey;
356    }
357}
358
359#################################################################################
360# Creating the file Feature.idt dynamically
361# Content:
362# Feature Feature_Parent Title Description Display Level Directory_ Attributes
363#################################################################################
364
365sub create_feature_table
366{
367    my ($modulesref, $basedir, $languagesarrayref, $allvariableshashref) = @_;
368
369    for ( my $m = 0; $m <= $#{$languagesarrayref}; $m++ )
370    {
371        my $onelanguage = ${$languagesarrayref}[$m];
372
373        my $infoline;
374
375        my @featuretable = ();
376
377        installer::windows::idtglobal::write_idt_header(\@featuretable, "feature");
378
379        for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
380        {
381            my $onefeature = ${$modulesref}[$i];
382
383            # Java and Ada only, if the correct settings are set
384            my $styles = "";
385            if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
386            if (( $styles =~ /\bJAVAMODULE\b/ ) && ( ! ($allvariableshashref->{'JAVAPRODUCT'} ))) { next; }
387            if (( $styles =~ /\bADAMODULE\b/ ) && ( ! ($allvariableshashref->{'ADAPRODUCT'} ))) { next; }
388
389            # Controlling the language!
390            # Only language independent feature or feature with the correct language will be included into the table
391
392            if (! (!(( $onefeature->{'ismultilingual'} )) || ( $onefeature->{'specificlanguage'} eq $onelanguage )) )  { next; }
393
394            my %feature = ();
395
396            $feature{'feature'} = get_feature_gid($onefeature);
397            $feature{'feature_parent'} = get_feature_parent($onefeature);
398            # if ( $onefeature->{'ParentID'} eq "" ) { $feature{'feature_parent'} = ""; }   # Root has no parent
399            $feature{'Title'} = $onefeature->{'Name'};
400            $feature{'Description'} = $onefeature->{'Description'};
401            $feature{'Display'} = get_feature_display($onefeature);
402            $feature{'Level'} = get_feature_level($onefeature);
403            $feature{'Directory_'} = get_feature_directory($onefeature);
404            $feature{'Attributes'} = get_feature_attributes($onefeature);
405
406            my $oneline = $feature{'feature'} . "\t" . $feature{'feature_parent'} . "\t" . $feature{'Title'} . "\t"
407                    . $feature{'Description'} . "\t" . $feature{'Display'} . "\t" . $feature{'Level'} . "\t"
408                    . $feature{'Directory_'} . "\t" . $feature{'Attributes'} . "\n";
409
410            push(@featuretable, $oneline);
411
412            # collecting all feature in global feature collector (so that properties can be set in property table)
413            if ( ! installer::existence::exists_in_array($feature{'feature'}, \@installer::globals::featurecollector) )
414            {
415                push(@installer::globals::featurecollector, $feature{'feature'});
416            }
417
418            # collecting all language feature in feature collector for check of language selection
419            if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && ( $onefeature->{'ParentID'} ne $installer::globals::rootmodulegid ))
420            {
421                $installer::globals::multilingual_only_modules{$feature{'feature'}} = 1;
422            }
423
424            # collecting all application feature in global feature collector for check of application selection
425            if ( $styles =~ /\bAPPLICATIONMODULE\b/ )
426            {
427                $installer::globals::application_modules{$feature{'feature'}} = 1;
428            }
429        }
430
431        # Saving the file
432
433        my $featuretablename = $basedir . $installer::globals::separator . "Feature.idt" . "." . $onelanguage;
434        installer::files::save_file($featuretablename ,\@featuretable);
435        $infoline = "Created idt file: $featuretablename\n";
436        push(@installer::globals::logfileinfo, $infoline);
437    }
438
439}
440
4411;
442