cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From reinh...@apache.org
Subject svn commit: r740500 [1/3] - in /cocoon/cocoon3/trunk/cocoon-stax: ./ src/main/java/org/apache/cocoon/stax/ src/main/java/org/apache/cocoon/stax/navigation/ src/test/java/org/apache/cocoon/stax/ src/test/java/org/apache/cocoon/stax/sample/src/ src/test/...
Date Tue, 03 Feb 2009 22:51:58 GMT
Author: reinhard
Date: Tue Feb  3 22:51:56 2009
New Revision: 740500

URL: http://svn.apache.org/viewvc?rev=740500&view=rev
Log:
COCOON3-18

Since our last release some time passed by and we did many changes to the "core" of the cocoon-stax module. The changes contained by this patch could be summerized as:

 * Introduced the marker interface for StAXPipelineComponent for the generified Pipeline interface as proposed by Steven in COCOON3-17.
 * Introduced a general workflow for working the peek() and nextEvent() calls in the same way
 * Increased the documentation at many places in the code
 * Introduced regex attribute finding capabilities to the FindStartElementNavigator and the InSubtreeNavigator
 * Added some additional testcases which also could be used as examples.

Added:
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXPipelineComponent.java   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/IncludeTransformer.java   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXPipelineComponent.java   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/MatchingType.java   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/IncludeTransformerTest.java   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/DaisyLinkRewriteTransformer.java   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/SubSetTransformer.java   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/test/DaisyLinkRewriteTransformerTest.java   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/test/StartElementAttributeModificationTransformerTest.java   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/test/StartEndElementPairModificationTransformerTest.java   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/test/SubSetTransformerTest.java   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/file_to_include.xml   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/includetest_input.xml   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/includetest_output.xml   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/daisy-document-input.xml   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/daisy-document-result.xml   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/special_root.xml   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/special_root_first.xml   (with props)
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/special_root_second.xml   (with props)
Modified:
    cocoon/cocoon3/trunk/cocoon-stax/pom.xml
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXProducer.java
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXTransformer.java
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXCleaningTransformer.java
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXConsumer.java
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXGenerator.java
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXProducer.java
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXSerializer.java
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindCorrespondingStartEndElementPairNavigator.java
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindEndElementNavigator.java
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindStartElementNavigator.java
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/InSubtreeNavigator.java
    cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/Navigator.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/CleaningTransformerTest.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/StAXPipelineTest.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/DeletionTransformer.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/ExampleAddTransformer.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/ExampleComplexTransformer.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/StartElementAttributeModificationTransformer.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/StartEndElementPairModificationTransformer.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/test/AddTransformerTest.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/test/ComplexTransformerTest.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/test/DeletionTransformerTest.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/test/StartElementAttributeModifaicationTransformerTest.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/test/StartEndElementPairModifaicationTransformerTest.java
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/complex-stax-test-document.xml
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/stax-test-document-add.xml
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/stax-test-document-clean.xml
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/stax-test-document-complex.xml
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/stax-test-document-modified1.xml
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/stax-test-document-modified2.xml
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/stax-test-document-nestedDifferent-modified.xml
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/stax-test-document-nestedDifferent.xml
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/sample/stax-test-document.xml
    cocoon/cocoon3/trunk/cocoon-stax/src/test/resources/org/apache/cocoon/stax/simple.xml

