Index: /main/trunk/ant-tasks/src/org/greenstone/anttasks/InsertUniqueValue.java
===================================================================
--- /main/trunk/ant-tasks/src/org/greenstone/anttasks/InsertUniqueValue.java	(revision 22480)
+++ /main/trunk/ant-tasks/src/org/greenstone/anttasks/InsertUniqueValue.java	(revision 22480)
@@ -0,0 +1,321 @@
+/*
+ *    InsertUniqueValue.java
+ *    A task to replace occurences of a given pattern with a given replacement in a given file
+ *
+ *    Copyright (C) 2005 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.anttasks;
+
+import java.util.ArrayList;
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.taskdefs.*;
+import java.util.*;
+import java.io.*;
+import java.util.regex.*;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.DirectoryScanner;
+
+public class InsertUniqueValue extends Task {
+
+	private File file = null;
+	private ArrayList jobs = null;
+	private FileSet fileset = null;
+	private String pattern = null;
+	private int fromLine = -1;
+	private int toLine = -1;
+	private boolean winPath = false;
+	private int count = 0;
+
+	public static void main( String[] args ) {
+
+		InsertUniqueValue rsr = new InsertUniqueValue();
+		rsr.setFile(new File (args[0]));
+		rsr.setPattern(args[1]);
+		rsr.setLines(args[3]);
+
+		rsr.execute();
+
+	}
+
+	public void execute() {
+
+		if ( file == null && fileset == null ) {
+			throw new BuildException( "Error - No file or fileset specified !!" );
+		}
+
+		if ( file != null && !file.exists() ) {
+			throw new BuildException( "Error - File not found !!" );
+		}
+
+		DirectoryScanner dirScanner = null;
+		if ( fileset != null ) {
+			dirScanner = fileset.getDirectoryScanner(project);
+			dirScanner.scan();
+		}
+
+		if ( jobs == null && pattern == null ) {
+			throw new BuildException( "Error - No pattern attribute and no nested jobs !!" );
+		}
+
+		if ( jobs != null && pattern != null ) {
+			throw new BuildException( "Error - Both pattern attribute and nested jobs given !!" );
+		}
+
+		if ( jobs != null ) {
+			for ( int i=0; i<jobs.size(); i++ ) {
+				if ( ((InsertUniqueValueJob)(jobs.get(i))).getPattern() == null ) {
+					throw new BuildException( "Error - One of the jobs lacks a pattern!!" );
+				}
+			}
+		}
+
+
+		//sus out filename(s)
+		File[] files = null;
+		if ( file != null ) {
+			files = new File[1];
+			files[0] = file;
+		} else {
+			String[] fileStrings = dirScanner.getIncludedFiles();
+			files = new File[fileStrings.length];
+			for ( int i=0; i<fileStrings.length; i++ ) {
+				files[i] = new File( dirScanner.getBasedir() + File.separator + fileStrings[i] );
+			}
+		}
+
+		//output greeting
+		System.out.println( "-------------------" );
+		System.out.println( " InsertUniqueValue " );
+		System.out.println( "-------------------" );
+
+		//output lines if necessary
+		if ( this.fromLine != -1 || this.toLine != -1 ) {
+			System.out.println( "Lines: " + (this.fromLine==-1?"Start":Integer.toString(this.fromLine)) + " ~ " + (this.toLine==-1?"End":Integer.toString(this.toLine)) );
+			System.out.println();
+		}
+
+		System.out.println( "Files: " );
+		for ( int fileIndex=0; fileIndex<files.length; fileIndex++ ) {
+
+			int noReplaces = 0;
+
+			File inputFile = files[fileIndex];
+			System.out.println( " " + inputFile );
+
+			//create the output stream
+			BufferedWriter out = null;
+			File temp = null;
+			try {
+				//create temp file.
+				temp = File.createTempFile("rsr", ".tmp");
+
+				//delete temp file when program exits.
+				temp.deleteOnExit();
+
+				//writer to temp file
+				out = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(temp), "UTF8") );
+
+			} catch (IOException e) {
+				throw new BuildException( "Error - Couldn't create or open the temp file" );
+			}
+
+
+			//create the input stream
+			BufferedReader in = null;
+			try {
+				in = new BufferedReader( new InputStreamReader(new FileInputStream(inputFile), "UTF8") );
+			} catch ( Exception e ) {
+				throw new BuildException( "Error - Couldn't open the specified file" );
+			}
+
+			//pass the file through, searching and replacing
+			String line = null;
+			int lineNumber = 1;
+			boolean hasMoreLines = true;
+			while ( hasMoreLines ) {
+
+				try {
+					line = in.readLine();
+				} catch ( Exception e ) {
+					System.err.println( e.getMessage() );
+					throw new BuildException( "Error - Couldn't read from the specified file" );
+				}
+
+				if ( line == null ) {
+					hasMoreLines = false;
+				} else {
+
+					//only if within the given line range
+					if ( ( fromLine == -1 || lineNumber >= fromLine ) && ( toLine == -1 || lineNumber < toLine ) ) {
+						String oldLine = line;
+						if ( pattern != null ) {
+							int index = 0;
+							int prevIndex = 0;
+							StringBuffer newLine = new StringBuffer();
+							while((index = line.indexOf((String)pattern, index)) != -1)
+							{
+								newLine.append(line.substring(prevIndex, index));
+								newLine.append(pattern + count++);
+								index += pattern.length();
+								prevIndex = index;
+							}
+							newLine.append(line.substring(prevIndex, line.length()));
+							line = newLine.toString();
+						} else {
+							for ( int i=0; i<jobs.size(); i++ ) {
+								int index = 0;
+								int prevIndex = 0;
+								StringBuffer newLine = new StringBuffer();
+								String currentPattern = ((InsertUniqueValueJob)(jobs.get(i))).getPattern();
+								while((index = line.indexOf((String)currentPattern, index)) != -1)
+								{
+									newLine.append(line.substring(prevIndex, index));
+									newLine.append(currentPattern + count++);
+									index += currentPattern.length();
+									prevIndex = index;
+								}
+								newLine.append(line.substring(prevIndex, line.length()));
+								line = newLine.toString();
+							}
+						}
+						if ( !oldLine.equals( line ) ) {
+							noReplaces++;
+						}
+					}
+
+					try {
+						out.write( line );
+						out.newLine();
+					} catch ( Exception e ) {
+						throw new BuildException( "Error - Couldn't write to the temp file" );
+					}
+				}
+				lineNumber++;
+			}
+			
+			try {
+				//close them both up
+				in.close();
+				out.close();
+			} catch ( Exception e ) {
+				throw new BuildException( "Error - Couldn't close a file" );
+			}
+
+
+			//copy the new file (temp) over the original
+			InputStream i;
+			OutputStream o;
+			try {
+				i = new FileInputStream(temp);
+				o = new FileOutputStream(inputFile);
+
+			} catch ( Exception e ) {
+				throw new BuildException( "Error - Couldn't open the temp file" );
+			}
+
+			try {
+		
+				// Transfer bytes from in to out
+				byte[] buf = new byte[1024];
+				int len;
+				while ((len = i.read(buf)) > 0) {
+				   o.write(buf, 0, len);
+				}
+
+				//close them up
+				i.close();
+				o.close();
+			} catch ( Exception e ) {
+				throw new BuildException( "Error - Couldn't write to the specified file" );
+			}
+
+		
+			if ( noReplaces == 0 ) {
+				System.out.println( " No Changes Made" );
+			} else if ( noReplaces == 1 ) {
+				System.out.println( " Successfully changed 1 line" );
+			} else {
+				System.out.println( " Successfully changed " + noReplaces + " lines" );
+			}
+			System.out.println();
+
+		}
+
+	}
+
+	public void setFile(File file) {
+		if ( this.fileset != null || this.file != null ) {
+			throw new BuildException( "Error - Only one file or one fileset may be given!!" );
+		}
+		this.file = file;
+	}
+
+	public void setLines(String lines) {
+		//lines should be in the form "2" or "2-5"
+
+		//trim
+		lines.replaceAll("\\s","");
+
+		if ( lines == "" ) {
+			throw new BuildException( "Error - no line number(s) given in lines attribute!! " );
+		}
+
+		//split into parts
+		String[] parts = lines.split("-",2);
+
+		try {
+			if ( parts.length == 1 ) {
+				this.fromLine = Integer.parseInt( parts[0] );
+				this.toLine = this.fromLine + 1;
+			} else {
+				if ( !parts[0].equals("") ) this.fromLine = Integer.parseInt( parts[0] );
+				if ( !parts[1].equals("") ) this.toLine = Integer.parseInt( parts[1] );
+			}
+		} catch( NumberFormatException nfe ) {
+			throw new BuildException( "Error - invalid line numbers given in lines attribute!! '" + parts[0] + "' - '" + parts[1] + "'" );
+		}
+
+	}
+
+
+	public void setPattern(String pattern) {
+		this.pattern = pattern;
+	}
+
+	public void setWinPath( boolean isWinPath ) {
+		this.winPath = isWinPath;
+	}
+
+	public InsertUniqueValueJob createJob() {
+		InsertUniqueValueJob job = new InsertUniqueValueJob();
+		if ( jobs == null ) {
+			jobs = new ArrayList();
+		}
+		jobs.add( job );
+		return job;
+
+	}
+
+	public FileSet createFileset() {
+		if ( this.fileset != null || this.file != null ) {
+			throw new BuildException( "Error - Only one file or one fileset may be given!!" );
+		}
+		fileset = new FileSet();
+		return fileset;
+	}
+
+}
Index: /main/trunk/ant-tasks/src/org/greenstone/anttasks/InsertUniqueValueJob.java
===================================================================
--- /main/trunk/ant-tasks/src/org/greenstone/anttasks/InsertUniqueValueJob.java	(revision 22480)
+++ /main/trunk/ant-tasks/src/org/greenstone/anttasks/InsertUniqueValueJob.java	(revision 22480)
@@ -0,0 +1,23 @@
+package org.greenstone.anttasks;
+public class InsertUniqueValueJob extends org.apache.tools.ant.types.DataType {
+
+	String pattern = null;
+	boolean winPath = false;
+
+	public void setPattern(String pattern) {
+		this.pattern = pattern;
+	}
+
+	public void setWinPath( boolean winPath ) {
+		this.winPath = winPath;
+	}
+
+	public String getPattern() {
+		return pattern;
+	}
+	public boolean getWinPath() {
+		return winPath;
+	}
+
+}
+
