Author: rgardler
Date: Tue Nov 21 04:05:30 2006
New Revision: 477642

URL: http://svn.apache.org/viewvc?view=rev&rev=477642
Log:
Instroduce an AggregateSourceDocument to facilitate document aggregation.
It doesn't do anything yet, I needed to bring it in at this point to make
optional source documents work.

Added:
    
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/document/AggregatedSourceDocument.java
   (with props)
Modified:
    
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/Controller.java
    
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/IController.java
    
forrest/trunk/whiteboard/forrest2/core/src/test/org/apache/forrest/test/core/TestController.java

Modified: 
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/Controller.java
URL: 
http://svn.apache.org/viewvc/forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/Controller.java?view=diff&rev=477642&r1=477641&r2=477642
==============================================================================
--- 
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/Controller.java
 (original)
+++ 
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/Controller.java
 Tue Nov 21 04:05:30 2006
@@ -23,12 +23,14 @@
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.forrest.core.document.AbstractOutputDocument;
 import org.apache.forrest.core.document.AbstractSourceDocument;
 import org.apache.forrest.core.document.AggregateInteralDocument;
+import org.apache.forrest.core.document.AggregatedSourceDocument;
 import org.apache.forrest.core.document.DefaultOutputDocument;
 import org.apache.forrest.core.document.IDocument;
 import org.apache.forrest.core.document.InternalDocument;
@@ -69,7 +71,7 @@
 
        private final Map<URI, List<Location>> sourceLocationsCache = new 
HashMap<URI, List<Location>>();
 
-       private final Map<URI, List<AbstractSourceDocument>> sourceDocsCache = 
new HashMap<URI, List<AbstractSourceDocument>>();
+       private final Map<URI, AbstractSourceDocument> sourceDocsCache = new 
HashMap<URI, AbstractSourceDocument>();
 
        private final Map<URI, List<InternalDocument>> internalDocsCache = new 
HashMap<URI, List<InternalDocument>>();
 
@@ -148,8 +150,7 @@
                this.sourceLocationsCache.put(requestURI, sourceLocs);
 
                final List<AbstractSourceDocument> sourceDocs = this
-                               .loadSourceDocuments(requestURI, sourceLocs);
-               this.sourceDocsCache.put(requestURI, sourceDocs);
+                               .loadAllSourceDocuments(requestURI, sourceLocs);
 
                final List<InternalDocument> internalDocs = this
                                .processInputPlugins(sourceDocs);
@@ -167,7 +168,7 @@
         * 
         * @param sourceDocuments
         * @throws IOException
-        * @throws ProcessingException 
+        * @throws ProcessingException
         */
        private List<InternalDocument> processInputPlugins(
                        final List<AbstractSourceDocument> sourceDocuments)
