/*
 * Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of the License "Eclipse Public License v1.0"
 * which accompanies this distribution, and is available
 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
 *
 * Initial Contributors:
 * Nokia Corporation - initial contribution.
 *
 * Contributors:
 *
 * Description: 
 *
 */

package com.nokia.helium.synergy.ant.taskdefs;

import org.apache.tools.ant.BuildException;

/**
 * ANT wrapper task for the GSCM rbt.pl script.
 * 
 * <pre>
 * Deconfigure Only:
 * 
 * Usage: &lt;hlm:rebaseanddeconf database=&quot;${dbname}&quot;
 *                              password=&quot;${UNIX-password}&quot; 
 *                              verbosity=&quot;${0-3}&quot;
 *                              ccmProject=&quot;${ccm.project.name}&quot; 
 *                              release=&quot;${release.name}&quot;
 *                              deconfigure=&quot;yes&quot; /&gt;
 * </pre>
 * 
 * <pre>
 * Rebaseline Only:
 * 
 * Usage:   &lt;hlm:rebaseanddeconf database=&quot;${dbname}&quot;
 *                              password=&quot;${UNIX-password}&quot; 
 *                              verbosity=&quot;${0-3}&quot;
 *                              ccmProject=&quot;${ccm.project.name}&quot;
 *                              release=&quot;${release.name}&quot; 
 *                              releaseBaseline=&quot;yes&quot; 
 *                              skipDeconfigure=&quot;yes&quot; /&gt;
 * </pre>
 * 
 * <pre>
 * Rebaseline with deconfigure:
 * 
 * Usage:   &lt;hlm:rebaseanddeconf database=&quot;${dbname}&quot;
 *                              password=&quot;${UNIX-password}&quot; 
 *                              verbosity=&quot;${0-3}&quot;
 *                              ccmProject=&quot;${ccm.project.name}&quot;
 *                              release=&quot;${release.name}&quot; 
 *                              releaseBaseline=&quot;yes&quot; 
 *                              deconfigure=&quot;yes&quot; /&gt;
 * </pre>
 * 
 * @ant.task name="rebaseanddeconf" category="SCM"
 */
public class RBTTask extends AbstractScmBaseTask {

    // The attributes of this task
    private String baseline; // -B baselinename = Four-part name of existing
    // baseline (incompatible with -p and -n)
    private String version; // -v version = New project hierarchy version
    private String release; // -r release = New release object name (Two-part
    // name)
    private String newBaselineName; // -n name = New baseline name

    private Boolean releaseBaseline; // -R = Release the newly created baseline
    private Boolean publish; // -P = Publish the newly created baseline
    private Boolean deconfigure; // -s = Replace subprojects only (NO
    // REBASELINE)
    private Boolean leaveFoldersWritable; // -F = Don't freeze folders (Leave
    // folders writable)
    private Boolean enableTaskRebadgingGenericRelease; // -t = Enable task
    // rebadging (associated
    // modifiable tasks with
    // generic release only)
    private Boolean enableTaskRebadging; // -T = Enable task rebadging (all
    // associated modifiable tasks)
    private Boolean rebadgeObjectVersions; // -o = Rebadge object versions
    // (requires ccm_admin)
    private Boolean createBaselineForRollingReleaseTag; // -i = Create
    // additional
    // integration baseline
    // for rolling-release
    // tag
    private Boolean skipDeconfigure; // -S = Do NOT replace subprojects (NO
    // DECONFIGURE)
    private Boolean active; // -a = Specified release remains active
    private Boolean useBranchReleaseMethodology; // -b = Utilize branch release

    // methodology

    /**
     * Return the baseline.
     * 
     * @return the baseline.
     */
    public String getBaseline() {
        return baseline;
    }

    /**
     * Set four-part name of existing baseline (incompatible with 'projectName'
     * and 'baselineName' attributes) to be used by rebaseline.pl script.
     * 
     * @param baseline
     *            is the baseline to set
     * @ant.not-required
     */
    public void setBaseline(String baseline) {
        this.baseline = baseline;
        log("Set baseline to " + baseline);
    }

    /**
     * Return the version.
     * 
     * @return the version.
     */
    public String getVersion() {
        return version;
    }

    /**
     * Set version of new project created.
     * 
     * @param version
     *            is the version to set.
     * @ant.not-required
     */
    public void setVersion(String version) {
        this.version = version;
        log("Set version to " + version);
    }

    /**
     * Return the leaveFoldersWritable.
     * 
     * @return the leaveFoldersWritable.
     */
    public Boolean getLeaveFoldersWritable() {
        return leaveFoldersWritable;
    }

    /**
     * Set whether to leave the folders writable in the baseline project
     * created.
     * 
     * @param leaveFoldersWritable
     *            indicates whether to leave folders writable.
     * @ant.not-required Default is no.
     */
    public void setLeaveFoldersWritable(Boolean leaveFoldersWritable) {
        this.leaveFoldersWritable = leaveFoldersWritable;
        log("Set leaveFoldersWritable to " + leaveFoldersWritable);
    }

