View Javadoc
1   /*
2    * Copyright (C) 2003-2007 eXo Platform SAS.
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Affero General Public License
6    * as published by the Free Software Foundation; either version 3
7    * of the License, or (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program; if not, see<http://www.gnu.org/licenses/>.
16   */
17  package org.exoplatform.ecm.jcr.model;
18  
19  import java.util.*;
20  
21  import javax.jcr.*;
22  import javax.jcr.version.Version;
23  import javax.jcr.version.VersionIterator;
24  
25  import org.exoplatform.ecm.webui.utils.Utils;
26  import org.exoplatform.services.cms.documents.VersionHistoryUtils;
27  import org.exoplatform.services.cms.impl.DMSConfiguration;
28  import org.exoplatform.services.jcr.core.ManageableRepository;
29  import org.exoplatform.services.jcr.ext.common.SessionProvider;
30  import org.exoplatform.services.log.ExoLogger;
31  import org.exoplatform.services.log.Log;
32  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
33  
34  public class VersionNode {
35    private static final String EXO_LAST_MODIFIED_DATE = "exo:lastModifiedDate";
36  
37    private boolean           isExpanded     = true;
38  
39    private List<VersionNode> children_      = new ArrayList<VersionNode>();
40  
41    private static final Log  LOG            = ExoLogger.getLogger(VersionNode.class.getName());
42  
43    private Calendar          createdTime_;
44  
45    private String            name_          = "";
46  
47    private String            displayName         = "";
48  
49    private String            path_          = "";
50  
51    private String            ws_            = "";
52  
53    private String            uuid_;
54  
55    private String[]          versionLabels_ = new String[] {};
56  
57    private String            author_        = "";
58  
59    public VersionNode(Node node, Session session) {
60      Version version = node instanceof Version ? (Version) node : null;
61      try {
62        Property property = getProperty(node, EXO_LAST_MODIFIED_DATE);
63        if (property != null) {
64          createdTime_ = property.getDate();
65        }
66        name_ = version == null ? "" : version.getName();
67        path_ = node.getPath();
68        ws_ = node.getSession().getWorkspace().getName();
69        uuid_ = node.getUUID();
70        Property prop = getProperty(node, Utils.EXO_LASTMODIFIER);
71        author_ = prop == null ? null : prop.getString();
72        if (version == null) {
73          if (node.isNodeType(Utils.MIX_VERSIONABLE)) {
74            addVersions(node, session);
75          }
76        } else {
77          addVersions(node, session);
78        }
79      } catch (Exception e) {
80        if (LOG.isErrorEnabled()) {
81          LOG.error("Unexpected error", e);
82        }
83      }
84    }
85  
86    /**
87     * Add versions of the given node as children with the right name and display name, and set
88     * the name dan display name of the current version.
89     * If the node has a property exo:maxVersion, it means some versions have been removed and
90     * we must use this value as the current version.
91     * If the node has a property exo:versionList, it means some versions have been removed then
92     * some others have been created. Since the display name of the versions does not follow the sequential numbering
93     * anymore (for example 1,3,4 if version 2 has been removed), the property exo:versionList maps the
94     * version name with the correct display name.
95     * To be noted : display name is always decremented by 1 from the version index of offset since
96     * we want the display name to start from 0
97     * @param node JCR node
98     * @param session JCR session
99     * @throws RepositoryException
100    */
101   private void addVersions(Node node, Session session) throws RepositoryException {
102     if(node instanceof Version) {
103       Version version = (Version) node;
104       versionLabels_ = version.getContainingHistory().getVersionLabels(version);
105     } else {
106       int maxVersion = 0;
107       Map<String, String> mapVersionName = new HashMap<>();
108       if(node.isNodeType(VersionHistoryUtils.MIX_DISPLAY_VERSION_NAME)){
109         //maxVersion of root version
110         if(node.hasProperty(VersionHistoryUtils.MAX_VERSION_PROPERTY)){
111           maxVersion = (int) node.getProperty(VersionHistoryUtils.MAX_VERSION_PROPERTY).getLong();
112         }
113         //list of version name entries (jcrID, display version)
114         if(node.hasProperty(VersionHistoryUtils.LIST_VERSION_PROPERTY)){
115           Value[] values = node.getProperty(VersionHistoryUtils.LIST_VERSION_PROPERTY).getValues();
116           for (Value value : values){
117             mapVersionName.put(value.getString().split(VersionHistoryUtils.VERSION_SEPARATOR)[0],
118                     value.getString().split(VersionHistoryUtils.VERSION_SEPARATOR)[1]);
119           }
120         }
121       }
122       Version rootVersion = node.getVersionHistory().getRootVersion();
123       VersionIterator allVersions = node.getVersionHistory().getAllVersions();
124       int maxIndex = 0;
125       while (allVersions.hasNext()) {
126         Version version = allVersions.nextVersion();
127 
128         if(version.getUUID().equals(rootVersion.getUUID())) {
129           continue;
130         }
131 
132         int versionIndex = Integer.parseInt(version.getName());
133         maxIndex = Math.max(maxIndex , versionIndex);
134 
135         String versionOffset = mapVersionName.get(version.getName());
136 
137         VersionNode versionNode = new VersionNode(version, session);
138         if(versionOffset != null) {
139           versionNode.setDisplayName(String.valueOf(Integer.parseInt(versionOffset) - 1));
140         } else {
141           versionNode.setDisplayName(String.valueOf(versionIndex - 1));
142         }
143         children_.add(versionNode);
144       }
145       name_ = String.valueOf(maxIndex + 1);
146       displayName = maxVersion > 0 ?  String.valueOf(maxVersion - 1) : String.valueOf(maxIndex);
147       versionLabels_ = node.getVersionHistory().getVersionLabels(rootVersion);
148     }
149   }
150 
151   private Property getProperty(Node node, String propName) throws RepositoryException {
152     Property property = null;
153     if (node.hasProperty(propName)) {
154       property = node.getProperty(propName);
155     } else if (node.hasNode(Utils.JCR_FROZEN) && node.getNode(Utils.JCR_FROZEN).hasProperty(propName)) {
156       property = node.getNode(Utils.JCR_FROZEN).getProperty(propName);
157     }
158     return property;
159   }
160 
161   public boolean isExpanded() {
162     return isExpanded;
163   }
164 
165   public void setExpanded(boolean isExpanded) {
166     this.isExpanded = isExpanded;
167   }
168 
169   public String getName() {
170     return name_;
171   }
172 
173   public String getDisplayName() {
174     return displayName;
175   }
176 
177   public void setDisplayName(String displayName_) {
178     this.displayName = displayName_;
179   }
180 
181   public String getWs() {
182     return ws_;
183   }
184 
185   public String getPath() {
186     return path_;
187   }
188 
189   public int getChildrenSize() {
190     return children_.size();
191   }
192 
193   public List<VersionNode> getChildren() {
194     return children_;
195   }
196 
197   public Calendar getCreatedTime() {
198     return createdTime_;
199   }
200 
201   public String getAuthor() {
202     return author_;
203   }
204 
205   public String[] getVersionLabels() {
206     return versionLabels_;
207   }
208 
209   public Node getNode(String nodeName) throws RepositoryException {
210     DMSConfiguration dmsConf = WCMCoreUtils.getService(DMSConfiguration.class);
211     String systemWS = dmsConf.getConfig().getSystemWorkspace();
212     ManageableRepository repo = WCMCoreUtils.getRepository();
213     SessionProvider provider = systemWS.equals(ws_) ? WCMCoreUtils.getSystemSessionProvider()
214                                                    : WCMCoreUtils.getUserSessionProvider();
215     return ((Node) provider.getSession(ws_, repo).getItem(path_)).getNode(nodeName);
216   }
217 
218   public boolean hasNode(String nodeName) throws Exception {
219     DMSConfiguration dmsConf = WCMCoreUtils.getService(DMSConfiguration.class);
220     String systemWS = dmsConf.getConfig().getSystemWorkspace();
221     ManageableRepository repo = WCMCoreUtils.getRepository();
222     SessionProvider provider = systemWS.equals(ws_) ? WCMCoreUtils.getSystemSessionProvider()
223                                                    : WCMCoreUtils.getUserSessionProvider();
224     return ((Node) provider.getSession(ws_, repo).getItem(path_)).hasNode(nodeName);
225   }
226 
227   public String getUUID() {
228     return uuid_;
229   }
230 
231   public VersionNode findVersionNode(String path) throws RepositoryException {
232     if (path_.equals(path))
233       return this;
234     VersionNode node = null;
235     Iterator<VersionNode> iter = children_.iterator();
236     while (iter.hasNext()) {
237       VersionNode child = (VersionNode) iter.next();
238       node = child.findVersionNode(path);
239       if (node != null)
240         return node;
241     }
242     return null;
243   }
244 
245   public void removeVersionInChild(VersionNode versionNode1, VersionNode versionNodeRemove) throws RepositoryException {
246     if (versionNode1.getChildren().contains(versionNodeRemove))
247       versionNode1.getChildren().remove(versionNodeRemove);
248     else {
249       for (VersionNode vsN : versionNode1.getChildren()) {
250         removeVersionInChild(vsN, versionNodeRemove);
251       }
252     }
253   }
254 
255 }