You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by co...@apache.org on 2003/05/01 23:53:18 UTC

cvs commit: cocoon-2.1/src/scratchpad/src/org/apache/cocoon/generation TraxGenerator.java

coliver     2003/05/01 14:53:18

  Added:       src/scratchpad/src/org/apache/cocoon/components/jxdom
                        DocumentAdapter.java
               src/scratchpad/src/org/apache/cocoon/generation
                        TraxGenerator.java
  Log:
  Attempt at XSLT-based template generator
  
  Revision  Changes    Path
  1.1                  cocoon-2.1/src/scratchpad/src/org/apache/cocoon/components/jxdom/DocumentAdapter.java
  
  Index: DocumentAdapter.java
  ===================================================================
  /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  
   ============================================================================
                     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 modifica-
   tion, 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 "Apache Cocoon" 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 (INCLU-
   DING, 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 created by
   Stefano Mazzocchi  <st...@apache.org>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.components.jxdom;
  
  import org.w3c.dom.*;
  import org.apache.commons.jxpath.*;
  import org.apache.commons.jxpath.ri.model.NodePointer;
  import org.apache.commons.jxpath.ri.QName;
  import java.util.*;
  
  /**
   * <p>DOM Wrapper for Java Beans and JavaScript objects utilizing Apache JXPath's Introspector.
   * </p>
   */
  
  public class DocumentAdapter implements Document {
      
      private static final CompiledExpression
          GET_SELF = JXPathContext.compile(".");
      private static final CompiledExpression
          GET_PARENT = JXPathContext.compile("..");
      private static final CompiledExpression 
          GET_ATTRS = JXPathContext.compile("@*");
      private static final CompiledExpression 
          GET_CHILD_NODES = JXPathContext.compile("*");
      private static final CompiledExpression 
          GET_ROOT = JXPathContext.compile("/");
  
      private static NamedNodeMap EMPTY_NODE_MAP = new NamedNodeMap() {
  	    public Node getNamedItem(String name) {
  		return null;
  	    }
  	    public Node setNamedItem(Node arg) 
                              throws DOMException {
  		notSupported();
  		return null;
  	    }
  	    public Node removeNamedItem(String name) 
  		throws DOMException {
  		notSupported();
  		return null;
  	    }
  	    public Node item(int index) {
  		return null;
  	    }
  	    public int getLength() {
  		return 0;
  	    }
  	    public Node getNamedItemNS(String namespaceURI,
  				       String localName) {
  		return null;
  	    }
  	    public Node setNamedItemNS(Node arg) 
  		throws DOMException {
  		notSupported();
  		return null;
  	    }
  	    public Node removeNamedItemNS(String namespaceURI,
  					  String localName)
  		throws DOMException {
  		notSupported();
  		return null;
  	    }
  	};
  
      private static final NodeList EMPTY_NODE_LIST = new NodeList() {
              public int getLength() {
                  return 0;
              }
              public Node item(int i) {
                  return null;
              }
          };
  
      private static final JXPathContextFactory jxpathContextFactory = 
  	JXPathContextFactory.newInstance();
  
      private static void notSupported() throws DOMException {
          throw new UnsupportedOperationException("Not Supported");
      }
  
      private static JXPathContext newContext(Object obj) {
  	return jxpathContextFactory.newContext(null, obj);
      }
  
      private ElementAdapter root;
  
      public DocumentAdapter(Object obj, String tagName) {
          root = new ElementAdapter(this, 
  				  GET_SELF.getPointer(newContext(obj), "."),
                                    -1,
                                    tagName,
                                    obj);
      }
  
      public abstract class NodeAdapter implements Node {
          Node parent;
          Pointer ptr;
          JXPathContext context;
  
          public Object unwrap() {
              if (ptr == null) {
                  return null;
              }
              return ptr.getNode();
          }
  
          NodeAdapter(Node parent, Pointer ptr) {
              this.parent = parent;
              this.ptr = ptr;
          }
  
          JXPathContext getContext() {
              if (this.context == null) {
                  this.context = newContext(ptr.getNode());
              }
              return this.context;
          }
  
          JXPathContext getParentContext() {
              if (this.parent instanceof NodeAdapter) {
                  NodeAdapter par = (NodeAdapter)parent;
                  return par.getContext();
              }
              return null;
          }
  
          Pointer getPointer(CompiledExpression expr) {
              return expr.getPointer(getParentContext(), "???");
          }
  
  	Object getValue(CompiledExpression expr) {
              return expr.getValue(getContext());
          }
  
          abstract public String getNodeName();
  
          public String getNodeValue() {
  	    return "";
          }
  
          public void setNodeValue(String nodeValue)
              throws DOMException {
              notSupported();
          }
  
          abstract public short getNodeType();
  
          public Node getParentNode() {
              return null;
          }
  
          public NodeList getChildNodes() {
              return EMPTY_NODE_LIST;
          }
  
          public Node getFirstChild() {
              return null;
          }
  
          public Node getLastChild() {
              return null;
          }
  
          public Node getPreviousSibling() {
              return null;
          }
  
          public Node getNextSibling() {
              return null;
          }
  
          public NamedNodeMap getAttributes() {
              return EMPTY_NODE_MAP;
          }
  
          public Document getOwnerDocument() {
              return DocumentAdapter.this;
          }
  
          public Node insertBefore(Node newChild, 
                                   Node refChild)
              throws DOMException {
              notSupported();
  	    return null;
          }
  
          public Node replaceChild(Node newChild, 
                                   Node oldChild)
              throws DOMException {
              notSupported();
  	    return null;
          }
  
          public Node removeChild(Node oldChild)
              throws DOMException {
              notSupported();
  	    return null;
          }
  
          public Node appendChild(Node newChild)
              throws DOMException {
              notSupported();
  	    return null;
          }
  
          public boolean hasChildNodes() {
              return false;
          }
  
          public Node cloneNode(boolean deep) {
              notSupported();
  	    return null;
          }        
  
          public void normalize() {
          }
  
          public boolean isSupported(String feature, 
                                     String version) {
              return false;
          }
  
          public String getNamespaceURI() {
              return null;
          }
  
          public String getPrefix() {
  	    return null;
          }
  
          public void setPrefix(String prefix)
              throws DOMException {
              notSupported();
          }
  
          public String getLocalName() {
              return getNodeName();
          }
  
          public boolean hasAttributes() {
              return false;
          }
  
      }
  
      public class TextAdapter extends NodeAdapter implements Text {
  
  	Object data;
  	String strValue;
  
  	TextAdapter(Node parent, Pointer ptr, Object data) {
  	    super(parent, ptr);
  	    this.data = data;
  	}
  
          public Object unwrap() {
              return data;
          }
  
  	public Node getParentNode() {
  	    return parent;
  	}
  
  	public short getNodeType() {
  	    return TEXT_NODE;
  	}
  
  	public String getNodeName() {
  	    return "#text";
  	}
  
  	public String getNodeValue() {
  	    if (strValue == null) {
  		if (data instanceof Boolean) {
  		    if (((Boolean)data).booleanValue()) {
  			strValue = "true";
  		    } else {
  			strValue = ""; // in XPath false is the empty string
  		    }
  		} else {
  		    strValue = String.valueOf(data);
  		}
  	    }
  	    return strValue;
  	}
  
  	public String getData()
  	    throws DOMException {
  	    return getNodeValue();
  	}
  
  	public void setData(String data)
  	    throws DOMException {
  	    notSupported();
  	}
  
  	public int getLength() {
  	    return getData().length();
  	}
  
  	public String substringData(int offset, 
  				    int count)
  	    throws DOMException {
  	    return getData().substring(0, count);
  	}
  
  	public void appendData(String arg)
  	    throws DOMException {
  	    notSupported();
  	}
  
  	public void insertData(int offset, 
  			       String arg)
  	    throws DOMException {
  	    notSupported();
  	}
  
  	public void deleteData(int offset, 
  			       int count)
  	    throws DOMException {
  	    notSupported();
  	}
  
  	public void replaceData(int offset, 
  				int count, 
  				String arg)
  	    throws DOMException {
  	    notSupported();
  	}
  
  	public Text splitText(int offset)
  	    throws DOMException {
  	    notSupported();
  	    return null;
  	}
  
      }
  
      public class ElementAdapter extends NodeAdapter implements Element {
  
          int myIndex;
          String tagName;
          Object nodeValue;
          NodeList childNodes;
  	NamedNodeMap attributes;
  	Node firstChild, lastChild, nextSibling, prevSibling;
  
          public Object unwrap() {
              return nodeValue;
          }
  
          JXPathContext getContext() {
              if (context == null) {
                  context = newContext(nodeValue);
              }
              return context;
          }
  
          ElementAdapter(Node parent, Pointer ptr, int index, String tagName,
                         Object nodeValue) {
              super(parent, ptr);
              myIndex = index;
              this.tagName = tagName;
              this.nodeValue = nodeValue;
              if (nodeValue instanceof String ||
                  nodeValue instanceof Boolean ||
                  nodeValue instanceof Number) {
                  final TextAdapter text = new TextAdapter(this, ptr,
                                                           nodeValue);
                  firstChild = lastChild = text;
                  childNodes = new NodeList() {
                          public int getLength() {
                              return 1;
                          }
                          public Node item(int i) {
                              return text;
                          }
                          
                      };
              }
          }
  
          public short getNodeType() {
              return ELEMENT_NODE;
          }
  
          public Node getParentNode() {
              return parent;
          }
  
  	public String getTagName() {
              return tagName;
  	}
  
          public String getNodeName() {
  	    return getTagName();
          }
  
          public String getLocalName() {
              return tagName;
          }
  	
  	public String getNodeValue() {
              if (ptr == null) {
                  return "";
              }
  	    return String.valueOf(nodeValue);
  	}
  
          public boolean hasChildNodes() {
              return getChildNodes().getLength() > 0;
          }
  
  
          public NodeList getChildNodes() {
              if (childNodes == null) {
  		final Pointer parentPtr = ptr;
  		final List nodeList = new ArrayList();
                  Iterator iter = GET_CHILD_NODES.iteratePointers(getContext());
                  for (int i = 0; iter.hasNext(); i++) {
  		    NodePointer p = (NodePointer)iter.next();
  		    Object nodeValue = p.getNode();
                      if (nodeValue instanceof NodeAdapter) {
                          p = (NodePointer) ((NodeAdapter)nodeValue).ptr;
                          nodeValue = p.getNode();
                      } else if (nodeValue instanceof DocumentAdapter) {
                          nodeValue = ((DocumentAdapter)nodeValue).unwrap();
                      }
  		    if (nodeValue instanceof Node) {
  			nodeList.add(nodeValue);
  		    } else {
                          QName q = p.getName();
  			nodeList.add(new ElementAdapter(this, p, i, 
                                                          q.getName(),
                                                          nodeValue));
  		    }
  		}
                  childNodes = new NodeList() {
                          public int getLength() {
                              return nodeList.size();
                          }
                          public Node item(int i) {
                              return (Node)nodeList.get(i);
                          }
                      };
              }
              return childNodes;
          }
  
          public Node getFirstChild() {
  	    getChildNodes();
  	    if (childNodes.getLength() > 0) {
  		return (Node)childNodes.item(0);
  	    }
  	    return null;
          }
          
          public Node getLastChild() {
  	    getChildNodes();
  	    if (childNodes.getLength() > 0) {
  		return (Node)childNodes.item(childNodes.getLength()-1);
  	    }
  	    return null;
          }
          
          public Node getPreviousSibling() {
  	    if (prevSibling == null) {
                  if (parent instanceof ElementAdapter) {
                      prevSibling = ((ElementAdapter)parent).getPreviousSibling(myIndex);
                  }
  	    }
  	    return prevSibling;
          }
  
          Node getPreviousSibling(int index) {
              int siblingIndex = index -1;
              getChildNodes();
              if (siblingIndex < 0 || 
                  siblingIndex >= childNodes.getLength()) return null;
              return childNodes.item(siblingIndex);
          }
  
          public Node getNextSibling() {
  	    if (nextSibling == null) {
                  if (parent instanceof ElementAdapter) {
                      nextSibling = ((ElementAdapter)parent).getNextSibling(myIndex);
                  }
  	    }
  	    return nextSibling;
          }
  
          Node getNextSibling(int index) {
              int siblingIndex = index +1;
              getChildNodes();
              if (siblingIndex < 0 || 
                  siblingIndex >= childNodes.getLength()) return null;
              return childNodes.item(siblingIndex);
          }
          
          public class AttrAdapter extends NodeAdapter implements Attr {
  
              final NodePointer np;
  
              AttrAdapter(Node par, NodePointer np) {
                  super(par, np);
                  this.np = np;
              }
              public short getNodeType() {
                  return ATTRIBUTE_NODE;
              }
              public String getNodeName() {
                  return getName();
              }
              public String getNodeValue() {
                  return getValue();
              }
              public String getName() {
                  return np.getName().getName();
              }
              public boolean getSpecified() {
                  return true;
              }
              public String getValue() {
                  Object val = np.getValue();
                  if (val == null) val = "";
                  return String.valueOf(val);
              }
              public void setValue(String value)
                  throws DOMException {
                  notSupported();
              }
              public Element getOwnerElement() {
                  return ElementAdapter.this;
              }
          };
  
          
          public NamedNodeMap getAttributes() {
              if (attributes == null) {
                  Iterator iter = GET_ATTRS.iteratePointers(getContext());
                  final List attrList = new ArrayList();
                  final Map nameMap = new HashMap();
                  final Map qnameMap = new HashMap();
                  while (iter.hasNext()) {
                      final NodePointer np = (NodePointer)iter.next();
                      Attr attr = new AttrAdapter(this, np);
                      attrList.add(attr);
                      String localName = np.getName().getName();
                      nameMap.put(localName, attr);
                      qnameMap.put("{"+np.getNamespaceURI() + "}" +
                                   localName, attr);
                  }
                  attributes = new NamedNodeMap() {
                          public Node getNamedItem(String name) {
                              return (Node)nameMap.get(name);
                          }
                          public Node setNamedItem(Node arg) 
                              throws DOMException {
                              notSupported();
  			    return null;
                          }
                          public Node removeNamedItem(String name) 
                              throws DOMException {
                              notSupported();
  			    return null;
                          }
                          public Node item(int index) {
                                  return (Node)attrList.get(index);
                          }
                          public int getLength() {
                              return attrList.size();
                          }
                          public Node getNamedItemNS(String namespaceURI,
                                                     String localName) {
                              return (Node)
                                  qnameMap.get("{"+ namespaceURI + "}"+
                                               localName);
                              
                          }
                          public Node setNamedItemNS(Node arg) 
                              throws DOMException {
                              notSupported();
  			    return null;
                          }
                          public Node removeNamedItemNS(String namespaceURI,
                                                        String localName)
                              throws DOMException {
                              notSupported();
  			    return null;
                          }
                      };
              }
  	    return attributes;
  	}
  
  	public String getAttribute(String name) {
  	    Attr a = getAttributeNode(name);
  	    if (a == null) return null;
  	    return a.getValue();
  	}
  
  	public void setAttribute(String name, 
  				 String value)
  	    throws DOMException {
  	    notSupported();
  	}
  
  	public void removeAttribute(String name)
  	    throws DOMException {
  	    notSupported();
  	}
  
  	public Attr getAttributeNode(String name) {
  	    NamedNodeMap map = getAttributes();
  	    if (map == null) return null;
  	    return (Attr)map.getNamedItem(name);
  	}
  
  	public Attr setAttributeNode(Attr newAttr)
  	    throws DOMException {
  	    notSupported();
  	    return null;
  	}
  
  	public Attr removeAttributeNode(Attr oldAttr)
  	    throws DOMException {
  	    notSupported();
  	    return null;
  	}
  
  	public NodeList getElementsByTagName(String name) {
  	    return EMPTY_NODE_LIST;
  	}
  
  	public String getAttributeNS(String namespaceURI, 
  				     String localName) {
  	    Attr a = getAttributeNodeNS(namespaceURI, localName);
  	    if (a == null) return null;
  	    return a.getValue();
  	}
  
  	public void setAttributeNS(String namespaceURI, 
  				   String qualifiedName, 
  				   String value)
  	    throws DOMException {
  	    notSupported();
  	}
  
  	public void removeAttributeNS(String namespaceURI, 
  				      String localName)
  	    throws DOMException {
  	    notSupported();
  	}
  
  	public Attr getAttributeNodeNS(String namespaceURI, 
  				       String localName) {
  	    NamedNodeMap map = getAttributes();
  	    if (map == null) return null;
  	    return (Attr)map.getNamedItemNS(namespaceURI, localName);
  	}
  
  	public Attr setAttributeNodeNS(Attr newAttr)
  	    throws DOMException {
  	    notSupported();
  	    return null;
  	}
  
  	public NodeList getElementsByTagNameNS(String namespaceURI, 
  					       String localName) {
  	    return EMPTY_NODE_LIST;
  	}
  
  	public boolean hasAttribute(String name) {
  	    return getAttributeNode(name) != null;
  	}
  
  	public boolean hasAttributeNS(String namespaceURI, 
  				      String localName) {
  	    return getAttributeNodeNS(namespaceURI, localName) != null;
  	}
  
          public boolean hasAttributes() {
              return getAttributes().getLength() > 0;
          }
  	
      }
  
      public DocumentType getDoctype() {
  	return null;
      }
  
      public DOMImplementation getImplementation() {
          return null;
      }
  
      public Element getDocumentElement() {
          return root;
      }
  
      public Element createElement(String tagName)
          throws DOMException {
          notSupported();
  	return null;
      }
  
      public DocumentFragment createDocumentFragment() {
          return null;
      }
  
      public Text createTextNode(String data) {
          return null;
      }
  
      public Comment createComment(String data) {
          return null;
      }
  
      public CDATASection createCDATASection(String data)
          throws DOMException {
          return null;
      }
  
      public ProcessingInstruction 
          createProcessingInstruction(String target, 
                                      String data)
          throws DOMException {
          return null;
      }
  
      public Attr createAttribute(String name)
          throws DOMException {
          return null;
      }
  
      public EntityReference createEntityReference(String name)
          throws DOMException {
          return null;
      }
  
      public NodeList getElementsByTagName(String tagname) {
          return null;
      }
  
      public Node importNode(Node importedNode, 
                             boolean deep)
          throws DOMException {
          return null;
      }
  
      public Element createElementNS(String namespaceURI, 
                                     String qualifiedName)
          throws DOMException {
          return null;
      }
  
      public Attr createAttributeNS(String namespaceURI, 
                                    String qualifiedName)
          throws DOMException {
          return null;
      }
  
      public NodeList getElementsByTagNameNS(String namespaceURI, 
                                             String localName) {
          return null;
      }
  
      public Element getElementById(String elementId) {
          return null;
      }
  
      public String getNodeName() {
          return root.getNodeName();
      }
  
      public String getNodeValue()
          throws DOMException {
          return root.getNodeValue();
      }
  
      public void setNodeValue(String nodeValue)
          throws DOMException {
          notSupported();
      }
  
      public short getNodeType() {
          return DOCUMENT_NODE;
      }
  
      public Node getParentNode() {
          return null;
      }
  
      public NodeList getChildNodes() {
          return root.getChildNodes();
      }
  
      public Node getFirstChild() {
          return root.getFirstChild();
      }
  
      public Node getLastChild() {
          return root.getLastChild();
      }
  
      public Node getPreviousSibling() {
          return null;
      }
  
      public Node getNextSibling() {
          return null;
      }
  
      public NamedNodeMap getAttributes() {
          return root.getAttributes();
      }
  
      public Document getOwnerDocument() {
          return this;
      }
  
      public Node insertBefore(Node newChild, 
                               Node refChild)
          throws DOMException {
          notSupported();
  	return null;
      }
  
      public Node replaceChild(Node newChild, 
                               Node oldChild)
          throws DOMException {
          notSupported();
  	return null;
      }
  
      public Node removeChild(Node oldChild)
          throws DOMException {
          notSupported();
  	return null;
      }
  
      public Node appendChild(Node newChild)
          throws DOMException {
          notSupported();
  	return null;
      }
  
      public boolean hasChildNodes() {
          return false;
      }
  
      public Node cloneNode(boolean deep) {
          notSupported();
  	return null;
      }        
  
      public void normalize() {
          root.normalize();
      }
  
      public boolean isSupported(String feature, 
                                 String version) {
          return false;
      }
  
      public String getNamespaceURI() {
          return root.getNamespaceURI();
      }
  
      public String getPrefix() {
  	return root.getPrefix();
      }
  
      public void setPrefix(String prefix)
          throws DOMException {
          notSupported();
      }
  
      public String getLocalName() {
          return root.getLocalName();
      }
  
      public boolean hasAttributes() {
          return root.hasAttributes();
      }
  
  
      public Object unwrap() {
          return root.unwrap();
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/scratchpad/src/org/apache/cocoon/generation/TraxGenerator.java
  
  Index: TraxGenerator.java
  ===================================================================
  /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  
   ============================================================================
                     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 modifica-
   tion, 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 "Apache Cocoon" 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 (INCLU-
   DING, 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 created by
   Stefano Mazzocchi  <st...@apache.org>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.generation;
  
  import org.apache.cocoon.components.flow.WebContinuation;
  import org.apache.cocoon.environment.ObjectModelHelper;
  import org.apache.cocoon.environment.Request;
  import org.apache.cocoon.environment.Response;
  import org.apache.cocoon.environment.Session;
  import org.apache.cocoon.environment.Context;
  import org.apache.cocoon.transformation.TraxTransformer;
  import org.apache.cocoon.ProcessingException;
  import java.io.IOException;
  import org.xml.sax.SAXException;
  import javax.xml.transform.dom.DOMSource;
  import javax.xml.transform.sax.SAXResult;
  import javax.xml.transform.Transformer;
  import javax.xml.transform.TransformerException;
  import org.w3c.dom.Node;
  import org.apache.cocoon.components.jxdom.DocumentAdapter;
  import org.apache.cocoon.xml.XMLConsumer;
  import org.apache.commons.jxpath.JXPathContext;
  import org.apache.commons.jxpath.JXPathIntrospector;
  import org.apache.commons.jxpath.JXPathBeanInfo;
  import org.apache.commons.jxpath.DynamicPropertyHandler;
  import org.apache.cocoon.environment.SourceResolver;
  import org.apache.cocoon.environment.Environment;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.cocoon.ProcessingException;
  import org.xml.sax.SAXException;
  import java.io.IOException;
  import java.util.Map;
  import java.util.HashMap;
  import java.beans.PropertyDescriptor;
  import java.lang.reflect.Method;
  
  /**
   * <p>XSLT Generator: works by taking java bean as an input "document"</p>
   */
  
  public class TraxGenerator extends TraxTransformer implements Generator {
      
      DocumentAdapter doc;
  
      public void setup(SourceResolver resolver, Map objectModel,
                        String src, Parameters parameters)
          throws ProcessingException, SAXException, IOException {
  	super.setup(resolver, objectModel, src, parameters);
          // FIX ME: When we decide proper way to pass "bean" and "kont"
          Object bean = ((Environment)resolver).getAttribute("bean-dict");
          WebContinuation kont = 
  	    (WebContinuation)((Environment)resolver).getAttribute("kont");
  	Map map = new HashMap();
  	Request request = ObjectModelHelper.getRequest(objectModel);
  	Response response = ObjectModelHelper.getResponse(objectModel);
  	Context context = ObjectModelHelper.getContext(objectModel);
          if (bean != null) {
  	    fillContext(bean, map);
              map.put("flowContext", bean);
              map.put("continuation", kont);
          }
          map.put("request", request);
          map.put("response", response);
          map.put("context", context);
          Object session = request.getSession(false);
          if (session != null) {
              map.put("session", session);
          }
  	doc = new DocumentAdapter(map, "document");
          super.setup(resolver, objectModel, src, parameters);
      }
  
      private void fillContext(Object contextObject, Map map) {
          if (contextObject == null) return;
          // Hack: I use jxpath to populate the context object's properties
          // in the jexl context
          final JXPathBeanInfo bi = 
              JXPathIntrospector.getBeanInfo(contextObject.getClass());
          if (bi.isDynamic()) {
              Class cl = bi.getDynamicPropertyHandlerClass();
              try {
                  DynamicPropertyHandler h = (DynamicPropertyHandler) cl.newInstance();
                  String[] result = h.getPropertyNames(contextObject);
                  for (int i = 0; i < result.length; i++) {
                      try {
                          map.put(result[i], 
  				(h.getProperty(contextObject, result[i])));
                      } catch (Exception exc) {
                          exc.printStackTrace();
                      }
                  }
              } catch (Exception ignored) {
                  ignored.printStackTrace();
              }
          } else {
              PropertyDescriptor[] props = bi.getPropertyDescriptors();
              for (int i = 0; i < props.length; i++) {
                  try {
                      Method read = props[i].getReadMethod();
                      if (read != null) {
                          map.put(props[i].getName(), 
                                  (read.invoke(contextObject, null)));
                      }
                  } catch (Exception ignored) {
                      ignored.printStackTrace();
                  }
              }
          }
      }
  
      public void generate()
          throws IOException, SAXException, ProcessingException {
  	DOMSource src = new DOMSource(doc);
  	javax.xml.transform.Transformer transformer = 
  	    transformerHandler.getTransformer();
  	SAXResult result = new SAXResult(xmlConsumer);
  	try {
  	    transformer.transform(src, result);
  	} catch (TransformerException exc) {
  	    throw new SAXException(exc.getMessage(), exc);
  	}
      }
  
      public void setConsumer(XMLConsumer consumer) {
  	xmlConsumer = consumer;
      }
  
      public void recycle() {
  	super.recycle();
  	doc = null;
      }
  
  }