/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2003 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 java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.TransformerException;

import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xml.serializer.OutputPropertiesFactory;
import org.apache.xml.serializer.OutputPropertyUtils;
import org.apache.xml.utils.FastStringBuffer;
import org.apache.xml.utils.QName;

/**
 * This class provides information from xsl:output elements. It is mainly
 * a wrapper for {@link java.util.Properties}, but can not extend that class
 * because it must be part of the {@link org.apache.xalan.templates.ElemTemplateElement}
 * heararchy.
 * <p>An OutputProperties list can contain another OutputProperties list as
 * its "defaults"; this second property list is searched if the property key
 * is not found in the original property list.</p>
 * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a>
 * @see <a href="http://www.w3.org/TR/xslt#output">xsl:output in XSLT Specification</a>
 *
 */
public class OutputProperties extends ElemTemplateElement
        implements Cloneable
{

  /**
   * Creates an empty OutputProperties with no default values.
   */
  public OutputProperties()
  {
    this(org.apache.xml.serializer.Method.XML);
  }

  /**
   * Creates an empty OutputProperties with the specified defaults.
   *
   * @param   defaults   the defaults.
   */
  public OutputProperties(Properties defaults)
  {
    m_properties = new Properties(defaults);
  }

  /**
   * Creates an empty OutputProperties with the defaults specified by
   * a property file.  The method argument is used to construct a string of
   * the form output_[method].properties (for instance, output_html.properties).
   * The output_xml.properties file is always used as the base.
   * <p>At the moment, anything other than 'text', 'xml', and 'html', will
   * use the output_xml.properties file.</p>
   *
   * @param   method non-null reference to method name.
   */
  public OutputProperties(String method)
  {
    m_properties = new Properties(
        OutputPropertiesFactory.getDefaultMethodProperties(method));
  }

  /**
   * Clone this OutputProperties, including a clone of the wrapped Properties
   * reference.
   *
   * @return A new OutputProperties reference, mutation of which should not
   *         effect this object.
   */
  public Object clone()
  {

    try
    {
      OutputProperties cloned = (OutputProperties) super.clone();

      cloned.m_properties = (Properties) cloned.m_properties.clone();

      return cloned;
    }
    catch (CloneNotSupportedException e)
    {
      return null;
    }
  }

  /**
   * Set an output property.
   *
   * @param key the key to be placed into the property list.
   * @param value the value corresponding to <tt>key</tt>.
   * @see javax.xml.transform.OutputKeys
   */
  public void setProperty(QName key, String value)
  {
    setProperty(key.toNamespacedString(), value);
  }

  /**
   * Set an output property.
   *
   * @param key the key to be placed into the property list.
   * @param value the value corresponding to <tt>key</tt>.
   * @see javax.xml.transform.OutputKeys
   */
  public void setProperty(String key, String value)
  {
    if(key.equals(OutputKeys.METHOD))
    {
      setMethodDefaults(value);
    }
    
    if (key.startsWith(OutputPropertiesFactory.S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL))
      key = OutputPropertiesFactory.S_BUILTIN_EXTENSIONS_UNIVERSAL
         + key.substring(OutputPropertiesFactory.S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL_LEN);
    
    m_properties.put(key, value);
  }

  /**
   * Searches for the property with the specified key in the property list.
   * If the key is not found in this property list, the default property list,
   * and its defaults, recursively, are then checked. The method returns
   * <code>null</code> if the property is not found.
   *
   * @param   key   the property key.
   * @return  the value in this property list with the specified key value.
   */
  public String getProperty(QName key)
  {
    return m_properties.getProperty(key.toNamespacedString());
  }

  /**
   * Searches for the property with the specified key in the property list.
   * If the key is not found in this property list, the default property list,
   * and its defaults, recursively, are then checked. The method returns
   * <code>null</code> if the property is not found.
   *
   * @param   key   the property key.
   * @return  the value in this property list with the specified key value.
   */
  public String getProperty(String key) 
  {
    if (key.startsWith(OutputPropertiesFactory.S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL))
      key = OutputPropertiesFactory.S_BUILTIN_EXTENSIONS_UNIVERSAL 
        + key.substring(OutputPropertiesFactory.S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL_LEN);
    return m_properties.getProperty(key);
  }

  /**
   * Set an output property.
   *
   * @param key the key to be placed into the property list.
   * @param value the value corresponding to <tt>key</tt>.
   * @see javax.xml.transform.OutputKeys
   */
  public void setBooleanProperty(QName key, boolean value)
  {
    m_properties.put(key.toNamespacedString(), value ? "yes" : "no");
  }

  /**
   * Set an output property.
   *
   * @param key the key to be placed into the property list.
   * @param value the value corresponding to <tt>key</tt>.
   * @see javax.xml.transform.OutputKeys
   */
  public void setBooleanProperty(String key, boolean value)
  {
    m_properties.put(key, value ? "yes" : "no");
  }

  /**
   * Searches for the boolean property with the specified key in the property list.
   * If the key is not found in this property list, the default property list,
   * and its defaults, recursively, are then checked. The method returns
   * <code>false</code> if the property is not found, or if the value is other
   * than "yes".
   *
   * @param   key   the property key.
   * @return  the value in this property list as a boolean value, or false
   * if null or not "yes".
   */
  public boolean getBooleanProperty(QName key)
  {
    return getBooleanProperty(key.toNamespacedString());
  }

  /**
   * Searches for the boolean property with the specified key in the property list.
   * If the key is not found in this property list, the default property list,
   * and its defaults, recursively, are then checked. The method returns
   * <code>false</code> if the property is not found, or if the value is other
   * than "yes".
   *
   * @param   key   the property key.
   * @return  the value in this property list as a boolean value, or false
   * if null or not "yes".
   */
  public boolean getBooleanProperty(String key)
  {
    return OutputPropertyUtils.getBooleanProperty(key, m_properties);
  }

  /**
   * Set an output property.
   *
   * @param key the key to be placed into the property list.
   * @param value the value corresponding to <tt>key</tt>.
   * @see javax.xml.transform.OutputKeys
   */
  public void setIntProperty(QName key, int value)
  {
    setIntProperty(key.toNamespacedString(), value);
  }

  /**
   * Set an output property.
   *
   * @param key the key to be placed into the property list.
   * @param value the value corresponding to <tt>key</tt>.
   * @see javax.xml.transform.OutputKeys
   */
  public void setIntProperty(String key, int value)
  {
    m_properties.put(key, Integer.toString(value));
  }

  /**
   * Searches for the int property with the specified key in the property list.
   * If the key is not found in this property list, the default property list,
   * and its defaults, recursively, are then checked. The method returns
   * <code>false</code> if the property is not found, or if the value is other
   * than "yes".
   *
   * @param   key   the property key.
   * @return  the value in this property list as a int value, or false
   * if null or not a number.
   */
  public int getIntProperty(QName key)
  {
    return getIntProperty(key.toNamespacedString());
  }

  /**
   * Searches for the int property with the specified key in the property list.
   * If the key is not found in this property list, the default property list,
   * and its defaults, recursively, are then checked. The method returns
   * <code>false</code> if the property is not found, or if the value is other
   * than "yes".
   *
   * @param   key   the property key.
   * @return  the value in this property list as a int value, or false
   * if null or not a number.
   */
  public int getIntProperty(String key)
  {
    return OutputPropertyUtils.getIntProperty(key, m_properties);
  }


  /**
   * Set an output property with a QName value.  The QName will be turned
   * into a string with the namespace in curly brackets.
   *
   * @param key the key to be placed into the property list.
   * @param value the value corresponding to <tt>key</tt>.
   * @see javax.xml.transform.OutputKeys
   */
  public void setQNameProperty(QName key, QName value)
  {
    setQNameProperty(key.toNamespacedString(), value);
  }
  
  /**
   * Reset the default properties based on the method.
   *
   * @param method the method value.
   * @see javax.xml.transform.OutputKeys
   */
  public void setMethodDefaults(String method)
  {
        String defaultMethod = m_properties.getProperty(OutputKeys.METHOD);
 
        if((null == defaultMethod) || !defaultMethod.equals(method)
         // bjm - add the next condition as a hack
         // but it is because both output_xml.properties and
         // output_unknown.properties have the same method=xml
         // for their default. Otherwise we end up with
         // a ToUnknownStream wraping a ToXMLStream even
         // when the users says method="xml"
         //
         || defaultMethod.equals("xml")
         )
        {
            Properties savedProps = m_properties;
            Properties newDefaults = 
                OutputPropertiesFactory.getDefaultMethodProperties(method);
            m_properties = new Properties(newDefaults);
            copyFrom(savedProps, false);
        }
  }
  

  /**
   * Set an output property with a QName value.  The QName will be turned
   * into a string with the namespace in curly brackets.
   *
   * @param key the key to be placed into the property list.
   * @param value the value corresponding to <tt>key</tt>.
   * @see javax.xml.transform.OutputKeys
   */
  public void setQNameProperty(String key, QName value)
  {
    setProperty(key, value.toNamespacedString());
  }

  /**
   * Searches for the qname property with the specified key in the property list.
   * If the key is not found in this property list, the default property list,
   * and its defaults, recursively, are then checked. The method returns
   * <code>null</code> if the property is not found.
   *
   * @param   key   the property key.
   * @return  the value in this property list as a QName value, or false
   * if null or not "yes".
   */
  public QName getQNameProperty(QName key)
  {
    return getQNameProperty(key.toNamespacedString());
  }

  /**
   * Searches for the qname property with the specified key in the property list.
   * If the key is not found in this property list, the default property list,
   * and its defaults, recursively, are then checked. The method returns
   * <code>null</code> if the property is not found.
   *
   * @param   key   the property key.
   * @return  the value in this property list as a QName value, or false
   * if null or not "yes".
   */
  public QName getQNameProperty(String key)
  {
    return getQNameProperty(key, m_properties);
  }

  /**
   * Searches for the qname property with the specified key in the property list.
   * If the key is not found in this property list, the default property list,
   * and its defaults, recursively, are then checked. The method returns
   * <code>null</code> if the property is not found.
   *
   * @param   key   the property key.
   * @param props the list of properties to search in.
   * @return  the value in this property list as a QName value, or false
   * if null or not "yes".
   */
  public static QName getQNameProperty(String key, Properties props)
  {

    String s = props.getProperty(key);

    if (null != s)
      return QName.getQNameFromString(s);
    else
      return null;
  }

  /**
   * Set an output property with a QName list value.  The QNames will be turned
   * into strings with the namespace in curly brackets.
   *
   * @param key the key to be placed into the property list.
   * @param v non-null list of QNames corresponding to <tt>key</tt>.
   * @see javax.xml.transform.OutputKeys
   */
  public void setQNameProperties(QName key, Vector v)
  {
    setQNameProperties(key.toNamespacedString(), v);
  }

  /**
   * Set an output property with a QName list value.  The QNames will be turned
   * into strings with the namespace in curly brackets.
   *
   * @param key the key to be placed into the property list.
   * @param v non-null list of QNames corresponding to <tt>key</tt>.
   * @see javax.xml.transform.OutputKeys
   */
  public void setQNameProperties(String key, Vector v)
  {

    int s = v.size();

    // Just an initial guess at reasonable tuning parameters
    FastStringBuffer fsb = new FastStringBuffer(9,9);

    for (int i = 0; i < s; i++)
    {
      QName qname = (QName) v.elementAt(i);

      fsb.append(qname.toNamespacedString());
      // Don't append space after last value
      if (i < s-1) 
        fsb.append(' ');
    }

    m_properties.put(key, fsb.toString());
  }

  /**
   * Searches for the list of qname properties with the specified key in
   * the property list.
   * If the key is not found in this property list, the default property list,
   * and its defaults, recursively, are then checked. The method returns
   * <code>null</code> if the property is not found.
   *
   * @param   key   the property key.
   * @return  the value in this property list as a vector of QNames, or false
   * if null or not "yes".
   */
  public Vector getQNameProperties(QName key)
  {
    return getQNameProperties(key.toNamespacedString());
  }

  /**
   * Searches for the list of qname properties with the specified key in
   * the property list.
   * If the key is not found in this property list, the default property list,
   * and its defaults, recursively, are then checked. The method returns
   * <code>null</code> if the property is not found.
   *
   * @param   key   the property key.
   * @return  the value in this property list as a vector of QNames, or false
   * if null or not "yes".
   */
  public Vector getQNameProperties(String key)
  {
    return getQNameProperties(key, m_properties);
  }

  /**
   * Searches for the list of qname properties with the specified key in
   * the property list.
   * If the key is not found in this property list, the default property list,
   * and its defaults, recursively, are then checked. The method returns
   * <code>null</code> if the property is not found.
   *
   * @param   key   the property key.
   * @param props the list of properties to search in.
   * @return  the value in this property list as a vector of QNames, or false
   * if null or not "yes".
   */
  public static Vector getQNameProperties(String key, Properties props)
  {

    String s = props.getProperty(key);

    if (null != s)
    {
      Vector v = new Vector();
      int l = s.length();
      boolean inCurly = false;
      FastStringBuffer buf = new FastStringBuffer();

      // parse through string, breaking on whitespaces.  I do this instead 
      // of a tokenizer so I can track whitespace inside of curly brackets, 
      // which theoretically shouldn't happen if they contain legal URLs.
      for (int i = 0; i < l; i++)
      {
        char c = s.charAt(i);

        if (Character.isWhitespace(c))
        {
          if (!inCurly)
          {
            if (buf.length() > 0)
            {
              QName qname = QName.getQNameFromString(buf.toString());
              v.addElement(qname);
              buf.reset();
            }
            continue;
          }
        }
        else if ('{' == c)
          inCurly = true;
        else if ('}' == c)
          inCurly = false;

        buf.append(c);
      }

      if (buf.length() > 0)
      {
        QName qname = QName.getQNameFromString(buf.toString());
        v.addElement(qname);
        buf.reset();
      }

      return v;
    }
    else
      return null;
  }

  /**
   * This function is called to recompose all of the output format extended elements.
   *
   * @param root non-null reference to the stylesheet root object.
   */
  public void recompose(StylesheetRoot root)
    throws TransformerException
  {
    root.recomposeOutput(this);
  }

  /**
   * 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 TransformerException
  {

    super.compose(sroot);

  }

  /**
   * Get the Properties object that this class wraps.
   *
   * @return non-null reference to Properties object.
   */
  public Properties getProperties()
  {
    return m_properties;
  }
  
  /**
   * Copy the keys and values from the source to this object.  This will
   * not copy the default values.  This is meant to be used by going from
   * a higher precedence object to a lower precedence object, so that if a
   * key already exists, this method will not reset it.
   *
   * @param src non-null reference to the source properties.
   */
  public void copyFrom(Properties src)
  {
    copyFrom(src, true);
  }

  /**
   * Copy the keys and values from the source to this object.  This will
   * not copy the default values.  This is meant to be used by going from
   * a higher precedence object to a lower precedence object, so that if a
   * key already exists, this method will not reset it.
   *
   * @param src non-null reference to the source properties.
   * @param shouldResetDefaults true if the defaults should be reset based on 
   *                            the method property.
   */
  public void copyFrom(Properties src, boolean shouldResetDefaults)
  {

    Enumeration keys = src.keys();

    while (keys.hasMoreElements())
    {
      String key = (String) keys.nextElement();
    
      if (!isLegalPropertyKey(key))
        throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_OUTPUT_PROPERTY_NOT_RECOGNIZED, new Object[]{key})); //"output property not recognized: "
      
      Object oldValue = m_properties.get(key);
      if (null == oldValue)
      {
        String val = (String) src.get(key);
        
        if(shouldResetDefaults && key.equals(OutputKeys.METHOD))
        {
          setMethodDefaults(val);
        }

        m_properties.put(key, val);
      }
      else if (key.equals(OutputKeys.CDATA_SECTION_ELEMENTS))
      {
        m_properties.put(key, (String) oldValue + " " + (String) src.get(key));
      }
    }
  }

  /**
   * Copy the keys and values from the source to this object.  This will
   * not copy the default values.  This is meant to be used by going from
   * a higher precedence object to a lower precedence object, so that if a
   * key already exists, this method will not reset it.
   *
   * @param opsrc non-null reference to an OutputProperties.
   */
  public void copyFrom(OutputProperties opsrc)
    throws TransformerException
  {
   // Bugzilla 6157: recover from xsl:output statements
    // checkDuplicates(opsrc);
    copyFrom(opsrc.getProperties());
  }

  /**
   * Report if the key given as an argument is a legal xsl:output key.
   *
   * @param key non-null reference to key name.
   *
   * @return true if key is legal.
   */
  public static boolean isLegalPropertyKey(String key)
  {

    return (key.equals(OutputKeys.CDATA_SECTION_ELEMENTS)
            || key.equals(OutputKeys.DOCTYPE_PUBLIC)
            || key.equals(OutputKeys.DOCTYPE_SYSTEM)
            || key.equals(OutputKeys.ENCODING)
            || key.equals(OutputKeys.INDENT)
            || key.equals(OutputKeys.MEDIA_TYPE)
            || key.equals(OutputKeys.METHOD)
            || key.equals(OutputKeys.OMIT_XML_DECLARATION)
            || key.equals(OutputKeys.STANDALONE)
            || key.equals(OutputKeys.VERSION)
            || (key.length() > 0) 
                  && (key.charAt(0) == '{') 
                  && (key.lastIndexOf('{') == 0)
                  && (key.indexOf('}') > 0)
                  && (key.lastIndexOf('}') == key.indexOf('}')));
  }

  /** The output properties.
   *  @serial */
  private Properties m_properties = null;

    /**
     * Creates an empty OutputProperties with the defaults specified by
     * a property file.  The method argument is used to construct a string of
     * the form output_[method].properties (for instance, output_html.properties).
     * The output_xml.properties file is always used as the base.
     * <p>At the moment, anything other than 'text', 'xml', and 'html', will
     * use the output_xml.properties file.</p>
     *
     * @param   method non-null reference to method name.
     *
     * @return Properties object that holds the defaults for the given method.
     * 
     * @deprecated Use org.apache.xml.serializer.OuputPropertiesFactory.
     * getDefaultMethodProperties directly.
     */
    static public Properties getDefaultMethodProperties(String method)
    {
        return org.apache.xml.serializer.OutputPropertiesFactory.getDefaultMethodProperties(method);
    }
}
