/*
 * Enhydra Java Application Server Project
 *
 * The contents of this file are subject to the Enhydra Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License on
 * the Enhydra web site ( http://www.enhydra.org/ ).
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific terms governing rights and limitations
 * under the License.
 *
 * The Initial Developer of the Enhydra Application Server is Lutris
 * Technologies, Inc. The Enhydra Application Server and portions created
 * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
 * All Rights Reserved.
 *
 * Contributor(s):
 *  @author     christianc@lutris.com
 *
 * $Id: CopyAndReplace.java,v 1.1 2001/09/08 06:15:37 cryd0221 Exp $
 */
package org.enhydra.barracuda.taskdefs;

import java.util.*;
import java.io.*;
import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.*;
import org.apache.tools.ant.types.*;

/**
 * <p>A consolidated copy and replace task that extends the basic Ant Copy
 * taskdef.
 *
 * <p>In addition, once files have been copied, a replace function is also
 * run on them. This replace will only affect the files that actually
 * get copied; it will not affect any other files in the directory.
 *
 * <p>The replace occurs using a simply properties file, rather than 
 * specifying replace parameters via the xml. The format of this file
 * looks something like this:
 *
 * <ul>
 *   <li>token="some target text" value="some replacement text"</li>
 *   <li>token='some target text called "blah"' value='some replacement text named "blech"'</li>
 *   <li>token=~some target text with " and '~ value=^some replacement text with ' and "^</li>
 * </ul>
 *
 * <p>As you can see, the format is flexible. Tokens are identified with "token=" and 
 * values are identified by "value=". The actual token/value delimiters are 
 * taken to be the first character following the = sign. This could be a double
 * quote, single quote, or any other character (ie. if the text you wish to 
 * replace contains both double and single quotes, you might want to use a ~
 * delimiter or something like that).
 *
 * @author Christian Cryder <a href="mailto:christianc@enhydra.org">christianc@enhydra.org</a>
 */
public class CopyAndReplace extends Copy {

    protected File mappingsFile = null; //the mappings file 

    /**
     * Sets the mappings file.
     */
    public void setMappings(File mappingsFile) {
        this.mappingsFile = mappingsFile;
    }

    /**
     * <p>Actually does the file (and possibly empty directory) copies.
     * This is a good method for subclasses to override. 
     *
     * <p>Note that all the copy functionality occurs by simply deferring
     * to the superclass implementation. The replace functionality follows:
     *
     * <ul>
     *    <li><p>first we make sure there is a mappings file</li>
     *    <li><p>next we parse it to determine all token/value mapings</li>
     *    <li><p>finally we iterate through the list of files that actually
     *          got copied and we create Replace task for each of them. This
     *          task contains all the various token/value mappings, and
     *          gets executed for each file, effectively making all the 
     *          necessary text substitutions</li>
     * <ul>
     */
    protected void doFileOperations() {
        //start by allowing the basic copy to occur
        super.doFileOperations();
        
        //if the mappings file is null or doesn't exist just return
        if (mappingsFile==null) return;
        List mappings = new ArrayList();
        if (!mappingsFile.exists()) {
            log("Unable to find mappings file: "+mappingsFile+" ... files copied but no text replace occurred", Project.MSG_ERR);
            return;            
        }

        //start by reading the mappings file
        List tokenList = new ArrayList();
        List valueList = new ArrayList();
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(mappingsFile)));
            while (true) {
                String s = br.readLine();
                if (s==null) break;
                String token = null;
                String value = null;

                //get the token                
                int spos = s.indexOf("token=");
                if (spos<0 || spos+6>=s.length()) continue;
                spos+=6;
                String delim = s.substring(spos,spos+1);
                spos+=1;
                int epos = s.indexOf(delim, spos+1);
                if (epos<0 || epos+1>=s.length()) continue;
                token = s.substring(spos, epos);
                if (token==null) continue;

                //get the value
                spos = s.indexOf("value=", epos+1);
                if (spos<0 || spos+6>=s.length()) continue;
                spos+=6;
                delim = s.substring(spos,spos+1);
                spos+=1;
                epos = s.indexOf(delim, spos+1);
                if (epos<0) continue;
                value = s.substring(spos, epos);
                if (value==null) continue;
                
                tokenList.add(token);
                valueList.add(value);
            }
        } catch (IOException e) {
            System.out.println ("Error reading file "+mappingsFile+":"+e);
            return;
        }
        
        //now iterate through the file copy list
        if (fileCopyMap.size() > 0) {
            log("Replacing text in copied files");

            Enumeration e = fileCopyMap.keys();
            while (e.hasMoreElements()) {
                //figure out the target file
                String fromFile = (String) e.nextElement();
                String toFile = (String) fileCopyMap.get(fromFile);
                File targetFile = new File(toFile);
                
                //do the replace on each file (this is important: we only
                //want to do the replace on files we actually copied in)
                Replace replace = new Replace();
                replace.setProject(project);
                replace.setFile(targetFile);
                for (int i=0, max=tokenList.size(); i<max; i++) {
                    Replace.Replacefilter rf = replace.createReplacefilter();
                    rf.setToken((String) tokenList.get(i));
                    rf.setValue((String) valueList.get(i));
                }
                replace.execute();
            }        
        }
    }
}
