Package org.fcrepo.client.utility.validate.process

Source Code of org.fcrepo.client.utility.validate.process.ValidatorProcessParameters

/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/

package org.fcrepo.client.utility.validate.process;

import java.io.File;

import java.net.MalformedURLException;
import java.net.URL;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.fcrepo.client.utility.validate.remote.ServiceInfo;
import org.fcrepo.server.errors.QueryParseException;
import org.fcrepo.server.search.Condition;
import org.fcrepo.server.search.FieldSearchQuery;

/**
* Parse and store the command-line arguments for the {@link ValidatorProcess}.
*
* @author Jim Blake
*/
public class ValidatorProcessParameters {

    /**
     * A description of how to invoke the process.
     */
    public static final String USAGE =
            "usage: ValidatorProcess -serverurl <url> -username <username> "
                    + "-password <password> "
                    + "{-terms <terms> | -query <query> | -pidfile <path>} "
                    + "[-verbose]";

    /**
     * Required parameter: the base url of the Fedora repository server. E.g.
     * <code>http://localhost:8080/fedora</code>
     */
    public static final String PARAMETER_SERVER_URL = "-serverurl";

    /**
     * Required parameter: a user who is authorized to access the repository
     * objects. E.g. <code>fedoraAdmin</code>
     */
    public static final String PARAMETER_USERNAME = "-username";

    /**
     * Required parameter: the password for the user specified by '-username'.
     * E.g. <code>fedoraAdminPassword</code>
     */
    public static final String PARAMETER_PASSWORD = "-password";

    /**
     * Optional parameter: a "terms" string that can be passed to the
     * <code>findObjects</code> method in API-A. Supply any of -terms, -query,
     * or -pidfile, but not more than one. E.g. <code>demo*</code>
     */
    public static final String PARAMETER_TERMS = "-terms";

    /**
     * Optional parameter: a "query" string that can be passed to the
     * <code>findObjects</code> method in API-A. Supply any of -terms, -query,
     * or -pidfile, but not more than one. E.g. <code>state~A</code>
     */
    public static final String PARAMETER_QUERY = "-query";

    /**
     * Optional parameter: the path to a file containing a list of PIDs - these
     * are the objects to be validated - one PID per line, blank lines are
     * ignored, lines beginning with octothorpe ('#'), are comments. Supply any
     * of -terms, -query, or -pidfile, but not more than one. E.g.
     * <code>/usr/local/junk/pidfile.txt</code>
     */
    public static final String PARAMETER_PIDFILE = "-pidfile";

    /**
     * Optional parameter: whether to print all messages during validation.
     * Normally, only messages that are relevant to an object's being marked
     * invalid or indeterminate are printed.
     */
    public static final String PARAMETER_VERBOSE = "-verbose";

    public enum IteratorType {
        FS_QUERY, PIDFILE
    }

    private static final Set<String> ALL_PARAMETERS =
            Collections.unmodifiableSet(new HashSet<String>(Arrays
                    .asList(PARAMETER_SERVER_URL,
                            PARAMETER_USERNAME,
                            PARAMETER_PASSWORD,
                            PARAMETER_TERMS,
                            PARAMETER_QUERY,
                            PARAMETER_PIDFILE,
                            PARAMETER_VERBOSE)));

    /**
     * The URL, username and password of the repository we are operating
     * against.
     */
    private final ServiceInfo serviceInfo;

    /**
     * If the command-line arguments contain -terms or -query, this is set to
     * {@link IteratorType#FS_QUERY}. If we have a -pidfile instead, this is
     * set to {@link IteratorType#PIDFILE}.
     */
    private final IteratorType iteratorType;

    /**
     * An API-A query object, built from either the -terms or -query parameter.
     */
    private final FieldSearchQuery fieldSearchQuery;

    /**
     * A pidfile, from the -pidfile parameter.
     */
    private final File pidfile;

    /**
     * Whether to print verbose messages, from the -verbose parameter.
     */
    private final boolean verbose;

    /**
     * Parse the command line arguments and check for validity.
     */
    public ValidatorProcessParameters(String[] args) {
        Map<String, String> parms = parseArgsIntoMap(args);

        String username = getRequiredParameter(PARAMETER_USERNAME, parms);
        String password = getRequiredParameter(PARAMETER_PASSWORD, parms);
        URL serverUrl = getRequiredUrlParameter(PARAMETER_SERVER_URL, parms);
        serviceInfo = new ServiceInfo(serverUrl, username, password);

        String query = getOptionalParameter(PARAMETER_QUERY, parms);
        String terms = getOptionalParameter(PARAMETER_TERMS, parms);
        String pidfileParm = getOptionalParameter(PARAMETER_PIDFILE, parms);

        iteratorType = figureOutIteratorType(query, terms, pidfileParm);
        if (iteratorType == IteratorType.FS_QUERY) {
            fieldSearchQuery = assembleFieldSearchQuery(query, terms);
            pidfile = null;
        } else {
            fieldSearchQuery = null;
            pidfile = assemblePidfile(pidfileParm);
        }

        if (parms.containsKey(PARAMETER_VERBOSE)) {
            verbose = true;
        } else {
            verbose = false;
        }
    }

