Package eu.planets_project.ifr.core.services.migration.genericwrapper1

Source Code of eu.planets_project.ifr.core.services.migration.genericwrapper1.MigrationPath

package eu.planets_project.ifr.core.services.migration.genericwrapper1;

import eu.planets_project.services.datatypes.Parameter;
import eu.planets_project.ifr.core.services.migration.genericwrapper1.exceptions.MigrationException;

import java.net.URI;
import java.util.*;
import java.util.logging.Logger;

/**
* Migration path containing all information necessary to execute a (chain of)
* command-line migration tool(s).
*
* @author Asger Blekinge-Rasmussen
* @author Thomas Skou Hansen <tsh@statsbiblioteket.dk>
*/
public class MigrationPath implements Cloneable {

    // TODO: Should implement an interface to allow
    // implement new versions to support new
    // configuration file formats.

    private Logger log = Logger.getLogger(MigrationPath.class.getName());

    private URI sourceFormatURI;
    private URI destinationFormatURI;
    private List<TempFile> tempFiles;
    private Map<String, String> newTempFiles;
    private TempFile tempSourceFile;
    private TempFile tempOutputFile;
    private Map<String, Parameter> parameters;
    private Map<String, Preset> presets;
    private List<String> commandLine;
    private String defaultPreset;

    /**
     * The default constructor has default access, as it should only be used by
     * factories.
     */
    MigrationPath() {
        this.parameters = new HashMap<String, Parameter>();
        this.presets = new HashMap<String, Preset>();
        this.tempFiles = new ArrayList<TempFile>();
        this.newTempFiles = new HashMap<String, String>();
    }

    /**
     * Test whether the tool expects its input from a temporary input file or
     * standard input. If the response is <code>true</code> then the caller must
     * call {@link #getTempSourceFile()} to get hold of the temp input file
     *
     * @return <code>true</code> if the tool must have its input via a temporary
     *         file and otherwise <code>false</code>
     */
    public boolean useTempSourceFile() {
        return this.tempSourceFile != null;
    }

    /**
     * Get the temp file object for the input fule
     *
     * @return the temp file
     */
    public TempFile getTempSourceFile() {
        return this.tempSourceFile;
    }

    /**
     * Set the temp input file to be used
     *
     * @param tempFile
     *            the temp file
     */
    public void setTempInputFile(TempFile tempFile) {
        this.tempSourceFile = tempFile;
    }

    /**
     * Test whether the tool needs to write its output to a temporary file or
     * standard input. If the response is <code>true</code> then the caller must
     * call {@link #getTempOutputFile} to get the output file
     *
     * @return <code>true</code> if the tool needs a temporary file to be
     *         created for its output and otherwise <code>false</code>
     */
    public boolean useTempDestinationFile() {
        return this.tempOutputFile != null;
    }

    /**
     * Get the temp output file
     * @return the temporary output file
     */
    public TempFile getTempOutputFile() {
        return this.tempOutputFile;
    }

    /**
     * Set the temp file
     * @param tempOutputFile
     */
    public void setTempOutputFile(TempFile tempOutputFile) {
        this.tempOutputFile = tempOutputFile;
    }

