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);
}
}