You are viewing a plain text version of this content. The canonical link for it is here.
Posted to svn@forrest.apache.org by th...@apache.org on 2005/11/30 12:15:16 UTC
svn commit: r349923 [1/2] - in /forrest/trunk:
main/template-sites/v2/src/documentation/content/xdocs/
main/template-sites/v2/src/documentation/resources/themes/common/html/
whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/...
Author: thorsten
Date: Wed Nov 30 03:14:46 2005
New Revision: 349923
URL: http://svn.apache.org/viewcvs?rev=349923&view=rev
Log:
First preview of the dispatcher transformer. The transformer is not yet finished, this commit is more a basis for discussion and a personal online
backup then a finished first implementation!!!
See changes in the output.xmap to see how to define the transformer. If you test in v2 then request http://localhost:8888/test.dispatcher to see code
in action.
I added my testing code as well to better test the transformer, consider this code as foo-code-> no functionality just testing.
Added:
forrest/trunk/main/template-sites/v2/src/documentation/content/xdocs/index-foo.fv
forrest/trunk/main/template-sites/v2/src/documentation/resources/themes/common/html/nav-main-testing-foo.ft
forrest/trunk/main/template-sites/v2/src/documentation/resources/themes/common/html/nav-main-testing.ft
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/ContractBean.java (with props)
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/DispatcherException.java (with props)
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/DispatcherHelper.java (with props)
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/transformation/
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/transformation/DispatcherTransformer.java (with props)
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/util/
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/util/SourceUtil.java (with props)
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/lenya/
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/lenya/xml/
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/lenya/xml/DocumentHelper.java (with props)
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/lenya/xml/NamespaceHelper.java (with props)
Modified:
forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.output.themer/output.xmap
Added: forrest/trunk/main/template-sites/v2/src/documentation/content/xdocs/index-foo.fv
URL: http://svn.apache.org/viewcvs/forrest/trunk/main/template-sites/v2/src/documentation/content/xdocs/index-foo.fv?rev=349923&view=auto
==============================================================================
--- forrest/trunk/main/template-sites/v2/src/documentation/content/xdocs/index-foo.fv (added)
+++ forrest/trunk/main/template-sites/v2/src/documentation/content/xdocs/index-foo.fv Wed Nov 30 03:14:46 2005
@@ -0,0 +1,32 @@
+<forrest:views xmlns:forrest="http://apache.org/forrest/templates/1.0"
+ xmlns:jx="http://apache.org/cocoon/templates/jx/1.0">
+ <forrest:view type="xml">
+ <forrest:hook name="test">
+ <forrest:contract name="nav-main-testing"
+ dataURI="cocoon://index.navigation.xml">
+ <forrest:property name="nav-main-testing-test1" >x</forrest:property>
+ <forrest:property name="nav-main-testing-test2" >
+ <foo/>
+ </forrest:property>
+ <forrest:property name="nav-main-testing-test3" >xxx</forrest:property>
+ </forrest:contract>
+ </forrest:hook>
+ </forrest:view>
+ <forrest:view type="html" hooksXpath="/html/body">
+ <forrest:hook name="test">
+ <forrest:hook name="anotherXz">
+ <forrest:contract name="nav-main-testing-foo" />
+ </forrest:hook>
+ <forrest:hook name="test2">
+ <forrest:contract name="nav-main-testing"
+ dataURI="cocoon://index.navigation.xml">
+ <forrest:property name="nav-main-testing-test1" >x</forrest:property>
+ <forrest:property name="nav-main-testing-test2" >
+ <foo/>
+ </forrest:property>
+ </forrest:contract>
+ </forrest:hook>
+ </forrest:hook>
+ <forrest:hook name="anotherX"/>
+ </forrest:view>
+</forrest:views>
\ No newline at end of file
Added: forrest/trunk/main/template-sites/v2/src/documentation/resources/themes/common/html/nav-main-testing-foo.ft
URL: http://svn.apache.org/viewcvs/forrest/trunk/main/template-sites/v2/src/documentation/resources/themes/common/html/nav-main-testing-foo.ft?rev=349923&view=auto
==============================================================================
--- forrest/trunk/main/template-sites/v2/src/documentation/resources/themes/common/html/nav-main-testing-foo.ft (added)
+++ forrest/trunk/main/template-sites/v2/src/documentation/resources/themes/common/html/nav-main-testing-foo.ft Wed Nov 30 03:14:46 2005
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2002-2005 The Apache Software Foundation or its licensors,
+ as applicable.
+
+ Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<forrest:contract name="nav-main-testing-foo" type="nugget"
+ xmlns:forrest="http://apache.org/forrest/templates/1.0">
+ <description>
+ nav-main will output the main or primary navigation AKA tabs.
+ </description>
+ <usage><![CDATA[<forrest:contract name="nav-main-testing-foo" nugget="cocoon://#{$cocoon/parameters/getRequest}.navigation.xml"/>]]>
+ </usage>
+ <forrest:template
+ xmlns:forrest="http://apache.org/forrest/templates/1.0"
+ format="html" name="nav-main-testing-foo" inputFormat="xsl" >
+ <xsl:stylesheet version="1.1"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:template match="/" >
+ <forrest:content>
+ <forrest:part> nav-main-testing-foo testing - no @xpath</forrest:part>
+ </forrest:content>
+ </xsl:template>
+ </xsl:stylesheet>
+ </forrest:template>
+</forrest:contract>
\ No newline at end of file
Added: forrest/trunk/main/template-sites/v2/src/documentation/resources/themes/common/html/nav-main-testing.ft
URL: http://svn.apache.org/viewcvs/forrest/trunk/main/template-sites/v2/src/documentation/resources/themes/common/html/nav-main-testing.ft?rev=349923&view=auto
==============================================================================
--- forrest/trunk/main/template-sites/v2/src/documentation/resources/themes/common/html/nav-main-testing.ft (added)
+++ forrest/trunk/main/template-sites/v2/src/documentation/resources/themes/common/html/nav-main-testing.ft Wed Nov 30 03:14:46 2005
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2002-2005 The Apache Software Foundation or its licensors,
+ as applicable.
+
+ Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<forrest:contract name="nav-main-testing" type="nugget"
+ xmlns:forrest="http://apache.org/forrest/templates/1.0">
+ <description>
+ nav-main will output the main or primary navigation AKA tabs.
+ </description>
+ <usage><![CDATA[<forrest:contract name="nav-main-testing" nugget="cocoon://#{$cocoon/parameters/getRequest}.navigation.xml"/>]]>
+ </usage>
+ <forrest:template
+ xmlns:forrest="http://apache.org/forrest/templates/1.0"
+ format="html" name="nav-main-testing" inputFormat="xsl" >
+
+ <xsl:stylesheet version="1.1"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:param name="nav-main-testing" select="/"/>
+ <xsl:param name="nav-main-testing-test1" select="'test'"/>
+ <xsl:template match="/" >
+ <forrest:content>
+ <forrest:part>
+ value-of select="$nav-main-testing-test1": <xsl:value-of select="$nav-main-testing-test1"/>
+ <div id="tabs"> <xsl:comment>+ |start Tabs new +</xsl:comment>
+ <xsl:copy-of
+ select="$nav-main-testing/navigation/tab/ul[@id='nav-main']"/>
+ <xsl:comment>+ |end Tabs +</xsl:comment> </div>
+ </forrest:part>
+ <forrest:part xpath="/html/head">
+ <forrest:part> nav-main-testing-foo testing - xpath="/html/head"</forrest:part>
+ </forrest:part>
+ </forrest:content>
+ </xsl:template>
+ </xsl:stylesheet>
+ </forrest:template>
+</forrest:contract>
\ No newline at end of file
Added: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/ContractBean.java
URL: http://svn.apache.org/viewcvs/forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/ContractBean.java?rev=349923&view=auto
==============================================================================
--- forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/ContractBean.java (added)
+++ forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/ContractBean.java Wed Nov 30 03:14:46 2005
@@ -0,0 +1,437 @@
+package org.apache.forrest.dispatcher;
+
+import java.beans.Beans;
+import java.util.HashMap;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.lenya.xml.NamespaceHelper;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * @author thorsten
+ *
+ */
+public class ContractBean extends Beans {
+
+ /**
+ * The resolver prefix
+ */
+ public static final String CONTRACT_RESOLVE_PREFIX = "cocoon://resolve.contract";
+
+ /**
+ * <code>forrest:contract</code> element is used to include extra content
+ * and/or functionality.
+ *
+ * <p>
+ * extra functionality requested from a uri via CONTRACT_NUGGET_ATTRIBUTE
+ * attribute - example:
+ * </p>
+ *
+ * <pre>
+ * <forrest:contract name="nav-section" dataURI="cocoon://index.navigation.xml"/>
+ * </pre>
+ */
+ public static final String CONTRACT_ELEMENT = "contract";
+
+ /**
+ * Each contract can contact business services to get the data model. The
+ * attribute "CONTRACT_NUGGET_ATTRIBUTE" contains the uri to contact for
+ * business data
+ */
+ public static final String CONTRACT_NUGGET_ATTRIBUTE = "dataURI";
+
+ /**
+ * Each contract must have an unique identifier. The attribute "CONTRACT_ID_ATTRIBUTE"
+ * contains this id
+ */
+ public static final String CONTRACT_ID_ATTRIBUTE = "name";
+
+ /**
+ * Each contract implementation needs to define the input format for the transformation.
+ * ATM we only support xsl. The attribute "CONTRACT_IMPL_INPUT_FORMAT_ATTRIBUTE"
+ * defines the input format for transformation
+ */
+ public static final String CONTRACT_IMPL_INPUT_FORMAT_ATTRIBUTE = "inputFormat";
+
+ /**
+ * Each contract implementation needs to define the input format for the transformation.
+ * ATM we only support xsl. The attribute "CONTRACT_IMPL_INPUT_FORMAT_ATTRIBUTE"
+ * defines the input format for transformation
+ */
+ public static final String CONTRACT_IMPL_ROOT_ELEMENT = "forrest:template";
+
+ private static final String PROPERTY_ID_ATTRIBUTE = "name";
+
+ private HashMap contract;
+
+ private Element structurerContract;
+
+ private Element[] propertyList;
+
+ private Document contractImpl;
+
+ private Element contractDescription;
+
+ private Element contractUsage;
+
+ private Document contractRawData;
+
+ private Transformer contractTransformer;
+
+ private DOMResult contractResultData;
+
+ private boolean isNugget = false;
+
+ private boolean hasProperties = false;
+
+ private String contractName;
+
+ private String nuggetUri;
+
+ protected NamespaceHelper namespaceHelper;
+
+ protected DispatcherHelper dispatcherHelper;
+
+ protected ServiceManager manager;
+
+ /**
+ * @param element
+ * @param namespaceHelper
+ * @deprecated
+ */
+ public ContractBean(Element element, NamespaceHelper namespaceHelper) {
+ this.contract = new HashMap();
+ this.namespaceHelper = namespaceHelper;
+ this.loadStructurer(element);
+ }
+
+ /**
+ * The ContractBean contains all fields to work with contracts. It is a
+ * helper bean.
+ *
+ * Helpers (forrest:contracts) mainly adapt and transform the presentation
+ * model (pm), but also help with any limited business processing that is
+ * initiated from the structurer by forrest:properties by passing this
+ * information to the transfomer.
+ *
+ * @param manager
+ * @throws ParserConfigurationException
+ */
+ public ContractBean(ServiceManager manager)
+ throws ParserConfigurationException {
+ this.manager = manager;
+ this.contract = new HashMap();
+ dispatcherHelper = new DispatcherHelper(manager);
+ }
+
+ /**
+ * The ContractBean contains all fields to work with contracts. It is a
+ * helper bean.
+ *
+ * Helpers (forrest:contracts) mainly adapt and transform the presentation
+ * model (pm), but also help with any limited business processing that is
+ * initiated from the structurer by forrest:properties by passing this
+ * information to the transfomer.
+ *
+ * @throws ParserConfigurationException
+ */
+ public ContractBean() {}
+
+ /**
+ * @param structurer
+ * @deprecated
+ */
+ private void loadStructurer(Element structurer) {
+ this.setStructurerContract(structurer);
+ this.setNugget(structurer.hasAttribute(CONTRACT_NUGGET_ATTRIBUTE));
+ this.setHasProperties(structurer.hasChildNodes());
+ if (hasProperties) {
+ this.propertyList = namespaceHelper.getChildren(structurer);
+ }
+ this.setContractName(structurer.getAttribute(CONTRACT_ID_ATTRIBUTE));
+ /*
+ * if (this.isNugget) { this.setNuggetUri(structurer
+ * .getAttribute(CONTRACT_NUGGET_ATTRIBUTE)); }
+ */
+ }
+
+ /**
+ * setContractImpl(String contractUri)
+ *
+ * This method set the actual contract implementation via a URI.
+ *
+ * Here we set the description and the usage instruction of the contract
+ * implementation. As well we prepare the transformer. The simplest form is
+ * a contract that does not need a pm. It can provide all data through the
+ * transformation. A more dynamic contract would provide properties to the
+ * transformation (contractImpl) to apply limited business logic.
+ *
+ * @param contractUri
+ * @throws Exception
+ */
+ public void setContractImpl(String contractUri) throws Exception {
+ Document contractImpl = dispatcherHelper.getDocument(contractUri);
+ this.contractImpl = contractImpl;
+ contractImplHelper(contractImpl);
+ }
+
+ /**
+ * setContractImpl(String contractUri)
+ *
+ * This method set the actual contract implementation via a URI.
+ *
+ * Here we set the description and the usage instruction of the contract
+ * implementation. As well we prepare the transformer. The simplest form is
+ * a contract that does not need a pm. It can provide all data through the
+ * transformation. A more dynamic contract would provide properties to the
+ * transformation (contractImpl) to apply limited business logic.
+ *
+ * @param contractUri
+ * @throws Exception
+ */
+ public void setContractImpl(Document contractImpl) throws Exception {
+ this.contractImpl = contractImpl;
+ contractImplHelper(contractImpl);
+ }
+
+ /**
+ * @param contractImpl
+ * @throws Exception
+ * @throws TransformerFactoryConfigurationError
+ * @throws TransformerConfigurationException
+ * @throws IllegalArgumentException
+ */
+ private void contractImplHelper(Document contractImpl) throws Exception,
+ TransformerFactoryConfigurationError,
+ TransformerConfigurationException, IllegalArgumentException {
+ NodeList template = contractImpl
+ .getElementsByTagName(CONTRACT_IMPL_ROOT_ELEMENT);
+ if (template.getLength() == 1) {
+ Element templateElement = (Element) template.item(0);
+ String format = templateElement.getAttribute(CONTRACT_IMPL_INPUT_FORMAT_ATTRIBUTE);
+ if ("".equals(format) | format == null) {
+ throw new DispatcherException(DispatcherException.ERROR_500 + "\n"
+ + "component: ContractBean" + "\n"
+ + "message: inputFormat cannot be null");
+ } else if ("xsl".equals(format)) {
+ NodeList list_transformer = contractImpl
+ .getElementsByTagName("xsl:stylesheet");
+ if (list_transformer.getLength() == 1) {
+ Element node = (Element) list_transformer.item(0);
+ TransformerFactory tFactory = TransformerFactory
+ .newInstance();
+ DOMSource stylesource = new DOMSource(node);
+ Transformer transformer = tFactory
+ .newTransformer(stylesource);
+ if (transformer == null)
+ throw new DispatcherException(
+ DispatcherException.ERROR_500
+ + "\n"
+ + "component: ContractBean"
+ + "\n"
+ + "message: Could not setup transformer in the contractBean."
+ + "\n"
+ + "Please check that the contract implementation is wellformed and valid");
+ /*
+ * FIXME: Set default properties
+ */
+ // transformer.setParameter()
+ transformer.setOutputProperty(
+ OutputKeys.OMIT_XML_DECLARATION, "yes");
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+ this.contractTransformer = transformer;
+ }
+ } else {
+ throw new DispatcherException( DispatcherException.ERROR_404+ "\n"
+ + "component: ContractBean" + "\n"
+ + "message: inputFormat=\""+format+"\" not implemented");
+ }
+ }
+ NodeList description = contractImpl.getElementsByTagName("description");
+ if (description.getLength() == 1) {
+ Element node = (Element) description.item(0);
+ this.contractDescription = node;
+ }
+ NodeList usage = contractImpl.getElementsByTagName("usage");
+ if (usage.getLength() == 1) {
+ Element node = (Element) usage.item(0);
+ this.contractUsage = node;
+ }
+ }
+
+ public HashMap getContract() {
+ return contract;
+ }
+
+ public void put(Object key, Object element) {
+ this.contract.put(key, element);
+ }
+
+ public String getContractName() {
+ return contractName;
+ }
+
+ public void setContractName(String contractName) {
+ this.contractName = contractName;
+ }
+
+ public boolean isHasProperties() {
+ return hasProperties;
+ }
+
+ public void setHasProperties(boolean hasProperties) {
+ this.hasProperties = hasProperties;
+ }
+
+ public boolean isNugget() {
+ return isNugget;
+ }
+
+ public void setNugget(boolean isNugget) {
+ this.isNugget = isNugget;
+ }
+
+ public String getNuggetUri() {
+ return nuggetUri;
+ }
+
+ /**
+ * The presentation model (contractRawData) has to be requested by the
+ * contract if it needs it. This is be done by setting the
+ * CONTRACT_NUGGET_ATTRIBUTE attribute in the structurer which then use this
+ * method to set the contractRawData.
+ * <p>
+ * Extra functionality requested from a uri via CONTRACT_NUGGET_ATTRIBUTE
+ * attribute - example:
+ * </p>
+ *
+ * <pre>
+ * <forrest:contract name="nav-section" dataURI="cocoon://index.navigation.xml"/>
+ * </pre>
+ *
+ * @param nuggetUri
+ * @throws Exception
+ */
+ public void setNuggetUri(String nuggetUri) throws Exception {
+ this.nuggetUri = nuggetUri;
+ Document rawData = dispatcherHelper.getDocument(nuggetUri);
+ this.contractRawData = rawData;
+ }
+
+ public Node getContractRawData() {
+ return contractRawData;
+ }
+
+ /**
+ * This method invokes the transformation of the this.contractRawData with
+ * the this.contractTransformer (make sure you set them before). The result
+ * is set to this.contractResultData.
+ *
+ * @throws TransformerException
+ */
+ public void setContractResultData() throws TransformerException {
+ if (this.getContractRawData() == null
+ || this.contractTransformer == null) {
+ throw new TransformerException(
+ "You need to invoke first the transfomer and the rawData.");
+ } else {
+ DOMSource source = new DOMSource(contractRawData);
+ DOMResult result = new DOMResult();
+ this.contractTransformer.transform(source, result);
+ this.setContractResultData(result);
+ }
+ }
+
+ public void setContractRawData(Document contractRawData) {
+ this.contractRawData = contractRawData;
+ }
+
+ public Transformer getContractTransformer() {
+ return contractTransformer;
+ }
+
+ public void setContractTransformer(Transformer contractTransformer) {
+ this.contractTransformer = contractTransformer;
+ }
+
+ public Element getStructurerContract() {
+ return structurerContract;
+ }
+
+ public void setStructurerContract(Element structurerContract) {
+ this.structurerContract = structurerContract;
+ }
+
+ public Document getContractImpl() {
+ return contractImpl;
+ }
+
+ public Element getContractDescription() {
+ return contractDescription;
+ }
+
+ public void setContractDescription(Element contractDescription) {
+ this.contractDescription = contractDescription;
+ }
+
+ public Element getContractUsage() {
+ return contractUsage;
+ }
+
+ public void setContractUsage(Element contractUsage) {
+ this.contractUsage = contractUsage;
+ }
+
+ public Element[] getPropertyList() {
+ return propertyList;
+ }
+
+ public void setPropertyList(Element[] propertyList) {
+ this.propertyList = propertyList;
+ }
+
+ public DOMResult getContractResultData() {
+ return contractResultData;
+ }
+
+ public void setContractResultData(DOMResult contractResultData) {
+ this.contractResultData = contractResultData;
+ }
+
+ public void recycle() {
+ this.contract = null;
+ this.contractDescription = null;
+ this.contractImpl = null;
+ this.contractName = null;
+ this.contractRawData = null;
+ this.contractResultData = null;
+ this.contractTransformer = null;
+ this.contractUsage = null;
+ this.dispatcherHelper = null;
+ this.hasProperties = false;
+ this.isNugget = false;
+ this.namespaceHelper = null;
+ this.nuggetUri = null;
+ this.propertyList = null;
+ this.structurerContract = null;
+ }
+
+ public void initialize() throws ParserConfigurationException {
+ this.contract = new HashMap();
+ dispatcherHelper = new DispatcherHelper(this.manager);
+ }
+}
Propchange: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/ContractBean.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/DispatcherException.java
URL: http://svn.apache.org/viewcvs/forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/DispatcherException.java?rev=349923&view=auto
==============================================================================
--- forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/DispatcherException.java (added)
+++ forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/DispatcherException.java Wed Nov 30 03:14:46 2005
@@ -0,0 +1,46 @@
+package org.apache.forrest.dispatcher;
+
+/**
+ * Dispatcher Exception
+ */
+public class DispatcherException extends Exception {
+ public static final String ERROR_404 = "code: 404 - Source not found";
+ public static final String ERROR_500 = "code: 500 - Internal server error";
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates a new DispatcherException.
+ */
+ public DispatcherException() {
+ super();
+ }
+
+ /**
+ * Creates a new DispatcherException.
+ * @param message the exception message
+ */
+ public DispatcherException(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new DispatcherException.
+ * @param message the exception message
+ * @param cause the cause of the exception
+ */
+ public DispatcherException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a new DispatcherException.
+ * @param cause the cause of the exception
+ */
+ public DispatcherException(Throwable cause) {
+ super(cause);
+ }
+
+}
Propchange: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/DispatcherException.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/DispatcherHelper.java
URL: http://svn.apache.org/viewcvs/forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/DispatcherHelper.java?rev=349923&view=auto
==============================================================================
--- forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/DispatcherHelper.java (added)
+++ forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/DispatcherHelper.java Wed Nov 30 03:14:46 2005
@@ -0,0 +1,96 @@
+package org.apache.forrest.dispatcher;
+
+import java.beans.Beans;
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.xml.IncludeXMLConsumer;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.cocoon.xml.dom.DOMBuilder;
+import org.apache.excalibur.source.SourceNotFoundException;
+import org.apache.lenya.xml.NamespaceHelper;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+public class DispatcherHelper extends Beans {
+ /**
+ * The namespace for the dispatcher configuration is
+ * http://apache.org/forrest/templates/1.0
+ */
+ static public final String DISPATCHER_NAMESPACE_URI = "http://apache.org/forrest/templates/1.0";
+
+ /**
+ * The namespace prefix for this namespace.
+ */
+ static public final String DISPATCHER_PREFIX = "forrest";
+
+ private NamespaceHelper namespaceHelper;
+
+ private ServiceManager manager;
+
+ /**
+ * Create a DOM representation of this dispatcher.
+ *
+ * @return A DOM document.
+ * @throws ServiceException
+ * if a general error occurs.
+ * @throws SourceNotFoundException
+ * if the dispatcher's source can not be found
+ * @throws ParserConfigurationException
+ * if an error occurs during XML parsing.
+ * @throws SAXException
+ * if an error occurs during XML parsing.
+ * @throws IOException
+ * if an error occurs during source access..
+ */
+ protected Document getDocument(String uri) throws Exception {
+ Document doc = org.apache.forrest.dispatcher.util.SourceUtil.readDOM(uri,
+ this.manager);
+ if (doc != null) {
+ this.namespaceHelper = new NamespaceHelper(
+ DISPATCHER_NAMESPACE_URI, DISPATCHER_PREFIX, doc);
+ }
+ return namespaceHelper.getDocument();
+ }
+
+ /**
+ * Creates a new document with the param rootName
+ *
+ * @param rootName
+ * @return
+ * @throws SAXException
+ */
+ public Document createDocument(String rootName) throws SAXException {
+ DOMBuilder builder = new DOMBuilder();
+ builder.startDocument();
+ builder.startElement("", rootName, rootName, XMLUtils.EMPTY_ATTRIBUTES);
+ builder.endElement("", rootName, rootName);
+ builder.endDocument();
+ return builder.getDocument();
+
+ }
+
+ public DispatcherHelper(ServiceManager manager)
+ throws ParserConfigurationException {
+ this.manager = manager;
+ this.namespaceHelper = new NamespaceHelper(DISPATCHER_NAMESPACE_URI,
+ DISPATCHER_PREFIX, "foo");
+ }
+
+ public NamespaceHelper getNamespaceHelper() {
+ return namespaceHelper;
+ }
+
+ public void setNamespaceHelper(NamespaceHelper namespaceHelper) {
+ this.namespaceHelper = namespaceHelper;
+ }
+
+ public void setNamespaceHelper(String uri, String prefix, String localName)
+ throws ParserConfigurationException {
+ this.namespaceHelper = new NamespaceHelper(uri, prefix, localName);
+ }
+
+}
Propchange: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/DispatcherHelper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/transformation/DispatcherTransformer.java
URL: http://svn.apache.org/viewcvs/forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/transformation/DispatcherTransformer.java?rev=349923&view=auto
==============================================================================
--- forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/transformation/DispatcherTransformer.java (added)
+++ forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/transformation/DispatcherTransformer.java Wed Nov 30 03:14:46 2005
@@ -0,0 +1,838 @@
+package org.apache.forrest.dispatcher.transformation;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.caching.CacheableProcessingComponent;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.transformation.AbstractSAXTransformer;
+import org.apache.cocoon.xml.IncludeXMLConsumer;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.cocoon.xml.dom.DOMBuilder;
+import org.apache.cocoon.xml.dom.DOMUtil;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.xml.xpath.XPathProcessor;
+import org.apache.forrest.dispatcher.ContractBean;
+import org.apache.forrest.dispatcher.DispatcherHelper;
+import org.apache.lenya.xml.NamespaceHelper;
+import org.apache.xpath.CachedXPathAPI;
+import org.apache.xpath.XPathAPI;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import org.w3c.dom.DOMImplementation;
+
+public class DispatcherTransformer extends AbstractSAXTransformer implements
+ Disposable, CacheableProcessingComponent {
+
+ /* Node and attribute names */
+ /**
+ * <code>forrest:view</code> element is used to structure contracts and
+ * hooks into format specific container. It allows to configure x different
+ * format for the request.
+ *
+ * <pre>
+ * <<strong>forrest:view</strong> format="html"/>
+ * </pre>
+ */
+ public static final String STRUCTURER_ELEMENT = "view";
+
+ /**
+ * <code>forrest:view</code> element is used to structure contracts and
+ * hooks into format specific container. It allows to configure x different
+ * format for the request. The attribute which identify a view format is
+ * <strong>format</strong>.
+ *
+ * <pre>
+ * <forrest:view <strong>format</strong>="html"/>
+ * </pre>
+ */
+ public static final String STRUCTURER_FORMAT_ATTRIBUTE = "type";
+
+ public static final String STRUCTURER_HOOK_XPATH_ATTRIBUTE = "hooksXpath";
+
+ protected String requestedFormat;
+
+ private boolean includeNodes = true;
+
+ /**
+ * <code>forrest:hook</code> element is used to structure the elements. It
+ * allows to create skeletons that a designer needs to apply a specific
+ * layout via e.g. css. In html for example
+ *
+ * <pre>
+ * <forrest:hook name="test"/>
+ * </pre>
+ *
+ * <p>
+ * will be transformed to
+ * </p>
+ *
+ * <pre>
+ * <div id="test"/>
+ * </pre>
+ */
+ public static final String DISPATCHER_HOOK_ELEMENT = "hook";
+
+ /**
+ * <code>forrest:css</code> element is used to apply a specific layout via
+ * css. In html for example
+ *
+ * <pre>
+ * <forrest:css url="pelt.basic.css" media="screen" theme="Pelt"/>
+ * </pre>
+ *
+ * <p>
+ * will be transformed to
+ * </p>
+ *
+ * <pre>
+ * <link media="screen" href="../themes/pelt.basic.css" title="Pelt" rel="stylesheet" type="text/css" />
+ * </pre>
+ */
+ public static final String DISPATCHER_CSS_ELEMENT = "css";
+
+ /**
+ * Each contract can have properties, which are definite e.g. in the
+ * structurer index.fv and used in the contract.
+ *
+ * <pre>
+ * <forrest:contract name="nav-main-testing" nugget="cocoon://index.navigation.xml">
+ * <forrest:property name="nav-main-testing-test1" >Just a test</forrest:property>
+ * </forrest:contract>
+ * </pre>
+ */
+ public static final String CONTRACT_PROPERTY_ELEMENT = "property";
+
+ public static final String CONTRACT_PROPERTY_ID_ATTRIBUTE = "name";
+
+ private String propertyID;
+
+ private boolean insideProperties = false;
+
+ /**
+ * Convenience object, so we don't need to create an AttributesImpl for
+ * every element.
+ */
+ protected AttributesImpl attributes;
+
+ protected String currentFormat;
+
+ private boolean insideContract = false;
+
+ protected ContractBean contract;
+
+ /**
+ * The namespace used by the transformer for the SAX events filtering. This
+ * either equals to the {@link #defaultNamespaceURI} or to the value set by
+ * the <code>namespaceURI</code> sitemap parameter for the pipeline. Must
+ * never be null.
+ */
+ protected String namespaceURI;
+
+ /**
+ * This is the default namespace used by the transformer. Implementations
+ * should set its value in the constructor. Must never be null.
+ */
+ protected String defaultNamespaceURI;
+
+ private DOMBuilder builder, dispatcherBuilder;
+
+ private DOMUtil domUtil;
+
+ private DocumentFragment frag;
+
+ private Element rootNode;
+
+ private XPathProcessor processor;
+
+ private CachedXPathAPI xpathApi;
+
+ private Document document;
+
+ private NamespaceHelper dispatcher;
+
+ private Map storedPrefixMap;
+
+ private String path = null;
+
+ private boolean recording;
+
+ private DispatcherHelper dispatcherHelper;
+
+ private HashMap domHash;
+
+ /**
+ * Constructor Set the namespace
+ */
+ public DispatcherTransformer() {
+ this.defaultNamespaceURI = DispatcherHelper.DISPATCHER_NAMESPACE_URI;
+ }
+
+ // FIXME: turn on caching!!!
+ /**
+ * Generate the unique key. This key must be unique inside the space of this
+ * component.
+ *
+ * @return The generated key hashes the src
+ */
+ public Serializable getKey() {
+ return null;
+ }
+
+ // FIXME: turn on caching!!!
+ /**
+ * Generate the validity object.
+ *
+ * @return The generated validity object or <code>null</code> if the
+ * component is currently not cacheable.
+ */
+ public SourceValidity getValidity() {
+ return null;
+ }
+
+ /**
+ * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+ */
+ public void service(ServiceManager manager) throws ServiceException {
+ super.service(manager);
+ }
+
+ /**
+ * @see org.apache.avalon.framework.activity.Disposable#dispose()
+ */
+ public void dispose() {
+ if (null != this.manager) {
+ this.manager = null;
+ }
+ insideProperties = false;
+ super.dispose();
+ }
+
+ /**
+ * Recycle the component
+ */
+ public void recycle() {
+ insideProperties = false;
+ super.recycle();
+ }
+
+ /**
+ * Setup the file generator. Try to get the last modification date of the
+ * source for caching.
+ */
+ public void setup(SourceResolver resolver, Map objectModel, String src,
+ Parameters par) throws ProcessingException, SAXException,
+ IOException {
+ super.setup(resolver, objectModel, src, par);
+ // domUtil = new DOMUtil();
+ /*
+ * DOMImplementation domImpl = new
+ * org.apache.xerces.dom.DOMImplementationImpl(); DocumentType docType =
+ * domImpl.createDocumentType("rootElementName", "public ID", "system
+ * ID"); Document doc = domImpl.createDocument("", "rootElementName",
+ * docType);
+ *
+ */
+ this.processor = null;
+ this.dispatcherHelper = null;
+ this.xpathApi = null;
+ this.contract = null;
+ try {
+ this.domHash = new HashMap();
+ this.xpathApi = new CachedXPathAPI();
+ this.dispatcherHelper = new DispatcherHelper(manager);
+ this.processor = (XPathProcessor) this.manager
+ .lookup(XPathProcessor.ROLE);
+ } catch (Exception e) {
+ String error = " dispatcherError:\n Could not set up the dispatcherHelper!\n DispatcherStack: "
+ + e;
+ getLogger().error(error);
+ throw new ProcessingException(error);
+ }
+ storedPrefixMap = new HashMap();
+ insideProperties = false;
+ this.requestedFormat = parameters.getParameter(
+ STRUCTURER_FORMAT_ATTRIBUTE, null);
+ if (requestedFormat == null) {
+ String error = " dispatcherError:\n You have to set the \"type\" parameter in the sitemap!";
+ getLogger().error(error);
+ throw new ProcessingException(error);
+ }
+ }
+
+ public void startElement(String uri, String name, String raw,
+ Attributes attr) throws SAXException {
+ // Process start element event
+ // Are we inside of properties? If so we need to record the elements.
+ if (this.insideProperties) {
+ if (this.includeNodes) {
+ try {
+ this.builder.startElement(uri, name, raw, attr);
+ } catch (SAXException e) {
+ this.insideProperties = false;
+ String error = " dispatcherError:\n The contract \""
+ + contract.getContractName()
+ + "\" has thrown in the property with ID \""
+ + this.propertyID + "\" following error: " + e;
+ getLogger().error(error);
+ throw new SAXException(error);
+ }
+ }
+ } else if (DispatcherHelper.DISPATCHER_NAMESPACE_URI.equals(uri)) {
+ /*
+ * We are in the dispatcher ns.
+ */
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Starting dispatcher element: " + raw);
+ }
+ if (STRUCTURER_ELEMENT.equals(name))
+ structurerProcessingStart(attr);
+ else if (DISPATCHER_HOOK_ELEMENT.equals(name)) {
+ if (this.includeNodes) {
+ hookProcessingStart(name, raw, attr);
+ }
+ } else if (ContractBean.CONTRACT_ELEMENT.equals(name)) {
+ if (this.includeNodes) {
+ contractProcessingStart(attr);
+ }
+ } else if (CONTRACT_PROPERTY_ELEMENT.equals(name)) {
+ this.insideProperties = true;
+ if (this.includeNodes)
+ propertyProcessingStart(uri, name, raw, attr);
+ } else {
+ if (this.includeNodes)
+ super.startElement(uri, name, raw, attr);
+ }
+ } else {
+ super.startElement(uri, name, raw, attr);
+ }
+ }
+
+ /**
+ * @param name
+ * @param raw
+ * @param attr
+ * @throws DOMException
+ * @throws SAXException
+ */
+ private void hookProcessingStart(String name, String raw, Attributes attr)
+ throws DOMException, SAXException {
+ /* create a DOM node from the current sax event */
+ Element currentElement = dispatcher.getDocument().createElement(name);
+ setAttributesDOM(attr, currentElement);
+ if (path == null || path.equals("")) {
+ path = raw;
+ this.rootNode.appendChild(currentElement);
+ } else {
+ /* calculate, prepare and add node to the dispatcher */
+ try {
+ String tempPath = path + "/" + name;
+ Node xpathNode;
+ String[] xpath = DOMUtil.buildPathArray(path);
+ xpathNode = DOMUtil
+ .getFirstNodeFromPath(rootNode, xpath, false);
+ if (xpathNode == null)
+ createXpathNode(attr, tempPath);
+ else
+ xpathNode.appendChild(currentElement);
+ } catch (Exception e) {
+ String error = " dispatcherError:\n Could not set up xpath!\n\n DispatcherStack:\n "
+ + e;
+ getLogger().error(error);
+ throw new SAXException(error);
+ }
+ path = path + "/" + name;
+ }
+ }
+
+ /**
+ * @param attr
+ * @param tempPath
+ * @throws ProcessingException
+ * @throws DOMException
+ */
+ private void createXpathNode(Attributes attr, String tempPath)
+ throws ProcessingException, DOMException {
+ Node xpathNode;
+ xpathNode = DOMUtil
+ .selectSingleNode(rootNode, tempPath, this.processor);
+ if (attr != null)
+ setAttributesDOM(attr, xpathNode);
+ }
+
+ /**
+ * @param attr
+ * @param tempPath
+ * @throws ProcessingException
+ * @throws DOMException
+ */
+ private Node createXpathNode(String tempPath) throws ProcessingException,
+ DOMException {
+ Node xpathNode;
+ xpathNode = DOMUtil
+ .selectSingleNode(rootNode, tempPath, this.processor);
+ return xpathNode;
+ }
+
+ /**
+ * @param attr
+ * @param xpathNode
+ * @throws DOMException
+ */
+ private void setAttributesDOM(Attributes attr, Node xpathNode)
+ throws DOMException {
+ for (int i = 0; i < attr.getLength(); i++) {
+ String localName = attr.getLocalName(i);
+ String value = attr.getValue(i);
+ ((Element) xpathNode).setAttribute(localName, value);
+ }
+ }
+
+ public void endElement(String uri, String name, String raw)
+ throws SAXException {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Ending element: " + raw);
+ }
+ // Are we inside of properties? If so we need to record the elements.
+ if (this.insideProperties) {
+ propertyProcessingEnd(uri, name, raw);
+ } else if (DispatcherHelper.DISPATCHER_NAMESPACE_URI.equals(uri)) {
+ if (STRUCTURER_ELEMENT.equals(name)) {
+ structurerProcessingEnd(raw);
+ } else if (ContractBean.CONTRACT_ELEMENT.equals(name)) {
+ if (this.includeNodes)
+ contractProcessingEnd();
+ } else if (DISPATCHER_HOOK_ELEMENT.equals(name)) {
+ if (this.includeNodes) {
+ if (path.lastIndexOf("/") > -1)
+ path = path.substring(0, path.lastIndexOf("/"));
+ else
+ path = null;
+ }
+ } else {
+ if (this.includeNodes)
+ super.endElement(uri, name, raw);
+ }
+ } else {
+ super.endElement(uri, name, raw);
+ }
+ }
+
+ /**
+ * view type="?" Here we check which format we have in the view. That should
+ * be extended to matching the requested format
+ *
+ * @param attr
+ * @throws SAXException
+ */
+ private void structurerProcessingStart(Attributes attr) throws SAXException {
+ for (int i = 0; i < attr.getLength(); i++) {
+ String localName = attr.getLocalName(i);
+ String value = attr.getValue(i);
+ if (localName.equals(STRUCTURER_FORMAT_ATTRIBUTE)) {
+ currentFormat = value;
+ }
+ if (localName.equals(STRUCTURER_HOOK_XPATH_ATTRIBUTE)) {
+ if ("/".equals(String.valueOf(value.charAt(0)))) {
+ path = "result" + value;
+ } else {
+ path = "result/" + value;
+ }
+ }
+ }
+ if (requestedFormat.equals(currentFormat)) {
+ if (path == null)
+ path = "result/";
+ this.includeNodes = true;
+ this.recording = true;
+ try {
+ dispatcherHelper.setNamespaceHelper(
+ DispatcherHelper.DISPATCHER_NAMESPACE_URI,
+ DispatcherHelper.DISPATCHER_PREFIX, STRUCTURER_ELEMENT);
+ this.dispatcher = dispatcherHelper.getNamespaceHelper();
+ this.document = dispatcher.getDocument();
+ this.rootNode = document.getDocumentElement();
+ this.rootNode.setAttribute(STRUCTURER_FORMAT_ATTRIBUTE,
+ currentFormat);
+ this.rootNode.setAttribute(STRUCTURER_HOOK_XPATH_ATTRIBUTE,
+ path);
+ // we create the path node for the result node
+ DOMUtil.selectSingleNode(rootNode, path, this.processor);
+ } catch (Exception e) {
+ String error = " dispatcherError:\n could not setup dispatcherHelper! \""
+ + "\n dispatcherErrorStack:\n" + e;
+ getLogger().error(error + e);
+ this.recording = false;
+ throw new SAXException(error + e);
+ }
+
+ } else {
+ path = null; // unset path because we do not process the node
+ this.includeNodes = false;
+ this.recording = false;
+ }
+ }
+
+ /**
+ * @param raw
+ * @throws SAXException
+ */
+ private void structurerProcessingEnd(String raw) throws SAXException {
+ if (this.recording) {
+ XMLUtils.valueOf(new IncludeXMLConsumer(super.xmlConsumer),
+ this.rootNode);
+ this.recording = false;
+ }
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(
+ "Ending \"" + STRUCTURER_ELEMENT + "\" element: " + raw);
+ }
+ }
+
+ /**
+ * We have found a contract. Now we have to prepare a bean to later add it
+ * to the output stream in the endElement.
+ *
+ * @param attr
+ * @throws SAXException
+ */
+ private void contractProcessingStart(Attributes attr) throws SAXException {
+ this.insideContract = true;
+ try {
+ if (contract == null)
+ contract = new ContractBean(this.manager);
+ else
+ contract.initialize();
+ } catch (ParserConfigurationException e) {
+ throw new SAXException("originally ParserConfigurationException"
+ + e);
+ }
+ for (int i = 0; i < attr.getLength(); i++) {
+ String localName = attr.getLocalName(i);
+ String value = attr.getValue(i);
+ if (ContractBean.CONTRACT_ID_ATTRIBUTE.equals(localName)) {
+ // getting the contract name
+ contract.setContractName(value);
+ String contractUri = ContractBean.CONTRACT_RESOLVE_PREFIX + "."
+ + currentFormat + "." + value;
+ try {
+ Document doc = org.apache.forrest.dispatcher.util.SourceUtil
+ .readDOM(contractUri, this.manager);
+ contract.setContractImpl(doc);
+ // contract.setContractImpl(contractUri);
+ } catch (Exception e) {
+ String error = " dispatcherError:\n The contract \""
+ + contract.getContractName()
+ + "\" has thrown following errorStack by resolving the implementation from \""
+ + contractUri + "\".\n dispatcherErrorStack:\n";
+ getLogger().error(error + e);
+ throw new SAXException(error + e);
+ }
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(
+ "DISPATCHER_CONTRACT_ID_ATTRIBUTE" + "-->"
+ + localName + "\n" + "value" + "-->"
+ + value);
+ }
+ } else if (ContractBean.CONTRACT_NUGGET_ATTRIBUTE.equals(localName)) {
+ // contract is a nugget-contract
+ contract.setNugget(true);
+ try {
+ Document doc = org.apache.forrest.dispatcher.util.SourceUtil
+ .readDOM(value, this.manager);
+ contract.setContractRawData(doc);
+ // contract.setNuggetUri(value);
+ } catch (Exception e) {
+ String error = " dispatcherError:\n The contract \""
+ + contract.getContractName()
+ + "\" has thrown following errorStack by resolving raw data from \""
+ + value + "\".\n dispatcherErrorStack:\n ";
+ getLogger().error(error + e);
+ throw new SAXException(error + e);
+ }
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(
+ "ContractBean.CONTRACT_NUGGET_ATTRIBUTE" + "-->"
+ + localName + "\n" + "value" + "-->"
+ + value);
+ }
+ } else {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(
+ "localName" + "-->" + localName
+ + " not implemented");
+ }
+ }
+ }
+ /*
+ * if we do not have a nugget add a foo element to the raw data to
+ * invoke the transformation.
+ */
+ if (!contract.isNugget()) {
+ Document foo;
+ try {
+ foo = dispatcherHelper.createDocument("foo");
+ contract.setContractRawData(foo);
+ } catch (Exception e) {
+ String error = " dispatcherError:\n The contract \""
+ + contract.getContractName()
+ + "\" has thrown following errorStack by creating the dummy foo document."
+ + ".\n dispatcherErrorStack:\n ";
+ getLogger().error(error + e);
+ throw new SAXException(error + e);
+ }
+ /*
+ * Document fooDoc =// (Document)
+ * dispatcherHelper.getNamespaceHelper().getDocument();
+ * fooDoc.createElement("foo");
+ * contract.getFooData().getOwnerDocument();
+ */
+ }
+ }
+
+ /**
+ * @throws SAXException
+ */
+ private void contractProcessingEnd() throws SAXException {
+ try {
+ contract.setContractResultData();
+ Document node = (Document) contract.getContractResultData()
+ .getNode();
+ Document root = this.rootNode.getOwnerDocument();
+ /*
+ * debug code - uncomment it if you need it! will output the
+ * contract resulting data to sysout
+ *
+ * DOMSource source = new DOMSource(node); StreamResult result = new
+ * StreamResult(System.out);
+ * contract.getContractTransformer().transform(source, result);
+ */
+
+ /*
+ * append this node to the current path after testing where there is
+ * a fixed location for the contract content. If so then add it
+ * there.
+ */
+ NodeList contentChildren = node.getElementsByTagNameNS(
+ DispatcherHelper.DISPATCHER_NAMESPACE_URI, "part");
+ for (int i = 0; i < contentChildren.getLength(); i++) {
+ Element contentChild = (Element) contentChildren.item(i);
+ if (contentChild != null) {
+ String location = contentChild.getAttribute("xpath");
+ if (location.equals("") | location == null) {
+ String[] xpath = DOMUtil.buildPathArray(path);
+ Node xpathNode = DOMUtil.getFirstNodeFromPath(rootNode,
+ xpath, false);
+ if (xpathNode != null) {
+ if (node.hasChildNodes()) {
+ Node toMove = root.importNode(contentChild,
+ true);
+ xpathNode.appendChild(toMove);
+ }
+ }
+ } else {
+ if (location.charAt(0) == '/')
+ location = "result" + location;
+ else
+ location = "result/" + location;
+ Node xpathNode;
+ String[] xpath = DOMUtil.buildPathArray(location);
+ xpathNode = DOMUtil.getFirstNodeFromPath(rootNode,
+ xpath, false);
+ if (xpathNode != null) {
+ if (node.hasChildNodes()) {
+ Node toMove = root.importNode(contentChild,
+ true);
+ xpathNode.appendChild(toMove);
+ }
+ } else {
+ xpathNode = createXpathNode(location);
+ if (node.hasChildNodes()) {
+ Node toMove = root.importNode(contentChild,
+ true);
+ xpathNode.appendChild(toMove);
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ String error = " dispatcherError:\n The contract \""
+ + contract.getContractName()
+ + "\" has thrown following error while trying to transform the final markup: "
+ + e;
+ getLogger().error(error);
+ throw new SAXException(error);
+ } finally {
+ this.insideContract = false;
+ this.contract.recycle();
+ }
+ }
+
+ /**
+ * @param uri
+ * @param name
+ * @param raw
+ * @param attr
+ * @throws SAXException
+ */
+ private void propertyProcessingStart(String uri, String name, String raw,
+ Attributes attr) throws SAXException {
+ for (int i = 0; i < attr.getLength(); i++) {
+ String localName = attr.getLocalName(i);
+ String value = attr.getValue(i);
+ if (CONTRACT_PROPERTY_ID_ATTRIBUTE.equals(localName)) {
+ this.propertyID = value;
+ }
+ }
+ if (this.propertyID.equals("") | this.propertyID == null) {
+ String error = " dispatcherError:\n The contract \""
+ + contract.getContractName()
+ + "\" has no identifier attribute \""
+ + CONTRACT_PROPERTY_ID_ATTRIBUTE + "\" in the " + raw;
+ getLogger().error(error);
+ throw new SAXException(error);
+ }
+ this.builder = new DOMBuilder();
+ this.builder.startDocument();
+ launchStoredMappings();
+ this.builder.startElement(uri, name, raw, attr);
+ }
+
+ /**
+ * @param uri
+ * @param name
+ * @param raw
+ * @throws SAXException
+ */
+ private void propertyProcessingEnd(String uri, String name, String raw)
+ throws SAXException {
+ if (CONTRACT_PROPERTY_ELEMENT.equals(name)) {
+ this.insideProperties = false;
+ if (this.includeNodes) {
+ this.builder.endElement(uri, name, raw);
+ this.builder.endDocument();
+ if (getLogger().isDebugEnabled()) {
+ getLogger()
+ .debug(
+ "DispatcherTransformer: putting DOM tree into the contract transformer");
+ }
+ Transformer transformer = contract.getContractTransformer();
+ transformer.setParameter(this.propertyID, this.builder
+ .getDocument().getFirstChild());
+ contract.setContractTransformer(transformer);
+ this.propertyID = "";
+ contract.setHasProperties(true);
+ if (getLogger().isDebugEnabled()) {
+ getLogger()
+ .debug(
+ "DispatcherTransformer: DOM tree is in the contract transformer");
+ }
+ this.builder = null;
+ }
+ } else {
+ if (this.includeNodes)
+ this.builder.endElement(uri, name, raw);
+ }
+ }
+
+ public void characters(char c[], int start, int len) throws SAXException {
+ if (this.insideProperties) {
+ if (this.includeNodes)
+ this.builder.characters(c, start, len);
+ } else {
+ if (this.includeNodes)
+ super.contentHandler.characters(c, start, len);
+ }
+ }
+
+ public void startCDATA() throws SAXException {
+ if (this.insideProperties) {
+ if (this.includeNodes)
+ this.builder.startCDATA();
+ } else {
+ if (this.includeNodes)
+ super.lexicalHandler.startCDATA();
+ }
+ }
+
+ public void endCDATA() throws SAXException {
+ if (this.insideProperties) {
+ if (this.includeNodes)
+ this.builder.endCDATA();
+ } else {
+ if (this.includeNodes)
+ super.lexicalHandler.endCDATA();
+ }
+ }
+
+ /** BEGIN SAX ContentHandler handlers * */
+
+ public void startPrefixMapping(String prefix, String uri)
+ throws SAXException {
+ super.startPrefixMapping(prefix, uri);
+ if (this.insideProperties) {
+ if (this.includeNodes)
+ this.builder.startPrefixMapping(prefix, uri);
+ } else {
+ storePrefixMapping(prefix, uri);
+ }
+ }
+
+ /** END SAX ContentHandler handlers * */
+
+ protected void storePrefixMapping(String prefix, String uri) {
+ storedPrefixMap.put(prefix, uri);
+ }
+
+ protected void launchStoredMappings() throws SAXException {
+ Iterator it = storedPrefixMap.keySet().iterator();
+ while (it.hasNext()) {
+ String pre = (String) it.next();
+ String uri = (String) storedPrefixMap.get(pre);
+ getLogger().debug(
+ "WriteSessionTransformer: launching prefix mapping[ pre: "
+ + pre + " uri: " + uri + " ]");
+ this.builder.startPrefixMapping(pre, uri);
+ }
+ }
+
+ protected void launchStoredMappingsDispatcher() throws SAXException {
+ Iterator it = storedPrefixMap.keySet().iterator();
+ while (it.hasNext()) {
+ String pre = (String) it.next();
+ String uri = (String) storedPrefixMap.get(pre);
+ getLogger().debug(
+ "WriteSessionTransformer: launching prefix mapping[ pre: "
+ + pre + " uri: " + uri + " ]");
+ this.dispatcherBuilder.startPrefixMapping(pre, uri);
+ }
+ }
+
+}
Propchange: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/transformation/DispatcherTransformer.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/util/SourceUtil.java
URL: http://svn.apache.org/viewcvs/forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/util/SourceUtil.java?rev=349923&view=auto
==============================================================================
--- forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/util/SourceUtil.java (added)
+++ forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/util/SourceUtil.java Wed Nov 30 03:14:46 2005
@@ -0,0 +1,52 @@
+package org.apache.forrest.dispatcher.util;
+
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceNotFoundException;
+import org.apache.lenya.xml.DocumentHelper;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+public class SourceUtil {
+ /**
+ * Reads a DOM from a source.
+ * @param sourceUri The source URI.
+ * @param manager The service manager.
+ * @return A document or <code>null</code> if the source does not exist.
+ * @throws ServiceException if an error occurs.
+ * @throws SourceNotFoundException if an error occurs.
+ * @throws ParserConfigurationException if an error occurs.
+ * @throws SAXException if an error occurs.
+ * @throws IOException if an error occurs.
+ */
+ public static Document readDOM(String sourceUri, ServiceManager manager)
+ throws ServiceException, SourceNotFoundException, ParserConfigurationException,
+ SAXException, IOException {
+ SourceResolver resolver = null;
+ Source source = null;
+ Document document = null;
+ try {
+
+ resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
+ source = resolver.resolveURI(sourceUri);
+
+ if (source.exists()) {
+ document = DocumentHelper.readDocument(source.getInputStream());
+ }
+ } finally {
+ if (resolver != null) {
+ if (source != null) {
+ resolver.release(source);
+ }
+ manager.release(resolver);
+ }
+ }
+ return document;
+ }
+}
Propchange: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/forrest/dispatcher/util/SourceUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/lenya/xml/DocumentHelper.java
URL: http://svn.apache.org/viewcvs/forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/lenya/xml/DocumentHelper.java?rev=349923&view=auto
==============================================================================
--- forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/lenya/xml/DocumentHelper.java (added)
+++ forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/lenya/xml/DocumentHelper.java Wed Nov 30 03:14:46 2005
@@ -0,0 +1,446 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.lenya.xml;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.xml.resolver.tools.CatalogResolver;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.SAXException;
+
+/**
+ * Various utility methods to work with JAXP.
+ * @version $Id: DocumentHelper.java 264963 2005-08-31 07:58:45Z andreas $
+ */
+public class DocumentHelper {
+ /**
+ * Creates a non-validating and namespace-aware DocumentBuilder.
+ * @return A new DocumentBuilder object.
+ * @throws ParserConfigurationException if an error occurs
+ */
+ public static DocumentBuilder createBuilder() throws ParserConfigurationException {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+
+ CatalogResolver cr = new CatalogResolver();
+ builder.setEntityResolver(cr);
+ return builder;
+ }
+
+ /**
+ * Creates a document. A xmlns:prefix="namespaceUri" attribute is added to
+ * the document element.
+ * @param namespaceUri The namespace URL of the root element.
+ * @param qualifiedName The qualified name of the root element.
+ * @param documentType The type of document to be created or null. When
+ * doctype is not null, its Node.ownerDocument attribute is set
+ * to the document being created.
+ * @return A new Document object.
+ * @throws DOMException if an error occurs
+ * @throws ParserConfigurationException if an error occurs
+ * @see org.w3c.dom.DOMImplementation#createDocument(String, String,
+ * DocumentType)
+ */
+ public static Document createDocument(String namespaceUri, String qualifiedName,
+ DocumentType documentType) throws DOMException, ParserConfigurationException {
+ DocumentBuilder builder = createBuilder();
+ Document document = builder.getDOMImplementation().createDocument(namespaceUri,
+ qualifiedName,
+ documentType);
+
+ // add xmlns:prefix attribute
+ String name = "xmlns";
+ int index = qualifiedName.indexOf(":");
+
+ if (index > -1) {
+ name += (":" + qualifiedName.substring(0, index));
+ }
+
+ document.getDocumentElement().setAttributeNS("http://www.w3.org/2000/xmlns/",
+ name,
+ namespaceUri);
+
+ return document;
+ }
+
+ /**
+ * Reads a document from a file.
+ * @return A document.
+ * @param file The file to load the document from.
+ * @throws ParserConfigurationException if an error occurs
+ * @throws SAXException if an error occurs
+ * @throws IOException if an error occurs
+ */
+ public static Document readDocument(File file) throws ParserConfigurationException,
+ SAXException, IOException {
+ DocumentBuilder builder = createBuilder();
+ return builder.parse(file);
+ }
+
+ /**
+ * Reads a document from a URL.
+ * @return A document.
+ * @param url The URL to load the document from.
+ * @throws ParserConfigurationException if an error occurs
+ * @throws SAXException if an error occurs
+ * @throws IOException if an error occurs
+ */
+ public static Document readDocument(URL url) throws ParserConfigurationException, SAXException,
+ IOException {
+ DocumentBuilder builder = createBuilder();
+ return builder.parse(url.toString());
+ }
+
+ /**
+ * Reads a document from a URI.
+ * @return A document.
+ * @param uri The URI to load the document from.
+ * @throws ParserConfigurationException if an error occurs
+ * @throws SAXException if an error occurs
+ * @throws IOException if an error occurs
+ */
+ public static Document readDocument(URI uri) throws ParserConfigurationException, SAXException,
+ IOException {
+ DocumentBuilder builder = createBuilder();
+ return builder.parse(uri.toString());
+ }
+
+ /**
+ * Reads a document from a string.
+ * @return A document.
+ * @param string The string to load the document from.
+ * @throws ParserConfigurationException if an error occurs
+ * @throws SAXException if an error occurs
+ * @throws IOException if an error occurs
+ */
+ public static Document readDocument(String string) throws ParserConfigurationException,
+ SAXException, IOException {
+ DocumentBuilder builder = createBuilder();
+ return builder.parse(string);
+ }
+
+ /**
+ * Reads a document from an input stream.
+ * @return A document.
+ * @param stream The input stream to load the document from.
+ * @throws ParserConfigurationException if an error occurs
+ * @throws SAXException if an error occurs
+ * @throws IOException if an error occurs
+ */
+ public static Document readDocument(InputStream stream) throws ParserConfigurationException,
+ SAXException, IOException {
+ DocumentBuilder builder = createBuilder();
+ return builder.parse(stream);
+ }
+
+ /**
+ * Writes a document to a file. A new file is created if it does not exist.
+ * @param document The document to save.
+ * @param file The file to save the document to.
+ * @throws IOException if an error occurs
+ * @throws TransformerConfigurationException if an error occurs
+ * @throws TransformerException if an error occurs
+ */
+ public static void writeDocument(Document document, File file)
+ throws TransformerConfigurationException, TransformerException, IOException {
+ // sanity checks
+ if (document == null)
+ throw new IllegalArgumentException("illegal usage, parameter document may not be null");
+ if (file == null)
+ throw new IllegalArgumentException("illegal usage, parameter file may not be null");
+
+ file.getParentFile().mkdirs();
+ file.createNewFile();
+
+ DOMSource source = new DOMSource(document);
+ StreamResult result = new StreamResult(file);
+ getTransformer(document.getDoctype()).transform(source, result);
+ }
+
+ /**
+ * Writes a document to a writer.
+ * @param document The document to write.
+ * @param writer The writer to write the document to.
+ * @throws TransformerConfigurationException if an error occurs
+ * @throws TransformerException if an error occurs
+ */
+ public static void writeDocument(Document document, Writer writer)
+ throws TransformerConfigurationException, TransformerException {
+
+ // sanity checks
+ if (document == null)
+ throw new IllegalArgumentException("illegal usage of DocumentHelper::writeDocument(), parameter document may not be null");
+
+ DOMSource source = new DOMSource(document);
+ StreamResult result = new StreamResult(writer);
+ getTransformer(document.getDoctype()).transform(source, result);
+ }
+
+ /**
+ * Get the transformer.
+ * @param documentType the document type
+ * @return a transformer
+ * @throws TransformerConfigurationException if an error occurs
+ */
+ protected static Transformer getTransformer(DocumentType documentType)
+ throws TransformerConfigurationException {
+ TransformerFactory factory = TransformerFactory.newInstance();
+ Transformer transformer = factory.newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+
+ if (documentType != null) {
+ if (documentType.getPublicId() != null)
+ transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, documentType.getPublicId());
+ if (documentType.getSystemId() != null)
+ transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, documentType.getSystemId());
+ }
+
+ return transformer;
+ }
+
+ /**
+ * Creates a document type.
+ * @param qualifiedName The qualified name of the document type.
+ * @param publicId The public identifier.
+ * @param systemId The system identifier.
+ * @return the document type
+ * @throws ParserConfigurationException if an error occurs
+ * @see org.w3c.dom.DOMImplementation#createDocumentType(java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ public DocumentType createDocumentType(String qualifiedName, String publicId, String systemId)
+ throws ParserConfigurationException {
+ DocumentBuilder builder = createBuilder();
+
+ return builder.getDOMImplementation().createDocumentType(qualifiedName, publicId, systemId);
+ }
+
+ /**
+ * Returns the first child element of an element that belong to a certain
+ * namespace or <code>null</code> if none exists.
+ * @param element The parent element.
+ * @param namespaceUri The namespace that the childen must belong to.
+ * @return The first child element or <code>null</code> if none exists.
+ */
+ public static Element getFirstChild(Element element, String namespaceUri) {
+ return getFirstChild(element, namespaceUri, "*");
+ }
+
+ /**
+ * Returns the first child element of an element that belongs to a certain
+ * namespace and has a certain local name or <code>null</code> if none
+ * exists.
+ * @param element The parent element.
+ * @param namespaceUri The namespace that the childen must belong to.
+ * @param localName The local name of the children.
+ * @return The child element or <code>null</code> if none exists.
+ */
+ public static Element getFirstChild(Element element, String namespaceUri, String localName) {
+ Element[] children = getChildren(element, namespaceUri, localName);
+
+ if (children.length > 0) {
+ return children[0];
+ }
+ return null;
+ }
+
+ /**
+ * Returns all child elements of an element, regardless of the namespace.
+ * @param element The parent element.
+ * @return The child elements.
+ */
+ public static Element[] getChildren(Element element) {
+ List childElements = new ArrayList();
+ NodeList children = element.getElementsByTagName("*");
+
+ for (int i = 0; i < children.getLength(); i++) {
+ if (children.item(i).getParentNode() == element) {
+ childElements.add(children.item(i));
+ }
+ }
+
+ return (Element[]) childElements.toArray(new Element[childElements.size()]);
+ }
+
+ /**
+ * Returns all child elements of an element that belong to a certain
+ * namespace.
+ * @param element The parent element.
+ * @param namespaceUri The namespace that the childen must belong to.
+ * @return The child elements.
+ */
+ public static Element[] getChildren(Element element, String namespaceUri) {
+ return getChildren(element, namespaceUri, "*");
+ }
+
+ /**
+ * Returns all child elements of an element that belong to a certain
+ * namespace and have a certain local name.
+ * @param element The parent element.
+ * @param namespaceUri The namespace that the childen must belong to.
+ * @param localName The local name of the children.
+ * @return The child elements.
+ */
+ public static Element[] getChildren(Element element, String namespaceUri, String localName) {
+ List childElements = new ArrayList();
+ NodeList children = element.getElementsByTagNameNS(namespaceUri, localName);
+
+ for (int i = 0; i < children.getLength(); i++) {
+ if (children.item(i).getParentNode() == element) {
+ childElements.add(children.item(i));
+ }
+ }
+
+ return (Element[]) childElements.toArray(new Element[childElements.size()]);
+ }
+
+ /**
+ * Returns the text inside an element. Only the child text nodes of this
+ * element are collected.
+ * @param element The element.
+ * @return The text inside the element.
+ */
+ public static String getSimpleElementText(Element element) {
+ StringBuffer buffer = new StringBuffer();
+ NodeList children = element.getChildNodes();
+
+ for (int i = 0; i < children.getLength(); i++) {
+ Node child = children.item(i);
+
+ if (child instanceof Text) {
+ buffer.append(child.getNodeValue());
+ }
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * Replaces all child nodes of an element by a single text node.
+ * @param element The element.
+ * @param text The text to insert.
+ */
+ public static void setSimpleElementText(Element element, String text) {
+ NodeList children = element.getChildNodes();
+
+ for (int i = 0; i < children.getLength(); i++) {
+ Node child = children.item(i);
+ element.removeChild(child);
+ }
+
+ Node textNode = element.getOwnerDocument().createTextNode(text);
+ element.appendChild(textNode);
+ }
+
+ /**
+ * Returns all following sibling elements of an element that belong to a
+ * certain namespace.
+ * @param element The parent element.
+ * @param namespaceUri The namespace that the childen must belong to.
+ * @return The following sibling elements.
+ */
+ public static Element[] getNextSiblings(Element element, String namespaceUri) {
+ return getNextSiblings(element, namespaceUri, "*");
+ }
+
+ /**
+ * Returns all following sibling elements of an element that belong to a
+ * certain namespace. and have a certain local name.
+ * @param element The parent element.
+ * @param namespaceUri The namespace that the childen must belong to.
+ * @param localName The local name of the children.
+ * @return The following sibling elements.
+ */
+ public static Element[] getNextSiblings(Element element, String namespaceUri, String localName) {
+ List childElements = new ArrayList();
+ Element parent = (Element) element.getParentNode();
+ Element[] children = getChildren(parent, namespaceUri, localName);
+
+ int l = children.length;
+ for (int i = 0; i < children.length; i++) {
+ if (children[i] == element) {
+ l = i;
+ }
+ if (i > l) {
+ childElements.add(children[i]);
+ }
+ }
+
+ return (Element[]) childElements.toArray(new Element[childElements.size()]);
+ }
+
+ /**
+ * Returns all preceding sibling elements of an element that belong to a
+ * certain namespace.
+ * @param element The parent element.
+ * @param namespaceUri The namespace that the childen must belong to.
+ * @return The preceding sibling elements.
+ */
+ public static Element[] getPrecedingSiblings(Element element, String namespaceUri) {
+ return getPrecedingSiblings(element, namespaceUri, "*");
+ }
+
+ /**
+ * Returns all preceding sibling elements of an element that belong to a
+ * certain namespace. and have a certain local name.
+ * @param element The parent element.
+ * @param namespaceUri The namespace that the childen must belong to.
+ * @param localName The local name of the children.
+ * @return The preceding sibling elements.
+ */
+ public static Element[] getPrecedingSiblings(Element element, String namespaceUri,
+ String localName) {
+ List childElements = new ArrayList();
+ Element parent = (Element) element.getParentNode();
+ Element[] children = getChildren(parent, namespaceUri, localName);
+
+ int i = 0;
+ while (children[i] != element && i < children.length) {
+ childElements.add(children[i]);
+ i++;
+ }
+
+ return (Element[]) childElements.toArray(new Element[childElements.size()]);
+ }
+}
Propchange: forrest/trunk/whiteboard/plugins/org.apache.forrest.plugin.internal.structurer/src/java/org/apache/lenya/xml/DocumentHelper.java
------------------------------------------------------------------------------
svn:eol-style = native