/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/tools/stores/Stores.java,v 1.3 2004/07/30 06:52:06 ozeigermann Exp $
 * $Revision: 1.3 $
 * $Date: 2004/07/30 06:52:06 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.slide.store.tamino.tools.stores;

import java.io.File;
import org.apache.slide.store.tamino.tools.Command;
import org.apache.slide.store.tamino.tools.Tws;
import org.apache.slide.store.tamino.tools.stores.XDomainFileHandler;
import org.apache.slide.util.Strings;
import org.apache.slide.util.XAssertionFailed;
import org.apache.slide.util.XException;
import org.apache.slide.util.XUri;
import org.apache.slide.util.cli.Abort;
import org.apache.slide.util.cli.Actuals;
import org.apache.slide.util.cli.CommandLine;


/**
 ** Tool to handle store-specific configuration information contained in the Domain.XML
 ** file. This class is not synchronized, it assumes to be executed in a separate VM (thus,
 ** it cannot conflict with a running xdav server).
 **
 ** @author    peter.nevermann@softwareag.com
 ** @version   $Revision: 1.3 $
 **/
public class Stores extends Tws {
    public Stores() {
        super(new String[] { CMD_NEW, CMD_LIST, CMD_REMOVE, CMD_GET, CMD_SET, CMD_TAKEOVER },
              "stores",
              "Adds and removes stores in Domain.xml.",
              new String[] {
                    "Configures a Tamino collection as a store for the Tamino WebDAV Server. "+
                    "The relevant parameters are automatically changed in the configuration file " +
                    "Domain.xml.",
                    "A store and its associated stores for DeltaV-related resources are always "+
                    "treated as a unit. These additional stores can be individual or shared, "+
                    "depending on whether the global path parameters (e.g. historypath) are "+
                    "parameterized by ${store} or not." },
                  "Commands:\n"+
                  "  list                    Print list of configured stores. If the option -all\n"+
                  "                          is specified, the associated stores for DeltaV-\n"+
                  "                          related resources and system stores are displayed.\n"+
                  "  get                     Print the XML configuration for the store specified \n"+
                  "                          by -store; if a directory is specified by -outDir,\n"+
                  "                          a file <store>.xml is created in that location.\n"+
                  "                          ---\n"+
                  "                          If -global is specified instead of a store:\n"+
                  "                          Print the global configuration parameters; if a \n"+
                  "                          directory is specified by -outDir, a file \n"+
                  "                          deltav.xml is created in that location.\n"+
                  "  set                     Set the store configuration from the XML file given\n"+
                  "                          by -configFile;\n"+
                  "                          As the store name is taken from the file name, the \n"+
                  "                          -store option is not required; however, if it\n"+
                  "                          is specified it takes precedence.\n"+
                  "                          If the store exists, its configuration is replaced\n"+
                  "                          by the given one; otherwise, a new store\n"+
                  "                          configuration is added.\n"+
                  "                          The associated stores for DeltaV-related resources \n"+
                  "                          are created automatically, if necessary.\n"+
                  "                          ---\n"+
                  "                          If -global is additionally specified:\n"+
                  "                          Set the global configuration from the XML file \n"+
                  "                          given by -configFile; if global parameters exist, \n"+
                  "                          they are replaced by the given ones; otherwise, \n"+
                  "                          new global parameters are added.\n"+
                  "  remove                  Remove the store configuration for the store \n"+
                  "                          specified by -store.\n"+
                  "                          The associated stores for DeltaV-related resources \n"+
                  "                          are removed automatically, if not shared. Shared \n"+
                  "                          DeltaV store configurations are removed when the \n"+
                  "                          last store configuration is removed.\n"+
                  "                          ---\n"+
                  "                          If -global is specified instead of a store:\n"+
                  "                          The global parameters are removed. \n"+
                  "  takeover                Take-over store configurations from a different\n"+
                  "                          Domain.xml file.\n"+
                  "                          As an application, store configurations from a\n"+
                  "                          previous Tamino WebDAV Server version can be taken\n"+
                  "                          over.\n"+
                  "                          Use the -fromDomainFile option to specify the \n"+
                  "                          source Domain.xml file. If a store is specified by\n"+
                  "                          -store, only that store is taken-over. Otherwise, all\n"+
                  "                          stores are taken over. Use the -overwrite option to\n"+
                  "                          specify whether existing stores should be \n"+
                  "                          overwritten.\n"+
                  "\nOptions:\n"+
                  "  -?, -help               This help information.\n"+
                  "  -domainFile <path>      The path to the Domain.xml file; if omitted, the file\n"+
                  "                          is sought in the directory TAMINOWEBDAVSERVER_HOME.\n"+
                  "  -store <store>          The name of the store.\n"+
                  "  -global                 Refers to the global configuration parameters.\n"+
                  "  -configFile <file>      The input file for the setConfig command;\n"+
                  "                          the XML file must conform to the following DTD:\n"+
                  "                          <!ELEMENT configuration (parameter+,\n"+
                  "                              history?, workspace?, workingresource?)>\n"+
                  "                          <!ATTLIST configuration\n"+
                  "                              namespace CDATA #IMPLIED>\n"+
                  "                          <!ELEMENT parameter (#PCDATA)>\n"+
                  "                          <!ATTLIST parameter\n"+
                  "                              name CDATA #REQUIRED>\n"+
                  "                          <!ELEMENT history (parameter+)>\n"+
                  "                          <!ELEMENT workspace (parameter+)>\n"+
                  "                          <!ELEMENT workingresource (parameter+)>\n"+
                  "  -url <url>              URL to create store at.\n"+
                  "  -outDir <dir>           The output directory for the getConfig command.\n"+
                  "  -fromDomainFile <path>  The path to the source Domain.xml file for the \n"+
                  "                          takeover command.\n"+
                  "  -overwrite              The overwrite flag for the takeover command.\n"+
                  "\n"+
                  "Examples:\n"+
                  "  inodavstores set -configFile mydir/testcoll.xml\n"+
                  "  inodavstores set -url http://localhost/tamino/mydb/newcoll\n"+
                  "  inodavstores remove -store testcoll\n");
    }
    