    /**
     * Return the rebadgeObjectVersions
     * 
     * @return the rebadgeObjectVersions.
     */
    public Boolean getRebadgeObjectVersions() {
        return rebadgeObjectVersions;
    }

    /**
     * Set whether to rebadge object versions in the rebaseline.pl script.
     * 
     * @param rebadgeObjectVersions
     *            indicates whether to rebadge object versions to a given
     *            release tag.
     * @ant.not-required Default is no.
     */
    public void setRebadgeObjectVersions(Boolean rebadgeObjectVersions) {
        this.rebadgeObjectVersions = rebadgeObjectVersions;
        log("Set rebadgeObjectVersions to " + rebadgeObjectVersions);
    }

    /**
     * Return the releaseBaseline.
     * 
     * @return the releaseBaseline.
     */
    public Boolean getReleaseBaseline() {
        return releaseBaseline;
    }

    /**
     * Set whether to release the newly created baseline or not.
     * 
     * @param releaseBaseline
     *            indicates whether to release the newly created baseline
     */
    public void setReleaseBaseline(Boolean releaseBaseline) {
        this.releaseBaseline = releaseBaseline;
        log("Set releaseBaseline to " + releaseBaseline);
    }

    /**
     * Return the publish.
     * 
     * @return the publish.
     */
    public Boolean getPublish() {
        return publish;
    }

    /**
     * Set whether to publish the newly created baseline or not.
     * 
     * @param publish
     *            the publish to set
     */
    public void setPublish(Boolean publish) {
        this.publish = publish;
        log("Set publish to " + publish);
    }

    /**
     * Return the createBaselineForRollingReleaseTag.
     * 
     * @return the createBaselineForRollingReleaseTag.
     */
    public Boolean getCreateBaselineForRollingReleaseTag() {
        return createBaselineForRollingReleaseTag;
    }

    /**
     * Set whether to create additional integration baseline for rolling-release
     * tag.
     * 
     * @param createBaselineForRollingReleaseTag
     * @ant.not-required Default is no.
     */
    public void setCreateBaselineForRollingReleaseTag(
            Boolean createBaselineForRollingReleaseTag) {
        this.createBaselineForRollingReleaseTag = createBaselineForRollingReleaseTag;
        log("Set createBaselineForRollingReleaseTag to "
                + createBaselineForRollingReleaseTag);
    }

    /**
     * Return the enableTaskRebadgingGenericRelease.
     * 
     * @return the enableTaskRebadgingGenericRelease.
     */
    public Boolean getEnableTaskRebadgingGenericRelease() {
        return enableTaskRebadgingGenericRelease;
    }

    /**
     * Set enable task rebadging (associated modifiable tasks with generic
     * release only). Not supported in rebaseline.pl
     * 
     * @param enableTaskRebadgingGenericRelease
     *            the enableTaskRebadgingGenericRelease to set
     */
    public void setEnableTaskRebadgingGenericRelease(
            Boolean enableTaskRebadgingGenericRelease) {
        this.enableTaskRebadgingGenericRelease = enableTaskRebadgingGenericRelease;
        log("Set enableTaskRebadgingGenericRelease to "
                + enableTaskRebadgingGenericRelease);
    }

    /**
     * Return the enableTaskRebadging
     * 
     * @return the enableTaskRebadging.
     */
    public Boolean getEnableTaskRebadging() {
        return enableTaskRebadging;
    }

    /**
     * Set enable task rebadging (all associated modifiable tasks). Not
     * supported in rebaseline.pl
     * 
     * @param enableTaskRebadging
     *            the enableTaskRebadging to set
     */
    public void setEnableTaskRebadging(Boolean enableTaskRebadging) {
        this.enableTaskRebadging = enableTaskRebadging;
        log("Set enableTaskRebadging to " + enableTaskRebadging);
    }

    /**
     * Return the skipDeconfigure.
     * 
     * @return the skipDeconfigure.
     */
    public Boolean getSkipDeconfigure() {
        return skipDeconfigure;
    }

    /**
     * Set to skip deconfigure.
     * 
     * @param skipDeconfigure
     *            the skipDeconfigure to set
     */
    public void setSkipDeconfigure(Boolean skipDeconfigure) {
        this.skipDeconfigure = skipDeconfigure;
        log("Set skipDeconfigure to " + skipDeconfigure);
    }

    /**
     * Return the deconfigure
     * 
     * @return the deconfigure.
     */
    public Boolean getDeconfigure() {
        return deconfigure;
    }

    /**
     * Set deconfigure.
     * 
     * @param deconfigure
     *            the deconfigure to set
     */
    public void setDeconfigure(Boolean deconfigure) {
        this.deconfigure = deconfigure;
        log("Set deconfigure to " + deconfigure);
    }

    /**
     * Return the active.
     * 
     * @return the active.
     */
    public Boolean getActive() {
        return active;
    }

