/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:  
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, Lotus
 * Development Corporation., http://www.lotus.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
package org.apache.xalan.templates;

import org.w3c.dom.*;

import org.xml.sax.*;

import org.apache.xpath.*;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xalan.transformer.TransformerImpl;

/**
 * <meta name="usage" content="advanced"/>
 * Implement xsl:sort.
 * <pre>
 * <!ELEMENT xsl:sort EMPTY>
 * <!ATTLIST xsl:sort
 *   select %expr; "."
 *   lang %avt; #IMPLIED
 *   data-type %avt; "text"
 *   order %avt; "ascending"
 *   case-order %avt; #IMPLIED
 * >
 * <!-- xsl:sort cannot occur after any other elements or
 * any non-whitespace character -->
 * </pre>
 * @see <a href="http://www.w3.org/TR/xslt#sorting">sorting in XSLT Specification</a>
 */
public class ElemSort extends ElemTemplateElement
{

  /**
   * xsl:sort has a select attribute whose value is an expression.
   * @serial
   */
  private XPath m_selectExpression = null;

  /**
   * Set the "select" attribute.
   * xsl:sort has a select attribute whose value is an expression.
   * For each node to be processed, the expression is evaluated
   * with that node as the current node and with the complete
   * list of nodes being processed in unsorted order as the current
   * node list. The resulting object is converted to a string as if
   * by a call to the string function; this string is used as the
   * sort key for that node. The default value of the select attribute
   * is ., which will cause the string-value of the current node to
   * be used as the sort key.
   *
   * @param v Value to set for the "select" attribute
   */
  public void setSelect(XPath v)
  {

    if (v.getPatternString().indexOf("{") < 0)
      m_selectExpression = v;
    else
      error(XSLTErrorResources.ER_NO_CURLYBRACE, null);
  }

  /**
   * Get the "select" attribute.
   * xsl:sort has a select attribute whose value is an expression.
   * For each node to be processed, the expression is evaluated
   * with that node as the current node and with the complete
   * list of nodes being processed in unsorted order as the current
   * node list. The resulting object is converted to a string as if
   * by a call to the string function; this string is used as the
   * sort key for that node. The default value of the select attribute
   * is ., which will cause the string-value of the current node to
   * be used as the sort key.
   *
   * @return The value of the "select" attribute
   */
  public XPath getSelect()
  {
    return m_selectExpression;
  }

  /**
   * lang specifies the language of the sort keys.
   * @serial
   */
  private AVT m_lang_avt = null;

  /**
   * Set the "lang" attribute.
   * lang specifies the language of the sort keys; it has the same
   * range of values as xml:lang [XML]; if no lang value is
   * specified, the language should be determined from the system environment.
   *
   * @param v The value to set for the "lang" attribute
   */
  public void setLang(AVT v)
  {
    m_lang_avt = v;
  }

  /**
   * Get the "lang" attribute.
   * lang specifies the language of the sort keys; it has the same
   * range of values as xml:lang [XML]; if no lang value is
   * specified, the language should be determined from the system environment.
   *
   * @return The value of the "lang" attribute
   */
  public AVT getLang()
  {
    return m_lang_avt;
  }

  /**
   * data-type specifies the data type of the
   * strings to be sorted.
   * @serial
   */
  private AVT m_dataType_avt = null;

  /**
   * Set the "data-type" attribute.
   * <code>data-type</code> specifies the data type of the
   * strings; the following values are allowed:
   * <ul>
   * <li>
   * <code>text</code> specifies that the sort keys should be
   * sorted lexicographically in the culturally correct manner for the
   * language specified by <code>lang</code>.
   * </li>
   * <li>
   * <code>number</code> specifies that the sort keys should be
   * converted to numbers and then sorted according to the numeric value;
   * the sort key is converted to a number as if by a call to the
   * <b><a href="http://www.w3.org/TR/xpath#function-number">number</a></b> function; the <code>lang</code>
   * attribute is ignored.
   * </li>
   * <li>
   * A <a href="http://www.w3.org/TR/REC-xml-names#NT-QName">QName</a> with a prefix
   * is expanded into an <a href="http://www.w3.org/TR/xpath#dt-expanded-name">expanded-name</a> as described
   * in <a href="#qname">[<b>2.4 Qualified Names</b>]</a>; the expanded-name identifies the data-type;
   * the behavior in this case is not specified by this document.
   * </li>
   * </ul>
   * <p>The default value is <code>text</code>.</p>
   * <blockquote>
   * <b>NOTE: </b>The XSL Working Group plans that future versions of XSLT will
   * leverage XML Schemas to define further values for this
   * attribute.</blockquote>
   *
   * @param v Value to set for the "data-type" attribute
   */
  public void setDataType(AVT v)
  {
    m_dataType_avt = v;
  }

