xref: /AOO41X/main/solenv/bin/modules/installer/windows/feature.pm (revision d62abd1a66f4ba03ba5ec1e8fa54ad53c228495c)
19780544fSAndrew Rist#**************************************************************
2cdf0e10cSrcweir#
39780544fSAndrew Rist#  Licensed to the Apache Software Foundation (ASF) under one
49780544fSAndrew Rist#  or more contributor license agreements.  See the NOTICE file
59780544fSAndrew Rist#  distributed with this work for additional information
69780544fSAndrew Rist#  regarding copyright ownership.  The ASF licenses this file
79780544fSAndrew Rist#  to you under the Apache License, Version 2.0 (the
89780544fSAndrew Rist#  "License"); you may not use this file except in compliance
99780544fSAndrew Rist#  with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir#
119780544fSAndrew Rist#    http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir#
139780544fSAndrew Rist#  Unless required by applicable law or agreed to in writing,
149780544fSAndrew Rist#  software distributed under the License is distributed on an
159780544fSAndrew Rist#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169780544fSAndrew Rist#  KIND, either express or implied.  See the License for the
179780544fSAndrew Rist#  specific language governing permissions and limitations
189780544fSAndrew Rist#  under the License.
19cdf0e10cSrcweir#
209780544fSAndrew Rist#**************************************************************
219780544fSAndrew Rist
229780544fSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweirpackage installer::windows::feature;
25cdf0e10cSrcweir
26cdf0e10cSrcweiruse installer::existence;
27cdf0e10cSrcweiruse installer::exiter;
28cdf0e10cSrcweiruse installer::files;
29cdf0e10cSrcweiruse installer::globals;
30cdf0e10cSrcweiruse installer::sorter;
31cdf0e10cSrcweiruse installer::worker;
32cdf0e10cSrcweiruse installer::windows::idtglobal;
33cdf0e10cSrcweiruse installer::windows::language;
34cdf0e10cSrcweir
35cdf0e10cSrcweir##############################################################
36cdf0e10cSrcweir# Returning the gid for a feature.
37cdf0e10cSrcweir# Attention: Maximum length
38cdf0e10cSrcweir##############################################################
39cdf0e10cSrcweir
40cdf0e10cSrcweirsub get_feature_gid
41cdf0e10cSrcweir{
42cdf0e10cSrcweir	my ($onefeature) = @_;
43cdf0e10cSrcweir
44cdf0e10cSrcweir	my $gid = "";
45cdf0e10cSrcweir
46cdf0e10cSrcweir	if ( $onefeature->{'gid'} ) { $gid = $onefeature->{'gid'}; }
47cdf0e10cSrcweir
48cdf0e10cSrcweir	# Attention: Maximum feature length is 38!
49cdf0e10cSrcweir	installer::windows::idtglobal::shorten_feature_gid(\$gid);
50cdf0e10cSrcweir
51cdf0e10cSrcweir	return $gid
52cdf0e10cSrcweir}
53cdf0e10cSrcweir
54cdf0e10cSrcweir##############################################################
55cdf0e10cSrcweir# Returning the gid of the parent.
56cdf0e10cSrcweir# Attention: Maximum length
57cdf0e10cSrcweir##############################################################
58cdf0e10cSrcweir
59cdf0e10cSrcweirsub get_feature_parent
60cdf0e10cSrcweir{
61cdf0e10cSrcweir	my ($onefeature) = @_;
62cdf0e10cSrcweir
63cdf0e10cSrcweir	my $parentgid = "";
64cdf0e10cSrcweir
65cdf0e10cSrcweir	if ( $onefeature->{'ParentID'} ) { $parentgid = $onefeature->{'ParentID'}; }
66cdf0e10cSrcweir
67cdf0e10cSrcweir	# The modules, hanging directly below the root, have to be root modules.
68cdf0e10cSrcweir	# Only then it is possible to make the "real" root module invisible by
69cdf0e10cSrcweir	# setting the display to "0".
70cdf0e10cSrcweir
71cdf0e10cSrcweir	if ( $parentgid eq $installer::globals::rootmodulegid ) { $parentgid = ""; }
72cdf0e10cSrcweir
73cdf0e10cSrcweir	# Attention: Maximum feature length is 38!
74cdf0e10cSrcweir	installer::windows::idtglobal::shorten_feature_gid(\$parentgid);
75cdf0e10cSrcweir
76cdf0e10cSrcweir	return $parentgid
77cdf0e10cSrcweir}
78cdf0e10cSrcweir
79cdf0e10cSrcweir##############################################################
80cdf0e10cSrcweir# Returning the display for a feature.
81cdf0e10cSrcweir# 0: Feature is not shown
82cdf0e10cSrcweir# odd: subfeatures are shown
83cdf0e10cSrcweir# even:  subfeatures are not shown
84cdf0e10cSrcweir##############################################################
85cdf0e10cSrcweir
86cdf0e10cSrcweirsub get_feature_display
87cdf0e10cSrcweir{
88cdf0e10cSrcweir	my ($onefeature) = @_;
89cdf0e10cSrcweir
90cdf0e10cSrcweir	my $display;
91cdf0e10cSrcweir	my $parentid = "";
92cdf0e10cSrcweir
93cdf0e10cSrcweir	if ( $onefeature->{'ParentID'} ) { $parentid = $onefeature->{'ParentID'}; }
94cdf0e10cSrcweir
95cdf0e10cSrcweir	if ( $parentid eq "" )
96cdf0e10cSrcweir	{
97cdf0e10cSrcweir		$display = "0";									# root module is not visible
98cdf0e10cSrcweir	}
99cdf0e10cSrcweir	elsif ( $onefeature->{'gid'} eq "gid_Module_Prg")	# program module shows subfeatures
100cdf0e10cSrcweir	{
101cdf0e10cSrcweir		$display = "1";									# root module shows subfeatures
102cdf0e10cSrcweir	}
103cdf0e10cSrcweir	else
104cdf0e10cSrcweir	{
105cdf0e10cSrcweir		$display = "2";									# all other modules do not show subfeatures
106cdf0e10cSrcweir	}
107cdf0e10cSrcweir
108cdf0e10cSrcweir	# special case: Feature has flag "HIDDEN_ROOT" -> $display is 0
109cdf0e10cSrcweir	my $styles = "";
110cdf0e10cSrcweir	if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; }
111cdf0e10cSrcweir	if ( $styles =~ /\bHIDDEN_ROOT\b/ ) { $display = "0"; }
112cdf0e10cSrcweir
113cdf0e10cSrcweir	# Special handling for language modules. Only visible in multilingual installation set
114cdf0e10cSrcweir	if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && ( ! $installer::globals::ismultilingual )) { $display = "0"; }
115cdf0e10cSrcweir
116cdf0e10cSrcweir	# Special handling for c05office. No program module visible.
117cdf0e10cSrcweir	if (( $onefeature->{'gid'} eq "gid_Module_Prg" ) && ( $installer::globals::product =~ /c05office/i )) { $display = "0";	}
118cdf0e10cSrcweir
119cdf0e10cSrcweir	# making all feature invisible in Language packs!
120cdf0e10cSrcweir	if ( $installer::globals::languagepack ) { $display = "0"; }
121cdf0e10cSrcweir
122cdf0e10cSrcweir	return $display
123cdf0e10cSrcweir}
124cdf0e10cSrcweir
125cdf0e10cSrcweir##############################################################
126cdf0e10cSrcweir# Returning the level for a feature.
127cdf0e10cSrcweir##############################################################
128cdf0e10cSrcweir
129cdf0e10cSrcweirsub get_feature_level
130cdf0e10cSrcweir{
131cdf0e10cSrcweir	my ($onefeature) = @_;
132cdf0e10cSrcweir
133cdf0e10cSrcweir	my $level = "20";	# the default
134cdf0e10cSrcweir
135cdf0e10cSrcweir	my $localdefault = "";
136cdf0e10cSrcweir
137cdf0e10cSrcweir	if ( $onefeature->{'Default'} ) { $localdefault = $onefeature->{'Default'}; }
138cdf0e10cSrcweir
139cdf0e10cSrcweir	if ( $localdefault eq "NO" )	# explicitely set Default = "NO"
140cdf0e10cSrcweir	{
141cdf0e10cSrcweir		$level = "200";				# deselected in default installation, base is 100
142cdf0e10cSrcweir		if ( $installer::globals::patch ) { $level = "20"; }
143cdf0e10cSrcweir	}
144cdf0e10cSrcweir
145cdf0e10cSrcweir	# special handling for Java and Ada
146cdf0e10cSrcweir	if ( $onefeature->{'Name'} )
147cdf0e10cSrcweir	{
148cdf0e10cSrcweir		if ( $onefeature->{'Name'} =~ /java/i ) { $level = $level + 40; }
149cdf0e10cSrcweir	}
150cdf0e10cSrcweir
151cdf0e10cSrcweir	# if FeatureLevel is defined in scp, this will be used
152cdf0e10cSrcweir
153cdf0e10cSrcweir	if ( $onefeature->{'FeatureLevel'} ) { $level = $onefeature->{'FeatureLevel'}; }
154cdf0e10cSrcweir
155cdf0e10cSrcweir	return $level
156cdf0e10cSrcweir}
157cdf0e10cSrcweir
158cdf0e10cSrcweir##############################################################
159cdf0e10cSrcweir# Returning the directory for a feature.
160cdf0e10cSrcweir##############################################################
161cdf0e10cSrcweir
162cdf0e10cSrcweirsub get_feature_directory
163cdf0e10cSrcweir{
164cdf0e10cSrcweir	my ($onefeature) = @_;
165cdf0e10cSrcweir
166cdf0e10cSrcweir	my $directory;
167cdf0e10cSrcweir
168cdf0e10cSrcweir	$directory = "INSTALLLOCATION";
169cdf0e10cSrcweir
170cdf0e10cSrcweir	return $directory
171cdf0e10cSrcweir}
172cdf0e10cSrcweir
173cdf0e10cSrcweir##############################################################
174cdf0e10cSrcweir# Returning the directory for a feature.
175cdf0e10cSrcweir##############################################################
176cdf0e10cSrcweir
177cdf0e10cSrcweirsub get_feature_attributes
178cdf0e10cSrcweir{
179cdf0e10cSrcweir	my ($onefeature) = @_;
180cdf0e10cSrcweir
181cdf0e10cSrcweir	my $attributes;
182cdf0e10cSrcweir
183cdf0e10cSrcweir	# No advertising of features and no leaving on network.
184cdf0e10cSrcweir	# Feature without parent must not have the "2"
185cdf0e10cSrcweir
186cdf0e10cSrcweir	my $parentgid = "";
187cdf0e10cSrcweir	if ( $onefeature->{'ParentID'} ) { $parentgid = $onefeature->{'ParentID'}; }
188cdf0e10cSrcweir
189cdf0e10cSrcweir	if (( $parentgid eq "" ) || ( $parentgid eq $installer::globals::rootmodulegid )) { $attributes = "8"; }
190cdf0e10cSrcweir	else { $attributes = "10"; }
191cdf0e10cSrcweir
192cdf0e10cSrcweir	return $attributes
193cdf0e10cSrcweir}
194cdf0e10cSrcweir
195cdf0e10cSrcweir#################################################################################
196cdf0e10cSrcweir# Replacing one variable in one files
197cdf0e10cSrcweir#################################################################################
198cdf0e10cSrcweir
199cdf0e10cSrcweirsub replace_one_variable
200cdf0e10cSrcweir{
201cdf0e10cSrcweir	my ($translationfile, $variable, $searchstring) = @_;
202cdf0e10cSrcweir
203cdf0e10cSrcweir	for ( my $i = 0; $i <= $#{$translationfile}; $i++ )
204cdf0e10cSrcweir	{
205cdf0e10cSrcweir		${$translationfile}[$i] =~ s/\%$searchstring/$variable/g;
206cdf0e10cSrcweir	}
207cdf0e10cSrcweir}
208cdf0e10cSrcweir
209cdf0e10cSrcweir#################################################################################
210cdf0e10cSrcweir# Replacing the variables in the feature names and descriptions
211cdf0e10cSrcweir#################################################################################
212cdf0e10cSrcweir
213cdf0e10cSrcweirsub replace_variables
214cdf0e10cSrcweir{
215cdf0e10cSrcweir	my ($translationfile, $variableshashref) = @_;
216cdf0e10cSrcweir
217cdf0e10cSrcweir	foreach $key (keys %{$variableshashref})
218cdf0e10cSrcweir	{
219cdf0e10cSrcweir		my $value = $variableshashref->{$key};
220cdf0e10cSrcweir		replace_one_variable($translationfile, $value, $key);
221cdf0e10cSrcweir	}
222cdf0e10cSrcweir}
223cdf0e10cSrcweir
224cdf0e10cSrcweir#################################################################################
225cdf0e10cSrcweir# Collecting the feature recursively.
226cdf0e10cSrcweir#################################################################################
227cdf0e10cSrcweir
228cdf0e10cSrcweirsub collect_modules_recursive
229cdf0e10cSrcweir{
230cdf0e10cSrcweir	my ($modulesref, $parentid, $feature, $directaccess, $directgid, $directparent, $directsortkey, $sorted) = @_;
231cdf0e10cSrcweir
232cdf0e10cSrcweir	my @allchildren = ();
233cdf0e10cSrcweir	my $childrenexist = 0;
234cdf0e10cSrcweir
235cdf0e10cSrcweir	# Collecting children from Module $parentid
236cdf0e10cSrcweir
237cdf0e10cSrcweir	my $modulegid;
238cdf0e10cSrcweir	foreach $modulegid ( keys %{$directparent})
239cdf0e10cSrcweir	{
240cdf0e10cSrcweir		if ( $directparent->{$modulegid} eq $parentid )
241cdf0e10cSrcweir		{
242cdf0e10cSrcweir			my %childhash = ( "gid" => "$modulegid", "Sortkey" => "$directsortkey->{$modulegid}");
243cdf0e10cSrcweir			push(@allchildren, \%childhash);
244cdf0e10cSrcweir			$childrenexist = 1;
245cdf0e10cSrcweir		}
246cdf0e10cSrcweir	}
247cdf0e10cSrcweir
248cdf0e10cSrcweir	# Sorting children
249cdf0e10cSrcweir
250cdf0e10cSrcweir	if ( $childrenexist )
251cdf0e10cSrcweir	{
252cdf0e10cSrcweir		# Sort children
253cdf0e10cSrcweir		installer::sorter::sort_array_of_hashes_numerically(\@allchildren, "Sortkey");
254cdf0e10cSrcweir
255cdf0e10cSrcweir		# Adding children to new array
256cdf0e10cSrcweir		my $childhashref;
257cdf0e10cSrcweir		foreach $childhashref ( @allchildren )
258cdf0e10cSrcweir		{
259cdf0e10cSrcweir			my $gid = $childhashref->{'gid'};
260cdf0e10cSrcweir
261cdf0e10cSrcweir			# Saving all lines, that have this 'gid'
262cdf0e10cSrcweir
263cdf0e10cSrcweir			my $unique;
264cdf0e10cSrcweir			foreach $unique ( keys %{$directgid} )
265cdf0e10cSrcweir			{
266cdf0e10cSrcweir				if ( $directgid->{$unique} eq $gid )
267cdf0e10cSrcweir				{
268cdf0e10cSrcweir					push(@{$feature}, ${$modulesref}[$directaccess->{$unique}]);
269cdf0e10cSrcweir					if ( $sorted->{$unique} == 1 ) { installer::exiter::exit_program("ERROR: Sorting feature failed! \"$unique\" already sorted.", "sort_feature"); }
270cdf0e10cSrcweir					$sorted->{$unique} = 1;
271cdf0e10cSrcweir				}
272cdf0e10cSrcweir			}
273cdf0e10cSrcweir
274cdf0e10cSrcweir			collect_modules_recursive($modulesref, $gid, $feature, $directaccess, $directgid, $directparent, $directsortkey, $sorted);
275cdf0e10cSrcweir		}
276cdf0e10cSrcweir	}
277cdf0e10cSrcweir}
278cdf0e10cSrcweir
279cdf0e10cSrcweir#################################################################################
280cdf0e10cSrcweir# Sorting the feature in specified order. Evaluated is the key "Sortkey", that
281cdf0e10cSrcweir# is set in scp2 projects.
282cdf0e10cSrcweir# The display order of modules in Windows Installer is dependent from the order
283cdf0e10cSrcweir# in the idt file. Therefore the order of the modules array has to be adapted
284cdf0e10cSrcweir# to the Sortkey order, before the idt file is created.
285cdf0e10cSrcweir#################################################################################
286cdf0e10cSrcweir
287cdf0e10cSrcweirsub sort_feature
288cdf0e10cSrcweir{
289cdf0e10cSrcweir	my ($modulesref) = @_;
290cdf0e10cSrcweir
291cdf0e10cSrcweir	my @feature = ();
292cdf0e10cSrcweir
293cdf0e10cSrcweir	my %directaccess = ();
294cdf0e10cSrcweir	my %directparent = ();
295cdf0e10cSrcweir	my %directgid = ();
296cdf0e10cSrcweir	my %directsortkey = ();
297cdf0e10cSrcweir	my %sorted = ();
298cdf0e10cSrcweir
299cdf0e10cSrcweir	for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
300cdf0e10cSrcweir	{
301cdf0e10cSrcweir		my $onefeature = ${$modulesref}[$i];
302cdf0e10cSrcweir
303cdf0e10cSrcweir		my $uniquekey = $onefeature->{'uniquekey'};
304cdf0e10cSrcweir		my $modulegid = $onefeature->{'gid'};
305cdf0e10cSrcweir
306cdf0e10cSrcweir		$directaccess{$uniquekey} = $i;
307cdf0e10cSrcweir
308cdf0e10cSrcweir		$directgid{$uniquekey} = $onefeature->{'gid'};
309cdf0e10cSrcweir
310cdf0e10cSrcweir		# ParentID and Sortkey are not saved for the 'uniquekey', but only for the 'gid'
311cdf0e10cSrcweir
312cdf0e10cSrcweir		if ( $onefeature->{'ParentID'} ) { $directparent{$modulegid} = $onefeature->{'ParentID'}; }
313cdf0e10cSrcweir		else { $directparent{$modulegid} = ""; }
314cdf0e10cSrcweir
315cdf0e10cSrcweir		if ( $onefeature->{'Sortkey'} ) { $directsortkey{$modulegid} = $onefeature->{'Sortkey'}; }
316cdf0e10cSrcweir		else { $directsortkey{$modulegid} = "9999"; }
317cdf0e10cSrcweir
318cdf0e10cSrcweir		# Bookkeeping:
319cdf0e10cSrcweir		$sorted{$uniquekey} = 0;
320cdf0e10cSrcweir	}
321cdf0e10cSrcweir
322cdf0e10cSrcweir	# Searching all feature recursively, beginning with ParentID = ""
323cdf0e10cSrcweir	my $parentid = "";
324cdf0e10cSrcweir	collect_modules_recursive($modulesref, $parentid, \@feature, \%directaccess, \%directgid, \%directparent, \%directsortkey, \%sorted);
325cdf0e10cSrcweir
326cdf0e10cSrcweir	# Bookkeeping
327cdf0e10cSrcweir	my $modulekey;
328cdf0e10cSrcweir	foreach $modulekey ( keys %sorted )
329cdf0e10cSrcweir	{
330cdf0e10cSrcweir		if ( $sorted{$modulekey} == 0 )
331cdf0e10cSrcweir		{
332b274bc22SAndre Fischer            $installer::logger::Lang->printf(
333b274bc22SAndre Fischer                "Warning: Module \"%s\" could not be sorted. Added to the end of the module array.\n",
334b274bc22SAndre Fischer                $modulekey);
335cdf0e10cSrcweir			push(@feature, ${$modulesref}[$directaccess{$modulekey}]);
336cdf0e10cSrcweir		}
337cdf0e10cSrcweir	}
338cdf0e10cSrcweir
339cdf0e10cSrcweir	return \@feature;
340cdf0e10cSrcweir}
341cdf0e10cSrcweir
342cdf0e10cSrcweir#################################################################################
343cdf0e10cSrcweir# Adding a unique key to the modules array. The gid is not unique for
344cdf0e10cSrcweir# multilingual modules. Only the combination from gid and specific language
345cdf0e10cSrcweir# is unique. Uniqueness is required for sorting mechanism.
346cdf0e10cSrcweir#################################################################################
347cdf0e10cSrcweir
348cdf0e10cSrcweirsub add_uniquekey
349cdf0e10cSrcweir{
350cdf0e10cSrcweir	my ( $modulesref ) = @_;
351cdf0e10cSrcweir
352cdf0e10cSrcweir	for ( my $i = 0; $i <= $#{$modulesref}; $i++ )
353cdf0e10cSrcweir	{
354cdf0e10cSrcweir		my $uniquekey = ${$modulesref}[$i]->{'gid'};
355cdf0e10cSrcweir		if ( ${$modulesref}[$i]->{'specificlanguage'} ) { $uniquekey = $uniquekey . "_" . ${$modulesref}[$i]->{'specificlanguage'}; }
356cdf0e10cSrcweir		${$modulesref}[$i]->{'uniquekey'} = $uniquekey;
357cdf0e10cSrcweir	}
358cdf0e10cSrcweir}
359cdf0e10cSrcweir
360cdf0e10cSrcweir#################################################################################
361cdf0e10cSrcweir# Creating the file Feature.idt dynamically
362cdf0e10cSrcweir# Content:
363cdf0e10cSrcweir# Feature Feature_Parent Title Description Display Level Directory_ Attributes
364cdf0e10cSrcweir#################################################################################
365cdf0e10cSrcweir
366677600b0SAndre Fischersub prepare_feature_table ($$$)
367cdf0e10cSrcweir{
368677600b0SAndre Fischer	my ($modules, $language, $variables) = @_;
369cdf0e10cSrcweir
370677600b0SAndre Fischer    my $features = [];
371677600b0SAndre Fischer
372677600b0SAndre Fischer    foreach my $onefeature (@$modules)
373cdf0e10cSrcweir    {
374cdf0e10cSrcweir        # Java and Ada only, if the correct settings are set
375*d62abd1aSAndre Fischer        my $styles = $onefeature->{'Styles'};
376*d62abd1aSAndre Fischer        $styles = "" unless defined $styles;
377677600b0SAndre Fischer        if (( $styles =~ /\bJAVAMODULE\b/ ) && ( ! ($variables->{'JAVAPRODUCT'} ))) { next; }
378cdf0e10cSrcweir
379cdf0e10cSrcweir        # Controlling the language!
380cdf0e10cSrcweir        # Only language independent feature or feature with the correct language will be included into the table
381cdf0e10cSrcweir
382677600b0SAndre Fischer        next if $onefeature->{'ismultilingual'} && ($onefeature->{'specificlanguage'} ne $language);
383cdf0e10cSrcweir
384677600b0SAndre Fischer        my $feature_gid =get_feature_gid($onefeature);
385cdf0e10cSrcweir
386677600b0SAndre Fischer        my $feature = {
387677600b0SAndre Fischer            'Feature' => $feature_gid,
388677600b0SAndre Fischer            'Feature_Parent' => get_feature_parent($onefeature),
389677600b0SAndre Fischer            'Title' => $onefeature->{'Name'},
390677600b0SAndre Fischer            'Description' => $onefeature->{'Description'},
391677600b0SAndre Fischer            'Display' => get_feature_display($onefeature),
392677600b0SAndre Fischer            'Level' => get_feature_level($onefeature),
393677600b0SAndre Fischer            'Directory_' => get_feature_directory($onefeature),
394677600b0SAndre Fischer            'Attributes' => get_feature_attributes($onefeature)
395677600b0SAndre Fischer        };
396677600b0SAndre Fischer        push @$features, $feature;
397cdf0e10cSrcweir
398cdf0e10cSrcweir        # collecting all feature in global feature collector (so that properties can be set in property table)
399677600b0SAndre Fischer        $installer::globals::featurecollector{$feature_gid} = 1;
400cdf0e10cSrcweir
401cdf0e10cSrcweir        # collecting all language feature in feature collector for check of language selection
402677600b0SAndre Fischer        if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && $onefeature->{'ParentID'} ne $installer::globals::rootmodulegid)
403cdf0e10cSrcweir        {
404677600b0SAndre Fischer            $installer::globals::multilingual_only_modules{$feature_gid} = 1;
405cdf0e10cSrcweir        }
406cdf0e10cSrcweir
407cdf0e10cSrcweir        # collecting all application feature in global feature collector for check of application selection
408cdf0e10cSrcweir        if ( $styles =~ /\bAPPLICATIONMODULE\b/ )
409cdf0e10cSrcweir        {
410677600b0SAndre Fischer            $installer::globals::application_modules{$feature_gid} = 1;
411cdf0e10cSrcweir        }
412cdf0e10cSrcweir    }
413cdf0e10cSrcweir
414677600b0SAndre Fischer    return $features;
415cdf0e10cSrcweir}
416677600b0SAndre Fischer
417677600b0SAndre Fischer
418677600b0SAndre Fischer
419677600b0SAndre Fischer
420677600b0SAndre Fischer=head add_missing_features($features)
421677600b0SAndre Fischer
422677600b0SAndre Fischer    When we are building a release, then there may be features missing
423677600b0SAndre Fischer    that where present in the source release.  As missing features
424677600b0SAndre Fischer    would prevent patches from being created, we add the missing
425677600b0SAndre Fischer    features.
426677600b0SAndre Fischer
427677600b0SAndre Fischer    The returned feature hash is either identical to the given
428677600b0SAndre Fischer    $features or is a copy with the missing features added.
429677600b0SAndre Fischer
430677600b0SAndre Fischer=cut
431677600b0SAndre Fischer
432677600b0SAndre Fischersub add_missing_features ($)
433677600b0SAndre Fischer{
434677600b0SAndre Fischer    my ($features) = @_;
435677600b0SAndre Fischer
436677600b0SAndre Fischer    return $features if ! $installer::globals::is_release;
437677600b0SAndre Fischer
438677600b0SAndre Fischer    # Aquire the feature list of the source release.
439677600b0SAndre Fischer    my $source_feature_table = $installer::globals::source_msi->GetTable("Feature");
440677600b0SAndre Fischer    my $feature_column_index = $source_feature_table->GetColumnIndex("Feature");
441677600b0SAndre Fischer
442677600b0SAndre Fischer    # Prepare fast lookup of the target features.
443677600b0SAndre Fischer    my %target_feature_map = map {$_->{'Feature'} => $_} @$features;
444677600b0SAndre Fischer
445677600b0SAndre Fischer    # Find missing features.
446677600b0SAndre Fischer    my @missing_features = ();
447677600b0SAndre Fischer    foreach my $source_feature_row (@{$source_feature_table->GetAllRows()})
448677600b0SAndre Fischer    {
449677600b0SAndre Fischer        my $feature_gid = $source_feature_row->GetValue($feature_column_index);
450677600b0SAndre Fischer        if ( ! defined $target_feature_map{$feature_gid})
451677600b0SAndre Fischer        {
452677600b0SAndre Fischer            push @missing_features, $source_feature_row;
453677600b0SAndre Fischer        }
454677600b0SAndre Fischer    }
455677600b0SAndre Fischer
456677600b0SAndre Fischer    # Return when there are no missing features.
457677600b0SAndre Fischer    return $features if scalar @missing_features==0;
458677600b0SAndre Fischer
459677600b0SAndre Fischer    # Process the missing features.
460677600b0SAndre Fischer    my $extended_features = [@$features];
461677600b0SAndre Fischer    foreach my $missing_feature_row (@missing_features)
462677600b0SAndre Fischer    {
463677600b0SAndre Fischer        my %feature = map
464677600b0SAndre Fischer            {$_ => $missing_feature_row->GetValue($_)}
465677600b0SAndre Fischer            ('Feature', 'Feature_Parent', 'Title', 'Description', 'Display', 'Level', 'Directory_', 'Attributes');
466677600b0SAndre Fischer        push @$extended_features, \%feature;
467677600b0SAndre Fischer
468677600b0SAndre Fischer        $installer::logger::Lang->printf("added missing feature %s\n", $feature->{'Feature'});
469677600b0SAndre Fischer    }
470677600b0SAndre Fischer    return $extended_features;
471677600b0SAndre Fischer}
472677600b0SAndre Fischer
473677600b0SAndre Fischer
474677600b0SAndre Fischer
475677600b0SAndre Fischer
476677600b0SAndre Fischersub create_feature_table ($$$)
477677600b0SAndre Fischer{
478677600b0SAndre Fischer	my ($basedir, $language, $features) = @_;
479677600b0SAndre Fischer
480677600b0SAndre Fischer    my @feature_table = ();
481677600b0SAndre Fischer    installer::windows::idtglobal::write_idt_header(\@feature_table, "feature");
482677600b0SAndre Fischer
483677600b0SAndre Fischer    foreach my $feature (@$features)
484677600b0SAndre Fischer    {
485677600b0SAndre Fischer        my $line = join("\t",
486677600b0SAndre Fischer            $feature->{'Feature'},
487677600b0SAndre Fischer            $feature->{'Feature_Parent'},
488677600b0SAndre Fischer            $feature->{'Title'},
489677600b0SAndre Fischer            $feature->{'Description'},
490677600b0SAndre Fischer            $feature->{'Display'},
491677600b0SAndre Fischer            $feature->{'Level'},
492677600b0SAndre Fischer            $feature->{'Directory_'},
493677600b0SAndre Fischer            $feature->{'Attributes'}) . "\n";
494677600b0SAndre Fischer
495677600b0SAndre Fischer        push(@feature_table, $line);
496677600b0SAndre Fischer    }
497677600b0SAndre Fischer
498677600b0SAndre Fischer    my $filename = $basedir . $installer::globals::separator . "Feature.idt" . "." . $language;
499677600b0SAndre Fischer    installer::files::save_file($filename ,\@feature_table);
500677600b0SAndre Fischer    $installer::logger::Lang->printf("Created idt file: %s\n", $filename);
501cdf0e10cSrcweir}
502cdf0e10cSrcweir
503cdf0e10cSrcweir1;
504