/*
 ******************************************************************************
 * Copyright (C) 2004, International Business Machines Corporation and   *
 * others. All Rights Reserved.                                               *
 ******************************************************************************
 */
/**
 * @author Ram Viswanadha
 *
 * This tool validates xml against DTD ... IE 6 does not do a good job
 */
package org.unicode.cldr.util;

public class XPathTokenizer{
    char[] xpath;
    int current;
    
    public XPathTokenizer(StringBuffer path){
        this(path.toString());
    }
    public XPathTokenizer(String path){
        xpath = path.toCharArray();
        if(path.indexOf("..")== 0){
            current = 0;
        }else{
            // this is absolute
            // since xpath starts with "//"
            current = 2;
        }
    }
    public String nextToken(){
        boolean inquote = false;
        String retval;
        int save = current; 
        while(current < xpath.length){
            switch(xpath[current]){
                case '\'':
                   inquote = (inquote==true)? false:true;
                   current++;
                   break;
                case '/':
                    if(inquote==false){
                        retval  = new String(xpath,save, (current-save));
                        current++; //skip past the separator
                        return retval;
                    }
                    //fall through
                default:
                    current++;
            }
        }
        if(current == xpath.length){
            retval = new String(xpath,save, (current-save));
            current++;
            return retval;
        }
        return null;
    }
    public static StringBuffer deleteToken(StringBuffer xpath){
        int length = xpath.length(); 
        int current =  length - 1;
        while(current > 0 ){
            boolean inquote = false;
            switch(xpath.charAt(current)){
                case '\'':
                    inquote = (inquote==true)? false:true;
                    current--;
                    break;
                case '/':
                    if(inquote==false){
                        if(current < length){
                            xpath.delete(current, length);
                        }
                        return xpath;
                    }
                    //fall through
                default:
                    current--;
            }
        }
        return xpath;
    }
    
    public static StringBuilder deleteToken(StringBuilder xpath){
      int length = xpath.length(); 
      int current =  length - 1;
      while(current > 0 ){
          boolean inquote = false;
          switch(xpath.charAt(current)){
              case '\'':
                  inquote = (inquote==true)? false:true;
                  current--;
                  break;
              case '/':
                  if(inquote==false){
                      if(current < length){
                          xpath.delete(current, length);
                      }
                      return xpath;
                  }
                  //fall through
              default:
                  current--;
          }
      }
      return xpath;
  }
    /**
     * This method will try to convert a relative xpath to absolute
     * xpath. 
     * TODO: The method will only resolve relative tokens in the begining
     * of the string. Try to handle embedded ".."
     * @param xpath
     * @param fullPath
     * @return
     * @deprecated - use version that takes StringBuilder instead
     */
    @Deprecated
    public static StringBuffer relativeToAbsolute(String xpath, StringBuffer fullPath){
        if(!xpath.startsWith("..")){
            fullPath.setLength(0);
            fullPath.append(xpath);
            return fullPath;
        }
        XPathTokenizer tokenizer = new XPathTokenizer(xpath);
        String token=tokenizer.nextToken();
        StringBuffer retVal = new StringBuffer();
        retVal.append(fullPath);
        while(token.equals("..")){
            deleteToken(retVal);
            token = tokenizer.nextToken();
        }
        while(token!=null){
            retVal.append("/");
            retVal.append(token);
            token = tokenizer.nextToken();
        }
        return retVal;
    }
    
    public static StringBuilder relativeToAbsolute(String xpath, StringBuilder fullPath){
      if(!xpath.startsWith("..")){
          fullPath.setLength(0);
          fullPath.append(xpath);
          return fullPath;
      }
      XPathTokenizer tokenizer = new XPathTokenizer(xpath);
      String token=tokenizer.nextToken();
      StringBuilder retVal = new StringBuilder();
      retVal.append(fullPath);
      while(token.equals("..")){
          deleteToken(retVal);
          token = tokenizer.nextToken();
      }
      while(token!=null){
          retVal.append("/");
          retVal.append(token);
          token = tokenizer.nextToken();
      }
      return retVal;
  }
}

