Java tutorial
/** * This file Copyright (c) 2008-2012 Magnolia International * Ltd. (http://www.magnolia-cms.com). All rights reserved. * * * This file is dual-licensed under both the Magnolia * Network Agreement and the GNU General Public License. * You may elect to use one or the other of these licenses. * * This file is distributed in the hope that it will be * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. * Redistribution, except as permitted by whichever of the GPL * or MNA you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or * modify this file under the terms of the GNU General * Public License, Version 3, as published by the Free Software * Foundation. You should have received a copy of the GNU * General Public License, Version 3 along with this program; * if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * 2. For the Magnolia Network Agreement (MNA), this file * and the accompanying materials are made available under the * terms of the MNA which accompanies this distribution, and * is available at http://www.magnolia-cms.com/mna.html * * Any modifications to this file must keep this entire header * intact. * */ package info.magnolia.cms.util; import info.magnolia.cms.core.AbstractContent; import info.magnolia.cms.core.Content; import info.magnolia.cms.core.ItemType; import info.magnolia.cms.core.NodeData; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.jcr.PathNotFoundException; import javax.jcr.RepositoryException; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This wrapper inherits content from the parent hierarchy. The method {@link #isAnchor()} defines * the anchor to which the inheritance is performed relative to. By default the anchor is a page * (mgnl:content). * <p> * The inheritance is then performed as follows: * <ul> * <li>try to get the content directly</li> * <li>find next anchor</li> * <li>try to get the content from the anchor</li> * <li>repeat until no anchor can be found anymore (root)</li> * </ul> * <p> * The {@link #getChildren()} methods merge the direct and inherited children by first adding the * inherited children to the collection and then the direct children. * @author pbracher * @version $Id$ */ public class InheritanceContentWrapper extends ContentWrapper { private static Logger log = LoggerFactory.getLogger(InheritanceContentWrapper.class); /** * From where the inheritance started. */ private final Content start; /** * Used if in the {@link #wrap(Content)} method. */ public InheritanceContentWrapper(Content wrappedContent, Content start) { super(wrappedContent); this.start = start; } /** * Starts the inheritance. */ public InheritanceContentWrapper(Content node) { this(node, node); } @Override public boolean hasContent(String name) throws RepositoryException { return getContentSafely(name) != null; } @Override public Content getContent(String name) throws RepositoryException { Content inherited = getContentSafely(name); if (inherited == null) { throw new PathNotFoundException( "Can't inherit a node [" + name + "] on node [" + getWrappedContent().getHandle() + "]"); } return inherited; } @Override public Collection<Content> getChildren(ContentFilter filter, String namePattern, Comparator<Content> orderCriteria) { List<Content> children = new ArrayList<Content>(); // add inherited children try { Content inherited = getContentSafely(findNextAnchor(), resolveInnerPath()); if (inherited != null) { children.addAll(((AbstractContent) inherited).getChildren(filter, namePattern, orderCriteria)); } } catch (RepositoryException e) { throw new RuntimeException("Can't inherit children from " + getWrappedContent(), e); } // add direct children children.addAll(((AbstractContent) getWrappedContent()).getChildren(filter, namePattern, orderCriteria)); if (orderCriteria != null) { Collections.sort(children, orderCriteria); } return wrapContentNodes(children); } /** * Returns the inner path of the this node up to the anchor. */ protected String resolveInnerPath() throws RepositoryException { final String path; InheritanceContentWrapper anchor = findAnchor(); // if no anchor left we are relative to the root if (anchor == null) { path = this.getHandle(); } else { path = StringUtils.substringAfter(this.getHandle(), anchor.getHandle()); } return StringUtils.removeStart(path, "/"); } /** * This method returns null if no content has been found. */ protected Content getContentSafely(String name) throws RepositoryException { if (getWrappedContent().hasContent(name)) { return super.getContent(name); } String innerPath = resolveInnerPath() + "/" + name; innerPath = StringUtils.removeStart(innerPath, "/"); Content inherited = getContentSafely(findNextAnchor(), innerPath); return inherited; } /** * This method returns null if no content has been found. */ protected Content getContentSafely(InheritanceContentWrapper anchor, String path) throws RepositoryException { if (anchor == null) { return null; } if (StringUtils.isEmpty(path)) { return anchor; } return anchor.getContentSafely(path); } /** * Find the anchor for this node. */ protected InheritanceContentWrapper findAnchor() throws RepositoryException { if (getLevel() == 0) { return null; } if (isAnchor()) { return this; } // until the current node is the anchor return ((InheritanceContentWrapper) getParent()).findAnchor(); } /** * Find next anchor. */ protected InheritanceContentWrapper findNextAnchor() throws RepositoryException { final InheritanceContentWrapper currentAnchor = findAnchor(); if (currentAnchor != null && getLevel() > 0) { return ((InheritanceContentWrapper) currentAnchor.getParent()).findAnchor(); } return null; } /** * True if this node is an anchor. By default true if this node is of type mgnl:content (page) */ protected boolean isAnchor() { return isNodeType(ItemType.CONTENT.getSystemName()); } @Override public NodeData getNodeData(String name) { try { if (getWrappedContent().hasNodeData(name)) { return getWrappedContent().getNodeData(name); } Content inherited = getContentSafely(findNextAnchor(), resolveInnerPath()); if (inherited != null) { return inherited.getNodeData(name); } } catch (RepositoryException e) { throw new RuntimeException("Can't inherit nodedata " + name + " for " + getWrappedContent(), e); } // creates a none existing node data in the standard manner return super.getNodeData(name); } @Override public boolean hasNodeData(String name) throws RepositoryException { try { if (getWrappedContent().hasNodeData(name)) { return getWrappedContent().hasNodeData(name); } Content inherited = getContentSafely(findNextAnchor(), resolveInnerPath()); if (inherited != null) { return inherited.hasNodeData(name); } } catch (RepositoryException e) { throw new RuntimeException("Can't inherit nodedata " + name + " for " + getWrappedContent(), e); } // creates a none existing node data in the standard manner return super.hasNodeData(name); } /** * Wrap returned nodes. Sets the inherited flag */ @Override protected Content wrap(Content node) { // only wrap once if (node instanceof InheritanceContentWrapper) { return node; } return new InheritanceContentWrapper(node, start); } /** * True if this is not a sub node of the starting point. */ public boolean isInherited() { return !getWrappedContent().getHandle().startsWith(start.getHandle()); } }