/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package com.windowtester.codegen.util;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
/**
* A utility class that proposes fresh file names given a directory.
*/
public class FileNameProposer {
/** A default (or suffix) filename */
private final String _defaultFileName;
/** The target directory */
private final File _dir;
/** The extension of stream files */
private static final String STREAM_EXTENSION = ".xml"; //TODO: move constant
/**
* Create an instance.
* @param dir - the root directory
* @param defaultFileName - a default file name
*/
public FileNameProposer(String defaultFileName, File dir) {
_defaultFileName = defaultFileName;
_dir = dir;
}
/**
* Propose a fresh filename which is based on the most recently modified
* file with an int index (e.g., "newFile3.xml").
* @return a fresh String file name
*/
public String propose() {
File recent = getMostRecentltyModifiedFile(_dir);
String name = recent == null ? _defaultFileName : recent.getName();
return findAvailableNextIncrement(name, _dir);
}
/**
* Given a name and a directory, find the next available increment of
* it's index (e.g., if "newFile1.xml" and "newFile2.xml" exist,
* "newFile3.xml" would be proposed).
* @param name - the file name
* @param dir - the target directory
* @return a String representing the next available name
*/
private static String findAvailableNextIncrement(String name, File dir) {
name = name.split("\\.")[0];
ParsedName parsedName = parseName(name);
int index = parsedName.index;
name = parsedName.name;
File[] files = dir.listFiles();
String proposal;
boolean matched;
for ( ; ; ) {
matched = false;
proposal = name + index++ + STREAM_EXTENSION;
if (files == null)
return proposal;
for (int i = 0; !matched && i < files.length; i++) {
if (files[i].getName().equals(proposal))
matched = true;
}
if (!matched)
return proposal;
}
}
/**
* Parse this name into a name piece and an index
* @param name - the name to parse
* @return a ParsedName
*/
private static ParsedName parseName(String name) {
boolean done = false;
StringBuffer sb = new StringBuffer();
int i;
for (i=name.length()-1; !done && i >= 0; --i) {
char ch = name.charAt(i);
if (Character.isDigit(ch))
sb.append(ch);
else
done = true;
}
ParsedName parsedName = new ParsedName();
parsedName.index = sb.length() == 0 ? -1 : Integer.parseInt(sb.reverse().toString());
parsedName.name = sb.length() == 0 ? name : name.substring(0,i+2);
return parsedName;
}
/**
* Get the index of the given name (e.g., "newFile12.xml" -> 12)
* @param name - the name to parse
* @return an int index, or -1 if none is present
*/
private static int getIndex(String name) {
boolean done = false;
StringBuffer sb = new StringBuffer();
for (int i=name.length()-1; !done && i >= 0; --i) {
char ch = name.charAt(i);
if (Character.isDigit(ch))
sb.append(ch);
else
done = true;
}
return sb.length() == 0 ? -1 : Integer.parseInt(sb.reverse().toString());
}
/**
* Get the most recently edited file (irrespective of extension).
* @param dir - the directory in which to perform the search
* @return the most recently edited file
*/
public static File getMostRecentltyModifiedFile(File dir) {
return getMostRecentltyModifiedFile(dir, null);
}
/**
* Get the most recently edited file with a given extension.
* @param dir - the directory in which to perform the search
* @param extension - extension by which to filter file selections (null if extension is ignored)
* @return the most recently edited file
*/
public static File getMostRecentltyModifiedFile(File dir, String extension) {
File[] files = dir.listFiles();
if (files == null || files.length == 0)
return null;
//handle extension-based filtering
if (extension != null) {
Collection filtered = new ArrayList();
for (int i = 0; i < files.length; i++) {
if (files[i].getName().endsWith(extension))
filtered.add(files[i]);
}
files = (File[]) filtered.toArray(new File[]{});
}
Arrays.sort(files, new Comparator(){
public int compare(Object f1, Object f2) {
//not supported in JDK1.3
// Long l1 = Long.valueOf(((File)f1).lastModified());
// Long l2 = Long.valueOf(((File)f2).lastModified());
String l1 = Long.toString(((File)f1).lastModified());
String l2 = Long.toString(((File)f2).lastModified());
return l2.compareTo(l1);
}
});
return files[0];
}
public static void main(String[] args) {
System.out.println(getIndex("file13"));
}
/**
* A data holder class for parsed names.
*/
static class ParsedName {
/** The name component */
public String name;
/** The integer index */
public int index;
}
}