org.pentaho.di.resource.SimpleResourceNaming.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.di.resource.SimpleResourceNaming.java

Source

/*! ******************************************************************************
 *
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com
 *
 *******************************************************************************
 *
 * 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.pentaho.di.resource;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.pentaho.di.core.variables.VariableSpace;

public class SimpleResourceNaming implements ResourceNamingInterface {

    private final Map<String, String> namedResources = new HashMap<String, String>();

    /**
     * The fileSystemPrefix would be appropriate for something like:
     *
     * zip://somefile.zip! or somefilesystem://export/folder/
     */
    private String fileSystemPrefix;

    private boolean useOriginalPathInTargetName;

    private Map<String, String> directoryMap;
    private int parameterNr;

    public SimpleResourceNaming() {
        super();

        directoryMap = new HashMap<String, String>();
        parameterNr = 0;
    }

    public SimpleResourceNaming(String fileSystemPrefix) {
        super();
        this.fileSystemPrefix = fileSystemPrefix;
    }

    public String nameResource(FileObject fileObject, VariableSpace space, boolean includeFileName)
            throws FileSystemException {
        if (includeFileName) {
            return handleDataFile(fileObject.getName().getBaseName(), fileObject.getParent().getURL().toString(),
                    "");
        } else {
            return handleDataFile("", fileObject.getURL().toString(), "");
        }
    }

    public String nameResource(String prefix, String originalFilePath, String extension,
            FileNamingType namingType) {
        switch (namingType) {
        case DATA_FILE:
            return handleDataFile(prefix, originalFilePath, extension);

        case SHELL_SCRIPT:
            return handleScript(prefix, originalFilePath, extension);

        case TRANSFORMATION:
        case JOB:
            return handleTransformationOrJob(prefix, originalFilePath, extension);

        default:
            throw new AssertionError("Unknown file naming type: " + namingType);
        }
    }

    private String handleTransformationOrJob(String prefix, String originalFilePath, String extension) {
        //
        // End result could look like any of the following:
        //
        // Inputs:
        // Prefix : Marc Sample Transformation
        // Original Path: D:\japps\pentaho\kettle\samples
        // Extension : .ktr
        //
        // Output Example 1 (no file system prefix, no path used)
        // Marc_Sample_Transformation.ktr
        // Output Example 2 (file system prefix: ${KETTLE_FILE_BASE}!, no path used)
        // ${KETTLE_FILE_BASE}!Marc_Sample_Transformation.ktr
        // Output Example 3 (file system prefix: ${KETTLE_FILE_BASE}!, path is used)
        // ${KETTLE_FILE_BASE}!japps/pentaho/kettle/samples/Marc_Sample_Transformation.ktr
        //
        //
        assert prefix != null;
        assert extension != null;

        String lookup = (originalFilePath != null ? originalFilePath : "") + "/" + prefix + "." + extension;
        String rtn = namedResources.get(lookup);
        if (rtn == null) {
            // Never generated a name for this... Generate a new file name
            String fixedPath = null;
            if (useOriginalPathInTargetName) {
                fixedPath = fixPath(originalFilePath);
            }

            rtn = (fileSystemPrefix != null ? fileSystemPrefix : "")
                    + (fixedPath != null ? fixedPath + (fixedPath.endsWith("/") ? "" : "/") : "")
                    + fixFileName(prefix, extension);

            String ext = (extension.charAt(0) == '.' ? extension : "." + extension);

            String uniqueId = this.getFileNameUniqueIdentifier(rtn, extension);
            rtn += (uniqueId != null ? "_" + uniqueId : "");
            rtn += ext;

            namedResources.put(lookup, rtn); // Keep track of already generated object names...
        }
        return rtn;
    }

    private String handleScript(String prefix, String originalFilePath, String extension) {
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * We have a data file and we need to create a reference to this (relative/absolute) path name. The cleanest way to do
     * this is by calculating the absolute filename. Then we put the path to the file in a parameter that we remember.
     *
     * FILE_LOCATION_01, FILE_LOCATION_02, etc.
     *
     * We keep a unique list of parameters this way.
     *
     * @param prefix
     *          the name of the file (foo.csv)
     * @param originalFilePath
     *          directory in which the file lives (file://path/to/foo/bar/)
     * @param extension
     *          ignored (null)
     * @return the new filename including the created parameter...
     */
    private String handleDataFile(String prefix, String originalFilePath, String extension) {

        // See if we find the path in the directory map that we have...
        //
        String parameter = directoryMap.get(originalFilePath);
        if (parameter == null) {

            parameter = createNewParameterName(originalFilePath);

            // Add it to the map...
            //
            directoryMap.put(originalFilePath, parameter);
        }

        return "${" + parameter + "}/" + prefix;
    }

    /**
     * Create a parameter name from an path TODO: actually use the original path
     *
     * @param originalFilePath
     * @return the new parameter name
     */
    private String createNewParameterName(String originalFilePath) {
        parameterNr++;
        return "DATA_PATH_" + parameterNr;
    }

    protected String getFileNameUniqueIdentifier(String filename, String extension) {
        //
        // This implementation assumes that the file name will be sufficiently
        // unique.
        //
        return null;
    }

    protected String fixPath(String originalPathName) {
        // This should convert all of the following into foo\bar or foo/bar
        // D:\foo\bar
        // /foo/bar
        // \\server\share\foo\bar
        //
        String rtn = originalPathName.substring(getPrefixLength(originalPathName));
        // Now, rtn has either either foo/bar or foo\bar. So, convert the \ to /
        // and return.
        return rtn.replace('\\', '/');
    }

    private int getPrefixLength(String fileName) {
        if (fileName.charAt(1) == ':') { // Handle D:\foo\bar\
            return 3;
        } else if (fileName.charAt(0) == '\\' && fileName.charAt(1) == '\\') { // Handle \\server\sharename\foo\bar
            int start = 0;
            int slashesFound = 0;
            for (int i = 2; i < fileName.length(); i++) {
                if (fileName.charAt(i) == '\\') {
                    slashesFound++;
                }
                if (slashesFound == 2) {
                    start = i + 1;
                    break;
                }
            }
            return start;
        } else if (fileName.charAt(0) == '/') { // handle /foo/bar
            return 1;
        }
        return 0;
    }

    /**
     * This method turns a friendly name which could contain all manner of invalid characters for a file name into one
     * that's more conducive to being a file name.
     *
     * @param name
     *          The name to fix up.
     * @param extension
     *          the requested extension to see if we don't end up with 2 extensions (export of XML to XML)
     * @return
     */
    protected String fixFileName(String name, String extension) {
        int length = name.length();
        if (name.endsWith("." + extension)) {
            length -= 1 + extension.length();
        } else if (name.endsWith(extension)) {
            length -= extension.length();
        }

        StringBuffer buff = new StringBuffer(length);
        char ch;
        for (int i = 0; i < length; i++) {
            ch = name.charAt(i);
            if (ch == ' ') {
                buff.append(ch);
            } else {
                if ((ch <= '/') || (ch >= ':' && ch <= '?') || (ch >= '[' && ch <= '`')
                        || (ch >= '{' && ch <= '~')) {
                    buff.append('_');
                } else {
                    buff.append(ch);
                }
            }
        }
        return buff.toString();
    }

    public String getFileSystemPrefix() {
        return this.fileSystemPrefix;
    }

    public void setFileSystemPrefix(String value) {
        this.fileSystemPrefix = value;
    }

    public boolean getUseOriginalPathInTargetName() {
        return this.useOriginalPathInTargetName;
    }

    public void setUseOriginalPathInTargetName(boolean value) {
        this.useOriginalPathInTargetName = value;
    }

    /**
     * @return the directoryMap
     */
    public Map<String, String> getDirectoryMap() {
        return directoryMap;
    }

    /**
     * @param directoryMap
     *          the directoryMap to set
     */
    public void setDirectoryMap(Map<String, String> directoryMap) {
        this.directoryMap = directoryMap;
    }
}