    /**
     * Get the command line with the parameter identifiers substituted with the
     * parameters specified by <code>toolParameters</code>, and any tempfiles
     * replaces with their absolute location.
     *
     * The command line should be ready to feed into the processrunner.
     *
     * Note that all the temp files must have been initialised with File objects
     * by this time, as the absolute location of these files are replaced into
     * the command line
     *
     * @param toolParameters
     *            the parameters to the tool
     * @return String containing the processed command line, ready for
     *         execution.
     * @throws MigrationException
     *             if not all necessary parameters, or temporary files were
     *             defined in order to substitute all the identifiers in the
     *             command line.
     */
    public List<String> getCommandLine(Collection<Parameter> toolParameters)
            throws MigrationException {

        this.log.info("Entering getCommandLine");
        // Get a complete list of identifiers in the command line.
        final Set<String> usedIdentifiers = getIdentifiers(this.commandLine);

        // TODO: Work with other presets than the default one

        String defaultpreset = getDefaultPreset();
        // if the tool parameters contain this preset
        boolean setDefault = false;
        for (Parameter toolparam : toolParameters) {
            if (toolparam.getName().equals(defaultpreset)) {
                setDefault = true;
                Collection<Parameter> presetparams = this.presets.get(defaultpreset)
                        .getParameters(toolparam.getValue());
                toolParameters.addAll(presetparams);
                break;
            }
        }

        // if the tool parameters does not contain this preset
        if (!setDefault) {
            // lookup the value of the default preset
            // get the param names and values from there
            Preset preset = this.presets.get(defaultpreset);
            if (preset != null) {
                Collection<Parameter> defaultparams = preset
                        .getDefaultParameters();
                toolParameters.addAll(defaultparams);
            } else {
                // There is no default preset
            }
        }

        final Set<String> validIdentifiers = getValidParameterNames(toolParameters);

        this.log.info("Found these valid identifiers");
        this.log.info(validIdentifiers.toString());

        this.log.info(this.tempSourceFile.toString());
        for (TempFile tempfile : this.tempFiles) {
            this.log.info("Adding tempfile " + tempfile.getCodename()
                    + " as valid identifier");
            validIdentifiers.add(tempfile.getCodename());
        }

        if (useTempSourceFile()) {
            this.log.info("Adding temp input file as valid identifier "
                    + this.tempSourceFile.getCodename());
            validIdentifiers.add(this.tempSourceFile.getCodename());
        }

        if (useTempDestinationFile()) {
            this.log.info("Adding temp dest file as valid identifier: "
                    + this.tempOutputFile.getCodename());
            validIdentifiers.add(this.tempOutputFile.getCodename());
        }

        // TODO: Check the parameters and filename mappings for injection
        // attacks by sanity checking the parameters -
        // throw exception in case of failure. However, it may be safe omitting
        // the test for the file name mappings, as they are solely based on the
        // configuration file and what the generic wrapper is doing.

        if (!validIdentifiers.containsAll(usedIdentifiers)) {
            usedIdentifiers.removeAll(validIdentifiers);
            throw new MigrationException("Cannot build the command line. "
                    + "Missing values for these identifiers: "
                    + usedIdentifiers);
        }

        List<String> executableCommandLine = new ArrayList<String>();
        for (String cmd : this.commandLine) {
            for (Parameter parameter : toolParameters) {
                cmd = cmd.replaceAll("#" + parameter.getName(), parameter
                        .getValue());
            }

            for (TempFile tempFile : this.tempFiles) {
                cmd = cmd.replaceAll("#" + tempFile.getCodename(), tempFile
                        .getFile().getAbsolutePath());
            }
            if (useTempSourceFile()) {
                cmd = cmd.replaceAll("#" + this.tempSourceFile.getCodename(),
                        this.tempSourceFile.getFile().getAbsolutePath());
            }
            if (useTempDestinationFile()) {
                cmd = cmd.replaceAll("#" + this.tempOutputFile.getCodename(),
                        this.tempOutputFile.getFile().getAbsolutePath());
            }
            executableCommandLine.add(cmd);
        }

        return executableCommandLine;
    }

    /**
     * Get a <code>Set</code> containing all the names of parameters from
     * <code>parameters</code> that have been initialised with a value, and are
     * thus valid.
     *
     * @param parameters
     *            a <code>Collection</code> of parameters to get valid
     *            parameters from.
     * @return a <code>Set</code> containing the names of all the parameters
     *         from <code>parameters</code> that have a value.
     */
    private Set<String> getValidParameterNames(Collection<Parameter> parameters) {
        Set<String> validParameters = new HashSet<String>();
        for (Parameter parameter : parameters) {
            final String parameterName = parameter.getName();
            if ((parameterName != null) && ("".equals(parameterName) == false)
                    && (parameter.getValue() != null)) {
                validParameters.add(parameterName);
            }
        }

        return validParameters;
    }

