How to get a list of all components?

Comments

3 comments

  • Avatar
    juanjo

    It is not currently possible to programatically list them. Do you have a very big number of components? Are they distributed in multiple files? Are you using componentGroups?

  • Avatar
    Dirk Stegemann

    With a list of all components, I had hoped to write a function that iterates over all packed components, and logs some of their properties.

    Something like this:

    <foreach variables="currentComponent" values="${listOfAllComponents}">
        <actionList>
            <logMessage text="${currentComponent.name}.description: '${currentComponent.description}'" />
            <logMessage text="${currentComponent.name}.canBeEdited: '${currentComponent.canBeEdited}'" />
            <logMessage text="${currentComponent.name}.selected:    '${currentComponent.selected}'" />
            <logMessage text="${currentComponent.name}.show:        '${currentComponent.show}'" />
        </actionList>
    </foreach>
    

    I helped myself by adding a similar code into each component's <initializationActionList>:

    <component>
        <initializationActionList>
            <logMessage text="<hard-coded component name>.selected: '${component(<hard-coded component name>).selected}'" />
        </initializationActionList>
        ...
    <component>
    

    Which raises the new question: is it possible to reference a component's attributes from within the component's actionLists without having to refer to its name?

    It would be nicer to have something generic like

    <component>
        <initializationActionList>
            <logMessage text="THIS.selected: '${component(THIS).selected}'" />
        </initializationActionList>
        ...
    <component>
    
  • Avatar
    DevHopeful_2012

    We required the same functionality, but, to go a bit further, certain components were platform-specific and we wanted to know if the component was selected/deselected after the user's selection. So, as a workaround, I wrote the below custom function which is called in the installer's initializationActionList. Then, the UI can use this list to iterate over, in order to determine what is selected at any given time. Of course, this requires an updated list of all possible components, so it isn't the most ideal solution.

    <!--
            getComponentLists
    
            parameters:
                None
    
            return values:
                all_components_list - all component names
    
                select_all_components_list - comma separated version of the
                all_components_list for selection/deselection
    
            Notes:  This function is for grouping components into lists that can be
            used for the installer summary, resetting default selections, and toggling
            the visibility for different views.  Due to the fact that some components
            may be platform-specific and are not packed, this is a non-trivial task.
    
            Remember to leave whitespace after the last element of any of the lists.
            Otherwise, if the last element is not packed, the regex will not correctly
            remove it from the list.
        -->
        <actionDefinition>
            <name>getComponentLists</name>
            <actionList>
                <!-- Initialize list with all possible components -->
                <setInstallerVariable name="all_components_list">
                    <value>core project.component(core)
        foo project.component(foo)
        bar project.component(bar)
        samples_linux_only project.component(samples).component(linux_only)
        mac_only project.component(samples).component(mac_only)
        </value>
                </setInstallerVariable>
                <!-- Loop to see which components exist -->
                <foreach>
                    <values>${all_components_list}</values>
                    <variables>component_name full_component_name</variables>
                    <actionList>
                        <!-- Skip components which do exist -->
                        <continue>
                            <ruleList>
                                <componentTest logic="exists" name="${component_name}"/>
                            </ruleList>
                        </continue>
                        <!-- If it doesn't exist, remove it from the list -->
                        <setInstallerVariableFromRegEx>
                            <name>all_components_list</name>
                            <pattern>(.*)(\s?${component_name}\s.*\(${component_name}\)\s)(.*)</pattern>
                            <substitution>\1\3</substitution>
                            <text>${all_components_list}</text>
                        </setInstallerVariableFromRegEx>
                    </actionList>
                </foreach>
                <logMessage>
                    <text>getComponentLists: all_components_list = ${all_components_list}</text>
                    <ruleList>
                        <compareValues logic="greater" value1="${project.debugLevel}" value2="0"/>
                    </ruleList>
                </logMessage>
                <!-- Create comma separated list for all deselection/selection -->
                <setInstallerVariableFromRegEx>
                    <name>select_all_components_list</name>
                    <pattern>\sproject.[a-z_\(\).]*\s?</pattern>
                    <substitution> </substitution>
                    <text>${all_components_list}</text>
                </setInstallerVariableFromRegEx>
                <!-- Replace whitespace with comma -->
                <setInstallerVariableFromRegEx>
                    <name>select_all_components_list</name>
                    <pattern>\s+</pattern>
                    <substitution>,</substitution>
                    <text>${select_all_components_list}</text>
                </setInstallerVariableFromRegEx>
                <!-- Remove trailing comma -->
                <setInstallerVariableFromRegEx>
                    <name>select_all_components_list</name>
                    <pattern>,$</pattern>
                    <substitution></substitution>
                    <text>${select_all_components_list}</text>
                </setInstallerVariableFromRegEx>
                <logMessage>
                    <text>getComponentLists: select_all_components_list = ${select_all_components_list}</text>
                    <ruleList>
                        <compareValues logic="greater" value1="${project.debugLevel}" value2="0"/>
                    </ruleList>
                </logMessage>
                <!-- export variables to global scope i.e. return values -->
                <globalVariables>
                    <names>all_components_list select_all_components_list</names>
                </globalVariables>
            </actionList>
        </actionDefinition>
    

    Some notes:

    1. The first list has a tuple of component_name and component_accessor, as any particular component may be contained in a componentGroup in the event that you want to access it's properties. Not sure if this is still necessary, of if Bitrock has an easier way to do that now.
    2. You have to check for the existence of the components (unless you always include them all). This is due to attempting to access a non-existent component's attribute, such as "${component(linux_only).selected}" on windows, throws a runtime error.
    3. The second list can be used to selectAll/deselectAll or selecting/deselecting some other groups, without any errors from missing components.

Please sign in to leave a comment.