@@ -177,7 +178,8 @@
                for (int i = 0; i < sourceDocuments.size(); i++) {
                        final AbstractSourceDocument doc = 
sourceDocuments.get(i);
                        if (doc == null) {
-                               throw new ProcessingException("No source 
document is available.");
+                               throw new ProcessingException(
+                                               "No source document is 
available.");
                        }
                        AbstractInputPlugin plugin = getInputPlugin(doc);
                        results.add((InternalDocument) plugin.process(doc));
@@ -249,7 +251,7 @@
        }
 
        /**
-        * Load each of the source documents.
+        * Load each of the source documents into the docuemnt cache.
         * 
         * @throws MalformedURLException
         * @throws ProcessingException
@@ -258,20 +260,44 @@
         * @fixme handle document types other than HTML
         * @fixme resource handlers should be provided from a factory class
         */
-       private List<AbstractSourceDocument> loadSourceDocuments(
-                       URI requestURI, final List<Location> sourceLocations) 
throws MalformedURLException,
+       private List<AbstractSourceDocument> loadAllSourceDocuments(URI 
requestURI,
+                       final List<Location> sourceLocations) throws 
MalformedURLException,
                        ProcessingException {
                final List<AbstractSourceDocument> results = new 
ArrayList<AbstractSourceDocument>(
                                sourceLocations.size());
 
                for (int i = 0; i < sourceLocations.size(); i++) {
                        final Location location = sourceLocations.get(i);
-                       IReader reader = getReader(location);
-                       results.add(reader.read(this, requestURI, location));
+                       AbstractSourceDocument doc = 
loadSourceDocument(requestURI,
+                                       location);
+                       results.add(doc);
                }
                return results;
        }
 
+       private AbstractSourceDocument loadSourceDocument(URI requestURI,
+                       final Location location) throws ProcessingException,
+                       MalformedURLException {
+               AbstractSourceDocument doc = sourceDocsCache.get(requestURI);
+               if (doc == null) {
+                       IReader reader = getReader(location);
+                       doc = reader.read(this, requestURI, location);
+                       addToSourceDocCache(requestURI, doc);
+               }
+               return doc;
+       }
+
+       private void addToSourceDocCache(URI requestURI, AbstractSourceDocument 
doc) {
+               AbstractSourceDocument sourceDoc = 
sourceDocsCache.get(requestURI);
+               if (sourceDoc instanceof AggregatedSourceDocument) {
+                       AggregatedSourceDocument aggDoc = 
(AggregatedSourceDocument) sourceDoc;
+                       if (!aggDoc.contains(doc)) {
+                               aggDoc.add(doc);
+                       }
+               }
+               this.sourceDocsCache.put(requestURI, doc);
+       }
+
        /*
         * (non-Javadoc)
         * 
@@ -290,25 +316,69 @@
        }
 
        /**
-        * Resolve the input documents for a given request.
+        * Resolve the source locations for a given request. The result is a 
list of
+        * locations that make up the source document. If the list contains a 
single
+        * location then the document will be read. If it contains multiple
+        * locations they will be aggregated into a single document.
         * 
         * @param requestURI
         * @return
         * @throws LocationmapException
         * @throws MalformedURLException
         *             if the Request URI is not valid
+        * @throws ProcessingException
         * @FIXME handle fall through if the first location is not correct
         */
        private List<Location> resolveSources(final URI requestURI)
-                       throws LocationmapException, MalformedURLException {
+                       throws LocationmapException, MalformedURLException,
+                       ProcessingException {
                final List<List<Location>> possibleLocs = this.locationMap
                                .get(requestURI);
                if (possibleLocs == null || possibleLocs.size() == 0)
                        throw new LocationmapException(
                                        "Unable to find a source location for " 
+ requestURI);
-               // TODO: we need to test for the validity of a location and 
return the
-               // first matching one instead of returning the first location 
regardless
-               return possibleLocs.get(0);
+
+               List<Location> result = new ArrayList<Location>();
+               Boolean isValid = false;
+               for (List<Location> locs : possibleLocs) {
+                       result = new ArrayList<Location>();
+                       isValid = true;
+                       Iterator<Location> sourceLocs = locs.iterator();
+                       Location loc;
+                       while (sourceLocs.hasNext() && isValid) {
+                               loc = sourceLocs.next();
+                               if (sourceExists(requestURI, loc)) {
+                                       result.add(loc);
+                               } else {
+                                       if (loc.isRequired()) {
+                                               isValid = false;
+                                       }
+                               }
+                       }
+                       if (isValid)
+                               break;
+               }
+               if (!isValid) {
+                       throw new ProcessingException(
+                                       "Unable to find a valid source location 
for "
+                                                       + 
requestURI.toASCIIString());
+               }
+               return result;
+       }
+
+       /**
+        * Test to see if a given source document exists.
+        * 
+        * @param loc
+        * @return
+        * @throws ProcessingException
+        * @throws MalformedURLException
+        * @TODO we need a more efficient test for existence.
+        */
+       private boolean sourceExists(URI requestURI, Location location)
+                       throws MalformedURLException, ProcessingException {
+               AbstractSourceDocument doc = loadSourceDocument(requestURI, 
location);
+               return doc != null;
        }
 
        /*
@@ -331,20 +401,19 @@
         * 
         * @see 
org.apache.forrest.core.IController#getSourceDocuments(java.net.URI)
         */
-       public List<AbstractSourceDocument> getSourceDocuments(final URI 
requestURI)
+       public AbstractSourceDocument getSourceDocuments(final URI requestURI)
                        throws MalformedURLException, ProcessingException {
-               List<AbstractSourceDocument> sources = this.sourceDocsCache
-                               .get(requestURI);
-               if (sources == null)
+               AbstractSourceDocument source = 
this.sourceDocsCache.get(requestURI);
+               if (source == null)
                        try {
                                this.processRequest(requestURI);
-                               sources = this.sourceDocsCache.get(requestURI);
+                               source = this.sourceDocsCache.get(requestURI);
                        } catch (final Exception e) {
                                throw new ProcessingException(
                                                "Unable to retrieve the source 
documents for "
                                                                + requestURI, 
e);
                        }
-               return sources;
+               return source;
        }
 
        /*
@@ -377,19 +446,17 @@
        public AbstractOutputDocument getOutputDocument(final URI requestURI)
                        throws MalformedURLException, ProcessingException {
                if (requestURI.getPath().endsWith(this.sourceURLExtension)) {
-                       final List<AbstractSourceDocument> sources = this
+                       final AbstractSourceDocument doc = this
                                        .getSourceDocuments(requestURI);
                        final StringBuffer content = new StringBuffer();
-                       for (final AbstractSourceDocument doc : sources) {
-                               try {
-                                       
content.append(doc.getContentAsString());
-                               } catch (final IOException e) {
-                                       content
-                                                       .append("<error>Unable 
to read source document for ");
-                                       content.append(requestURI);
-                                       content.append("</error>");
-                               }
+                       try {
+                               content.append(doc.getContentAsString());
+                       } catch (final IOException e) {
+                               content.append("<error>Unable to read source 
document for ");
+                               content.append(requestURI);
+                               content.append("</error>");
                        }
+
                        final DefaultOutputDocument output = new 
DefaultOutputDocument(
                                        content.toString());
                        return output;

Modified: 
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/IController.java
URL: 
http://svn.apache.org/viewvc/forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/IController.java?view=diff&rev=477642&r1=477641&r2=477642
==============================================================================
--- 
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/IController.java
 (original)
+++ 
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/IController.java
 Tue Nov 21 04:05:30 2006
@@ -45,7 +45,7 @@
         * @throws MalformedURLException
         * @throws IOException
         */
-       public abstract List<AbstractSourceDocument> getSourceDocuments(
+       public abstract AbstractSourceDocument getSourceDocuments(
                        final URI requestURI) throws MalformedURLException,
                        ProcessingException;
 

Added: 
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/document/AggregatedSourceDocument.java
URL: 
http://svn.apache.org/viewvc/forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/document/AggregatedSourceDocument.java?view=auto&rev=477642
==============================================================================
--- 
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/document/AggregatedSourceDocument.java
 (added)
+++ 
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/document/AggregatedSourceDocument.java
 Tue Nov 21 04:05:30 2006
@@ -0,0 +1,53 @@
+/*
+ * 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.forrest.core.document;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * An aggregated source document is used to represent
+ * a source document that consists of a number of 
+ * separate documents.
+ * 
+ */
+public class AggregatedSourceDocument extends AbstractSourceDocument {
+
+       List<AbstractSourceDocument> docs = new 
ArrayList<AbstractSourceDocument>();
+
+       /**
+        * Look to see if this aggregation of documents contains
+        * a specificed document.
+        * 
+        * @param doc
+        * @return
+        */
+       public boolean contains(AbstractSourceDocument doc) {
+               return docs.contains(doc);
+       }
+
+       /**
+        * Add a document to the aggregated documents list.
+        * @param doc
+        */
+       public boolean add(AbstractSourceDocument doc) {
+               return docs.add(doc);
+       }
+       
+}
\ No newline at end of file

Propchange: 
forrest/trunk/whiteboard/forrest2/core/src/core/org/apache/forrest/core/document/AggregatedSourceDocument.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
forrest/trunk/whiteboard/forrest2/core/src/test/org/apache/forrest/test/core/TestController.java
URL: 
http://svn.apache.org/viewvc/forrest/trunk/whiteboard/forrest2/core/src/test/org/apache/forrest/test/core/TestController.java?view=diff&rev=477642&r1=477641&r2=477642
==============================================================================
--- 
forrest/trunk/whiteboard/forrest2/core/src/test/org/apache/forrest/test/core/TestController.java
 (original)
+++ 
forrest/trunk/whiteboard/forrest2/core/src/test/org/apache/forrest/test/core/TestController.java
 Tue Nov 21 04:05:30 2006
@@ -28,6 +28,7 @@
 import org.apache.forrest.core.IController;
 import org.apache.forrest.core.document.AbstractOutputDocument;
 import org.apache.forrest.core.document.AbstractSourceDocument;
+import org.apache.forrest.core.document.AggregatedSourceDocument;
 import org.apache.forrest.core.document.InternalDocument;
 import org.apache.forrest.core.exception.LocationmapException;
 import org.apache.forrest.core.exception.ProcessingException;
@@ -82,9 +83,9 @@
 
        public void testSourceDocuments() throws IOException, 
ProcessingException,
                        URISyntaxException {
-               final List<AbstractSourceDocument> documents = this.controller
+               final AbstractSourceDocument document = this.controller
                                .getSourceDocuments(new URI(XHTML_REQUEST_URI));
-               assertNotNull(documents);
+               assertNotNull(document);
                // AbstractSourceDocument firstDoc = documents.get(0);
                // AbstractSourceDocument secondDoc = documents.get(1);
                // assertFalse(firstDoc.equals(secondDoc));
@@ -92,17 +93,13 @@
 
        public void testInternalDocuments() throws IOException,
                        ProcessingException, URISyntaxException {
-               final List<AbstractSourceDocument> srcDocs = this.controller
+               final AbstractSourceDocument srcDoc = this.controller
                                .getSourceDocuments(new URI(XHTML_REQUEST_URI));
                final List<InternalDocument> internalDocs = this.controller
                                .getInternalDocuments(new 
URI(XHTML_REQUEST_URI));
-               final AbstractSourceDocument firstSrcDoc = srcDocs.get(0);
-               // AbstractSourceDocument secondSrcDoc = srcDocs.get(1);
+               final AbstractSourceDocument firstSrcDoc = srcDoc;
                final InternalDocument firstIntDoc = internalDocs.get(0);
-               // InternalDocument secondIntDoc = internalDocs.get(1);
                assertFalse(firstSrcDoc.equals(firstIntDoc));
-               // assertFalse(secondSrcDoc.equals(secondIntDoc));
-               // assertFalse(firstIntDoc.equals(secondIntDoc));
        }
 
        public void testProcessRequest() throws IOException, 
ProcessingException,
@@ -118,14 +115,13 @@
 
        public void testReader() throws ProcessingException, 
MalformedURLException,
                        URISyntaxException {
-               final List<AbstractSourceDocument> source = this.controller
+               final AbstractSourceDocument source = this.controller
                                .getSourceDocuments(new 
URI(HELLO_WORLD_REQUEST_URI));
-               assertEquals(
-                               "Should have a single internal document for 
Hello World request",
-                               1, source.size());
-               final AbstractSourceDocument doc = source.get(0);
+               assertTrue(
+                               "Should not have an aggregated document for 
Hello World request",
+                               ! (source instanceof AggregatedSourceDocument));
                assertEquals("Document type read by Hello world is incorrect",
-                               "org.apache.forrest.helloWorld", doc.getType());
+                               "org.apache.forrest.helloWorld", 
source.getType());
        }
 
        public void testForrestSourceRequest() throws ProcessingException,