Author: ard
Date: Wed Sep 26 14:03:07 2012
New Revision: 1390497

URL: http://svn.apache.org/viewvc?rev=1390497&view=rev
Log:
RAVE-697 added javadocs how the extends merging works and fixed the 
'allCanonicalPageFragmentsByPath' as currently only the root pages were 
accounted for

Modified:
    
rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/mvc/config/enhancers/ExtendsEnhancer.java

Modified: 
rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/mvc/config/enhancers/ExtendsEnhancer.java
URL: 
http://svn.apache.org/viewvc/rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/mvc/config/enhancers/ExtendsEnhancer.java?rev=1390497&r1=1390496&r2=1390497&view=diff
==============================================================================
--- 
rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/mvc/config/enhancers/ExtendsEnhancer.java
 (original)
+++ 
rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/mvc/config/enhancers/ExtendsEnhancer.java
 Wed Sep 26 14:03:07 2012
@@ -35,28 +35,70 @@ import org.apache.rave.portal.web.mvc.co
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * This class takes care of {@link PageFragment} extensions. When a pag 
fragment has a non-null {@link ExtendablePageFragment#getExtends()}
+ * this class will try to resolve the extension. When extended, the 'extends' 
is set to <code>null</code>.
+ *
+ * For the resolving of extensions, the following steps are implemented
+ *
+ * <ol>
+ *     <li>When some page fragment has an extends, the extended page fragment 
is looked up</li>
+ *     <li>if found, the extends page fragment is merged into the one 
extending it</li>
+ *     <li>merging is done as follows: Assume A extends B, then
+ *         <ol>
+ *             <li>All properties that are on B and not on A are added to 
A</li>
+ *             <li>All child nodes that A and B both have, are merged : The 
properties are merged, and the
+ *             children are merged</li>
+ *             <li>All child nodes from B that A does not have are deep-copied 
to A</li>
+ *         </ol>
+ *     </li>
+ * </ol>
+ * Note that in the above steps, that when merging child nodes, or 
deep-copying child nodes, also all those nodes and
+ * descendants are inspected for the 'extends' property, and when they have 
one, they are first enhanced. Also note that
+ * inheritance of canonical children are done BEFORE inheritance of those 
children.
+ *
+ * This for example assume the following hierarchy:
+ *
+ * <pre>
+ *      FOO
+ *        |-B
+ *        |    `C
+ *         `D
+ *
+ *      BAR (extends FOO)
+ *         `B (extends LUX/B)
+ *
+ *      LUX
+ *        `B
+ *          `C
+ * </pre>
+ *
+ * Then BAR inherits all properties from FOO that it does not have itself. 
Then, B is merged FIRST with the
+ * B from LUX/B, and after that, the result is merged with FOO/B. Then, next, 
D is deep dopied to BAR as well.
+ */
 public class ExtendsEnhancer implements PagesConfigEnhancer {
 
     private final static Logger log = 
LoggerFactory.getLogger(ExtendsEnhancer.class);
 
-    private final Map<String, MutablePageFragment> 
allCanonicalPageFragmentsByPath = new HashMap<String, MutablePageFragment>();
+    
     private final Set<String> alreadyResolved = new HashSet<String>();
 
+    private final Map<String, MutablePageFragment> 
allCanonicalPageFragmentsByPath = new HashMap<String, MutablePageFragment>();
+
     @Override
     public PagesConfig enhance(final PagesConfig pagesConfig) {
         alreadyResolved.clear();
         final Map<String,PageFragment> pages = pagesConfig.getPages();
 
-        // allCanonicalPageFragmentsByPath contains only page fragments that 
are canonical : In other words, only
+        // allCanonicalPageFragmentsByPath contains ALL page fragments that 
are canonical : In other words, only all the
         // fragments that are there BEFORE resolving extensions
         final Map<String, PageFragment> mutablePages = new HashMap<String, 
PageFragment>();
         
         for (PageFragment page : pages.values()) {
-            MutablePageFragment mutablePageFragment = new 
MutablePageFragment((ExtendablePageFragment)page, null);
+            MutablePageFragment mutablePageFragment = new 
MutablePageFragment((ExtendablePageFragment)page, null, 
allCanonicalPageFragmentsByPath);
             mutablePages.put(mutablePageFragment.getName(), 
mutablePageFragment);
-            allCanonicalPageFragmentsByPath.put(mutablePageFragment.getPath(), 
mutablePageFragment);
         }
-        
+
         // start the enhancement by traversing the allPageFragmentsByPath and 
find all the 'extends' and resolve them
         for (PageFragment page : mutablePages.values()) {
             resolveExtensions((MutablePageFragment)page);
@@ -122,7 +164,7 @@ public class ExtendsEnhancer implements 
             MutablePageFragment child = 
fragment.getChild(inheritedChild.getName());
             if (child == null) {
                 // now add to fragment a DEEP COPY from extendsFromChild
-                MutablePageFragment deepCopyChild = new 
MutablePageFragment(inheritedChild, fragment);
+                MutablePageFragment deepCopyChild = new 
MutablePageFragment(inheritedChild, fragment, null);
                 alreadyResolved.add(deepCopyChild.getPath());
                 fragment.addChild(deepCopyChild);
             }
@@ -190,8 +232,12 @@ public class ExtendsEnhancer implements 
          * constructor that creates a deep copy of PageFragments to 
MutablePageFragment's
          * @param fragment the fragment to deep copy
          * @param parent the parent fragment or <code>null</code> for root
+         * @param pageFragmentsByPath when MutablePageFragment needs to be add 
to allCanonicalPageFragmentsByPath this
+         *                                        param is not 
<code>null</code>. Otherwise, it is <code>null</code>
          */
-        private MutablePageFragment(ExtendablePageFragment fragment, 
MutablePageFragment parent) {
+        private MutablePageFragment(final ExtendablePageFragment fragment, 
+                                    final MutablePageFragment parent, 
+                                    final Map<String, MutablePageFragment> 
pageFragmentsByPath) {
             this.viewName = fragment.getViewName();
             this.name = fragment.getName();
             if (parent != null) {
@@ -199,6 +245,9 @@ public class ExtendsEnhancer implements 
             } else {
                 path = fragment.getName();
             }
+            if (pageFragmentsByPath != null) {
+                pageFragmentsByPath.put(path, this);
+            }
             this.parent = parent;
             this.description = fragment.getDescription();
             this.controller = fragment.getController();
@@ -209,7 +258,7 @@ public class ExtendsEnhancer implements 
                 // use LinkedHashMap to maintain order
                 children = new LinkedHashMap<String, 
MutablePageFragment>(fragment.getChildren().size());
                 for (PageFragment child : fragment.getChildren()) {
-                    MutablePageFragment mutableChild = new 
MutablePageFragment((ExtendablePageFragment)child, this);
+                    MutablePageFragment mutableChild = new 
MutablePageFragment((ExtendablePageFragment)child, this, pageFragmentsByPath);
                     children.put(mutableChild.getName(), mutableChild);
                 }
             }


Reply via email to