public static InheritanceParametersDefinitionProperty createMerged(
      ParametersDefinitionProperty prior, ParametersDefinitionProperty latter) {
    // Determining which owner to use for the new merge.
    // It needs to be an InheritanceProject!
    InheritanceProject newOwner = null;
    ParametersDefinitionProperty[] pdps = {latter, prior};

    for (ParametersDefinitionProperty pdp : pdps) {
      if (pdp.getOwner() != null && pdp.getOwner() instanceof InheritanceProject) {
        newOwner = (InheritanceProject) pdp.getOwner();
        break;
      }
    }

    // Then, we merge their ParameterDefinitions based on their name
    HashMap<String, ParameterDefinition> unifyMap = new HashMap<String, ParameterDefinition>();
    for (int i = pdps.length - 1; i >= 0; i--) {
      ParametersDefinitionProperty pdp = pdps[i];
      for (ParameterDefinition pd : pdp.getParameterDefinitions()) {
        unifyMap.put(pd.getName(), pd);
      }
    }
    List<ParameterDefinition> unifyList = new LinkedList<ParameterDefinition>(unifyMap.values());

    // With that, we create a new IPDP
    InheritanceParametersDefinitionProperty out =
        new InheritanceParametersDefinitionProperty(newOwner, unifyList);

    // At the end, we merge the scoping informations
    for (int i = pdps.length - 1; i >= 0; i--) {
      ParametersDefinitionProperty pdp = pdps[i];

      if (pdp instanceof InheritanceParametersDefinitionProperty) {
        // We deal with an already inherited parameter; so we need to
        // copy the scope exactly.
        InheritanceParametersDefinitionProperty ipdp =
            (InheritanceParametersDefinitionProperty) pdp;
        for (ScopeEntry scope : ipdp.getAllScopedParameterDefinitions()) {
          out.addScopedParameterDefinitions(scope);
        }
      } else {
        // No inheritance means the scope is fully local
        String ownerName = (pdp.getOwner() != null) ? pdp.getOwner().getName() : "";
        out.addScopedParameterDefinitions(ownerName, pdp.getParameterDefinitions());
      }
    }

    return out;
  }
  /**
   * Actually build a project, passing in parameters where appropriate
   *
   * @param project
   * @return
   */
  protected final boolean performBuildProject(AbstractProject<?, ?> project) {
    if (!project.hasPermission(AbstractProject.BUILD)) {
      LOGGER.log(Level.WARNING, "Insufficient permission to build job '" + project.getName() + "'");
      return false;
    }

    if (action.equals(BuildAction.POLL_SCM)) {
      project.schedulePolling();
      return true;
    }

    // no user parameters provided, just build it
    if (param == null) {
      project.scheduleBuild(new Cause.UserIdCause());
      return true;
    }

    ParametersDefinitionProperty pp =
        (ParametersDefinitionProperty) project.getProperty(ParametersDefinitionProperty.class);

    // project does not except any parameters, just build it
    if (pp == null) {
      project.scheduleBuild(new Cause.UserIdCause());
      return true;
    }

    List<ParameterDefinition> parameterDefinitions = pp.getParameterDefinitions();
    List<ParameterValue> values = new ArrayList<ParameterValue>();

    for (ParameterDefinition paramDef : parameterDefinitions) {

      if (!(paramDef instanceof StringParameterDefinition)) {
        // TODO add support for other parameter types
        values.add(paramDef.getDefaultParameterValue());
        continue;
      }

      StringParameterDefinition stringParamDef = (StringParameterDefinition) paramDef;
      ParameterValue value;

      // Did user supply this parameter?
      if (param.containsKey(paramDef.getName())) {
        value = stringParamDef.createValue(param.get(stringParamDef.getName()));
      } else {
        // No, then use the default value
        value = stringParamDef.createValue(stringParamDef.getDefaultValue());
      }

      values.add(value);
    }

    Jenkins.getInstance().getQueue().schedule(pp.getOwner(), 1, new ParametersAction(values));
    return true;
  }
 public void addScopedParameterDefinitions(ParametersDefinitionProperty pdp) {
   String owner = (pdp.getOwner() != null) ? pdp.getOwner().getName() : "";
   this.addScopedParameterDefinitions(owner, pdp.getParameterDefinitions());
 }