    /**
     * Decide which of the command line arguments are keywords and which are
     * values, and build a map to hold them.
     */
    private Map<String, String> parseArgsIntoMap(String[] args) {
        Map<String, String> parms = new HashMap<String, String>();

        for (int i = 0; i < args.length; i++) {
            String key = args[i];
            if (!isKeyword(key)) {
                throw new ValidatorProcessUsageException("'" + key
                        + "' is not a keyword.");
            }
            if (!ALL_PARAMETERS.contains(key)) {
                throw new ValidatorProcessUsageException("'" + key
                        + "' is not a recognized keyword.");
            }
            if (i >= args.length - 1) {
                parms.put(key, null);
            } else {
                String value = args[i + 1];
                if (isKeyword(value)) {
                    parms.put(key, null);
                } else {
                    parms.put(key, value);
                    i++;
                }
            }
        }

        return parms;
    }

    private boolean isKeyword(String arg) {
        return arg.startsWith("-");
    }

    /**
     * Get the requested parameter from the map. Complain if it's not found or
     * has a null value.
     */
    private String getRequiredParameter(String keyword,
                                        Map<String, String> parms) {
        if (!parms.containsKey(keyword)) {
            throw new ValidatorProcessUsageException("Parameter '" + keyword
                    + "' is required.");
        }

        String value = parms.get(keyword);
        if (value == null) {
            throw new ValidatorProcessUsageException("Parameter '" + keyword
                    + "' requires a value.");
        } else {
            return value;
        }
    }

    /**
     * Get the requested parameter from the map. Complain if not found, or not a
     * valid URL.
     */
    private URL getRequiredUrlParameter(String keyword,
                                        Map<String, String> parms) {
        String urlString = getRequiredParameter(keyword, parms);
        try {
            return new URL(urlString);
        } catch (MalformedURLException e) {
            throw new ValidatorProcessUsageException("Value '" + urlString
                    + "' for parameter '" + keyword + "' is not a valid URL: "
                    + e.getMessage());
        }
    }

    /**
     * Get the requested parameter from the map. If it's not there, return null,
     * but if it's there with no value, complain.
     */
    private String getOptionalParameter(String keyword,
                                        Map<String, String> parms) {
        if (!parms.containsKey(keyword)) {
            return null;
        }

        String value = parms.get(keyword);
        if (value == null) {
            throw new ValidatorProcessUsageException("If parameter '" + keyword
                    + "' is provided, it must have a value.");
        } else {
            return value;
        }
    }

    /**
     * Look at the parameters. Is this a query-based request or a pidfile-based
     * request? If we put in too many parms, or not enough, that's a problem.
     */
    private IteratorType figureOutIteratorType(String query,
                                               String terms,
                                               String pidfileParm) {
        int howMany =
                (query == null ? 0 : 1) + (terms == null ? 0 : 1)
                        + (pidfileParm == null ? 0 : 1);
        if (howMany == 0) {
            throw new ValidatorProcessUsageException("You must provide "
                    + "either '" + PARAMETER_QUERY + "', '" + PARAMETER_TERMS
                    + "' or '" + PARAMETER_PIDFILE + "'.");
        }
        if (howMany > 1) {
            throw new ValidatorProcessUsageException("You must provide only "
                    + "one of these parameters: '" + PARAMETER_QUERY + "', '"
                    + PARAMETER_TERMS + "' or '" + PARAMETER_PIDFILE + "'.");
        }

        return pidfileParm == null ? IteratorType.FS_QUERY
                : IteratorType.PIDFILE;
    }

    /**
     * A {@link FieldSearchQuery} may be made from a terms string or a query
     * string, but not both.
     */
    private FieldSearchQuery assembleFieldSearchQuery(String query, String terms) {
        if (terms != null) {
            return new FieldSearchQuery(terms);
        } else {
            try {
                return new FieldSearchQuery(Condition.getConditions(query));
            } catch (QueryParseException e) {
                throw new ValidatorProcessUsageException("Value '" + query
                        + "' of parameter '" + PARAMETER_QUERY
                        + "' is not a valid query string.");
            }
        }
    }

    /**
     * Is there a valid file out there for this parm? We already know that the
     * parms is not null.
     */
    private File assemblePidfile(String pidfileParm) {
        File pidfile = new File(pidfileParm);
        if (!pidfile.exists()) {
            throw new ValidatorProcessUsageException("-pidfile does not exist: '"
                    + pidfileParm + "'");
        }
        if (!pidfile.canRead()) {
            throw new ValidatorProcessUsageException("-pidfile is not readable: '"
                    + pidfileParm + "'");
        }
        return pidfile;
    }

    public ServiceInfo getServiceInfo() {
        return serviceInfo;
    }

    public IteratorType getIteratorType() {
        return iteratorType;
    }

    public FieldSearchQuery getQuery() {
        return fieldSearchQuery;
    }

    public File getPidfile() {
        return pidfile;
    }

    public boolean getVerbose() {
        return verbose;
    }
}
TOP

Related Classes of org.fcrepo.client.utility.validate.process.ValidatorProcessParameters

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.