/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2008 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53177 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: greve@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.framework.utils;
import java.io.File;
import java.text.ParseException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;
import org.deegree.framework.util.StringTools;
/**
* The class manipulates strings and concatenates them using mutliple delimeters and maps between relative and absolute
* paths. some method names are similar to those in the class String but with different parameters.
*
* @author <a href="mailto:elmasry@lat-lon.de">Moataz Elmasry</a>
* @author last edited by: $Author: elmasri$
*
* @version $Revision$, $Date: 8 May 2008 14:25:36$
*/
public class PathManipulator {
private PathManipulator() {
}
/**
* Gets the first match from the many delimiters give as input. So it takes multiple delimets, and returns the
* string from the begining to the first delimet
*
* @param source
* @param delimiters
* array of delimiters, the delimiter found first will be used and the function returns the text from
* firstIndex to the delimiter
* @param fromIndex
* the start index to look from
* @return String
*/
public static String getFirstMatch( String source, String[] delimiters, int fromIndex ) {
Vector<Delimiter> indices = new Vector<Delimiter>();
for ( int i = 0; i < delimiters.length; i++ ) {
// we added the indices of all matches to the vector
indices.add( new Delimiter( i, source.indexOf( delimiters[i] ), delimiters[i] ) );
}
Delimiter delimiter = getFirstIndex( indices );
if ( delimiter.value == null ) {
return null;
}
return source.substring( fromIndex, delimiter.foundAt + 1 );
}
/**
* Gets the first index of a match from the many delimiters given as input Takes many delimiters returns the
* delimiter that occured first
*
* @param collection
* @return instance of Delimiter class
*/
private static Delimiter getFirstIndex( Collection<Delimiter> collection ) {
Delimiter delimiter = new Delimiter( -1, 999, null );
Iterator<Delimiter> it = collection.iterator();
// comparing the matches to see which match occured first
while ( it.hasNext() ) {
Delimiter temp = (Delimiter) it.next();
int indexOf = temp.foundAt;
if ( indexOf < delimiter.foundAt && indexOf > -1 ) {
delimiter = temp;
}
}
return delimiter;
}
/**
* Split a string based on the given delimiters and return an array of strings(tokens)
*
* @param source
* @param delimiters
* @return tokens from a given string
*/
public static String[] splitString( String source, String[] delimiters ) {
if ( source == null || delimiters == null )
return null;
Vector<String> returnedStrings = new Vector<String>();
String tempSource = source;
while ( tempSource.length() != 0 ) {
int delimiterLength = 0;
String match = getFirstMatch( tempSource, delimiters, 0 );
// if this is the last token in the String
if ( match == null ) {
returnedStrings.add( tempSource );
break;
} else {
// removing any delimiters that could exist
for ( int i = 0; i < delimiters.length; i++ ) {
if ( match.contains( delimiters[i] ) ) {
match = match.replace( delimiters[i], "" );
delimiterLength = delimiters[i].length();
break;
}
}
// Ignore the . and don't add it to the array in case there was a ./ in the path for
// example
if ( !match.equals( "." ) ) {
returnedStrings.add( match );
}
tempSource = tempSource.substring( match.length() + delimiterLength, tempSource.length() );
}
}
String[] strings = new String[returnedStrings.size()];
for ( int i = 0; i < returnedStrings.size(); i++ ) {
strings[i] = returnedStrings.elementAt( i );
}
return strings;
}
/**
* Maps from a source sTring to a target String, based on the delimiters given the delimiters are basically "\\" or
* "/", but it also could be anything else Two absolute pathes should be given here Don't give relative
*
* @param folder
* @param fileName
* @param delimiters
* @return the mapped path
* @throws ParseException
*/
public static String mapRelativePath( String folder, String fileName, String[] delimiters )
throws ParseException {
folder = StringTools.replace( folder, "\\", "/", true );
fileName = StringTools.replace( fileName, "\\", "/", true );
if ( !fileName.toLowerCase().startsWith( "http:" ) ) {
if ( fileName.toLowerCase().startsWith( "file:" ) ) {
File f = new File( fileName.substring( 5 ) );
fileName = f.getAbsolutePath();
}
} else {
return fileName;
}
if ( !new File( folder ).isAbsolute() ) {
throw new ParseException( "The source path is not absolute", 0 );
}
if ( !new File( fileName ).isAbsolute() ) {
throw new ParseException( "The target path is not absolute", 0 );
}
String[] sourceTokens = splitString( folder, delimiters );
String[] targetTokens = splitString( fileName, delimiters );
if ( sourceTokens == null || targetTokens == null ) {
return null;
}
if ( sourceTokens.length == 0 || targetTokens.length == 0 ) {
return null;
}
int lessTokens = 0;
if ( sourceTokens.length < targetTokens.length ) {
lessTokens = sourceTokens.length;
} else {
lessTokens = targetTokens.length;
}
int counter = 0;
for ( counter = 0; counter < lessTokens; counter++ ) {
if ( counter == 0 ) {
if ( !sourceTokens[counter].toLowerCase().equals( targetTokens[counter].toLowerCase() ) ) {
break;
}
} else {
if ( !sourceTokens[counter].equals( targetTokens[counter] ) ) {
break;
}
}
}
StringBuffer buffer = new StringBuffer();
for ( int i = counter; i < sourceTokens.length; i++ ) {
buffer.append( "../" );
}
// This is used when the target is only one token different/larger than the source, so we
// just take
// the last token in the target
if ( ( counter == sourceTokens.length ) && ( sourceTokens.length == targetTokens.length + 1 )
&& ( sourceTokens[counter - 1].equals( targetTokens[counter - 1] ) ) ) {
return targetTokens[targetTokens.length - 1];
}
for ( int i = counter; i < targetTokens.length; i++ ) {
if ( buffer.length() == 0 ) {
// This is the first token in the path
buffer.append( "./" );
}
buffer.append( targetTokens[i] );
if ( i != targetTokens.length - 1 ) {
buffer.append( "/" );
}
}
return buffer.toString();
}
/**
* Maps from a source file to a target folder, based on the delimiters given the delimiters are basically "/" or
* "/", but it also could be anything else Two absolute pathes should be given here. Don't give relative. Default
* delimiters to use in order to divide each path into tokens are / and /
*
* @param file
* @param folder
* @return the mapped path
* @throws ParseException
*/
public static String mapRelativePath( String folder, String file )
throws ParseException {
String delimiters[] = { "/", "/" };
return mapRelativePath( folder, file, delimiters );
}
static class Delimiter {
int index;
String value;
int foundAt;
/**
* @param index
* @param foundAt
* @param value
*/
public Delimiter( int index, int foundAt, String value ) {
this.index = index;
this.value = value;
this.foundAt = foundAt;
}
}
public static void main( String[] args ) {
// String folder = "C:/das/ist/ein/ordner";
// String file = "C:/das/ist/ein/file/another/test.xml";
String folder = "D:\\java\\projekte\\deegree2_client\\resources\\";
String file = "D:/java/projekte/deegree2_client/resources/data/data/SGID100_CountyBoundaries.shp";
try {
File f = new File( PathManipulator.mapRelativePath( folder, file ) );
System.out.println(f.getPath());
} catch ( Exception e ) {
e.printStackTrace();
}
}
}