    /**
     * Get the names of all identifiers (all words with a leading '#') of the
     * form <code>%myIdentifier%</code> found in
     * <code>stringWithIdentifiers</code>. If the previous example was found in
     * the string, then the returned set would contain the string
     * &quot;myIdentifier&quot;.
     *
     * @param stringListWithIdentifiers
     *            a <code>String</code> containing identifiers.
     * @return a <code>Set</code> containing the identifiers found.
     */
    private Set<String> getIdentifiers(List<String> stringListWithIdentifiers) {
        Set<String> foundIdentifiers = new HashSet<String>();

        for (String stringWithIdentifiers : stringListWithIdentifiers) {
            StringTokenizer stringTokenizer = new StringTokenizer(
                    stringWithIdentifiers);
            while (stringTokenizer.hasMoreTokens()) {
                String identifier = stringTokenizer.nextToken();
                if (identifier.charAt(0) == '#') {
                    identifier = identifier.substring(1);
                    foundIdentifiers.add(identifier);
                }
            }
        }
        return foundIdentifiers;
    }

    /**
     * Get the unprocessed command line.
     *
     * @return String containing the unprocessed command line, containing
     *         parameter identifiers/keys.
     */
    public List<String> getCommandLine() {
        return this.commandLine;
    }

    /**
     * Set the command line attribute of this migration path. The command line
     * may contain tags of the form <code>%my_tag%</code> to indicate that
     * either a parameter or a name of a temporary file must be put in place at
     * a specific location. However, these tags must be defined using the
     * {@link #setToolParameters} methods.
     *
     * @param commandLine
     *            <code>String</code> containing the command line to set.
     */
    public void setCommandLine(List<String> commandLine) {
        this.commandLine = commandLine;
    }

    /**
     * Get the ID of the default preset category to apply if no preset or
     * parameters are specified by the user of this migration path.
     *
     * @return ID of the default preset category
     */
    public String getDefaultPreset() {
        return this.defaultPreset;
    }

    /**
     * Set the ID of the default preset category to apply if no preset or
     * parameters are specified by the user of this migration path.
     *
     * @param defaultPreset
     *            the ID of the default preset category.
     */
    public void setDefaultPreset(String defaultPreset) {
        this.defaultPreset = defaultPreset;
    }

    /**
     * Get the destination format <code>URI</code> of this migration path.
     *
     * @return <code>URI</code> identifying the destination format of this
     *         migration path.
     */
    public URI getDestinationFormat() {
        return this.destinationFormatURI;
    }

    /**
     * Set the destination format <code>URI</code> for this
     * <code>CliMigrationPath</code>.
     *
     * @param destinationFormatURI
     *            destination format <code>URI</code> to set.
     */
    public void setDestinationFormat(URI destinationFormatURI) {
        this.destinationFormatURI = destinationFormatURI;
    }

    /**
     * Get the source format <code>URI</code> of this migration path.
     *
     * @return <code>URI</code> identifying the source format of this migration
     *         path.
     */
    public URI getSourceFormat() {
        return this.sourceFormatURI;
    }

    /**
     * Set the source format <code>URI</code> for this
     * <code>CliMigrationPath</code>.
     *
     * @param sourceFormatURI
     *            source format <code>URI</code> to set.
     */
    public void setSourceFormat(URI sourceFormatURI) {
        this.sourceFormatURI = sourceFormatURI;
    }

    /**
     * Get the list of interim temp files.
     *
     * @return a list of temp files.
     */
    public List<TempFile> getTempFileDeclarations() {
        return this.tempFiles;
    }

    /**
     * Add a list of temp files
     * @param tempFileDeclarations
     * @deprecated {@link MigrationPath#addTempFilesDeclarations(Map)} will replace this method
     */
    @Deprecated
    public void addTempFilesDeclarations(List<TempFile> tempFileDeclarations) {
        this.tempFiles.addAll(tempFileDeclarations);

    }
   
    /**
     * Add a map defining the relationship between the labels in the command
     * line that should be substituted with file names of temporary files with
     * the actual names of these. Multiple calls to this method will just add
     * more mappings to the internal map, however, if a label in the specified
     * map has already been used in the internal map of this migration path,
     * then the previous mapping will be removed.
     *
     * @param tempFileDeclarations
     *            a map containing a paring of temp. file labels and optionally
     *            a file name to be added to the internal map.
     */
    public void addTempFilesDeclarations(
            Map<String, String> tempFileDeclarations) {

        this.newTempFiles.putAll(tempFileDeclarations);
    }

    //TODO: Kill when the time is right.
    /**
     * @param tempFileDeclaration
     */
    @Deprecated
    public void addTempFilesDeclaration(TempFile tempFileDeclaration) {
        this.tempFiles.add(tempFileDeclaration);

    }

    /**
     * Add a relationship between the <code>label</code> and
     * <code>filename</code>. The label must match a label used in the command
     * line, indicating that it should be substituted with a name of a temporary
     * file. That file name can either be specified by <code>filename</code> or
     * it will be auto-generated if it is omitted (<code>null</code>). Multiple
     * calls to this method will just add more mappings to the internal map,
     * however, if the specified label has already been used in the internal map
     * of this migration path, then the previous mapping will be removed.
     * @param label
     * @param filename
     *
     * @return the value previously associated with <code>label</code> or
     *         <code>null</code> if no value was associated with it. However, it
     *         may also indicate that <code>label</code> was actually associated
     *         with <code>null</code>.
     */
    public String addTempFilesDeclaration(String label, String filename) {

        return this.newTempFiles.put(label, filename);
    }

    /**
     * Get all the parameters that must be initialised in order to execute the
     * command line. The returned <code>Parameter</code> instances have no value
     * specified, thus, their values must be initialised prior calling the
     * {@link #getCommandLine} method to obtain the actual command line to
     * execute.
     *
     * @return <code>Collection</code> containing an <code>Parameter</code>
     *         instance for each parameter that must be specified in order to
     *         execute the command line of this migration path.
     */
    public Collection<Parameter> getToolParameters() {
        return this.parameters.values();
    }

    /**
     * Declare a list of parameters that the user of the tool must provide
     * values for in order to execute the tool.
     *
     * @param toolParameters
     *            Collection of tool parameters that must be initialised and
     *            passed on to the {@link #getCommandLine} method to get the
     *            actual command to execute.
     */
    public void setToolParameters(Collection<Parameter> toolParameters) {
        for (Parameter parameter : toolParameters) {
            this.parameters.put(parameter.getName(), parameter);
        }
    }

    /**
     * Get a collection of all available preset categories for this migration
     * path.
     *
     * @return <code>Collection</code> containing the names/IDs of all the
     *         available preset categories.
     */
    public Collection<String> getToolPresetCategories() {
        return this.presets.keySet();
    }

    @Override
  public String toString() {
        return "CliMigrationPath: " + this.sourceFormatURI + " -> "
                + this.destinationFormatURI + " Command: " + this.commandLine;
    }

    // TODO: clone() will probably be obsolete with the introduction of the new
    // version of the migration path factory
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone(); // To change body of overridden methods use File |
                              // Settings | File Templates.
    }

    /**
     * @return the Migration Path
     */
    public eu.planets_project.services.datatypes.MigrationPath getAsPlanetsPath() {
        URI outformat = getDestinationFormat();
        URI informat = getSourceFormat();
        List<Parameter> params = new ArrayList<Parameter>();

        for (Preset preset : this.presets.values()) {
            params.add(preset.getAsPlanetsParameter());
        }
        return new eu.planets_project.services.datatypes.MigrationPath(
                informat, outformat, params);
    }

    /**
     * @param preset
     */
    public void addPreset(Preset preset) {
        this.presets.put(preset.getName(), preset);
    }
}
TOP

Related Classes of eu.planets_project.ifr.core.services.migration.genericwrapper1.MigrationPath

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.