    public CommandLine commandLine() {
        CommandLine cl;
        
        cl = new CommandLine(false);
        cl.addOption(ARG_DOMAIN);
        cl.addOption(ARG_FROM);
        cl.addOption(ARG_CONFIG);
        cl.addOption(ARG_OUT);
        cl.addOption(ARG_STORE);
        cl.addOption(ARG_URL);
        cl.addSwitch(ARG_OVERWRITE);
        cl.addSwitch(ARG_GLOBAL);
        return cl;
    }
    
    public static final String
        CMD_NEW           = "new",
        CMD_LIST          = "list",
        CMD_GET           = "get",
        CMD_SET           = "set",
        CMD_REMOVE        = "remove",
        CMD_TAKEOVER      = "takeover";
    
    /** formal names */
    private static final String
        ARG_DOMAIN    = "domainFile",
        ARG_FROM      = "fromDomainFile",
        ARG_CONFIG    = "configFile",
        ARG_URL       = "url",
        ARG_OUT       = "outDir",
        ARG_STORE     = "store",
        ARG_OVERWRITE = "overwrite",
        ARG_GLOBAL    = "global";
    
    public Command dispatch(String cmd, Actuals actuals) throws Abort, XException {
        String domainXml;       // path to Domain.xml
        final String fromDomainFile; // path to source Domain.xml for takeover
        final String url;
        final String configXml;     // path to config file
        final String outDirName;        // output directory
        final File outDir;
        final String store;
        final boolean overwrite;    // overwrite flag for takeover command
        boolean globalConfig;
        final XDomainFileHandler dfh;
        final String namespace;
        
        namespace = getNamespace();
        domainXml = actuals.getString(ARG_DOMAIN);
        fromDomainFile = actuals.getString(ARG_FROM);
        configXml = actuals.getString(ARG_CONFIG);
        url = actuals.getString(ARG_URL);
        outDirName = actuals.getString(ARG_OUT);
        if (outDirName != null) {
            outDir = new File(outDirName);
            if (!outDir.isDirectory()) {
                throw new Abort("output directory does not exist: " + outDir);
            }
        } else {
            outDir = null;
        }
        store = actuals.getString(ARG_STORE);
        overwrite = actuals.getSwitch(ARG_OVERWRITE);
        globalConfig = actuals.getSwitch(ARG_GLOBAL);
        
        if (configXml != null) {
            File f = new File(configXml);
            if( !f.exists() ) {
                throw new Abort("File '" + configXml + "' not found");
            }
            if( !Strings.endsWithIgnoreCase(configXml, XUri.XML_SUFF) ) {
                throw new Abort("File '" + configXml + "' must end with '" + XUri.XML_SUFF + "'");
            }
        }
        if (CMD_NEW.equals(cmd)) {
            if (globalConfig) {
                return WriteCommand.newDomain(out, namespace, outDir);
            } else {
                exists(store);
                return WriteCommand.newStore(out, namespace, store, outDir);
            }
        } else {
            if (domainXml == null) {
                dfh = XDomainFileHandler.create(true);
            } else {
                dfh = XDomainFileHandler.create(domainXml);
            }
            if (CMD_LIST.equals(cmd)) {
                return StoreCommands.listStores(out, dfh, namespace);
            } else if (CMD_GET.equals(cmd)) {
                if (globalConfig) {
                    return WriteCommand.global(dfh, outDir, out);
                } else {
                    exists(store);
                    return WriteCommand.store(dfh, namespace, store, outDir, out);
                }
            } else if (CMD_REMOVE.equals(cmd)) {
                if (globalConfig) {
                    return StoreCommands.removeGlobal(out, dfh);
                } else {
                    exists(store);
                    return StoreCommands.removeStore(out, dfh, namespace, store);
                }
            } else if (CMD_SET.equals(cmd)) {
                if (globalConfig) {
                    return StoreCommands.setGlobal(out, dfh, configXml);
                } else {
                    return StoreCommands.setStore(out, dfh, namespace, url, configXml);
                }
            } else if (CMD_TAKEOVER.equals(cmd)) {
                return new Takeover(out, dfh, fromDomainFile, namespace, store, overwrite);
            } else {
                throw new XAssertionFailed();
            }
        }
    }
    
    private static void exists(String store) throws Abort {
        if (store == null) {
            throw new Abort("Missing store name");
        }
    }
}