  /**
   * Get the "data-type" attribute.
   * <code>data-type</code> specifies the data type of the
   * strings; the following values are allowed:
   * <ul>
   * <li>
   * <code>text</code> specifies that the sort keys should be
   * sorted lexicographically in the culturally correct manner for the
   * language specified by <code>lang</code>.
   * </li>
   * <li>
   * <code>number</code> specifies that the sort keys should be
   * converted to numbers and then sorted according to the numeric value;
   * the sort key is converted to a number as if by a call to the
   * <b><a href="http://www.w3.org/TR/xpath#function-number">number</a></b> function; the <code>lang</code>
   * attribute is ignored.
   * </li>
   * <li>
   * A <a href="http://www.w3.org/TR/REC-xml-names#NT-QName">QName</a> with a prefix
   * is expanded into an <a href="http://www.w3.org/TR/xpath#dt-expanded-name">expanded-name</a> as described
   * in <a href="#qname">[<b>2.4 Qualified Names</b>]</a>; the expanded-name identifies the data-type;
   * the behavior in this case is not specified by this document.
   * </li>
   * </ul>
   * <p>The default value is <code>text</code>.</p>
   * <blockquote>
   * <b>NOTE: </b>The XSL Working Group plans that future versions of XSLT will
   * leverage XML Schemas to define further values for this
   * attribute.</blockquote>
   *
   * @return The value of the "data-type" attribute
   */
  public AVT getDataType()
  {
    return m_dataType_avt;
  }

  /**
   * order specifies whether the strings should be sorted in ascending
   * or descending order.
   * @serial
   */
  private AVT m_order_avt = null;

  /**
   * Set the "order" attribute.
   * order specifies whether the strings should be sorted in ascending
   * or descending order; ascending specifies ascending order; descending
   * specifies descending order; the default is ascending.
   *
   * @param v The value to set for the "order" attribute
   */
  public void setOrder(AVT v)
  {
    m_order_avt = v;
  }

  /**
   * Get the "order" attribute.
   * order specifies whether the strings should be sorted in ascending
   * or descending order; ascending specifies ascending order; descending
   * specifies descending order; the default is ascending.
   *
   * @return The value of the "order" attribute
   */
  public AVT getOrder()
  {
    return m_order_avt;
  }

  /**
   * case-order has the value upper-first or lower-first.
   * The default value is language dependent.
   * @serial
   */
  private AVT m_caseorder_avt = null;

  /**
   * Set the "case-order" attribute.
   * case-order has the value upper-first or lower-first; this applies
   * when data-type="text", and specifies that upper-case letters should
   * sort before lower-case letters or vice-versa respectively.
   * For example, if lang="en", then A a B b are sorted with
   * case-order="upper-first" and a A b B are sorted with case-order="lower-first".
   * The default value is language dependent.
   *
   * @param v The value to set for the "case-order" attribute
   * 
   * @serial
   */
  public void setCaseOrder(AVT v)
  {
    m_caseorder_avt = v;
  }

  /**
   * Get the "case-order" attribute.
   * case-order has the value upper-first or lower-first; this applies
   * when data-type="text", and specifies that upper-case letters should
   * sort before lower-case letters or vice-versa respectively.
   * For example, if lang="en", then A a B b are sorted with
   * case-order="upper-first" and a A b B are sorted with case-order="lower-first".
   * The default value is language dependent.
   *
   * @return The value of the "case-order" attribute
   */
  public AVT getCaseOrder()
  {
    return m_caseorder_avt;
  }

  /**
   * Get an int constant identifying the type of element.
   * @see org.apache.xalan.templates.Constants
   *
   * @return The token ID of the element
   */
  public int getXSLToken()
  {
    return Constants.ELEMNAME_SORT;
  }

  /**
   * Return the node name.
   *
   * @return The element's name
   */
  public String getNodeName()
  {
    return Constants.ELEMNAME_SORT_STRING;
  }

  /**
   * Add a child to the child list.
   *
   * @param newChild Child to add to the child list
   *
   * @return Child just added to the child list
   *
   * @throws DOMException
   */
  public Node appendChild(Node newChild) throws DOMException
  {

    error(XSLTErrorResources.ER_CANNOT_ADD,
          new Object[]{ newChild.getNodeName(),
                        this.getNodeName() });  //"Can not add " +((ElemTemplateElement)newChild).m_elemName +

    //" to " + this.m_elemName);
    return null;
  }
  
  /**
   * This function is called after everything else has been
   * recomposed, and allows the template to set remaining
   * values that may be based on some other property that
   * depends on recomposition.
   */
  public void compose(StylesheetRoot sroot) 
    throws javax.xml.transform.TransformerException
  {
    super.compose(sroot);
    StylesheetRoot.ComposeState cstate = sroot.getComposeState();
    java.util.Vector vnames = cstate.getVariableNames();
    if(null != m_caseorder_avt)
      m_caseorder_avt.fixupVariables(vnames, cstate.getGlobalsSize());
    if(null != m_dataType_avt)
      m_dataType_avt.fixupVariables(vnames, cstate.getGlobalsSize());
    if(null != m_lang_avt)
      m_lang_avt.fixupVariables(vnames, cstate.getGlobalsSize());
    if(null != m_order_avt)
      m_order_avt.fixupVariables(vnames, cstate.getGlobalsSize());
    if(null != m_selectExpression)
      m_selectExpression.fixupVariables(vnames, cstate.getGlobalsSize());
  }
}
