View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors.
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   * 
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.jcr;
25  
26  import java.util.ArrayList;
27  import java.util.Calendar;
28  import java.util.List;
29  import javax.jcr.ItemNotFoundException;
30  import javax.jcr.Property;
31  import javax.jcr.RepositoryException;
32  import javax.jcr.Value;
33  import javax.jcr.version.Version;
34  import org.modeshape.graph.property.Name;
35  
36  /**
37   * Convenience wrapper around a version {@link JcrNode node}.
38   */
39  class JcrVersionNode extends JcrNode implements Version {
40  
41      private static final Version[] EMPTY_VERSION_ARRAY = new Version[0];
42  
43      JcrVersionNode( AbstractJcrNode node ) {
44          super(node.cache, node.nodeId, node.location);
45  
46          assert !node.isRoot() : "Versions should always be located in the /jcr:system/jcr:versionStorage subgraph";
47      }
48  
49      /**
50       * @{inheritDoc
51       */
52      @Override
53      public JcrVersionHistoryNode getContainingHistory() throws RepositoryException {
54          return new JcrVersionHistoryNode(getParent());
55      }
56  
57      /**
58       * @{inheritDoc
59       */
60      @Override
61      public Calendar getCreated() throws RepositoryException {
62          return getProperty(JcrLexicon.CREATED).getDate();
63      }
64  
65      /**
66       * Returns the frozen node (the child node named {@code jcr:frozenNode}) for this version, if one exists.
67       * 
68       * @return the frozen node for this version, if one exists
69       * @throws ItemNotFoundException if this version has no child with the name {@code jcr:frozenNode}. This should only happen
70       *         for root versions in a version history.
71       * @throws RepositoryException if an error occurs accessing the repository
72       */
73      public AbstractJcrNode getFrozenNode() throws RepositoryException {
74          return getNode(JcrLexicon.FROZEN_NODE);
75      }
76  
77      /**
78       * @{inheritDoc
79       */
80      @Override
81      public Version[] getPredecessors() throws RepositoryException {
82          return getNodesForProperty(JcrLexicon.PREDECESSORS);
83      }
84  
85      /**
86       * Returns the successor versions of this version. This corresponds to returning all the nt:version nodes referenced by the
87       * jcr:successors multi-value property in the nt:version node that represents this version.
88       */
89      @Override
90      public Version[] getSuccessors() throws RepositoryException {
91          return getNodesForProperty(JcrLexicon.SUCCESSORS);
92      }
93  
94      private final Version[] getNodesForProperty( Name propertyName ) throws RepositoryException {
95          assert JcrLexicon.SUCCESSORS.equals(propertyName) || JcrLexicon.PREDECESSORS.equals(propertyName);
96  
97          Property references = getProperty(propertyName);
98  
99          if (references == null) return EMPTY_VERSION_ARRAY;
100 
101         Value[] values = references.getValues();
102 
103         List<JcrVersionNode> versions = new ArrayList<JcrVersionNode>(values.length);
104 
105         for (int i = 0; i < values.length; i++) {
106             String uuid = values[i].getString();
107 
108             AbstractJcrNode node = session().getNodeByUUID(uuid);
109             versions.add((JcrVersionNode)node);
110         }
111 
112         return versions.toArray(EMPTY_VERSION_ARRAY);
113 
114     }
115 
116     private final JcrVersionNode getFirstNodeForProperty( Name propertyName ) throws RepositoryException {
117         assert JcrLexicon.SUCCESSORS.equals(propertyName) || JcrLexicon.PREDECESSORS.equals(propertyName);
118 
119         Property references = getProperty(propertyName);
120 
121         if (references == null) return null;
122 
123         Value[] values = references.getValues();
124         if (values.length == 0) return null;
125 
126         String uuid = values[0].getString();
127         AbstractJcrNode node = session().getNodeByUUID(uuid);
128 
129         return (JcrVersionNode)node;
130     }
131 
132     boolean isSuccessorOf( JcrVersionNode other ) throws RepositoryException {
133         if (!other.hasProperty(JcrLexicon.SUCCESSORS)) return false;
134 
135         Value[] successors = other.getProperty(JcrLexicon.SUCCESSORS).getValues();
136 
137         String uuidString = uuid().toString();
138         for (int i = 0; i < successors.length; i++) {
139             if (uuidString.equals(successors[i].getString())) {
140                 return true;
141             }
142         }
143 
144         return false;
145     }
146 
147     @Override
148     public JcrVersionNode getLinearPredecessor() throws RepositoryException {
149         return getFirstNodeForProperty(JcrLexicon.PREDECESSORS);
150     }
151 
152     @Override
153     public JcrVersionNode getLinearSuccessor() throws RepositoryException {
154         return getFirstNodeForProperty(JcrLexicon.SUCCESSORS);
155     }
156 
157 }