Modified: cocoon/cocoon3/trunk/cocoon-stax/pom.xml
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/pom.xml?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/pom.xml (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/pom.xml Tue Feb  3 22:51:56 2009
@@ -14,7 +14,8 @@
   the specific language governing permissions and limitations under the
   License.
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
   <modelVersion>4.0.0</modelVersion>
   <packaging>jar</packaging>
@@ -51,13 +52,13 @@
         </exclusion>
       </exclusions>
     </dependency>
-
-    <!-- test dependencies -->
     <dependency>
       <groupId>org.apache.cocoon.sax</groupId>
       <artifactId>cocoon-sax</artifactId>
-      <scope>test</scope>
-    </dependency>
+      <optional>true</optional>
+    </dependency>    
+
+    <!-- test dependencies -->
     <dependency>
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
@@ -83,7 +84,7 @@
           <source>1.6</source>
           <target>1.6</target>
         </configuration>
-      </plugin>      
+      </plugin>
     </plugins>
   </build>
 </project>

Added: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXPipelineComponent.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXPipelineComponent.java?rev=740500&view=auto
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXPipelineComponent.java (added)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXPipelineComponent.java Tue Feb  3 22:51:56 2009
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you 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.cocoon.stax;
+
+import javax.xml.stream.events.XMLEvent;
+
+import org.apache.cocoon.pipeline.component.AbstractPipelineComponent;
+import org.apache.cocoon.pipeline.component.PipelineComponent;
+
+/**
+ * Abstract base class for {@link PipelineComponent}s producing and/or consuming {@link XMLEvent}s.<br>
+ */
+public abstract class AbstractStAXPipelineComponent extends AbstractPipelineComponent implements StAXPipelineComponent {
+
+}

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXPipelineComponent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXPipelineComponent.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXPipelineComponent.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXProducer.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXProducer.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXProducer.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXProducer.java Tue Feb  3 22:51:56 2009
@@ -17,7 +17,6 @@
 package org.apache.cocoon.stax;
 
 import org.apache.cocoon.pipeline.SetupException;
-import org.apache.cocoon.pipeline.component.AbstractPipelineComponent;
 import org.apache.cocoon.pipeline.component.Consumer;
 import org.apache.cocoon.pipeline.component.Producer;
 
@@ -27,7 +26,7 @@
  * {@link StAXConsumer} is used, storing it and setting itself as the parent of
  * its consumer.
  */
-public abstract class AbstractStAXProducer extends AbstractPipelineComponent implements StAXProducer {
+public abstract class AbstractStAXProducer extends AbstractStAXPipelineComponent implements StAXProducer {
 
     private StAXConsumer consumer;
 

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXTransformer.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXTransformer.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXTransformer.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/AbstractStAXTransformer.java Tue Feb  3 22:51:56 2009
@@ -16,17 +16,26 @@
  */
 package org.apache.cocoon.stax;
 
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Queue;
+
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.events.XMLEvent;
 
 /**
- * Abstract transformer could/should be used for each StAXTransformer. This
- * class implementing the default behavior of the {@link StAXConsumer} and the
- * {@link StAXConsumer} interfaces.
+ * Abstract transformer could/should be used for each StAXTransformer. This class implements the
+ * default behavior of the {@link StAXConsumer} and the {@link StAXConsumer} interfaces.
+ * 
+ * Further more the {@link AbstractStAXTransformer} contains the queuing for StAX-events. This
+ * transformer abstracts the entire handling of {@link #nextEvent()} and {@link #peek()} behind a
+ * template method {@link #produceEvents()} which saves all produced events in a buffer and handles
+ * {@link #peek()}, {@link #nextEvent()} and {@link #hasNext()}.
  */
 public abstract class AbstractStAXTransformer extends AbstractStAXProducer implements StAXConsumer {
 
-    protected StAXProducer parent;
+    private StAXProducer parent;
+    private Queue<XMLEvent> queue = new LinkedList<XMLEvent>();
 
     /**
      * {@inheritDoc}
@@ -34,7 +43,7 @@
      * @see StAXConsumer#initiatePullProcessing()
      */
     @Override
-    public void initiatePullProcessing() {
+    public final void initiatePullProcessing() {
         this.getConsumer().initiatePullProcessing();
     }
 
@@ -44,18 +53,24 @@
      * @see StAXConsumer#setParent(StAXProducer)
      */
     @Override
-    public void setParent(StAXProducer parent) {
+    public final void setParent(StAXProducer parent) {
         this.parent = parent;
     }
 
     /**
      * {@inheritDoc}
      * 
+     * @throws XMLStreamException Error which could occure during producing events.
+     * 
      * @see StAXProducer#hasNext()
      */
     @Override
-    public boolean hasNext() {
-        return this.parent.hasNext();
+    public final boolean hasNext() throws XMLStreamException {
+        if (this.queue.isEmpty()) {
+            this.produceEvents();
+        }
+
+        return !this.queue.isEmpty();
     }
 
     /**
@@ -64,8 +79,8 @@
      * @see StAXProducer#nextEvent()
      */
     @Override
-    public XMLEvent nextEvent() throws XMLStreamException {
-        return this.parent.nextEvent();
+    public final XMLEvent nextEvent() {
+        return this.queue.poll();
     }
 
     /**
@@ -74,7 +89,56 @@
      * @see StAXProducer#peek()
      */
     @Override
-    public XMLEvent peek() throws XMLStreamException {
-        return this.parent.peek();
+    public final XMLEvent peek() {
+        return this.queue.peek();
+    }
+
+    /**
+     * Add a specific {@link XMLEvent} to an internal {@link Queue}.
+     * 
+     * @param event which should be added to the queue.
+     */
+    protected final void addEventToQueue(XMLEvent event) {
+        this.queue.add(event);
+    }
+
+    /**
+     * This {@link StAXProducer} is the parent of the module overwriting this
+     * {@link AbstractStAXTransformer}. It could be used in the {@link #produceEvents()} method to
+     * pull events from the parent or ask if it still has some.
+     */
+    protected final StAXProducer getParent() {
+        return this.parent;
+    }
+
+    /**
+     * Adds a {@link Collection} of {@link XMLEvent}s to an internal {@link Queue}.
+     * 
+     * @param events are a {@link Collection} of {@link XMLEvent}s which should be added to an
+     *            internal {@link Queue}.
+     */
+    protected final void addAllEventsToQueue(Collection<? extends XMLEvent> events) {
+        this.queue.addAll(events);
     }
+
+    /**
+     * Checks and returns if the internal {@link Queue} of {@link XMLEvent}s is empty.
+     * 
+     * @return checks and returns if the internal {@link Queue} of {@link XMLEvent}s is empty.
+     */
+    protected final boolean isQueueEmpty() {
+        return this.queue.isEmpty();
+    }
+
+    /**
+     * Template method which has to produce at least one {@link XMLEvent} and should add this to the
+     * internal {@link Queue} with the {@link #add(XMLEvent)} and {@link #addAll(Collection)}
+     * methods. If no {@link XMLEvent} is added by this method to the internal {@link Queue} an
+     * exception is thrown.
+     * 
+     * @throws XMLStreamException thrown if the {@link StAXProducer#nextEvent()} or the
+     *             {@link StAXProducer#peek()} method, called in the {@link #produceEvents()} method
+     *             throw any exceptions they have to be forwarded to the end of the pipeline.
+     */
+    protected abstract void produceEvents() throws XMLStreamException;
 }

Added: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/IncludeTransformer.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/IncludeTransformer.java?rev=740500&view=auto
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/IncludeTransformer.java (added)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/IncludeTransformer.java Tue Feb  3 22:51:56 2009
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.cocoon.stax;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.XMLEvent;
+
+import org.apache.cocoon.pipeline.ProcessingException;
+import org.apache.cocoon.pipeline.component.AbstractPipelineComponent;
+import org.apache.cocoon.pipeline.util.StringRepresentation;
+import org.apache.cocoon.stax.navigation.Navigator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A transformer that includes a xml document into another at the place where a include tag is found
+ * pointing at the document to include.
+ */
+public class IncludeTransformer extends AbstractStAXTransformer {
+
+    private final Log logger = LogFactory.getLog(this.getClass());
+
+    private static final String INCLUDE_NS = "http://apache.org/cocoon/3.0/include";
+
+    private static final String INCLUDE_EL = "include";
+
+    private static final String SRC_ATTR = "src";
+
+    private static final QName INCLUDE_QNAME = new QName(INCLUDE_NS, INCLUDE_EL);
+
+    private URL baseUrl;
+
+    private Navigator isIncludeEnd;
+
+    private Navigator isIncludeStart;
+
+    private StAXProducer includeDelegate;
+
+    /**
+     * Creates a new {@link IncludeTransformer} that includes a xml document into another at the
+     * place where a include tag is found pointing at the document to include.
+     */
+    public IncludeTransformer() {
+        this.isIncludeStart = new Navigator() {
+
+            private boolean active;
+
+            @Override
+            public boolean fulfillsCriteria(XMLEvent event) {
+                if (event.isStartElement()) {
+                    this.active = event.asStartElement().getName().equals(IncludeTransformer.INCLUDE_QNAME);
+                    return this.active;
+                }
+                this.active = false;
+                return this.active;
+            }
+
+            @Override
+            public boolean isActive() {
+                return this.active;
+            }
+        };
+        this.isIncludeEnd = new Navigator() {
+
+            private boolean active;
+
+            @Override
+            public boolean fulfillsCriteria(XMLEvent event) {
+                if (event.isEndElement()) {
+                    this.active = event.asEndElement().getName().equals(IncludeTransformer.INCLUDE_QNAME);
+                    return this.active;
+                }
+                this.active = false;
+                return this.active;
+            }
+
+            @Override
+            public boolean isActive() {
+                return this.active;
+            }
+        };
+
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.apache.cocoon.stax.AbstractStAXTransformer#produceEvents()
+     */
+    @Override
+    public void produceEvents() throws XMLStreamException {
+        while (this.getParent().hasNext()) {
+            if (this.includeDelegate == null) {
+                XMLEvent event = this.getParent().nextEvent();
+                if (this.isIncludeStart.fulfillsCriteria(event)) {
+                    Attribute sourceAttribute = event.asStartElement().getAttributeByName(new QName(SRC_ATTR));
+                    URL source = this.createSource(sourceAttribute.getValue());
+                    try {
+                        this.includeDelegate = new StAXGenerator(source.openConnection().getInputStream());
+                    } catch (IOException e) {
+                        String message = "Can't read from URL " + sourceAttribute.getValue();
+                        this.logger.error(message, e);
+                        throw new ProcessingException(message, e);
+                    }
+                } else if (!this.isIncludeEnd.fulfillsCriteria(event)) {
+                    this.addEventToQueue(event);
+                    return;
+                }
+
+            } else {
+                if (this.includeDelegate.hasNext()) {
+                    XMLEvent event = this.includeDelegate.nextEvent();
+                    if (!event.isStartDocument() && !event.isEndDocument()) {
+                        this.addEventToQueue(event);
+                        return;
+                    }
+                } else {
+                    this.includeDelegate = null;
+                }
+            }
+        }
+    }
+
+    /**
+     * Creates a url from a string.
+     * 
+     * @param sourceAtt The url represented as a string.
+     * @return The url of the specified string.
+     */
+    private URL createSource(String sourceAtt) {
+        try {
+            URL source = null;
+            if (sourceAtt.contains(":")) {
+                source = new URL(sourceAtt);
+            } else {
+                source = new URL(this.baseUrl, sourceAtt);
+            }
+            if (this.logger.isDebugEnabled()) {
+                this.logger.debug("Including source: " + source);
+            }
+
+            return source;
+        } catch (MalformedURLException e) {
+            String message = "Can't parse URL " + sourceAtt;
+            this.logger.error(message, e);
+            throw new ProcessingException(message, e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see AbstractPipelineComponent#setConfiguration(Map)
+     */
+    @Override
+    public void setConfiguration(Map<String, ? extends Object> configuration) {
+        this.setBaseUrl((URL) configuration.get("baseUrl"));
+    }
+
+    /**
+     * Sets the base url for this transformer.
+     * 
+     * @param baseUrl The new base url
+     */
+    public void setBaseUrl(URL baseUrl) {
+        this.baseUrl = baseUrl;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see Object#toString()
+     */
+    @Override
+    public String toString() {
+        return StringRepresentation.buildString(this, "baseUrl=" + this.baseUrl);
+    }
+}

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/IncludeTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/IncludeTransformer.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/IncludeTransformer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXCleaningTransformer.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXCleaningTransformer.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXCleaningTransformer.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXCleaningTransformer.java Tue Feb  3 22:51:56 2009
@@ -17,14 +17,16 @@
 package org.apache.cocoon.stax;
 
 import javax.xml.stream.XMLEventFactory;
-import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.events.StartElement;
 import javax.xml.stream.events.XMLEvent;
 
+import org.apache.cocoon.pipeline.component.sax.CleaningTransformer;
+
 /**
- * Transformer which is used to clean an xml document from all whitespaces, comments and namespace
- * start prefixes and end prefixes as its SAX counterpart the CleaningTransformer.
+ * Transformer which is used to clean a xml document from all whitespaces,
+ * comments and namespace start prefixes and end prefixes. Works similar to the
+ * {@link CleaningTransformer} for SAX pipelines.
  */
 public class StAXCleaningTransformer extends AbstractStAXTransformer {
 
@@ -33,34 +35,36 @@
     /**
      * {@inheritDoc}
      * 
-     * @see StAXProducer#nextEvent()
+     * @see org.apache.cocoon.stax.AbstractStAXTransformer#produceEvents()
      */
     @Override
-    public XMLEvent nextEvent() throws XMLStreamException {
-        XMLEvent event = null;
-        while (true) {
-            event = this.parent.nextEvent();
+    public void produceEvents() throws XMLStreamException {
+        while (this.getParent().hasNext()) {
+            XMLEvent event = this.getParent().nextEvent();
             if (event.isCharacters()) {
                 // remove char-events if only whitespaces
                 String allChars = event.asCharacters().getData();
                 for (int charCounter = 0; charCounter < allChars.length(); charCounter++) {
                     char eachChar = allChars.charAt(charCounter);
                     if (!Character.isWhitespace(eachChar) || eachChar == '\u00A0') {
-                        return event;
+                        this.addEventToQueue(event);
+                        return;
                     }
                 }
                 continue;
-            } else if (event.getEventType() == XMLStreamConstants.COMMENT) {
+            } else if (event.getEventType() == XMLEvent.COMMENT) {
                 // remove comments
                 continue;
             } else if (event.isStartElement()) {
                 // handle namespaces
                 StartElement startElement = event.asStartElement();
-                return eventFactory.createStartElement("", startElement.getNamespaceURI(""), startElement.getName().getLocalPart(),
-                        startElement.getAttributes(), null, startElement.getNamespaceContext());
+                this.addEventToQueue(eventFactory.createStartElement("", startElement.getNamespaceURI(""), startElement
+                        .getName().getLocalPart(), startElement.getAttributes(), null, startElement
+                        .getNamespaceContext()));
+                return;
             }
-
-            return event;
+            this.addEventToQueue(event);
+            return;
         }
     }
 }

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXConsumer.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXConsumer.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXConsumer.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXConsumer.java Tue Feb  3 22:51:56 2009
@@ -29,11 +29,11 @@
  * set the {@link Producer} for the consumer as parent directly to the
  * component.
  */
-public interface StAXConsumer extends Consumer {
+public interface StAXConsumer extends Consumer, StAXPipelineComponent {
 
     /**
      * Since the workflow in a pull pipeline is completely inverted compared to
-     * a sax pipeline this method is required to push the
+     * for example a SAX pipeline, this method is required to push the
      * {@link Starter#execute()} to the {@link Finisher} which should start
      * processing.
      */

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXGenerator.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXGenerator.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXGenerator.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXGenerator.java Tue Feb  3 22:51:56 2009
@@ -29,23 +29,19 @@
 import org.apache.cocoon.pipeline.component.Starter;
 
 /**
- * General element generator for a StAX pipeline directly taking all elements
- * from an internal {@link XMLEventReader} created from an {@link InputStream}
- * or directly from an {@link URL}.
+ * General element generator for a StAX pipeline directly taking all elements from an internal
+ * {@link XMLEventReader} created from an {@link InputStream} or directly from an {@link URL}.
  */
 public class StAXGenerator extends AbstractStAXProducer implements Starter {
 
     private XMLEventReader reader;
 
     /**
-     * Creating an {@link StAXGenerator} with an {@link XMLEventReader} from an
-     * {@link InputStream}.
+     * Creating an {@link StAXGenerator} with an {@link XMLEventReader} from an {@link InputStream}.
      * 
-     * @param inputStream
-     *            from which a {@link XMLEventReader} is produced read from
-     *            during the {@link StAXGenerator#execute()} method call.
-     * @throws SetupException
-     *             if any error occurred during the creation of the
+     * @param inputStream from which a {@link XMLEventReader} is produced read from during the
+     *            {@link StAXGenerator#execute()} method call.
+     * @throws SetupException if any error occurred during the creation of the
      *             {@link XMLEventReader}.
      */
     public StAXGenerator(InputStream inputStream) {

Added: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXPipelineComponent.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXPipelineComponent.java?rev=740500&view=auto
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXPipelineComponent.java (added)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXPipelineComponent.java Tue Feb  3 22:51:56 2009
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you 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.cocoon.stax;
+
+import javax.xml.stream.events.XMLEvent;
+
+import org.apache.cocoon.pipeline.component.PipelineComponent;
+
+/**
+ * This is a component used in a StAX pipeline.<br>
+ * A pipeline component consuming and/or producing {@link XMLEvent}s should implement this marker
+ * interface.
+ */
+public interface StAXPipelineComponent extends PipelineComponent {
+
+}

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXPipelineComponent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXPipelineComponent.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXPipelineComponent.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXProducer.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXProducer.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXProducer.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXProducer.java Tue Feb  3 22:51:56 2009
@@ -16,8 +16,6 @@
  */
 package org.apache.cocoon.stax;
 
-import java.util.NoSuchElementException;
-
 import javax.xml.stream.XMLEventReader;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.events.XMLEvent;
@@ -25,39 +23,31 @@
 import org.apache.cocoon.pipeline.component.Producer;
 
 /**
- * Extension of the cocoon {@link Producer} element for all StAX specific
- * components. This interface extends the base {@link Producer} with three
- * methods directly taken from the {@link XMLEventReader} interface which are
- * required to implement an StAX component.
+ * Extension of the cocoon {@link Producer} element for all StAX specific components. This interface
+ * extends the base {@link Producer} with three methods directly taken from the
+ * {@link XMLEventReader} interface which are required to implement an StAX component.
  */
-public interface StAXProducer extends Producer {
+public interface StAXProducer extends Producer, StAXPipelineComponent {
 
     /**
-     * Check the next XMLEvent without reading it from the stream. Returns null
-     * if the stream is at EOF or has no more XMLEvents. A call to peek() will
-     * be equal to the next return of next().
+     * Check the next XMLEvent without reading it from the stream. Returns null if the stream is at
+     * EOF or has no more XMLEvents. A call to peek() will be equal to the next return of next().
      * 
      * @see XMLEvent
-     * @throws XMLStreamException
      */
     public XMLEvent peek() throws XMLStreamException;
 
     /**
-     * Check if there are more events. Returns true if there are more events and
-     * false otherwise.
+     * Check if there are more events. Returns true if there are more events and false otherwise.
      * 
      * @return true if the event reader has more events, false otherwise
      */
-    public boolean hasNext();
+    public boolean hasNext() throws XMLStreamException;
 
     /**
      * Get the next XMLEvent
      * 
      * @see XMLEvent
-     * @throws XMLStreamException
-     *             if there is an error with the underlying XML.
-     * @throws NoSuchElementException
-     *             iteration has no more elements.
      */
     public XMLEvent nextEvent() throws XMLStreamException;
 }

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXSerializer.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXSerializer.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXSerializer.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/StAXSerializer.java Tue Feb  3 22:51:56 2009
@@ -29,15 +29,13 @@
 import org.apache.cocoon.pipeline.component.Finisher;
 
 /**
- * Standard implementation of the cocoon {@link Finisher} for StAX pipelines.
- * This pipeline pushes all events through the pipeline and write them to an
- * {@link XMLEventWriter} created from an {@link OutputStream} inserted in the
- * {@link Finisher#setOutputStream(OutputStream)}.
+ * Standard implementation of the cocoon {@link Finisher} for StAX pipelines. This pipeline pushes
+ * all events through the pipeline and write them UTF-8 encoded to an {@link XMLEventWriter} created
+ * from an {@link OutputStream} inserted in the {@link Finisher#setOutputStream(OutputStream)}.
  */
 public class StAXSerializer extends AbstractPipelineComponent implements StAXConsumer, Finisher {
 
     private StAXProducer parent;
-
     private XMLEventWriter writer;
 
     /**
@@ -48,7 +46,7 @@
     @Override
     public void setOutputStream(OutputStream outputStream) {
         try {
-            this.writer = XMLOutputFactory.newInstance().createXMLEventWriter(outputStream);
+            this.writer = XMLOutputFactory.newInstance().createXMLEventWriter(outputStream, "UTF-8");
         } catch (XMLStreamException e) {
             throw new SetupException("Error during setup an XMLEventWriter on the outputStream", e);
         } catch (FactoryConfigurationError e) {
@@ -63,12 +61,12 @@
      */
     @Override
     public void initiatePullProcessing() {
-        while (this.parent.hasNext()) {
-            try {
+        try {
+            while (this.parent.hasNext()) {
                 this.writer.add(this.parent.nextEvent());
-            } catch (XMLStreamException e) {
-                throw new ProcessingException("Error during writing output elements.", e);
             }
+        } catch (XMLStreamException e) {
+            throw new ProcessingException("Error during writing output elements.", e);
         }
 
         try {

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindCorrespondingStartEndElementPairNavigator.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindCorrespondingStartEndElementPairNavigator.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindCorrespondingStartEndElementPairNavigator.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindCorrespondingStartEndElementPairNavigator.java Tue Feb  3 22:51:56 2009
@@ -50,7 +50,7 @@
 public class FindCorrespondingStartEndElementPairNavigator implements Navigator {
 
     private String name;
-    private List<Attribute> attributes = new ArrayList<Attribute>();
+    private List<Attribute> attributes = new ArrayList<Attribute>();;
     private List<String> levelRememberer = new ArrayList<String>();
     private int count = 0;
     private boolean active;

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindEndElementNavigator.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindEndElementNavigator.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindEndElementNavigator.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindEndElementNavigator.java Tue Feb  3 22:51:56 2009
@@ -29,13 +29,11 @@
 
 /**
  * This implementation of the {@link Navigator} returns true of
- * {@link Navigator#fulfillsCriteria(XMLEvent)} any time it is called with a
- * {@link EndElement} full filling all conditions the {@link Navigator} was
- * created with.
+ * {@link Navigator#fulfillsCriteria(XMLEvent)} any time it is called with a {@link EndElement} full
+ * filling all conditions the {@link Navigator} was created with.
  * <p>
- * The "partner" of this {@link Navigator} is the
- * {@link FindStartElementNavigator} working exactly as the
- * {@link FindEndElementNavigator} for the {@link StartElement}.
+ * The "partner" of this {@link Navigator} is the {@link FindStartElementNavigator} working exactly
+ * as the {@link FindEndElementNavigator} for the {@link StartElement}.
  * 
  * <pre>
  * &lt;anyElement&gt; -&gt; false
@@ -88,9 +86,7 @@
                 this.active = false;
                 return this.active;
             }
-
             this.count++;
-
             for (Attribute attribute : this.attributes) {
                 if (!attribute.getValue().equals(element.getAttributeByName(attribute.getName()).getValue())) {
                     this.active = false;
@@ -98,7 +94,6 @@
                 }
             }
             this.levelRememberer.add(String.valueOf(this.count));
-
             this.active = false;
             return this.active;
         } else if (event.isEndElement()) {

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindStartElementNavigator.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindStartElementNavigator.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindStartElementNavigator.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/FindStartElementNavigator.java Tue Feb  3 22:51:56 2009
@@ -18,7 +18,10 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.xml.stream.events.Attribute;
 import javax.xml.stream.events.EndElement;
@@ -29,13 +32,13 @@
 
 /**
  * This implementation of the {@link Navigator} returns true of
- * {@link Navigator#fulfillsCriteria(XMLEvent)} any time it is called with a
- * {@link StartElement} full filling all conditions the {@link Navigator} was
- * created with.
+ * {@link Navigator#fulfillsCriteria(XMLEvent)} any time it is called with a {@link StartElement}
+ * full filling all conditions the {@link Navigator} was created with. There is also the possibility
+ * start the {@link Navigator} with a regex expression. For default regex is not activated for the
+ * sake of speed.
  * <p>
- * The "partner" of this {@link Navigator} is the
- * {@link FindEndElementNavigator} working exactly as the
- * {@link FindStartElementNavigator} for the {@link EndElement}.
+ * The "partner" of this {@link Navigator} is the {@link FindEndElementNavigator} working exactly as
+ * the {@link FindStartElementNavigator} for the {@link EndElement}.
  * 
  * <pre>
  * &lt;anyElement&gt; -&gt; false
@@ -51,13 +54,14 @@
     private String name;
     private List<Attribute> attributes = new ArrayList<Attribute>();
     private boolean active;
+    private MatchingType matchingType = MatchingType.StringMatch;
 
     public FindStartElementNavigator(String name) {
         this.name = name;
     }
 
     public FindStartElementNavigator(String name, List<Attribute> attributes) {
-        this.name = name;
+        this(name);
 
         if (attributes != null) {
             this.attributes = attributes;
@@ -65,38 +69,90 @@
     }
 
     public FindStartElementNavigator(String name, Attribute... attributes) {
-        this.name = name;
+        this(name);
 
         if (attributes != null) {
             this.attributes = new ArrayList<Attribute>(Arrays.asList(attributes));
         }
     }
 
+    public FindStartElementNavigator(String name, MatchingType matchingType, List<Attribute> attributes) {
+        this(name, attributes);
+
+        this.matchingType = matchingType;
+    }
+
+    public FindStartElementNavigator(String name, MatchingType matchingType, Attribute... attributes) {
+        this(name, attributes);
+
+        this.matchingType = matchingType;
+    }
+
     /**
      * {@inheritDoc}
      * 
      * @see Pipeline#fulfillsCriteria(XMLEvent)
      */
+    @SuppressWarnings("unchecked")
     @Override
     public boolean fulfillsCriteria(XMLEvent event) {
         if (event.isStartElement()) {
             StartElement element = (StartElement) event;
-            if (!element.getName().getLocalPart().equals(this.name)) {
+
+            boolean nameMatches = false;
+
+            switch (this.matchingType) {
+            case RegexMatch:
+                nameMatches = Pattern.compile(this.name).matcher(element.getName().getLocalPart()).matches();
+                break;
+            default:
+                nameMatches = element.getName().getLocalPart().equals(this.name);
+
+            }
+
+            if (!nameMatches) {
                 this.active = false;
                 return this.active;
             }
 
             for (Attribute attribute : this.attributes) {
-                if (!attribute.getValue().equals(element.getAttributeByName(attribute.getName()).getValue())) {
-                    this.active = false;
-                    return this.active;
+                switch (this.matchingType) {
+                case RegexMatch:
+                    boolean elementMatches = false;
+                    Pattern namePattern = Pattern.compile(attribute.getName().getLocalPart());
+                    Pattern valuePattern = Pattern.compile(attribute.getValue());
+
+                    Iterator<Attribute> elementAttributeIter = element.getAttributes();
+                    while (elementAttributeIter.hasNext()) {
+                        Attribute elementAttribute = elementAttributeIter.next();
+
+                        Matcher nameMatcher = namePattern.matcher(elementAttribute.getName().getLocalPart());
+                        Matcher valueMatcher = valuePattern.matcher(elementAttribute.getValue());
+
+                        if (nameMatcher.matches() && valueMatcher.matches()) {
+                            elementMatches = true;
+                            break;
+                        }
+                    }
+
+                    if (!elementMatches) {
+                        this.active = false;
+                        return this.active;
+                    }
+
+                    break;
+                default:
+                    Attribute foundAttribute = element.getAttributeByName(attribute.getName());
+                    if (foundAttribute == null || !attribute.getValue().equals(foundAttribute.getValue())) {
+                        this.active = false;
+                        return this.active;
+                    }
                 }
             }
 
             this.active = true;
             return this.active;
         }
-
         this.active = false;
         return this.active;
     }

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/InSubtreeNavigator.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/InSubtreeNavigator.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/InSubtreeNavigator.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/InSubtreeNavigator.java Tue Feb  3 22:51:56 2009
@@ -18,7 +18,10 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.xml.stream.events.Attribute;
 import javax.xml.stream.events.EndElement;
@@ -28,15 +31,13 @@
 import org.apache.cocoon.pipeline.Pipeline;
 
 /**
- * This {@link Navigator} implementation returns true as long it is in an opened
- * clause. The navigator starts the moment an {@link XMLEvent} is a
- * {@link StartElement} and matches all {@link Attribute}s and the name the
- * {@link Navigator} is initialized with. The moment the corresponding
- * {@link EndElement} is inserted the {@link Navigator} returns false. If the
- * same element is contained nested more often the {@link Navigator} starts
- * returning true the first element is inserted to the
- * {@link Navigator#fulfillsCriteria(XMLEvent)} method till exactly this node is
- * closed again with an {@link EndElement}.
+ * This {@link Navigator} implementation returns as long true as long it is in an opened clause. The
+ * navigator starts the moment an {@link XMLEvent} is a {@link StartElement} and matches all
+ * {@link Attribute}s and the name the {@link Navigator} is initialized with. The moment the
+ * corresponding {@link EndElement} is inserted the {@link Navigator} returns false. If the same
+ * element is contained nested more often the {@link Navigator} starts returning true the first
+ * element is inserted to the {@link Navigator#fulfillsCriteria(XMLEvent)} method till exactly this
+ * node is closed again with an {@link EndElement}.
  * 
  * <pre>
  *  &lt;anyElement&gt; -&gt; false
@@ -54,13 +55,14 @@
     private List<Attribute> attributes = new ArrayList<Attribute>();
     private int count = 0;
     private boolean active;
+    private MatchingType matchingType = MatchingType.StringMatch;
 
     public InSubtreeNavigator(String name) {
         this.name = name;
     }
 
     public InSubtreeNavigator(String name, List<Attribute> attributes) {
-        this.name = name;
+        this(name);
 
         if (attributes != null) {
             this.attributes = attributes;
@@ -68,45 +70,110 @@
     }
 
     public InSubtreeNavigator(String name, Attribute... attributes) {
-        this.name = name;
+        this(name);
 
         if (attributes != null) {
             this.attributes = new ArrayList<Attribute>(Arrays.asList(attributes));
         }
     }
 
+    public InSubtreeNavigator(String name, MatchingType matchingType, List<Attribute> attributes) {
+        this(name, attributes);
+
+        this.matchingType = matchingType;
+    }
+
+    public InSubtreeNavigator(String name, MatchingType matchingType, Attribute... attributes) {
+        this(name, attributes);
+
+        this.matchingType = matchingType;
+    }
+
     /**
      * {@inheritDoc}
      * 
      * @see Pipeline#fulfillsCriteria(XMLEvent)
      */
+    @SuppressWarnings("unchecked")
     @Override
     public boolean fulfillsCriteria(XMLEvent event) {
         if (event.isStartElement()) {
             StartElement element = (StartElement) event;
-            if (!element.getName().getLocalPart().equals(this.name)) {
+
+            boolean nameMatches = false;
+
+            switch (this.matchingType) {
+            case RegexMatch:
+                nameMatches = Pattern.compile(this.name).matcher(element.getName().getLocalPart()).matches();
+                break;
+            default:
+                nameMatches = element.getName().getLocalPart().equals(this.name);
+
+            }
+
+            if (!nameMatches) {
                 this.active = this.count > 0;
                 return this.count > 0;
             }
+
             if (this.count > 0) {
                 this.count++;
                 this.active = true;
                 return this.active;
             }
+
             for (Attribute attribute : this.attributes) {
-                if (!attribute.getValue().equals(element.getAttributeByName(attribute.getName()).getValue())) {
-                    this.active = false;
-                    return this.active;
+                switch (this.matchingType) {
+                case RegexMatch:
+                    boolean elementMatches = false;
+                    Pattern namePattern = Pattern.compile(attribute.getName().getLocalPart());
+                    Pattern valuePattern = Pattern.compile(attribute.getValue());
+
+                    Iterator<Attribute> elementAttributeIter = element.getAttributes();
+                    while (elementAttributeIter.hasNext()) {
+                        Attribute elementAttribute = elementAttributeIter.next();
+
+                        Matcher nameMatcher = namePattern.matcher(elementAttribute.getName().getLocalPart());
+                        Matcher valueMatcher = valuePattern.matcher(elementAttribute.getValue());
+
+                        if (nameMatcher.matches() && valueMatcher.matches()) {
+                            elementMatches = true;
+                            break;
+                        }
+                    }
+
+                    if (!elementMatches) {
+                        this.active = false;
+                        return this.active;
+                    }
+
+                    break;
+                default:
+                    Attribute foundAttribute = element.getAttributeByName(attribute.getName());
+                    if (foundAttribute == null || !attribute.getValue().equals(foundAttribute.getValue())) {
+                        this.active = false;
+                        return this.active;
+                    }
                 }
             }
 
             this.count++;
-
             this.active = true;
             return this.active;
         } else if (event.isEndElement()) {
             EndElement element = (EndElement) event;
-            if (element.getName().getLocalPart().equals(this.name) && this.count > 0) {
+
+            boolean nameMatches = false;
+
+            switch (this.matchingType) {
+            case RegexMatch:
+                nameMatches = Pattern.compile(this.name).matcher(element.getName().getLocalPart()).matches();
+
+            default:
+                nameMatches = element.getName().getLocalPart().equals(this.name);
+            }
+
+            if (nameMatches && this.count > 0) {
                 this.count--;
                 if (this.count == 0) {
                     this.active = true;
@@ -127,4 +194,12 @@
     public boolean isActive() {
         return this.active;
     }
+
+    public MatchingType getMatchingType() {
+        return this.matchingType;
+    }
+
+    public void setMatchingType(MatchingType matchingType) {
+        this.matchingType = matchingType;
+    }
 }

Added: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/MatchingType.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/MatchingType.java?rev=740500&view=auto
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/MatchingType.java (added)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/MatchingType.java Tue Feb  3 22:51:56 2009
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you 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.cocoon.stax.navigation;
+
+/**
+ * Type used to specify if an input string matches nodes according to exact strings or should be
+ * interpreted in another way.
+ */
+public enum MatchingType {
+    StringMatch, RegexMatch;
+}

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/MatchingType.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/MatchingType.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/MatchingType.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/Navigator.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/Navigator.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/Navigator.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/main/java/org/apache/cocoon/stax/navigation/Navigator.java Tue Feb  3 22:51:56 2009
@@ -23,33 +23,29 @@
 /**
  * Core interface for the navigation system in all StAX transformers.
  * <p>
- * Every navigator does the specific task to classify, according to a number of
- * xml-events, if the position in the tree matches specific values and therefore
- * decides if they are true or false and returns this value.
+ * Every navigator does the specific task to classify, according to a number of StAX events, if the
+ * position in the tree matches specific values and therefore decides if they are true or false and
+ * returns this value.
  */
 public interface Navigator {
 
     /**
-     * Depending on the {@link XMLEvent} it is returned if the navigator full
-     * fills the criteria the {@link Navigator} is build for.
+     * Depending on the {@link XMLEvent} it is returned if the navigator fulfills the criteria the
+     * {@link Navigator} is build for.
      * 
-     * @param event of the xml analysed at the moment.
-     * @return if the {@link XMLEvent} full fills all criteria of the
-     *         {@link Navigator}.
+     * @param event of the XML analyzed at the moment.
+     * @return if the {@link XMLEvent} full fills all criteria of the {@link Navigator}.
      */
     boolean fulfillsCriteria(XMLEvent event);
 
     /**
-     * Every time the {@link Navigator#fulfillsCriteria(XMLEvent)} the value
-     * returned by this method is stored internally in the {@link Navigator}.
-     * As long as the {@link Navigator#fulfillsCriteria(XMLEvent)} method is not
-     * called again this method returns the last returned value of the
-     * {@link Navigator#fulfillsCriteria(XMLEvent)} method. As long the
-     * {@link Navigator#fulfillsCriteria(XMLEvent)} is not called false should
-     * be returned.
+     * Every time the {@link Navigator#fulfillsCriteria(XMLEvent)} the value returned by this method
+     * is stored internally in the {@link Navigator}. As long as the
+     * {@link Navigator#fulfillsCriteria(XMLEvent)} method is not called again this method returns
+     * the last returned value of the {@link Navigator#fulfillsCriteria(XMLEvent)} method. As long
+     * the {@link Navigator#fulfillsCriteria(XMLEvent)} is not called false should be returned.
      * 
-     * @return the actual value returned by the
-     *         {@link Navigator#fulfillsCriteria(XMLEvent)} method.
+     * @return the actual value returned by the {@link Navigator#fulfillsCriteria(XMLEvent)} method.
      */
     boolean isActive();
 }

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/CleaningTransformerTest.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/CleaningTransformerTest.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/CleaningTransformerTest.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/CleaningTransformerTest.java Tue Feb  3 22:51:56 2009
@@ -22,6 +22,7 @@
 import java.io.InputStream;
 
 import org.apache.cocoon.pipeline.NonCachingPipeline;
+import org.apache.cocoon.pipeline.component.PipelineComponent;
 import org.apache.cocoon.pipeline.component.sax.CleaningTransformer;
 import org.apache.cocoon.pipeline.component.sax.StringGenerator;
 import org.apache.cocoon.pipeline.component.sax.XMLSerializer;
@@ -31,29 +32,29 @@
 import org.junit.Test;
 
 /**
- * Contains unit tests for a {@link StAXCleaningTransformer}.<br> * Comparison
- * if SAX and StAX Cleaning Transformer work identically.
+ * Contains unit tests for a {@link StAXCleaningTransformer}.<br> * Compares if SAX and StAX
+ * Cleaning Transformer work identically.
  */
 public class CleaningTransformerTest {
 
     /**
-     * Compares the output of the {@link StAXCleaningTransformer} with the
-     * output of the {@link CleaningTransformer} to show that they process input
-     * data identically.
+     * Compares the output of the {@link StAXCleaningTransformer} with the output of the
+     * {@link CleaningTransformer} to show that they process input data identically.
      * 
-     * @throws Exception Is thrown if an error occurs loading the files or in
-     *             the pipeline itself.
+     * @throws Exception Is thrown if an error occurs loading the files or in the pipeline itself.
      */
     @Test
     public void testCleaningTransformer() throws Exception {
-        ByteArrayOutputStream outputSAX = new ByteArrayOutputStream();
-        NonCachingPipeline pipeSAX = new NonCachingPipeline();
+        // TODO andreas.pieber [2009-01-27] use the correct generic parameter
+        // (SAXPipelineComponent) as soon as the SAX module allows this
+        NonCachingPipeline<PipelineComponent> pipeSAX = new NonCachingPipeline<PipelineComponent>();
         pipeSAX.addComponent(new StringGenerator(IOUtils.toString(CleaningTransformerTest.class.getResource(
-                "/org/apache/cocoon/stax/complex-stax-test-document.xml").openStream())));
+                "/org/apache/cocoon/stax/" + "complex-stax-test-document.xml").openStream())));
 
         pipeSAX.addComponent(new CleaningTransformer());
         pipeSAX.addComponent(new XMLSerializer());
 
+        ByteArrayOutputStream outputSAX = new ByteArrayOutputStream();
         pipeSAX.setup(outputSAX);
         pipeSAX.execute();
 
@@ -65,7 +66,7 @@
 
         ByteArrayOutputStream outputStAX = new ByteArrayOutputStream();
 
-        NonCachingPipeline pipeStAX = new NonCachingPipeline();
+        NonCachingPipeline<StAXPipelineComponent> pipeStAX = new NonCachingPipeline<StAXPipelineComponent>();
         pipeStAX.addComponent(new StAXGenerator(input));
         pipeStAX.addComponent(new StAXCleaningTransformer());
         pipeStAX.addComponent(new StAXSerializer());

Added: cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/IncludeTransformerTest.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/IncludeTransformerTest.java?rev=740500&view=auto
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/IncludeTransformerTest.java (added)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/IncludeTransformerTest.java Tue Feb  3 22:51:56 2009
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you 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.cocoon.stax;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import org.apache.cocoon.pipeline.NonCachingPipeline;
+import org.apache.cocoon.pipeline.Pipeline;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Test;
+
+/**
+ * Contains unit tests for the include transformer.<br>
+ * 
+ * It parses the input document for special include tags, which are replaced with a referenced
+ * documents.
+ */
+public class IncludeTransformerTest {
+
+    /**
+     * Shows a transformer including another document. Since the included document has to be
+     * referenced by an URL, it is copied to a temporary file.
+     * 
+     * @exception Exception Is thrown if an error occurs loading the files or in the pipeline
+     *                itself.
+     */
+    @Test
+    public void testInclude() throws Exception {
+        File input = File.createTempFile("C3STAXINC_INPUT", ".xml");
+        File include = File.createTempFile("C3STAXINC_INCLUDE", ".xml");
+        input.deleteOnExit();
+        include.deleteOnExit();
+
+        IOUtils.copy(IncludeTransformerTest.class.getResourceAsStream("/org/apache/cocoon/stax/file_to_include.xml"),
+                new FileOutputStream(include));
+        String inputSource = IOUtils.toString(
+                IncludeTransformerTest.class.getResourceAsStream("/org/apache/cocoon/stax/includetest_input.xml"))
+                .replaceAll("file_to_include\\.xml", include.toURI().toURL().toString());
+        FileUtils.writeStringToFile(input, inputSource);
+
+        Pipeline<StAXPipelineComponent> pipe = new NonCachingPipeline<StAXPipelineComponent>();
+        pipe.addComponent(new StAXGenerator(new FileInputStream(input)));
+        pipe.addComponent(new IncludeTransformer());
+        pipe.addComponent(new StAXSerializer());
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        pipe.setup(out);
+        pipe.execute();
+        out.close();
+
+        String correctOne = IOUtils.toString(IncludeTransformerTest.class
+                .getResourceAsStream("/org/apache/cocoon/stax/includetest_output.xml"));
+
+        XMLUnit.setIgnoreWhitespace(true);
+        Diff myDiff = new Diff(correctOne.toString(), new String(out.toByteArray()));
+        assertTrue("pieces of XML are similar " + myDiff, myDiff.similar());
+    }
+}

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/IncludeTransformerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/IncludeTransformerTest.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/IncludeTransformerTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/StAXPipelineTest.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/StAXPipelineTest.java?rev=740500&r1=740499&r2=740500&view=diff
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/StAXPipelineTest.java (original)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/StAXPipelineTest.java Tue Feb  3 22:51:56 2009
@@ -24,6 +24,7 @@
 import org.apache.cocoon.pipeline.NonCachingPipeline;
 import org.apache.cocoon.pipeline.Pipeline;
 import org.apache.cocoon.pipeline.SetupException;
+import org.apache.cocoon.pipeline.component.PipelineComponent;
 import org.apache.cocoon.pipeline.component.sax.StringGenerator;
 import org.apache.commons.io.IOUtils;
 import org.custommonkey.xmlunit.Diff;
@@ -31,23 +32,20 @@
 import org.junit.Test;
 
 /**
- * Contains unit tests for testing and presenting the most simple cases for a
- * StAX pipeline.
- * <ul>
- * <li>Communication between a StAX Generator and a StAX Serializer</li>
- * <li>Connection of SAX and StAX Components is detected as error</li>
- * </ul>
+ * Contains unit tests for testing and presenting the most simple cases for a StAX pipeline.<br>
+ * 
+ * Communication between a StAX Generator and a StAX Serializer<br>
+ * Connection of SAX and StAX Components is detected as error
  */
 public class StAXPipelineTest {
 
     /**
-     * Very simple test case loading a simple xml file as input stream, and
-     * starts the most simple pipeline (Generator -> Serializer) on it. Finally
-     * the output is compared to the file used for input. This test should
-     * present the most basic ideas about a StAX pipeline.
+     * Very simple test case loading a simple xml file as input stream, and starts the most simple
+     * pipeline (Generator -> Serializer) on it. Finally the output is compared to the file used for
+     * input. This test should present the most basic ideas about a StAX pipeline.
      * 
-     * @exception Exception Is thrown if an error occurs loading the files or in
-     *                the pipeline itself.
+     * @exception Exception Is thrown if an error occurs loading the files or in the pipeline
+     *                itself.
      */
     @Test
     public void testProducerConsumer() throws Exception {
@@ -55,7 +53,7 @@
 
         ByteArrayOutputStream out = new ByteArrayOutputStream();
 
-        Pipeline pipe = new NonCachingPipeline();
+        Pipeline<StAXPipelineComponent> pipe = new NonCachingPipeline<StAXPipelineComponent>();
         pipe.addComponent(new StAXGenerator(input));
         pipe.addComponent(new StAXSerializer());
         pipe.setup(out);
@@ -71,12 +69,12 @@
     }
 
     /**
-     * Demonstrates that connecting a SAX and a StAX component in the same
-     * pipeline results in a {@link SetupException}.
+     * Demonstrates that connecting a SAX and a StAX component in the same pipeline results in a
+     * {@link SetupException}.
      */
     @Test(expected = SetupException.class)
     public void pipelineWithWrongComponents() {
-        Pipeline pipeline = new NonCachingPipeline();
+        Pipeline<PipelineComponent> pipeline = new NonCachingPipeline<PipelineComponent>();
         pipeline.addComponent(new StringGenerator("<test/>"));
         pipeline.addComponent(new StAXSerializer());
 

Added: cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/DaisyLinkRewriteTransformer.java
URL: http://svn.apache.org/viewvc/cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/DaisyLinkRewriteTransformer.java?rev=740500&view=auto
==============================================================================
--- cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/DaisyLinkRewriteTransformer.java (added)
+++ cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/DaisyLinkRewriteTransformer.java Tue Feb  3 22:51:56 2009
@@ -0,0 +1,356 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you 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.cocoon.stax.sample.src;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+import org.apache.cocoon.pipeline.ProcessingException;
+import org.apache.cocoon.stax.AbstractStAXTransformer;
+import org.apache.cocoon.stax.navigation.FindStartElementNavigator;
+import org.apache.cocoon.stax.navigation.InSubtreeNavigator;
+import org.apache.cocoon.stax.navigation.Navigator;
+
+/**
+ * Rewrite the links of a Daisy publisher document. It shows the easier state management of StAX
+ * components, by having an implicit state through functions, which perform further pulls.
+ */
+public class DaisyLinkRewriteTransformer extends AbstractStAXTransformer {
+
+    private static final String DEFAULT_DATA_URL = "data/{id}/{filename}";
+    private static final String DEFAULT_IMG_URL = "image/{id}/{filename}";
+    private static final String LINK_INFO_EL = "linkInfo";
+    private static final String LINK_PART_INFO_EL = "linkPartInfo";
+    private static final String PUBLISHER_NS = "http://outerx.org/daisy/1.0#publisher";
+
+    private Navigator anchorNavigator = new FindStartElementNavigator("a");
+    private String currentPath;
+    private String dataUrl = DEFAULT_DATA_URL;
+
+    private XMLEventFactory eventFactory = XMLEventFactory.newInstance();
+    private Navigator imageNavigator = new FindStartElementNavigator("img");
+
+    private String imageUrl = DEFAULT_IMG_URL;
+
+    public DaisyLinkRewriteTransformer(String currentPath) {
+        this.currentPath = currentPath;
+    }
+
+    public DaisyLinkRewriteTransformer(String currentPath, String imageUrl, String dataUrl) {
+        this(currentPath);
+
+        this.imageUrl = imageUrl;
+        this.dataUrl = dataUrl;
+    }
+
+    /**
+     * Returns the attribute value of a StartElement or an empty String if there is no such
+     * attribute.
+     * 
+     * @param element the StartElement which has the attribute
+     * @param attributeName the name of the attribute.
+     * @return the value of the attribute or an empty string if there is no such attribute
+     */
+    protected String getAttributeValue(StartElement element, QName attributeName) {
+        Attribute attribute = element.getAttributeByName(attributeName);
+
+        if (attribute != null) {
+            return attribute.getValue();
+        } else {
+            return "";
+        }
+    }
+
+    protected String getAttributeValue(StartElement element, String attributeName) {
+        return this.getAttributeValue(element, new QName(attributeName));
+    }
+
+    protected String getLinkForAttachment(LinkInfo linkInfo) {
+        return this.relativizePath() + this.replaceVariables(this.dataUrl, linkInfo);
+    }
+
+    protected String getLinkForDocument(LinkInfo linkInfo) {
+        return this.relativizePath() + "part/WebpagePartGerman/" + linkInfo.getNavigationPath();
+    }
+
+    protected String getLinkForImage(LinkInfo linkInfo) {
+        return this.relativizePath() + this.replaceVariables(this.imageUrl, linkInfo);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.apache.cocoon.stax.AbstractStAXTransformer#produceEvents()
+     */
+    @Override
+    protected void produceEvents() throws XMLStreamException {
+        while (this.getParent().hasNext()) {
+            XMLEvent event = this.getParent().nextEvent();
+
+            if (this.anchorNavigator.fulfillsCriteria(event) || this.imageNavigator.fulfillsCriteria(event)) {
+                ArrayList<XMLEvent> innerContent = new ArrayList<XMLEvent>();
+                LinkInfo linkInfo = this.collectLinkInfo(innerContent);
+                if (linkInfo != null) {
+                    linkInfo.setNavigationPath(this.getAttributeValue(event.asStartElement(), PUBLISHER_NS,
+                            "navigationPath"));
+                    this.rewriteAttributesAndEmitEvent(event.asStartElement(), linkInfo);
+
+                    if (innerContent.size() != 0) {
+                        this.addAllEventsToQueue(innerContent);
+                    }
+                } else {
+                    this.addEventToQueue(event);
+
+                    if (innerContent.size() != 0) {
+                        this.addAllEventsToQueue(innerContent);
+                    }
+                }
+            } else {
+                this.addEventToQueue(event);
+                return;
+            }
+        }
+    }
+
+    protected String relativizePath() {
+        StringBuilder sb = new StringBuilder();
+
+        int matches = this.countSlashes(this.currentPath);
+        for (int i = 0; i < matches; i++) {
+            sb.append("../");
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Replaces placeholder in the expression with the values of the linkInfo object.
+     * 
+     * @param expression the expression with placeholders
+     * @param linkInfo the linkinfo object with the corresponding values.
+     * @return the expression with the correct values.
+     */
+    protected String replaceVariables(String expression, LinkInfo linkInfo) {
+        expression = expression.replace("{id}", linkInfo.getDocumentId());
+        expression = expression.replace("{filename}", linkInfo.getFileName());
+
+        return expression;
+    }
+
+    /**
+     * Parses the LinkInfo specific tags and assembles a linkInfo object.
+     * 
+     * @param events list for caching non link info specific events.
+     * @return a linkInfo object
+     * @throws XMLStreamException
+     */
+    private LinkInfo collectLinkInfo(List<XMLEvent> events) throws XMLStreamException {
+        Navigator linkInfoNavigator = new InSubtreeNavigator(LINK_INFO_EL);
+        Navigator linkInfoPartNavigator = new FindStartElementNavigator(LINK_PART_INFO_EL);
+        LinkInfo linkInfo = null;
+
+        while (this.getParent().hasNext()) {
+            XMLEvent event = this.getParent().peek();
+
+            if (linkInfoNavigator.fulfillsCriteria(event)) {
+                event = this.getParent().nextEvent();
+                if (linkInfoPartNavigator.fulfillsCriteria(event)) {
+                    if (linkInfo == null) {
+                        throw new ProcessingException(new NullPointerException(
+                                "The LinkInfo object mustn't be null here."));
+                    }
+
+                    String fileName = this.getAttributeValue(event.asStartElement(), "fileName");
+                    if (!"".equals(fileName)) {
+                        linkInfo.setFileName(fileName);
+                    }
+
+                } else if (event.isStartElement()) {
+                    linkInfo = new LinkInfo();
+
+                    StartElement linkInfoEvent = event.asStartElement();
+                    linkInfo.setHref(this.getAttributeValue(linkInfoEvent, "href"));
+                    linkInfo.setSource(this.getAttributeValue(linkInfoEvent, "src"));
+                    String documentType = this.getAttributeValue(linkInfoEvent, "documentType");
+
+                    if (documentType.equals("Attachment")) {
+                        linkInfo.setLinkInfoType(LinkInfoType.ATTACHEMENT);
+                    } else if (documentType.equals("Image")) {
+                        linkInfo.setLinkInfoType(LinkInfoType.IMAGE);
+                    }
+                }
+            } else if (event.isCharacters()) {
+                events.add(this.getParent().nextEvent());
+            } else {
+                return linkInfo;
+            }
+        }
+        return linkInfo;
+    }
+
+    private int countSlashes(String path) {
+        int count = 0;
+
+        for (int i = 0; i < path.length(); i++) {
+            if (path.charAt(i) == '/') {
+                count++;
+            }
+        }
+
+        return count;
+    }
+
+    /**
+     * Creates an attribute from the linkInfo and the localname.
+     * 
+     * @param localName the name of the tag
+     * @param linkInfo the linkInfo, from which the target link is constructed
+     * @return the assembled attribute
+     */
+    private Attribute createAttributeForLinkInfo(String localName, LinkInfo linkInfo) {
+        String value = null;
+
+        if (linkInfo.getLinkInfoType() == LinkInfoType.IMAGE) {
+            value = this.getLinkForImage(linkInfo);
+        } else
+
+        if (linkInfo.getLinkInfoType() == LinkInfoType.ATTACHEMENT) {
+            value = this.getLinkForAttachment(linkInfo);
+        } else {
+            value = this.getLinkForDocument(linkInfo);
+        }
+
+        return this.eventFactory.createAttribute(new QName(localName), value);
+    }
+
+    private String getAttributeValue(StartElement element, String namespace, String attributeName) {
+        return this.getAttributeValue(element, new QName(namespace, attributeName));
+    }
+
+    /**
+     * Rewrites the attribute of the start element with the information of the linkInfo and emits
+     * it.
+     * 
+     * @param event the start element.
+     * @param linkInfo the linkInfo.
+     */
+    private void rewriteAttributesAndEmitEvent(StartElement event, LinkInfo linkInfo) {
+        Iterator<?> oldAttributes = event.getAttributes();
+        Set<Attribute> attributes = new HashSet<Attribute>();
+        while (oldAttributes.hasNext()) {
+            Attribute attribute = (Attribute) oldAttributes.next();
+            // remove the linkinfo attributes
+            if (PUBLISHER_NS.equals(attribute.getName().getNamespaceURI())) {
+                continue;
+            }
+
+            String localName = attribute.getName().getLocalPart();
+            if (localName.equals("href") || localName.equals("src")) {
+                attributes.add(this.createAttributeForLinkInfo(localName, linkInfo));
+            } else {
+                attributes.add(attribute);
+            }
+
+        }
+        this.addEventToQueue(this.eventFactory.createStartElement(event.getName(), attributes.iterator(), event
+                .getNamespaces()));
+    }
+
+    protected static class LinkInfo {
+
+        private String fileName;
+        private String href;
+        private LinkInfoType linkInfoType = LinkInfoType.MISC;
+        private String navigationPath;
+        private String source;
+
+        public String getDocumentId() {
+            if (this.href != null && this.href.startsWith("daisy:")) {
+                return this.href.substring("daisy:".length());
+            }
+
+            if (this.source != null && this.source.startsWith("daisy:")) {
+                return this.source.substring("daisy:".length());
+            }
+
+            return null;
+        }
+
+        public String getFileName() {
+            return this.fileName;
+        }
+
+        public String getHref() {
+            return this.href;
+        }
+
+        public LinkInfoType getLinkInfoType() {
+            return this.linkInfoType;
+        }
+
+        public String getNavigationPath() {
+            return this.navigationPath;
+        }
+
+        public String getSource() {
+            return this.source;
+        }
+
+        public void setFileName(String fileName) {
+            this.fileName = fileName;
+        }
+
+        public void setHref(String href) {
+            this.href = href;
+        }
+
+        public void setLinkInfoType(LinkInfoType linkInfoType) {
+            this.linkInfoType = linkInfoType;
+        }
+
+        public void setNavigationPath(String navigationPath) {
+            if (navigationPath != null && navigationPath.startsWith("/")) {
+                navigationPath = navigationPath.substring(1);
+            }
+            this.navigationPath = navigationPath;
+        }
+
+        public void setSource(String source) {
+            this.source = source;
+        }
+
+        @Override
+        public String toString() {
+            return "LinkInfo[documentId=" + this.getDocumentId() + ", navigationPath=" + this.navigationPath
+                    + ", source=" + this.source + ", href=" + this.href + ", fileName=" + this.fileName + "]";
+        }
+    }
+
+    protected static enum LinkInfoType {
+        ATTACHEMENT, IMAGE, MISC
+    }
+}

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/DaisyLinkRewriteTransformer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/DaisyLinkRewriteTransformer.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/cocoon3/trunk/cocoon-stax/src/test/java/org/apache/cocoon/stax/sample/src/DaisyLinkRewriteTransformer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message