    /**
     * Set whether the current release is active or not.
     * 
     * @param active
     *            the active to set
     */
    public void setActive(Boolean active) {
        this.active = active;
        log("Set active to " + active);
    }

    /**
     * Return useBranchReleaseMethodology.
     * 
     * @return the useBranchReleaseMethodology.
     */
    public Boolean getUseBranchReleaseMethodology() {
        return useBranchReleaseMethodology;
    }

    /**
     * Set whether to utilize branch release methodology or not.
     * 
     * @param useBranchReleaseMethodology
     *            is the boolean value to set.
     * @ant.not-required Default is no.
     */
    public void setUseBranchReleaseMethodology(
            Boolean useBranchReleaseMethodology) {
        this.useBranchReleaseMethodology = useBranchReleaseMethodology;
        log("Set useBranchReleaseMethodology to " + useBranchReleaseMethodology);
    }

    /**
     * Return the release tag.
     * 
     * @return the release tag.
     */
    public String getRelease() {
        return release;
    }

    /**
     * Set release tag (Two-part name) for the release project created.
     * 
     * @param release
     *            is the release tag to set
     * @ant.not-required
     */
    public void setRelease(String release) {
        this.release = release;
        log("Set release to " + release);
    }

    /**
     * Return the newBaselineName.
     * 
     * @return the newBaselineName.
     */
    public String getNewBaselineName() {
        return newBaselineName;
    }

    /**
     * Set new baseline name to use.
     * 
     * @param newBaselineName
     *            is the new baseline name to set.
     * @ant.not-required
     */
    public void setNewBaselineName(String newBaselineName) {
        this.newBaselineName = newBaselineName;
        log("Set newBaselineName to " + newBaselineName);
    }

    protected String getExecutionScript() {
        return "rbt";
    }

    /**
     * Build a command list consisting of all the required and optional command
     * arguments of the current task.
     */
    protected void buildCommandList() {
        addCommandArg("database", "-d", true, getDatabase());
        addCommandArg("password", "-U", true, getPassword());
        addCommandArg("ccmProject", "-p", getCcmProject());
        addCommandArg("baseline", "-B", getBaseline());
        addCommandArg("version", "-v", getVersion());
        addCommandArg("releaseBaseline", "-R", getReleaseBaseline());
        addCommandArg("publish", "-P", getPublish());
        addCommandArg("deconfigure", "-s", getDeconfigure());
        addCommandArg("leaveFoldersWritable", "-F", getLeaveFoldersWritable());
        addCommandArg("enableTaskRebadgingGenericRelease", "-t",
                getEnableTaskRebadgingGenericRelease());
        addCommandArg("enableTaskRebadging", "-T", getEnableTaskRebadging());
        addCommandArg("rebadgeObjectVersions", "-o", getRebadgeObjectVersions());
        addCommandArg("createBaselineForRollingReleaseTag", "-i",
                getCreateBaselineForRollingReleaseTag());
        addCommandArg("active", "-a", getActive());
        addCommandArg("skipDeconfigure", "-S", getSkipDeconfigure());
        addCommandArg("useBranchReleaseMethodology", "-b",
                getUseBranchReleaseMethodology());
        addCommandArg("release", "-r", getRelease());
        addCommandArg("newBaselineName", "-n", getNewBaselineName());
    }

    /**
     * Method validates the given arguments.
     */
    protected void validateArguments() {

        if (baseline != null
                && (getCcmProject() != null || newBaselineName != null)) {
            throw new BuildException(
                    "Error: Option 'baseline' cannot be used with 'ccmProject' and 'newBaselineName'");
        }

        if (deconfigure != null && deconfigure && skipDeconfigure != null
                && skipDeconfigure) {
            throw new BuildException(
                    "Error: Use option either 'deconfigure' or 'skipDeconfigure'");
        }

        if (deconfigure != null && deconfigure && release == null) {
            throw new BuildException(
                    "Error: Option 'release' is mandatory if 'deconfigure' is set");
        }

        if (publish != null && publish && releaseBaseline != null
                && releaseBaseline) {
            throw new BuildException(
                    "Error: Use Option either 'publish' or 'releaseBaseline'");
        }

        if (enableTaskRebadging != null && enableTaskRebadging
                && enableTaskRebadgingGenericRelease != null
                && enableTaskRebadgingGenericRelease) {
            throw new BuildException(
                    "Error: Use Option either 'enableTaskRebadging' or 'enableTaskRebadgingGenericRelease'");
        }
    }

    /**
     * {@inheritDoc}
     */
    protected String getVerbosity(int choice) {
        String cmd = "";
        switch (choice) {
            case 0 :
                cmd = "-Q";
                break;
            case 1 :
                cmd = "-V";
                break;
            case 2 :
                cmd = "-I";
                break;
            case 3 :
                cmd = "-W";
                break;
            default :
                throw new BuildException("Error: Verbosity level is not recognised. "
                        + "Legal values are: 0 - quiet, 1 - verbose, 2 - Interactive "
                        + "or 3 - Walk-through Rehearsal");
        }
        return cmd;
    }

}
