/**
 * Copyright (C) 2003 France Telecom R&D
 *
 * 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 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
 */
package org.objectweb.util.ant;

import org.apache.tools.ant.taskdefs.CallTarget;
import org.apache.tools.ant.taskdefs.Property;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;

import java.util.StringTokenizer;
import java.util.Iterator;
import java.util.ArrayList;

/**
 *
 * @author S.Chassande-Barrioz
 */
public class TokenizedAntCall extends CallTarget {
    /**
     * is the list of tokens
     */
    private String tokenList = "";

    /**
     * is the list of separators
     */
    private String separators = " ";

    /**
     * is the name of the variable that receives the current token.
     */
    private String tokenVarName = "token";

    private ArrayList props = new ArrayList();

    public Property createParam() {
        Property p = super.createParam();
        props.add(p);
        return p;
    }

    public String getTokenList() {
        return tokenList;
    }

    public void setTokenList(String tokenList) {
        this.tokenList = tokenList;
    }

    public String getSeparators() {
        return separators;
    }

    public void setSeparators(String separators) {
        this.separators = separators;
    }

    public String getTokenVarName() {
        return tokenVarName;
    }

    public void setTokenVarName(String tokenVarName) {
        this.tokenVarName = tokenVarName;
    }

    public void execute() throws BuildException {
        log("tokenList=" + tokenList, Project.MSG_DEBUG);
        tokenList = getVal(tokenList)[0];
        log("effective TokenList=" + tokenList, Project.MSG_DEBUG);
        log("separators=" + separators, Project.MSG_DEBUG);
        StringTokenizer st = new StringTokenizer(tokenList, separators, false);
        while (st.hasMoreTokens()) {
            String tokenValue = st.nextToken();
            log("token value=" + tokenValue, Project.MSG_DEBUG);
            Property prop = super.createParam();
            prop.setName(tokenVarName);
            prop.setValue(tokenValue);
            super.execute();
            if (st.hasMoreTokens()) {
                Iterator it = props.iterator();
                while (it.hasNext()) {
                    Property old = (Property) it.next();
                    Property neo = super.createParam();
                    neo.setName(old.getName());
                    neo.setValue(old.getValue());
                }
            }
        }
    }

