View Javadoc

1   /**
2    * This file Copyright (c) 2003-2010 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.cms.util;
35  
36  import info.magnolia.cms.core.Content;
37  import info.magnolia.cms.core.ItemType;
38  import info.magnolia.cms.core.Content.ContentFilter;
39  
40  import javax.jcr.RepositoryException;
41  import java.util.ArrayList;
42  import java.util.Collection;
43  import java.util.List;
44  
45  /**
46   * A utility class to navigate amongst the siblings of a given node.
47   * This is not synchronized.
48   *
49   * @author gjoseph
50   * @version $Revision: $ ($Author: $)
51   */
52  public class SiblingsHelper {
53      /**
54       * Instantiates a SiblingsHelper representing the siblings of the given node and of the same type.
55       */
56      public static SiblingsHelper of(Content node) throws RepositoryException {
57          return new SiblingsHelper(node, filterForTypeOf(node));
58      }
59  
60      /**
61       * Instantiates a SiblingsHelper representing the children of the given node,
62       * where the current node is the first child of the same type as its parent.
63       */
64      public static SiblingsHelper childrenOf(Content parent) throws RepositoryException {
65          return childrenOf(parent, parent.getItemType());
66      }
67  
68      /**
69       * Instantiates a SiblingsHelper representing the children of the given node,
70       * where the current node is the first child of given type.
71       */
72      public static SiblingsHelper childrenOf(Content parent, ItemType childType) throws RepositoryException {
73          final NodeTypeFilter filter = new NodeTypeFilter(childType);
74          return childrenOf(parent, filter);
75      }
76  
77      /**
78       * Instantiates a SiblingsHelper representing the children of the given node,
79       * where the current node is the first child from all that pass the filter.
80       */
81      public static SiblingsHelper childrenOf(Content parent, ContentFilter filter) throws RepositoryException {
82          final Collection<Content> children = parent.getChildren(filter);
83          if (children.size() < 1) {
84              throw new IllegalStateException(parent + " has no children for " + filter);
85          }
86          final Content firstChild = children.iterator().next();
87          return new SiblingsHelper(firstChild, filter);
88      }
89  
90      private static NodeTypeFilter filterForTypeOf(Content node) throws RepositoryException {
91          final ItemType type = node.getItemType();
92          return new NodeTypeFilter(type);
93      }
94  
95      private final List<Content> siblings;
96      private final int lastIndex;
97      private Content current = null;
98      private int currentIndex = -1;
99  
100     private SiblingsHelper(Content node, Content.ContentFilter filter) throws RepositoryException {
101         this.siblings = new ArrayList<Content>(node.getParent().getChildren(filter));
102         this.lastIndex = siblings.size() - 1;
103         this.current = node;
104         // can't use indexOf to determine current index, as getParent().getChildren() returns a different instance of the node
105         for (int i = 0; i <= lastIndex; i++) {
106             final Content c = siblings.get(i);
107             if (c.getUUID().equals(current.getUUID())) {
108                 this.currentIndex = i;
109                 break;
110             }
111         }
112         if (currentIndex < 0) {
113             throw new IllegalStateException("Given node not found in its own siblings.");
114         }
115     }
116 
117     // next() and prev() are not called getNext() and getPrevious() because they change the state.
118     public Content next() {
119         // TODO : check if iterator hasNext();
120         this.currentIndex = currentIndex + 1;
121         this.current = siblings.get(currentIndex);
122         return current;
123     }
124 
125     public Content prev() {
126         // TODO : check if hasPrevious();
127         this.currentIndex = currentIndex - 1;
128         this.current = siblings.get(currentIndex);
129         return current;
130     }
131 
132     public Content goTofirst() {
133         this.currentIndex = 0;
134         this.current = siblings.get(currentIndex);
135         return current;
136     }
137 
138     public Content goTolast() {
139         this.currentIndex = siblings.size() - 1;
140         this.current = siblings.get(currentIndex);
141         return current;
142     }
143 
144     public Content getCurrent() {
145         return current;
146     }
147 
148     /**
149      * Returns the zero-based index of the current node.
150      */
151     public int getIndex() {
152         return currentIndex;
153     }
154 
155     public boolean isFirst() {
156         return currentIndex == 0;
157     }
158 
159     public boolean isLast() {
160         return currentIndex == lastIndex;
161     }
162 
163 }