/*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (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.mozilla.org/MPL/>.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 * language governing rights and limitations under the License.
 * 
 * The Original Code is the Venice Web Communities System.
 * 
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.dynamo.xmlrpc;

import java.util.*;
import org.w3c.dom.*;
import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.except.*;

class XMLMetadata implements XmlRpcTypeNames
{
  /*--------------------------------------------------------------------------------
   * Static data members
   *--------------------------------------------------------------------------------
   */

  private static final Set VALID_TYPES;

  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  private String m_method_name;
  private List m_signatures;
  private String m_docs;

  /*--------------------------------------------------------------------------------
   * Constructor
   *--------------------------------------------------------------------------------
   */

  XMLMetadata(Element md_root) throws ConfigException
  {
    XMLLoader loader = XMLLoader.get();
    try
    { // get the method name
      m_method_name = loader.getAttribute(md_root,"method");

      // look for method signatures
      ArrayList sigs = new ArrayList();
      List l_sigs = loader.getMatchingSubElements(md_root,"signature");
      Iterator it = l_sigs.iterator();
      while (it.hasNext())
      { // get each signature
	Element sig_elt = (Element)(it.next());

	// get the return type
	ArrayList sdata = new ArrayList();
	String s = loader.getSubElementText(sig_elt,"return").trim();
	verifyType(s);
	sdata.add(s);

	// get all parameters
	List l_parms = loader.getMatchingSubElements(sig_elt,"param");
	Iterator it2 = l_parms.iterator();
	while (it2.hasNext())
	{ // get each parameter in turn
	  Element elt = (Element)(it2.next());
	  s = loader.getText(elt).trim();
	  verifyType(s);
	  sdata.add(s);

	} // end while

	// add signature to the list
	sdata.trimToSize();
	sigs.add(Collections.unmodifiableList(sdata));

      } // end while

      if (sigs.isEmpty())
      { // no signatures - throw an exception
	ConfigException ce = new ConfigException(XMLMetadata.class,"XmlRpcMessages","md.noSigs");
	ce.setParameter(0,m_method_name);
	throw ce;

      } // end if

      // save the signatures
      sigs.trimToSize();
      m_signatures = Collections.unmodifiableList(sigs);

      // load the documentation
      DOMElementHelper h = new DOMElementHelper(md_root);
      m_docs = h.getSubElementText("doc");
      if (m_docs==null)
	m_docs = "";

    } // end try
    catch (XMLLoadException e)
    { // translate into ConfigException
      throw new ConfigException(e);

    } // end catch

  } // end constructor

  /*--------------------------------------------------------------------------------
   * Internal operations
   *--------------------------------------------------------------------------------
   */

  private static final void verifyType(String typename) throws ConfigException
  {
    if (!(VALID_TYPES.contains(typename)))
    { // type value is not valid
      ConfigException ce = new ConfigException(XMLMetadata.class,"XmlRpcMessages","md.badType");
      ce.setParameter(0,typename);
      throw ce;

    } // end if

  } // end verifyType

  /*--------------------------------------------------------------------------------
   * External operations
   *--------------------------------------------------------------------------------
   */

  String getMethodName()
  {
    return m_method_name;

  } // end getMethodName

  List getSignatures()
  {
    return m_signatures;

  } // end getSignatures

  String getDocumentation()
  {
    return m_docs;

  } // end getDocumentation

  /*--------------------------------------------------------------------------------
   * Static initializer
   *--------------------------------------------------------------------------------
   */

  static
  { // Initialize the valid type set.
    HashSet tmp = new HashSet();
    tmp.add(TYPE_INT);
    tmp.add(TYPE_BOOLEAN);
    tmp.add(TYPE_STRING);
    tmp.add(TYPE_DOUBLE);
    tmp.add(TYPE_DATETIME);
    tmp.add(TYPE_BASE64);
    tmp.add(TYPE_STRUCT);
    tmp.add(TYPE_ARRAY);
    VALID_TYPES = Collections.unmodifiableSet(tmp);

  } // end static initializer

} // end class XMLMetadata
