/* TransformerOutputProperties.java --
   Copyright (C) 2004 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath 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 2, or (at your option)
any later version.

GNU Classpath 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 GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package gnu.xml.transform;

import gnu.java.lang.CPStringBuilder;

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.xml.transform.OutputKeys;

/**
 * Helper class to manage JAXP user setting of output properties.
 *
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 */
class TransformerOutputProperties
  extends Properties
{

  final Properties defaultProperties;
  final Stylesheet stylesheet;
  boolean dirty;

  TransformerOutputProperties(Stylesheet stylesheet)
  {
    this.stylesheet = stylesheet;
    defaultProperties = new Properties();
    switch (stylesheet.outputMethod)
      {
      case Stylesheet.OUTPUT_XML:
        defaultProperties.put(OutputKeys.METHOD, "xml");
        break;
      case Stylesheet.OUTPUT_HTML:
        defaultProperties.put(OutputKeys.METHOD, "html");
        break;
      case Stylesheet.OUTPUT_TEXT:
        defaultProperties.put(OutputKeys.METHOD, "text");
        break;
      }
    if (stylesheet.outputVersion != null)
      {
        defaultProperties.put(OutputKeys.VERSION, stylesheet.outputVersion);
      }
    if (stylesheet.outputEncoding != null)
      {
        defaultProperties.put(OutputKeys.ENCODING, stylesheet.outputEncoding);
      }
    defaultProperties.put(OutputKeys.OMIT_XML_DECLARATION,
                          stylesheet.outputOmitXmlDeclaration ? "yes" : "no");
    defaultProperties.put(OutputKeys.STANDALONE,
                          stylesheet.outputStandalone ? "yes" : "no");
    if (stylesheet.outputPublicId != null)
      {
        defaultProperties.put(OutputKeys.DOCTYPE_PUBLIC,
                              stylesheet.outputPublicId);
      }
    if (stylesheet.outputSystemId != null)
      {
        defaultProperties.put(OutputKeys.DOCTYPE_SYSTEM,
                              stylesheet.outputSystemId);
      }
    CPStringBuilder buf = new CPStringBuilder();
    for (Iterator i = stylesheet.outputCdataSectionElements.iterator();
         i.hasNext(); )
      {
        if (buf.length() > 0)
          {
            buf.append(' ');
          }
        buf.append((String) i.next());
      }
    defaultProperties.put(OutputKeys.CDATA_SECTION_ELEMENTS, buf.toString());
    defaultProperties.put(OutputKeys.INDENT,
                          stylesheet.outputIndent ? "yes" : "no");
    if (stylesheet.outputMediaType != null)
      {
        defaultProperties.put(OutputKeys.MEDIA_TYPE,
                              stylesheet.outputMediaType);
      }
  }

  public String getProperty(String key)
  {
    String val = super.getProperty(key);
    if (val == null)
      {
        val = defaultProperties.getProperty(key);
      }
    return val;
  }

  public Object put(Object key, Object value)
  {
    Object ret = super.put(key, value);
    dirty = true;
    return ret;
  }

  public void clear()
  {
    super.clear();
    dirty = true;
  }

  /**
   * Applies the current set of properties to the underlying stylesheet.
   */
  void apply()
  {
    if (!dirty)
      {
        return;
      }
    String method = getProperty(OutputKeys.METHOD);
    if ("xml".equals(method))
      {
        stylesheet.outputMethod = Stylesheet.OUTPUT_XML;
      }
    else if ("html".equals(method))
      {
        stylesheet.outputMethod = Stylesheet.OUTPUT_HTML;
      }
    else if ("text".equals(method))
      {
        stylesheet.outputMethod = Stylesheet.OUTPUT_TEXT;
      }
    stylesheet.outputVersion = getProperty(OutputKeys.VERSION);
    stylesheet.outputEncoding = getProperty(OutputKeys.ENCODING);
    stylesheet.outputOmitXmlDeclaration =
      "yes".equals(getProperty(OutputKeys.OMIT_XML_DECLARATION));
    stylesheet.outputStandalone =
      "yes".equals(getProperty(OutputKeys.STANDALONE));
    stylesheet.outputPublicId = getProperty(OutputKeys.DOCTYPE_PUBLIC);
    stylesheet.outputSystemId = getProperty(OutputKeys.DOCTYPE_SYSTEM);
    StringTokenizer st =
      new StringTokenizer(getProperty(OutputKeys.CDATA_SECTION_ELEMENTS));
    Collection acc = new LinkedHashSet();
    while (st.hasMoreTokens())
      {
        acc.add(st.nextToken());
      }
    stylesheet.outputCdataSectionElements = acc;
    stylesheet.outputIndent = "yes".equals(getProperty(OutputKeys.INDENT));
    stylesheet.outputMediaType = getProperty(OutputKeys.MEDIA_TYPE);
    dirty = false;
  }

}
