protected List<Task> resolveTasks(final UpgradeContext context, boolean preTasks, ProcessingComponent pc) {
    if (null == pc) {
      return Collections.emptyList();
    }

    boolean forUpgrade = context.getDirection().isUpgrade();

    final List<Task> interim;

    if (forUpgrade) {
      interim = preTasks ? pc.preTasks : pc.postTasks;
    } else {
      interim = preTasks ? pc.preDowngradeTasks : pc.postDowngradeTasks;
    }

    if (CollectionUtils.isEmpty(interim)) {
      return Collections.emptyList();
    }

    List<Task> tasks = new ArrayList<>();
    for (Task t : interim) {
      boolean taskPassesScoping = context.isScoped(t.scope);
      boolean taskPassesCondition = true;

      // tasks can have conditions on them, so check to make sure the condition is satisfied
      if (null != t.condition && !t.condition.isSatisfied(context)) {
        taskPassesCondition = false;
      }

      if (taskPassesScoping && taskPassesCondition) {
        tasks.add(t);
      }
    }

    return tasks;
  }
Determine the list of pre- or post-tasks given these rules
<ul>
  <li>When performing an upgrade, only use upgrade tasks</li>
  <li>When performing a downgrade, use the downgrade tasks if they are defined</li>
  <li>When performing a downgrade, but no downgrade tasks exist, reuse the upgrade tasks</li>
</ul>
@param context     the upgrade context
@param preTasks    {@code true} if loading pre-(upgrade|downgrade) or {@code false for post-(upgrade|downgrade)
@param pc          the processing component holding task definitions
@return A collection, potentially empty, of the tasks to run, which may contain either
pre or post tasks if they exist, and the order depends on whether it's an upgrade or downgrade.
ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/orchestrate/StageWrapperBuilder.java