    private String[] getVal(String s) throws BuildException {
        int begin = s.indexOf("${");
        int end = s.indexOf("}");
        if (begin == -1) {
            if (end == -1) {
                return new String[]{s, ""};
            } else {
                return new String[]{
                    s.substring(0, end), s.substring(end + 1)
                };
            }
        } else {
            if (end == -1) {
                throw new BuildException("${ without } in the expression " + s);
            }
            if (end < begin) {
                return new String[]{
                    s.substring(0, end), s.substring(end + 1)};
            } else {
                String res = s.substring(0, begin);
                String[] ss = getVal(s.substring(begin + 2));
                if (ss[0].length() > 0) {
                    String varValue = getProject().getProperty(ss[0]);
                    if (varValue == null) {
                        throw new BuildException("No variable '" + ss[0] + "' found");
                    }
                    res += varValue;
                }
                String[] t = getVal(ss[1]);
                res += t[0];
                return new String[]{res, t[1]};
            }
        }
    }
/*
    private int curPosInTokenList = 0;
    private int lastCloseBrackPos = 0;
    private String effectiveTokenList = "";

    private void buildEffectiveTokenList() {
        while (curPosInTokenList != tokenList.length()) {
            System.out.println("curPosInTokenList= " + curPosInTokenList);
            effectiveTokenList += buildPartOfEffectiveTokenList();
        }
    }

    private String buildPartOfEffectiveTokenList() {
        System.out.println("buildPartOfEffectiveTokenList");
        String res = "";
        int begvar = tokenList.indexOf("${", curPosInTokenList);
        if (begvar == -1) {
            // Gets the content of tokenList before the opening of variable def
            res += tokenList.substring(curPosInTokenList, tokenList.length());
            curPosInTokenList = tokenList.length();
        } else {
            if (begvar != curPosInTokenList) {
                // Gets the content of tokenList before the opening of variable def
                res += tokenList.substring(curPosInTokenList, begvar);
                curPosInTokenList = begvar;
            }
            int endvar = tokenList.indexOf("}", curPosInTokenList + 2);
            int begnewvar = tokenList.indexOf("${", curPosInTokenList + 2);
            if (endvar == -1) {
                // There is no closing of variable def: ignore variable
                res += tokenList.substring(curPosInTokenList, tokenList.length());
                curPosInTokenList = tokenList.length();
                lastCloseBrackPos = tokenList.length();
            } else if (begnewvar == -1) {
                // There is no more variable def that follows the current one
                // OR
                // The next variable def is after the closing of current one:
                // sequential definitions!
                String varname = tokenList.substring(curPosInTokenList + 2, endvar);
                String value = (String) projectProperties.get(varname);
                if (value != null) {
                    res += value;
                }
                curPosInTokenList = endvar + 1;
                lastCloseBrackPos = endvar;
            } else if (endvar < begnewvar) {
                // There is no more variable def that follows the current one
                // OR
                // The next variable def is after the closing of current one:
                // sequential definitions!
                String varname = tokenList.substring(curPosInTokenList + 2, endvar);
                String value = (String) projectProperties.get(varname);
                if (value != null) {
                    res += value;
                }
                res += tokenList.substring(endvar + 1, begnewvar);
                curPosInTokenList = begnewvar;
                lastCloseBrackPos = endvar;
            } else {
                // The next variable def is before the closing of current one:
                // embedded definitions!
                String varname = "";
                curPosInTokenList += 2;
                do {
                    System.out.println("curPosInTokenList= " + curPosInTokenList + ", endvar= " + endvar + ", begnewvar= " + begnewvar);
                    varname += tokenList.substring(curPosInTokenList, begnewvar);
                    curPosInTokenList = begnewvar;
                    varname += buildPartOfEffectiveTokenList();
                    endvar = tokenList.indexOf("}", curPosInTokenList);
                    begnewvar = tokenList.indexOf("${", curPosInTokenList);
                    if (endvar == -1) {
                        res += "${" + varname + tokenList.substring(curPosInTokenList, tokenList.length());
                        curPosInTokenList = tokenList.length();
                        break;
                    }
                    if (begnewvar == -1) {
                        System.out.println("Embbeded variable= " + varname);
                        String value = (String) projectProperties.get(varname);
                        if (value != null) {
                            res += value;
                        }
                        curPosInTokenList = endvar + 1;
                        lastCloseBrackPos = endvar;
                        break;
                    }
                    if (endvar < begnewvar) {
                        System.out.println("Embbeded variable= " + varname);
                        String value = (String) projectProperties.get(varname);
                        if (value != null) {
                            res += value;
                        }
                        curPosInTokenList = endvar + 1;
                        lastCloseBrackPos = endvar;
                        break;
                    }
                } while (true);
            }
        }
        return res;
    }

    public static void main(String[] args) {
        Properties props = new Properties();
        TokenizedAntCall tac = new TokenizedAntCall();
        tac.projectProperties = props;
        props.setProperty("var1", "X");
        props.setProperty("var2", "Y");
        props.setProperty("num1", "1");
        props.setProperty("begvar", "va");

        tac.tokenList = "AAAAAAAAAAAAAAAAAA";
        tac.curPosInTokenList = 0;
        tac.lastCloseBrackPos = 0;
        tac.effectiveTokenList = "";
        tac.buildEffectiveTokenList();
        System.out.println("Expected Efftective Token List: [AAAAAAAAAAAAAAAAAA] - computed: [" + tac.effectiveTokenList + "]");

        tac.tokenList = "${var1}";
        tac.curPosInTokenList = 0;
        tac.lastCloseBrackPos = 0;
        tac.effectiveTokenList = "";
        tac.buildEffectiveTokenList();
        System.out.println("Expected Efftective Token List: [X] - computed: [" + tac.effectiveTokenList + "]");

        tac.tokenList = "AA${var1}AAA";
        tac.curPosInTokenList = 0;
        tac.lastCloseBrackPos = 0;
        tac.effectiveTokenList = "";
        tac.buildEffectiveTokenList();
        System.out.println("Expected Efftective Token List: [AAXAAA] - computed: [" + tac.effectiveTokenList + "]");

        tac.tokenList = "AA${var1}AAA${var2}A";
        tac.curPosInTokenList = 0;
        tac.lastCloseBrackPos = 0;
        tac.effectiveTokenList = "";
        tac.buildEffectiveTokenList();
        System.out.println("Expected Efftective Token List: [AAXAAAYA] - computed: [" + tac.effectiveTokenList + "]");

        tac.tokenList = "AA${var1}${var2}AAA";
        tac.curPosInTokenList = 0;
        tac.lastCloseBrackPos = 0;
        tac.effectiveTokenList = "";
        tac.buildEffectiveTokenList();
        System.out.println("Expected Efftective Token List: [AAXYAAA] - computed: [" + tac.effectiveTokenList + "]");

        tac.tokenList = "${var${num1}}";
        tac.curPosInTokenList = 0;
        tac.lastCloseBrackPos = 0;
        tac.effectiveTokenList = "";
        tac.buildEffectiveTokenList();
        System.out.println("Expected Efftective Token List: [X] - computed: [" + tac.effectiveTokenList + "]");

        tac.tokenList = "${${begvar}r${num1}}";
        tac.curPosInTokenList = 0;
        tac.lastCloseBrackPos = 0;
        tac.effectiveTokenList = "";
        tac.buildEffectiveTokenList();
        System.out.println("Expected Efftective Token List: [X] - computed: [" + tac.effectiveTokenList + "]");

        tac.tokenList = "${${beg${begvar}r}r${num1}}";
        tac.curPosInTokenList = 0;
        tac.lastCloseBrackPos = 0;
        tac.effectiveTokenList = "";
        tac.buildEffectiveTokenList();
        System.out.println("Expected Efftective Token List: [X] - computed: [" + tac.effectiveTokenList + "]");

        tac.tokenList = "${var2";
        tac.curPosInTokenList = 0;
        tac.lastCloseBrackPos = 0;
        tac.effectiveTokenList = "";
        tac.buildEffectiveTokenList();
        System.out.println("Expected Efftective Token List: [${var2] - computed: [" + tac.effectiveTokenList + "]");

        tac.tokenList = "AA${${begvar}A";
        tac.curPosInTokenList = 0;
        tac.lastCloseBrackPos = 0;
        tac.effectiveTokenList = "";
        tac.buildEffectiveTokenList();
        System.out.println("Expected Efftective Token List: [AA${vaA] - computed: [" + tac.effectiveTokenList + "]");

        tac.tokenList = "${${begvar${num1}}";
        tac.curPosInTokenList = 0;
        tac.lastCloseBrackPos = 0;
        tac.effectiveTokenList = "";
        tac.buildEffectiveTokenList();
        System.out.println("Expected Efftective Token List: [${] - computed: [" + tac.effectiveTokenList + "]");
    }
*/
}
