]> git.argeo.org Git - lgpl/argeo-commons.git/blob - server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java
fix bug 85 : JCR explorer refresh was not implemented for TreeParent objects of type...
[lgpl/argeo-commons.git] / server / plugins / org.argeo.jcr.ui.explorer / src / main / java / org / argeo / jcr / ui / explorer / editors / NodeVersionHistoryPage.java
1 /*
2 * Copyright (C) 2007-2012 Mathieu Baudier
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.jcr.ui.explorer.editors;
17
18 import java.text.DateFormat;
19 import java.text.SimpleDateFormat;
20 import java.util.ArrayList;
21 import java.util.Calendar;
22 import java.util.List;
23 import java.util.Map;
24
25 import javax.jcr.Node;
26 import javax.jcr.Property;
27 import javax.jcr.PropertyType;
28 import javax.jcr.RepositoryException;
29 import javax.jcr.Value;
30 import javax.jcr.nodetype.NodeType;
31 import javax.jcr.version.Version;
32 import javax.jcr.version.VersionHistory;
33 import javax.jcr.version.VersionIterator;
34 import javax.jcr.version.VersionManager;
35
36 import org.argeo.ArgeoException;
37 import org.argeo.jcr.JcrUtils;
38 import org.argeo.jcr.PropertyDiff;
39 import org.argeo.jcr.VersionDiff;
40 import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
41 import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
42 import org.argeo.jcr.ui.explorer.providers.FullVersioningTreeContentProvider;
43 import org.argeo.jcr.ui.explorer.providers.VersionLabelProvider;
44 import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener;
45 import org.eclipse.jface.viewers.ITreeContentProvider;
46 import org.eclipse.jface.viewers.TreeViewer;
47 import org.eclipse.swt.SWT;
48 import org.eclipse.swt.layout.GridData;
49 import org.eclipse.swt.layout.GridLayout;
50 import org.eclipse.swt.widgets.Composite;
51 import org.eclipse.swt.widgets.Text;
52 import org.eclipse.ui.forms.AbstractFormPart;
53 import org.eclipse.ui.forms.IManagedForm;
54 import org.eclipse.ui.forms.editor.FormEditor;
55 import org.eclipse.ui.forms.editor.FormPage;
56 import org.eclipse.ui.forms.widgets.FormToolkit;
57 import org.eclipse.ui.forms.widgets.ScrolledForm;
58 import org.eclipse.ui.forms.widgets.Section;
59 import org.eclipse.ui.forms.widgets.TableWrapData;
60 import org.eclipse.ui.forms.widgets.TableWrapLayout;
61
62 /**
63 * Offers two main sections : one to display a text area with a summary of all
64 * variations between a version and its predecessor and one tree view that
65 * enable browsing
66 * */
67 public class NodeVersionHistoryPage extends FormPage implements
68 JcrExplorerConstants {
69 // private final static Log log = LogFactory
70 // .getLog(NodeVersionHistoryPage.class);
71
72 // Utils
73 protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT);
74
75 // business objects
76 private Node currentNode;
77
78 // this page UI components
79 private FullVersioningTreeContentProvider nodeContentProvider;
80 private TreeViewer nodesViewer;
81 private FormToolkit tk;
82
83 public NodeVersionHistoryPage(FormEditor editor, String title,
84 Node currentNode) {
85 super(editor, "NodeVersionHistoryPage", title);
86 this.currentNode = currentNode;
87 }
88
89 protected void createFormContent(IManagedForm managedForm) {
90 ScrolledForm form = managedForm.getForm();
91 form.setText(JcrExplorerPlugin
92 .getMessage("nodeVersionHistoryPageTitle"));
93 tk = managedForm.getToolkit();
94 GridLayout twt = new GridLayout(1, false);
95 twt.marginWidth = twt.marginHeight = 5;
96 Composite body = form.getBody();
97 body.setLayout(twt);
98
99 try {
100 if (!currentNode.isNodeType(NodeType.MIX_VERSIONABLE)) {
101 tk.createLabel(body, JcrExplorerPlugin
102 .getMessage("warningUnversionableNode"));
103 } else {
104 createHistorySection(form.getBody());
105 createTreeSection(form.getBody());
106 }
107 } catch (RepositoryException e) {
108 throw new ArgeoException(
109 "Unexpected error while checking if node is versionable", e);
110 }
111 }
112
113 protected void createTreeSection(Composite parent) {
114 // Section Layout & MetaData
115 Section section = tk.createSection(parent, Section.TWISTIE);
116 section.setLayoutData(new GridData(GridData.FILL_BOTH));
117 section.setText(JcrExplorerPlugin.getMessage("versionTreeSectionTitle"));
118
119 // Section Body
120 Composite body = tk.createComposite(section, SWT.FILL);
121 // WARNING : 2 following lines are compulsory or body won't be
122 // displayed.
123 body.setLayout(new GridLayout());
124 section.setClient(body);
125
126 body.setLayoutData(new GridData(GridData.FILL_BOTH));
127 section.setExpanded(true);
128
129 nodeContentProvider = new FullVersioningTreeContentProvider();
130 nodesViewer = createNodeViewer(body, nodeContentProvider);
131 nodesViewer.setInput(currentNode);
132 }
133
134 protected TreeViewer createNodeViewer(Composite parent,
135 final ITreeContentProvider nodeContentProvider) {
136
137 final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
138
139 tmpNodeViewer.getTree().setLayoutData(
140 new GridData(SWT.FILL, SWT.FILL, true, true));
141
142 tmpNodeViewer.setContentProvider(nodeContentProvider);
143 tmpNodeViewer.setLabelProvider(new VersionLabelProvider());
144 tmpNodeViewer
145 .addDoubleClickListener(new GenericNodeDoubleClickListener(
146 tmpNodeViewer));
147 return tmpNodeViewer;
148 }
149
150 protected void createHistorySection(Composite parent) {
151
152 // Section Layout
153 Section section = tk.createSection(parent, Section.TWISTIE);
154 section.setLayoutData(new GridData(TableWrapData.FILL_GRAB));
155 TableWrapLayout twt = new TableWrapLayout();
156 section.setLayout(twt);
157
158 // Set title of the section
159 section.setText(JcrExplorerPlugin
160 .getMessage("versionHistorySectionTitle"));
161
162 final Text styledText = tk.createText(section, "", SWT.FULL_SELECTION
163 | SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
164 styledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
165 section.setClient(styledText);
166 refreshHistory(styledText);
167 styledText.setEditable(false);
168 section.setExpanded(false);
169
170 AbstractFormPart part = new AbstractFormPart() {
171 public void commit(boolean onSave) {
172 }
173
174 public void refresh() {
175 super.refresh();
176 refreshHistory(styledText);
177 }
178 };
179 getManagedForm().addPart(part);
180 }
181
182 protected void refreshHistory(Text styledText) {
183 try {
184 List<VersionDiff> lst = listHistoryDiff();
185 StringBuffer main = new StringBuffer("");
186
187 for (int i = lst.size() - 1; i >= 0; i--) {
188 if (i == 0)
189 main.append("Creation (");
190 else
191 main.append("Update " + i + " (");
192
193 if (lst.get(i).getUserId() != null)
194 main.append("UserId : " + lst.get(i).getUserId());
195
196 if (lst.get(i).getUserId() != null
197 && lst.get(i).getUpdateTime() != null)
198 main.append(", ");
199
200 if (lst.get(i).getUpdateTime() != null)
201 main.append("Date : "
202 + timeFormatter.format(lst.get(i).getUpdateTime()
203 .getTime()) + ")\n");
204
205 StringBuffer buf = new StringBuffer("");
206 Map<String, PropertyDiff> diffs = lst.get(i).getDiffs();
207 for (String prop : diffs.keySet()) {
208 PropertyDiff pd = diffs.get(prop);
209 // String propName = pd.getRelPath();
210 Value refValue = pd.getReferenceValue();
211 Value newValue = pd.getNewValue();
212 String refValueStr = "";
213 String newValueStr = "";
214
215 if (refValue != null) {
216 if (refValue.getType() == PropertyType.DATE) {
217 refValueStr = timeFormatter.format(refValue
218 .getDate().getTime());
219 } else
220 refValueStr = refValue.getString();
221 }
222 if (newValue != null) {
223 if (newValue.getType() == PropertyType.DATE) {
224 newValueStr = timeFormatter.format(newValue
225 .getDate().getTime());
226 } else
227 newValueStr = newValue.getString();
228 }
229
230 if (pd.getType() == PropertyDiff.MODIFIED) {
231 buf.append(prop).append(": ");
232 buf.append(refValueStr);
233 buf.append(" > ");
234 buf.append(newValueStr);
235 buf.append("\n");
236 } else if (pd.getType() == PropertyDiff.ADDED
237 && !"".equals(newValueStr)) {
238 // we don't list property that have been added with an
239 // empty string as value
240 buf.append(prop).append(": ");
241 buf.append(" + ");
242 buf.append(newValueStr);
243 buf.append("\n");
244 } else if (pd.getType() == PropertyDiff.REMOVED) {
245 buf.append(prop).append(": ");
246 buf.append(" - ");
247 buf.append(refValueStr);
248 buf.append("\n");
249 }
250 }
251 buf.append("\n");
252 main.append(buf);
253 }
254 styledText.setText(main.toString());
255 } catch (RepositoryException e) {
256 throw new ArgeoException("Cannot generate history for node", e);
257 }
258
259 }
260
261 public List<VersionDiff> listHistoryDiff() {
262 try {
263 List<VersionDiff> res = new ArrayList<VersionDiff>();
264 VersionManager versionManager = currentNode.getSession()
265 .getWorkspace().getVersionManager();
266 VersionHistory versionHistory = versionManager
267 .getVersionHistory(currentNode.getPath());
268
269 VersionIterator vit = versionHistory.getAllLinearVersions();
270 while (vit.hasNext()) {
271 Version version = vit.nextVersion();
272 Node node = version.getFrozenNode();
273 Version predecessor = null;
274 try {
275 predecessor = version.getLinearPredecessor();
276 } catch (Exception e) {
277 // no predecessor seems to throw an exception even if it
278 // shouldn't...
279 }
280 if (predecessor == null) {// original
281 } else {
282 Map<String, PropertyDiff> diffs = JcrUtils.diffProperties(
283 predecessor.getFrozenNode(), node);
284 if (!diffs.isEmpty()) {
285 String lastUserName = null;
286 Calendar lastUpdate = null;
287 try {
288 if (currentNode
289 .isNodeType(NodeType.MIX_LAST_MODIFIED)) {
290 lastUserName = node.getProperty(
291 Property.JCR_LAST_MODIFIED_BY)
292 .getString();
293 lastUpdate = node.getProperty(
294 Property.JCR_LAST_MODIFIED).getDate();
295 } else
296 lastUpdate = version.getProperty(
297 Property.JCR_CREATED).getDate();
298
299 } catch (Exception e) {
300 // Silent that info is optional
301 }
302 VersionDiff vd = new VersionDiff(lastUserName,
303 lastUpdate, diffs);
304 res.add(vd);
305 }
306 }
307 }
308 return res;
309 } catch (RepositoryException e) {
310 throw new ArgeoException("Cannot generate history for node ");
311 }
312
313 }
314
315 @Override
316 public void setActive(boolean active) {
317 super.setActive(active);
318 }
319 }