Re: how to convert AbsolutePath to RelativePath??
On 7 May 2006 20:54:11 -0700, u126561@yahoo.com.au wrote, quoted or
indirectly quoted someone who said :
Does anyone have any handy idea about convert AbsolutePath into
RelativePath??
Here is a class that does some of that sort of logic.
package com.mindprod.htmlmacros;
import java.io.File;
import java.io.IOException;
import java.util.regex.Pattern;
/**
* common tools for specific HTML macros, also configuring constants
*
* @author Roedy Green configuring constants in Head and configuring
constants
* should be moved to separate class.
*/
public class Tools {
// ------------------------------ FIELDS
------------------------------
/**
* true if we are debugging. Gets extra output
*/
private static final boolean DEBUGGING = false;
/**
* Pattern to split path into directory segments separated by /
*/
private static Pattern slashSplitter = Pattern.compile( "/" );
// -------------------------- STATIC METHODS
--------------------------
/**
* @param fileBeingProcessed the file having its macros expanded
*
* @return unqualified filename e.g. bushisms.html
*/
public static String getBasicNameWithExtension( File
fileBeingProcessed )
{
return fileBeingProcessed.getName();
}
/**
* e.g.
*/
/**
* @param fileBeingProcessed the file having its macros expanded
*
* @return extensionless filename e.g. bushisms
*/
public static String getBasicNameWithoutExtension( File
fileBeingProcessed )
{
String name = fileBeingProcessed.getName();
int place = name.lastIndexOf( '.' );
if ( place < 0 )
{
return name;
}
else
{
return name.substring( 0, place );
}
}
/**
* Where book cover images are kept for the given file
*
* @param fileBeingProcessed file having book cover images
inserted into it.
*
* @return relative url to the images directwory e.g.
.../bookcovers
*/
public static String getBookcoversDir( File fileBeingProcessed )
{
return getLevelString( fileBeingProcessed ) + "bookcovers";
}
/**
* @param fileBeingProcessed the file having its macros expanded
*
* @return fully qualified filename with / in names e.g.
* e:/mindprod/politics/bushisms.html with caps in
filename exact.
*/
public static String getCanonicalNameLocally( File
fileBeingProcessed )
{
try
{
return fileBeingProcessed.getCanonicalPath();
}
catch ( IOException e )
{
return fileBeingProcessed.getAbsolutePath();
}
}
/**
* @param fileBeingProcessed the file having its macros expanded
*
* @return fully qualified filename with / in names e.g.
* http://mindprod.com/politics/bushisms.html with caps in
filename
* exact.
*/
public static String getCanonicalNameOnWeb( File
fileBeingProcessed )
{
// chop of the lead E:/mindprod and prepend
http://mindprod.com
return "http://" + Configure.website + "/" +
getNameRelativeToWebRoot(
fileBeingProcessed );
}
/**
* @param fileBeingProcessed the file having its macros expanded
*
* @return just directory part of the name without trailing /,
with embedded /.
* e.g. politics, or laser not politics/laser
*/
public static String getDir( File fileBeingProcessed )
{
String path = getNameRelativeToWebRoot( fileBeingProcessed );
int place = path.lastIndexOf( '/' );
if ( place < 0 )
{
return "";
}
else
{
return path.substring( 0, place );
}
}
/** name of website we are preparing files for * */
// public static String websiteHost = "mindprod.com";
/**
* @param dir directory name, not fileBeingProcessed Get array of
directory
* segments that make up the directory, possibly empty.
* livinglove/methods gives { "livinglove" "methods" }
*
* @return just segments of directory name.
*/
private static String[] getDirSegments( String dir )
{
if ( dir == null || dir.length() == 0 )
{
// split would return one empty element
// in this case instead of empty array
return new String[ 0 ];
}
else
{
if ( dir.indexOf( '/' ) < 0 )
{
// faster than splitter, the normal case
return new String[] {dir};
}
else
{
// two or more directory segments
return slashSplitter.split( dir );
}
}
}
/**
* @param fileBeingProcessed the file having its macros expanded
*
* @return extension without the dot e.g. html
*/
public static String getExtension( File fileBeingProcessed )
{
String name = fileBeingProcessed.getName();
int place = name.lastIndexOf( '.' );
if ( place < 0 )
{
return "";
}
else
{
return name.substring( place + 1 );
}
}
/**
* Where images are kept for the given file
*
* @param fileBeingProcessed file having images inserted into it.
*
* @return relative url to the images directwory e.g. ../images
*/
public static String getImagesDir( File fileBeingProcessed )
{
return getLevelString( fileBeingProcessed ) + "images";
}
/**
* Get level
*
* @param fileBeingProcessed
*
* @return e.g. "../../" to get back to the root.
*/
public static int getLevel( File fileBeingProcessed )
{
String relative = getNameRelativeToWebRoot( fileBeingProcessed
);
int depth = 0;
int length = relative.length();
for ( int i = 0; i < length; i++ )
{
if ( relative.charAt( i ) == '/' )
{
depth++;
}
}
return depth;
}
/**
* Get string representing how deeply nested we are from the root.
*
* @param level depth we are from webRoot.
*
* @return empty for root, ../ for one deep, ../../ for two deep
*/
public static String getLevelString( int level )
{
if ( level < 0 )
{
throw new IllegalArgumentException(
"getLevelString: invalid directory nesting level "
+ level );
}
switch ( level )
{
case 0 :
return "";
case 1 :
return "../";
case 2 :
return "../../";
default :
StringBuilder sb = new StringBuilder( level * 3 );
for ( int i = 0; i < level; i++ )
{
sb.append( "../" );
}
return sb.toString();
} // end switch
}
/**
* Get string representing how deeply nested we are from the root.
*
* @param fileBeingProcessed file we are expanding.
*
* @return empty for root, ../ for one deep, ../../ for two deep
*/
public static String getLevelString( File fileBeingProcessed )
{
return getLevelString( getLevel( fileBeingProcessed ) );
}
/**
* @param fileBeingProcessed the file having its macros expanded
*
* @return name relative to localWebRoot with / in names
* e.g.politics/bushisms.html
*/
public static String getNameRelativeToWebRoot( File
fileBeingProcessed )
{
String canonicalName = getCanonicalNameLocally(
fileBeingProcessed );
assert canonicalName.toLowerCase()
.startsWith( Configure.localWebRoot ) : "not webroot
file "
+
canonicalName;
// chop off webRoot and lead \
return canonicalName.substring(
Configure.localWebRoot.length() + 1 )
.replace( '\\', '/' );
}
/**
* @param relativeFilename name of file relative to
fileBeingProcessed *
* @param fileBeingProcessed the file having its macros expanded
*
* @return name relative to localWebRoot with / in names
* e.g.politics/bushisms.html
*/
public static String getNameRelativeToWebRoot( String
relativeFilename,
File
fileBeingProcessed )
{
return getNameRelativeToWebRoot( new File( fileBeingProcessed
.getParent(), relativeFilename ) );
}
/**
* Currently duplicated in com.mindprod.filter.CommandLine Smarter
version
* of File.getParent. It has yet to be tested with all
combinations of
* absolute, relative, root, ., .., ../ ../sub C: C:\ etc.
*
* @param fileBeingProcessed the file having its macros expanded
*
* @return parent directory that file lives in as File object,
ready to use
* in FilenameFilter.accept.
*/
public static File getParent( File fileBeingProcessed )
{
String parent = fileBeingProcessed.getParent();
if ( parent == null || parent.length() == 0 )
{
// Sun's method failed, try another.
String fullName = fileBeingProcessed.getAbsolutePath();
String name = fileBeingProcessed.getName();
if ( name == null )
{
name = "";
}
parent = fullName.substring( 0, fullName.length() -
name.length() );
if ( parent == null || parent.length() == 0 )
{
throw new IllegalArgumentException( "Tools:getParent
failed" );
}
}
return new File( parent );
}
/**
* Generate a relative url from the current file
*
* @param fileBeingProcessed where the link will be embedded
* @param targetFilename file where link jumps to, webRoot
relative
*
* @return relative url
*/
public static String link( File fileBeingProcessed, String
targetFilename )
{
String[] sourceSegs = getDirSegments( getDir(
fileBeingProcessed ) );
File targetFile = new File( Configure.localWebRoot,
targetFilename );
String[] targetSegs = getDirSegments( getDir( targetFile ) );
// get base filname.ext
String targetName = getBasicNameWithExtension( targetFile );
// eliminate high order commonality
int last = Math.min( sourceSegs.length, targetSegs.length );
for ( int c = 0; c < last; c++ )
{
if ( !sourceSegs[ c ].equals( targetSegs[ c ] ) )
{
// we found a difference, note where
last = c;
break;
}
} // end for c
// fell out the bottom. That means source and target
directories are
// identical.
// up to but not including last.
// generate URL to work up the tree to common place
String result = getLevelString( sourceSegs.length - last /*
*
up levels
*
needed
*/ );
// work back down toward target
for ( int d = last; d < targetSegs.length; d++ )
{
result += targetSegs[ d ] + "/";
} // end for d
return result + targetName;
}
/**
* Test link method to generate relative references
*
* @param fromFilename filename relative to webRoot
* @param toFilename toFilename relative to webRoot
*/
private static void linkTest( String fromFilename, String
toFilename )
{
if ( DEBUGGING )
{
File fromFile = new File( Configure.localWebRoot,
fromFilename );
System.out
.println( "["
+ fromFilename
+ "]["
+ toFilename
+ "]["
+ link( fromFile, toFilename )
+ "]" );
}
}
/**
* excercise the methods on a given filename relative to the
webRoot
*
* @param filename webRoot relative filename to TEST methods on
*/
private static void test( String filename )
{
if ( DEBUGGING )
{
File f = new File( Configure.localWebRoot, filename );
System.out
.println( "local: [" + getCanonicalNameLocally( f
) + "]" );
System.out.println( "images: [" + getImagesDir( f ) + "]"
);
System.out.println( "book: [" + getBookcoversDir( f ) +
"]" );
System.out.println( "web: [" + getCanonicalNameOnWeb( f )
+ "]" );
System.out
.println( "relative: ["
+ getNameRelativeToWebRoot( f )
+ "]" );
System.out.println( "level: [" + getLevel( f ) + "]" );
System.out.println( "level: [" + getLevelString( f ) + "]"
);
System.out.println( "parent: [" + getParent( f ) + "]" );
System.out.println( "dir: [" + getDir( f ) + "]" );
String[] dirs = getDirSegments( getDir( f ) );
System.out.println( "segments: [" + dirs.length + "]" );
for ( int i = 0; i < dirs.length; i++ )
{
System.out.println( "seg: [" + dirs[ i ] + "]" );
}
System.out
.println( "name: ["
+ getBasicNameWithExtension( f )
+ "]" );
System.out
.println( "base: ["
+ getBasicNameWithoutExtension( f )
+ "]" );
System.out.println( "ext: [" + getExtension( f ) + "]" );
}
}
// --------------------------- main() method
---------------------------
/**
* TEST harness
*
* @param args not used
*/
public static void main( String[] args )
{
if ( DEBUGGING )
{
test( "livinglove/methods/icd.html" );
test( "livinglove/ll.html" );
test( "products.html" );
linkTest( "livinglove/methods/icd.html",
"livinglove/methods/pws.html" );
linkTest( "livinglove/methods/icd.html",
"livinglove/ll.html" );
linkTest( "livinglove/methods/icd.html", "products.html"
);
linkTest( "livinglove/methods/pws.html",
"livinglove/methods/icd.html" );
linkTest( "livinglove/ll.html",
"livinglove/methods/icd.html" );
linkTest( "products.html", "livinglove/methods/icd.html"
);
linkTest( "index.html", "products.html" );
linkTest( "index.html", "livinglove/ll.html" );
linkTest( "livinglove/ll.html", "livinglove/llbio.html" );
linkTest( "livinglove/ll.html",
"politics/laser/freedtrade.html" );
linkTest( "livinglove/ll.html",
"animalrights/dolphin.html" );
}
/*
* output should look like this: local:
* [E:\mindprod\livinglove\methods\icd.html] images:
[../../images]
* book: [../../bookcovers] web:
* [http://mindprod.com/livinglove/methods/icd.html] relative:
* [livinglove/methods/icd.html] level: [2] level: [../../]
parent:
* [E:\mindprod\livinglove\methods] dir: [livinglove/methods]
segments:
* [2] seg: [livinglove] seg: [methods] name: [icd.html] base:
[icd]
* ext: [html]
*/
}
}
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.