All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pentaho.di.resource.SimpleResourceNaming Maven / Gradle / Ivy

The newest version!
/*! ******************************************************************************
 *
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2017 by Hitachi Vantara : 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.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.pentaho.di.core.variables.VariableSpace;

public class SimpleResourceNaming implements ResourceNamingInterface {

  private final Map namedResources = new HashMap();

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

  private boolean useOriginalPathInTargetName;

  private Map directoryMap;
  private int parameterNr;

  public SimpleResourceNaming() {
    super();

    directoryMap = new HashMap();
    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();
    }

    StringBuilder buff = new StringBuilder( 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 getDirectoryMap() {
    return directoryMap;
  }

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy