| /* |
| * Copyright (c) 2014 Eike Stepper (Berlin, Germany) and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Eike Stepper - initial API and implementation |
| */ |
| package org.eclipse.oomph.setup.doc.concepts; |
| |
| import org.eclipse.oomph.setup.ScopeType; |
| import org.eclipse.oomph.setup.doc.concepts.DocScope.DocInstallation; |
| import org.eclipse.oomph.setup.doc.concepts.DocScope.DocProductCatalog; |
| import org.eclipse.oomph.setup.doc.concepts.DocScope.DocProductCatalog.DocProduct; |
| import org.eclipse.oomph.setup.doc.concepts.DocScope.DocProductCatalog.DocProduct.DocVersion; |
| import org.eclipse.oomph.setup.doc.concepts.DocScope.DocProjectCatalog; |
| import org.eclipse.oomph.setup.doc.concepts.DocScope.DocProjectCatalog.DocProject; |
| import org.eclipse.oomph.setup.doc.concepts.DocScope.DocProjectCatalog.DocProject.DocStream; |
| import org.eclipse.oomph.setup.doc.concepts.DocScope.DocUser; |
| import org.eclipse.oomph.setup.doc.concepts.DocScope.DocWorkspace; |
| import org.eclipse.oomph.setup.doc.concepts.DocTask.DocCompoundTask; |
| import org.eclipse.oomph.setup.doc.concepts.DocTask.DocP2Task; |
| import org.eclipse.oomph.setup.doc.concepts.DocTask.DocTrigger; |
| import org.eclipse.oomph.setup.doc.concepts.DocTask.DocVariableTask; |
| import org.eclipse.oomph.setup.doc.user.wizard.DocProductPage; |
| import org.eclipse.oomph.setup.doc.user.wizard.DocProjectPage; |
| import org.eclipse.oomph.setup.doc.user.wizard.DocVariablePage; |
| |
| /** |
| * Task Composition |
| * <p> |
| * The installation and provisioning process is driven by gathering a {@linkplain DocTask task} list from the available {@linkplain DocScope scopes} |
| * in preparation for {@link DocTaskExecution task execution}. |
| * </p> |
| * |
| * @number 500 |
| */ |
| public class DocTaskComposition |
| { |
| /** |
| * Scope List |
| * <p> |
| * In preparation for gathering a task list, |
| * an ordered list of {@link DocScope scopes} is collected. |
| */ |
| public static class ScopeList |
| { |
| /** |
| * The following process of collecting scopes is repeated once for each {@link DocStream stream} |
| * specified in the {@linkplain DocProjectPage project page} or in the {@linkplain DocWorkspace workspace}: |
| * <ul> |
| * |
| * <li> |
| * Visit the {@link DocVersion product version} |
| * as selected in the {@linkplain DocProductPage product page} or in the {@linkplain DocInstallation installation}. |
| * <ul> |
| * <li> |
| * Add that product version's containing {@linkplain DocProduct products}'s containing {@linkplain DocProductCatalog product catalog} to the list. |
| * Add that product version's containing product to the list. |
| * Add that product version itself to the list. |
| * </li> |
| * </ul> |
| * </li> |
| * |
| * <li> |
| * Visit a {@link DocStream stream} |
| * as selected in the {@linkplain DocProjectPage project page} or in the {@linkplain DocWorkspace workspace}, if there is one. |
| * <ul> |
| * <li> |
| * Add that stream's containing {@linkplain DocProject projects}'s containing {@linkplain DocProjectCatalog project catalog} to the list. |
| * Add that stream's outer-most containing project to the list |
| * and proceed down through the nested projects up to the stream's directly containing project, |
| * adding each project to the list along the way. |
| * Add that stream itself to the list. |
| * </li> |
| * </ul> |
| * </li> |
| * |
| * <li> |
| * Add the {@link DocInstallation installation} to the list. |
| * </li> |
| * |
| * <li> |
| * Add the {@link DocWorkspace workspace} to the list. |
| * </li> |
| * |
| * <li> |
| * Add the {@link DocUser user} to the list. |
| * </li> |
| * </ul> |
| * </p> |
| */ |
| public static String scopeList; |
| |
| /** |
| * <p> |
| * For each list of scopes, an ordered list of tasks is collected. |
| * Initially, for each scope in the list, |
| * three {@link DocVariableTask variables} are induced, |
| * one each for the {@link DocScope#name name}, {@link DocScope#label label}, and {@link DocScope#description description} |
| * attributes of the scope |
| * where the variable name is prefixed with the {@link ScopeType scope type} as follows: |
| * <ul> |
| * <li> |
| * <code>scope.product.catalog</code> |
| * </li> |
| * <li> |
| * <code>scope.product</code> |
| * </li> |
| * <li> |
| * <code>scope.product.version</code> |
| * </li> |
| * <li> |
| * <code>scope.project.catalog</code> |
| * </li> |
| * <li> |
| * <code>scope.project</code> |
| * </li> |
| * <li> |
| * <code>scope.project.stream</code> |
| * </li> |
| * <li> |
| * <code>scope.installation</code> |
| * </li> |
| * <li> |
| * <code>scope.workspace</code> |
| * </li> |
| * <li> |
| * <code>scope.user</code> |
| * </li> |
| * </ul> |
| * The value of each such variable will be the value of that attribute for the scope. |
| * If the scope's label is <code>null</code>, the name is used as the label value |
| * and if the scope's description is <code>null</code>, the scope's label is used as the description value. |
| * In addition, to the <code>name</code> variable, |
| * for each product, product version, project, and project stream |
| * an additional variable with the name suffix <code>.qualifier</code> is induced |
| * where the value is the {@link org.eclipse.oomph.setup.Scope#getQualifiedName() qualified name} of the scope. |
| * For example, |
| * the value of the <code>scope.project.stream.name.qualified</code> variable of the Oomph.setup project's master stream |
| * is <code>org.eclipse.oomph.master</code> |
| * All these induced variables are added, in scope order, to the initial gathered list of tasks. |
| * </p> |
| */ |
| public static String scopeVariables; |
| |
| /** |
| * <p> |
| * Additional tasks are gathered into the task list from the ordered scopes by visiting each contained task of each scope as follows: |
| * <ul> |
| * <li> |
| * If the task is disabled, |
| * ignore the task. |
| * </li> |
| * <li> |
| * If the list of scopes doesn't contain all of the task's restrictions, |
| * ignore the task. |
| * </li> |
| * <li> |
| * If the task is {@link DocCompoundTask compound}, |
| * recursively visit each of that compound task's contained tasks. |
| * </li> |
| * <li> |
| * Otherwise, |
| * add the task to the list of tasks. |
| * In other works, |
| * the gathered task list will only contain leaf tasks. |
| * </li> |
| * </ul> |
| * At the end of scope processing, |
| * the gathered task list contains |
| * all of the per-stream tasks, |
| * or just task list if there is no stream. |
| * Each task list (or the one task list) is further processed in two phases. |
| * The initial phase is applied for each task list separately. |
| * The per-stream task lists are then concatenated into a single list and the second phase is applied to that final composed list, |
| * or the one task list is further processed by the second phase. |
| * The processing of the the task list in each phase is roughly same. |
| * </p> |
| */ |
| public static String footer; |
| } |
| |
| /** |
| * Task List |
| * <p> |
| * The task list is processed to induce additional tasks, |
| * to {@link DocTask#override override and merge} tasks, |
| * to evaluate and expand variables |
| * and to {@link DocTask#order reorder} tasks. |
| * The members of the task list that are {@link DocVariableTask variables} induce an initial set of keys, |
| * i.e., a set of all variable names. |
| * Oomph tasks are modeled with EMF, |
| * so each task instance knows it corresponding EMF class. |
| * During the initial phase processing, |
| * the list of tasks is analyzed to determine the set of EMF classes that are required to implement all the tasks in the list. |
| * Each EMF class is processed as follows: |
| * <ul> |
| * <li> |
| * If the class contains enablement annotations, |
| * induce {@linkplain DocP2Task p2 tasks}, |
| * i.e., tasks to install the necessary implementations in the installed product, |
| * and add these induced tasks to the head of the task list. |
| * </li> |
| * <li> |
| * If the class contains variable annotations, |
| * induce the {@linkplain DocVariableTask variables} |
| * and add them to the head of the task list. |
| * </li> |
| * |
| * <li> |
| * Visit each attribute of the class as follows: |
| * <ul> |
| * If the attribute's type isn't String, |
| * ignore it. |
| * <li> |
| * If the attribute has both a variable annotation and a variable rule annotation, |
| * visit each instance of that attribute's class in the task list as follows: |
| * <ul> |
| * <li> |
| * If the attribute's value in that instance task is not empty, |
| * the rule isn't needed, |
| * so ignore it. |
| * </li> |
| * <li> |
| * If the instance task doesn't have an ID, |
| * or it does, |
| * but the key composed from the ID value, with '.' and the attribute name appended, |
| * is already in the list of induced keys, |
| * the rule isn't needed, |
| * so ignore it. |
| * </li> |
| * <li> |
| * Induce a rule variable for that attribute, |
| * if that rule variable hasn't already been induced for another task instance. |
| * </li> |
| * </ul> |
| * A mapping from rule variables to their inducing attribute is maintained. |
| * <li> |
| * </li> |
| * </li> |
| * </ul> |
| * </li> |
| * </ul> |
| * At the end of this processing for the first phase, |
| * the list of tasks includes additional induced variables and tasks. |
| * For the final phase, |
| * the composed list of tasks contains no variables, because they've all been evaluated and expanded, |
| * and the induced tasks are already present. |
| * </p> |
| */ |
| public static class TaskList |
| { |
| /** |
| * <p> |
| * Further processing proceeds as follows: |
| * <ul> |
| * <li> |
| * Build a substitution map, |
| * i.e., task-to-task map of substitutions by visiting each task as follows: |
| * <ul> |
| * <li> |
| * Put the task's {@link DocTask#override override token} into an token-to-task map, |
| * and if another task for that token is already present in the token-to-task map, |
| * the visited task is a substitution for that other task so add that to the substitution map. |
| * As such, |
| * tasks later in the list can override tasks earlier in the list. |
| * </li> |
| * The substitution map is then further processed to follow the substitution mappings so as to represent the direct substitutions. |
| * </ul> |
| * </li> |
| * </ul> |
| * </p> |
| */ |
| public static String substitutions; |
| |
| /** |
| * Initial Phase |
| * <p> |
| * For the initial phase processing, |
| * all the tasks are efficiently copied, |
| * including the copying of the containing scopes. |
| * The copying process takes the task-to-task {@link TaskList#substitutions substitution} map into account, |
| * i.e., each task is logically replaced in the copy by its {@link DocTask#override merged override}. |
| * As such, |
| * only the final overridden merged task remains in the resulting task list copy |
| * and all references to the overridden and overriding tasks will reference the final merged override instead. |
| * Further processing of the task list proceeds with this copied task list. |
| * </p> |
| * <p> |
| * An explicit key map, |
| * i.e., a map from variable name to variable, |
| * is computed by visiting each variable in the task list. |
| * Note that the preceding copying process will have eliminated duplicate variables. |
| * The initial phase processing then proceeds by visiting each task with a non-empty ID attribute as follows: |
| * <ul> |
| * <li> |
| * Visit each attribute of the task's EMF class |
| * with respect to the variable name induced by appending '.' and the attribute name to the value of the task's ID attribute: |
| * <ul> |
| * <li> |
| * If the attribute is the ID attribute of a task, |
| * or the attribute isn't a single-valued String-typed attribute, |
| * ignore it. |
| * </li> |
| * <li> |
| * If the explicit keys contains the induced variable's name, |
| * the task's value for the attribute is empty, |
| * and the attribute has a variable annotation, |
| * change the task's value for the attribute to be a reference to the explicit variable. |
| * </li> |
| * <li> |
| * If the explicit keys do not include the induced variable name, |
| * induce a new variable |
| * record that it's an explicit key, |
| * add it to the task list, |
| * and also do the following: |
| * <ul> |
| * <li> |
| * If the task's value for the attribute is empty, |
| * and the attribute has a variable annotation, |
| * change the task's value for the attribute to be a reference to the induced variable. |
| * </li> |
| * <li> |
| * Conversely, |
| * if the task's value for the attribute is non-empty, |
| * set the induced variable's value to that value, |
| * and as for the empty value case, |
| * if the attribute has a variable annotation, |
| * change the task's value for the attribute to be a reference to the induced variable. |
| * </li> |
| * <li> |
| * Also induce rule variables for each of the attribute's rule annotations, |
| * recording them as explicit keys. |
| * </li> |
| * <li> |
| * And finally, |
| * if the attribute has a variable annotation, |
| * and the induced variable's value is a self reference that would lead to circular evaluation, |
| * induce a yet another variable with the induced variable's name suffixed with <code>.explicit</code> |
| * from the explicit annotations of the attribute, |
| * and also change the self-referencing variable's value to refer to that explicit variable. |
| * </li> |
| * </ul> |
| * </li> |
| * </ul> |
| * </li> |
| * <li> |
| * Visit each task to handle its so called active annotations. |
| * Such annotations can be used on variables to compose a set of choices |
| * from choices defined in other variables, |
| * or to induce choices from the value of another variable. |
| * TODO examples |
| * </li> |
| * <li> |
| * Visit each variable task to build a key-to-value map. |
| * Analyze that map to determine the variable references, |
| * reordering the map base on this dependency analysis. |
| * And expand the variables in the ordered map. |
| * </li> |
| * <li> |
| * Expand the values of all attributes, of all tasks based on the key-to-value map, except those attributes marked as not expandable. |
| * E.g., the name attribute of a variable itself is not expanded. |
| * </li> |
| * <li> |
| * Recall that the gathering of tasks effectively {@link ScopeList#footer ignore} {@linkplain DocCompoundTask compound tasks}. |
| * But those compound tasks can specify {@link DocTask#order predecessors and successors} and well as {@link DocTask#restrictions restrictions}. |
| * As such, |
| * those predecessors and successors are expanded to become references to the leaf tasks. |
| * Furthermore, |
| * the resulting expanded predecessors and successors, |
| * as well at the restrictions, |
| * are propagated down to the leaf tasks. |
| * </li> |
| * </ul> |
| * <p> |
| */ |
| public static class InitialPhase |
| { |
| } |
| |
| /** |
| * Final Phase |
| * <p> |
| * The final phase processes a task list that is a concatenation of task lists produced from the initial phase, |
| * or just the one task list already processed by the initial phase. |
| * As such, |
| * it's working with task copies for which all variables have been expanded and eliminated. |
| * The processing for this phase augments the substitution map |
| * by analyzing the task list for structural duplicates. |
| * It then applies those substitutions, |
| * i.e., overriding and merging duplicate tasks, |
| * thereby reducing the task list before further processing. |
| * </p> |
| */ |
| public static class FinalPhase |
| { |
| } |
| |
| /** |
| * Reordering |
| * <p> |
| * The processing of the task list, |
| * particularly task {@link DocTask#override overriding} and merging, |
| * affects the overall order of the task list such that it's different from the original authored order gathered from the scopes. |
| * Not only that, |
| * when multiple streams are involved, |
| * {@linkplain FinalPhase final phase} processing is dealing with a concatenated list in which the tasks must be properly reordered. |
| * To support that, |
| * each task has an intrinsic {@link DocTask#order priority}; |
| * the task list is primarily sorted according to that priority. |
| * Each task also specifies {@link DocTask#order predecessors and successors}; |
| * the task list is secondarily sorted to respect that induced partial order. |
| * After these two sorting steps, |
| * the tasks in the list are modified to clear both the predecessors and successors |
| * and then the predecessors are set to form a chain that induces an overall order that's exactly this final order of sorted task list; |
| * this chain excludes variables. |
| * This chain of dependencies ensures that the final phase processing, |
| * which deals with the concatenated task lists, |
| * will properly interleave the tasks (because of the priority sorting) |
| * while also respecting the per-stream order of the multiple streams. |
| * <p> |
| */ |
| public static class Reorder |
| { |
| } |
| |
| /** |
| * Trigger Filtering |
| * <p> |
| * Each task that {@link DocTask#excludedTriggers excludes} the current {@link DocTrigger trigger} is removed from the task list. |
| * Note that the task list gathering process gathers <b>all</b> tasks |
| * because the task list is analyzed to determine which tasks need to be installed for all possible triggers. |
| * So for {@link DocTrigger#bootstrap bootstrap bootstrap }trigger, |
| * even the tasks that can't execute until they're running in an installed product are analyzed to ensure that, |
| * once the product is installed, |
| * the tasks that will need to perform in that installation, |
| * i.e., for {@link DocTrigger#startup startup} or {@link DocTrigger#manual manual} trigger, |
| * are properly installed. |
| * The processing of all tasks also implies that at bootstrap time, |
| * all variables that will be needed in the running installed product will be {@link DocVariablePage prompted} early |
| * and hence will already be available in the running installed product. |
| * </p> |
| */ |
| public static class Filter |
| { |
| } |
| |
| /** |
| * Consolidation |
| * <p> |
| * The final task list processing step |
| * removes all variables from the task list |
| * and {@link DocTask#consolidate consolidates} each remaining task. |
| * At this point, |
| * the tasks in the list are ready to be {@link DocTaskExecution performed}. |
| * </p> |
| */ |
| public static class Consolidation |
| { |
| } |
| } |
| } |