content: /*
   *  This file is part of AndroidIDE.
   *
   *  AndroidIDE 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 3 of the License, or
   *  (at your option) any later version.
   *
   *  AndroidIDE 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 AndroidIDE.  If not, see <https://www.gnu.org/licenses/>.
   */
  
  /*
   * reserved comment block
   * DO NOT REMOVE OR ALTER!
   */
  /*
   * Copyright 1999-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  /*
   * $Id: ExsltStrings.java,v 1.1.2.1 2005/08/01 02:08:48 jeffsuttor Exp $
   */
  package jaxp.sun.org.apache.xalan.internal.lib;
  
  import java.util.StringTokenizer;
  
  import jaxp.xml.parsers.DocumentBuilderFactory;
  import jaxp.xml.parsers.ParserConfigurationException;
  
  import jaxp.sun.org.apache.xml.internal.utils.WrappedRuntimeException;
  import jaxp.sun.org.apache.xpath.internal.NodeSet;
  
  import org.w3c.dom.Document;
  import org.w3c.dom.Element;
  import org.w3c.dom.Node;
  import org.w3c.dom.NodeList;
  import org.w3c.dom.Text;
  
  /**
   * This class contains EXSLT strings extension functions.
   *
   * It is accessed by specifying a namespace URI as follows:
   * <pre>
   *    xmlns:str="http://exslt.org/strings"
   * </pre>
   * The documentation for each function has been copied from the relevant
   * EXSLT Implementer page.
   *
   * @see <a href="http://www.exslt.org/">EXSLT</a>
  
   * @xsl.usage general
   */
  public class ExsltStrings extends ExsltBase
  {
     static final String JDK_DEFAULT_DOM = "jaxp.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl";
  
    /**
     * The str:align function aligns a string within another string.
     * <p>
     * The first argument gives the target string to be aligned. The second argument gives
     * the padding string within which it is to be aligned.
     * <p>
     * If the target string is shorter than the padding string then a range of characters
     * in the padding string are repaced with those in the target string. Which characters
     * are replaced depends on the value of the third argument, which gives the type of
     * alignment. It can be one of 'left', 'right' or 'center'. If no third argument is
     * given or if it is not one of these values, then it defaults to left alignment.
     * <p>
     * With left alignment, the range of characters replaced by the target string begins
     * with the first character in the padding string. With right alignment, the range of
     * characters replaced by the target string ends with the last character in the padding
     * string. With center alignment, the range of characters replaced by the target string
     * is in the middle of the padding string, such that either the number of unreplaced
     * characters on either side of the range is the same or there is one less on the left
     * than there is on the right.
     * <p>
     * If the target string is longer than the padding string, then it is truncated to be
     * the same length as the padding string and returned.
     *
     * @param targetStr The target string
     * @param paddingStr The padding string
     * @param type The type of alignment
     *
     * @return The string after alignment
     */
    public static String align(String targetStr, String paddingStr, String type)
    {
      if (targetStr.length() >= paddingStr.length())
        return targetStr.substring(0, paddingStr.length());
  
      if (type.equals("right"))
      {
        return paddingStr.substring(0, paddingStr.length() - targetStr.length()) + targetStr;
      }
      else if (type.equals("center"))
      {
        int startIndex = (paddingStr.length() - targetStr.length()) / 2;
        return paddingStr.substring(0, startIndex) + targetStr + paddingStr.substring(startIndex + targetStr.length());
      }
      // Default is left
      else
      {
        return targetStr + paddingStr.substring(targetStr.length());
      }
    }
  
    /**
     * See above
     */
    public static String align(String targetStr, String paddingStr)
    {
      return align(targetStr, paddingStr, "left");
    }
  
    /**
     * The str:concat function takes a node set and returns the concatenation of the
     * string values of the nodes in that node set. If the node set is empty, it returns
     * an empty string.
     *
     * @param nl A node set
     * @return The concatenation of the string values of the nodes in that node set
     */
    public static String concat(NodeList nl)
    {
      StringBuffer sb = new StringBuffer();
      for (int i = 0; i < nl.getLength(); i++)
      {
        Node node = nl.item(i);
        String value = toString(node);
  
        if (value != null && value.length() > 0)
          sb.append(value);
      }
  
      return sb.toString();
    }
  
    /**
     * The str:padding function creates a padding string of a certain length.
     * The first argument gives the length of the padding string to be created.
     * The second argument gives a string to be used to create the padding. This
     * string is repeated as many times as is necessary to create a string of the
     * length specified by the first argument; if the string is more than a character
     * long, it may have to be truncated to produce the required length. If no second
     * argument is specified, it defaults to a space (' '). If the second argument is
     * an empty string, str:padding returns an empty string.
     *
     * @param length The length of the padding string to be created
     * @param pattern The string to be used as pattern
     *
     * @return A padding string of the given length
     */
    public static String padding(double length, String pattern)
    {
      if (pattern == null || pattern.length() == 0)
        return "";
  
      StringBuffer sb = new StringBuffer();
      int len = (int)length;
      int numAdded = 0;
      int index = 0;
      while (numAdded < len)
      {
        if (index == pattern.length())
          index = 0;
  
        sb.append(pattern.charAt(index));
        index++;
        numAdded++;
      }
  
      return sb.toString();
    }
  
    /**
     * See above
     */
    public static String padding(double length)
    {
      return padding(length, " ");
    }
  
    /**
     * The str:split function splits up a string and returns a node set of token
     * elements, each containing one token from the string.
     * <p>
     * The first argument is the string to be split. The second argument is a pattern
     * string. The string given by the first argument is split at any occurrence of
     * this pattern. For example:
     * <pre>
     * str:split('a, simple, list', ', ') gives the node set consisting of:
     *
     * <token>a</token>
     * <token>simple</token>
     * <token>list</token>
     * </pre>
     * If the second argument is omitted, the default is the string '&#x20;' (i.e. a space).
     *
     * @param str The string to be split
     * @param pattern The pattern
     *
     * @return A node set of split tokens
     */
    public static NodeList split(String str, String pattern)
    {
  
  
      NodeSet resultSet = new NodeSet();
      resultSet.setShouldCacheNodes(true);
  
      boolean done = false;
      int fromIndex = 0;
      int matchIndex = 0;
      String token = null;
  
      while (!done && fromIndex < str.length())
      {
        matchIndex = str.indexOf(pattern, fromIndex);
        if (matchIndex >= 0)
        {
          token = str.substring(fromIndex, matchIndex);
          fromIndex = matchIndex + pattern.length();
        }
        else
        {
          done = true;
          token = str.substring(fromIndex);
        }
  
        Document doc = getDocument();
        synchronized (doc)
        {
          Element element = doc.createElement("token");
          Text text = doc.createTextNode(token);
          element.appendChild(text);
          resultSet.addNode(element);
        }
      }
  
      return resultSet;
    }
  
    /**
     * See above
     */
    public static NodeList split(String str)
    {
      return split(str, " ");
    }
  
    /**
     * The str:tokenize function splits up a string and returns a node set of token
     * elements, each containing one token from the string.
     * <p>
     * The first argument is the string to be tokenized. The second argument is a
     * string consisting of a number of characters. Each character in this string is
     * taken as a delimiting character. The string given by the first argument is split
     * at any occurrence of any of these characters. For example:
     * <pre>
     * str:tokenize('2001-06-03T11:40:23', '-T:') gives the node set consisting of:
     *
     * <token>2001</token>
     * <token>06</token>
     * <token>03</token>
     * <token>11</token>
     * <token>40</token>
     * <token>23</token>
     * </pre>
     * If the second argument is omitted, the default is the string '&#x9;&#xA;&#xD;&#x20;'
     * (i.e. whitespace characters).
     * <p>
     * If the second argument is an empty string, the function returns a set of token
     * elements, each of which holds a single character.
     * <p>
     * Note: This one is different from the tokenize extension function in the Xalan
     * namespace. The one in Xalan returns a set of Text nodes, while this one wraps
     * the Text nodes inside the token Element nodes.
     *
     * @param toTokenize The string to be tokenized
     * @param delims The delimiter string
     *
     * @return A node set of split token elements
     */
    public static NodeList tokenize(String toTokenize, String delims)
    {
  
  
      NodeSet resultSet = new NodeSet();
  
      if (delims != null && delims.length() > 0)
      {
        StringTokenizer lTokenizer = new StringTokenizer(toTokenize, delims);
  
        Document doc = getDocument();
        synchronized (doc)
        {
          while (lTokenizer.hasMoreTokens())
          {
            Element element = doc.createElement("token");
            element.appendChild(doc.createTextNode(lTokenizer.nextToken()));
            resultSet.addNode(element);
          }
        }
      }
      // If the delimiter is an empty string, create one token Element for
      // every single character.
      else
      {
  
        Document doc = getDocument();
        synchronized (doc)
        {
          for (int i = 0; i < toTokenize.length(); i++)
          {
            Element element = doc.createElement("token");
            element.appendChild(doc.createTextNode(toTokenize.substring(i, i+1)));
            resultSet.addNode(element);
          }
        }
      }
  
      return resultSet;
    }
  
    /**
     * See above
     */
    public static NodeList tokenize(String toTokenize)
    {
      return tokenize(toTokenize, " \t\n\r");
    }
  
      /**
     * @return an instance of DOM Document
       */
     private static Document getDocument()
     {
          try
          {
              if (System.getSecurityManager() == null) {
                  return DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
              } else {
                  return DocumentBuilderFactory.newInstance(JDK_DEFAULT_DOM, null).newDocumentBuilder().newDocument();
              }
          }
          catch(ParserConfigurationException pce)
          {
              throw new WrappedRuntimeException(pce);
          }
      }
  }
  