/**
 * $RCSfile$
 * Copyright 2002-2003 by Robert Simmons Jr., All Rights Reserved
 * 
 * Last Checked in by: $Author$
 * Last Checked in on: $Date$
 * Currently Locked By: $Locker$
 * Working Tag: $Name$
 * 
 * End: Mirror Standard Header.
***** DO NOT EDIT ABOVE THIS LINE *****/
package jconfer.client.generators;

import java.io.IOException;
import java.util.Map;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.generation.AbstractGenerator;
import org.apache.log4j.Logger;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

/** Defines the common ibase class for JConfer generators.
 *
 * <p><b><small>Current CVS Tag:  $Name$</b></small></p>
 * @version $Revision$
 * @author $author$
 */
public abstract class GeneratorBase extends AbstractGenerator {

  /** Holds the logger object. */
  private static final Logger LOGGER = Logger.getLogger(GeneratorBase.class);

  /** The namespace URI for JConfer. */
  protected static final String JCONFER_URI = "http://www.jconfer.org/";

  /** An Empty Attributes object declared for convenience.  */
  protected final AttributesImpl EMPTY_ATTRS = new AttributesImpl();

  /** Holds the initial context avoid beign looked up repeatedly. */
  protected InitialContext ictxt;

  /** Sub method for derived classes to override to generate the 
   * content of the page. The generate() method is used to provide the
   * common skeleton of JConfer XML documents. Subclasses should override
   * this method to insert content into the page. Then the page will
   * automatically be closed when this method returns.
   */
  public abstract void generateContent()
    throws Exception;

  /** {@inheritDoc} */
  public void generate()
    throws SAXException {
    try {
      generateHeader();
      generateContent();
      generateFooter();
    } catch (SAXException ex) {
      LOGGER.error(ex);
      throw ex;  // throw it without encasing it in another. 
    } catch (Exception ex) {
      // -- Encase other exceptions in a SAX exception and throw.
      LOGGER.error(ex);
      throw new SAXException("Error occurred in processing.", ex);
    }
  }

  /** {@inheritDoc} */
  public void recycle() {
    super.recycle();
  }

  /** {@inheritDoc} */
  public void setup(final SourceResolver resolver, final Map objectModel, 
                    final String src, final Parameters par)
    throws ProcessingException, SAXException, IOException {
    super.setup(resolver, objectModel, src, par);
    try {
      this.ictxt = new InitialContext();
    } catch (Exception ex) {
      throw new ProcessingException(ex);
    }
  }

  /** Helper method that writes out the common header of the resulting xml. */
  protected void generateFooter()
    throws SAXException {
    contentHandler.endElement(JCONFER_URI, "jconfer-page", 
                              "jconfer:jconfer-page");
    contentHandler.endDocument();
  }

  /** Helper method that writes out the common header of the resulting xml. */
  protected void generateHeader()
    throws SAXException {
    // -- Document initializaion. 
    this.contentHandler.startDocument();
    this.contentHandler.processingInstruction("xml", 
                                              "version=\"1.0\" encoding=\"UTF-8\"");
    // -- Root Element
    AttributesImpl attributes = new AttributesImpl();
    attributes.addAttribute("http://www.w3.org/2001/XMLSchema-instance", 
                            "schemaLocation", "xsi:schemaLocation", "", 
                            "http://www.jconfer.org/ ../XSD/JConfer.xsd");
    this.contentHandler.startElement(JCONFER_URI, "jconfer-page", 
                                     "jconfer:jconfer-page", attributes);
  }

  /** Utility method to lookup a JNDI reference. 
   *
   * @param dataType The class type to look up.
   * @param name The JNDI name to look up.
   */
  protected Object jndiLookup(final Class dataType, final String name)
    throws NamingException {
    Object obj = null; 
    obj = this.ictxt.lookup(name);
    return PortableRemoteObject.narrow(obj, dataType);
  }
}


