]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.ui.workbench/src/org/argeo/cms/ui/workbench/internal/jcr/parts/NodeVersionHistoryPage.java
Improve digest utilities
[lgpl/argeo-commons.git] / org.argeo.cms.ui.workbench / src / org / argeo / cms / ui / workbench / internal / jcr / parts / NodeVersionHistoryPage.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
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.cms.ui.workbench.internal.jcr.parts;
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.cms.ui.CmsConstants;
37 import org.argeo.cms.ui.jcr.FullVersioningTreeContentProvider;
38 import org.argeo.cms.ui.jcr.JcrDClickListener;
39 import org.argeo.cms.ui.jcr.VersionLabelProvider;
40 import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
41 import org.argeo.cms.ui.workbench.internal.WorkbenchConstants;
42 import org.argeo.eclipse.ui.EclipseUiException;
43 import org.argeo.jcr.JcrUtils;
44 import org.argeo.jcr.PropertyDiff;
45 import org.argeo.jcr.VersionDiff;
46 import org.eclipse.jface.viewers.ITreeContentProvider;
47 import org.eclipse.jface.viewers.TreeViewer;
48 import org.eclipse.swt.SWT;
49 import org.eclipse.swt.layout.GridData;
50 import org.eclipse.swt.layout.GridLayout;
51 import org.eclipse.swt.widgets.Composite;
52 import org.eclipse.swt.widgets.Text;
53 import org.eclipse.ui.forms.AbstractFormPart;
54 import org.eclipse.ui.forms.IManagedForm;
55 import org.eclipse.ui.forms.editor.FormEditor;
56 import org.eclipse.ui.forms.editor.FormPage;
57 import org.eclipse.ui.forms.widgets.FormToolkit;
58 import org.eclipse.ui.forms.widgets.ScrolledForm;
59 import org.eclipse.ui.forms.widgets.Section;
60 import org.eclipse.ui.forms.widgets.TableWrapData;
61 import org.eclipse.ui.forms.widgets.TableWrapLayout;
62
63 /**
64 * Offers two main sections : one to display a text area with a summary of all
65 * variations between a version and its predecessor and one tree view that
66 * enable browsing
67 */
68 public class NodeVersionHistoryPage extends FormPage implements WorkbenchConstants {
69 // private final static Log log = LogFactory
70 // .getLog(NodeVersionHistoryPage.class);
71
72 // Utils
73 protected DateFormat timeFormatter = new SimpleDateFormat(CmsConstants.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, Node currentNode) {
84 super(editor, "NodeVersionHistoryPage", title);
85 this.currentNode = currentNode;
86 }
87
88 protected void createFormContent(IManagedForm managedForm) {
89 ScrolledForm form = managedForm.getForm();
90 form.setText(WorkbenchUiPlugin.getMessage("nodeVersionHistoryPageTitle"));
91 tk = managedForm.getToolkit();
92 Composite innerBox = form.getBody();
93 // Composite innerBox = new Composite(body, SWT.NO_FOCUS);
94 GridLayout twt = new GridLayout(1, false);
95 twt.marginWidth = twt.marginHeight = 5;
96 innerBox.setLayout(twt);
97 try {
98 if (!currentNode.isNodeType(NodeType.MIX_VERSIONABLE)) {
99 tk.createLabel(innerBox, WorkbenchUiPlugin.getMessage("warningUnversionableNode"));
100 } else {
101 createHistorySection(innerBox);
102 createTreeSection(innerBox);
103 }
104 } catch (RepositoryException e) {
105 throw new EclipseUiException("Unable to check if node is versionable", e);
106 }
107 }
108
109 protected void createTreeSection(Composite parent) {
110 Section section = tk.createSection(parent, Section.TWISTIE);
111 section.setLayoutData(new GridData(GridData.FILL_BOTH));
112 section.setText(WorkbenchUiPlugin.getMessage("versionTreeSectionTitle"));
113
114 Composite body = tk.createComposite(section, SWT.FILL);
115 section.setClient(body);
116 section.setExpanded(true);
117 body.setLayoutData(new GridData(GridData.FILL_BOTH));
118 body.setLayout(new GridLayout());
119
120 nodeContentProvider = new FullVersioningTreeContentProvider();
121 nodesViewer = createNodeViewer(body, nodeContentProvider);
122 nodesViewer.setInput(currentNode);
123 }
124
125 protected TreeViewer createNodeViewer(Composite parent, final ITreeContentProvider nodeContentProvider) {
126
127 final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI);
128
129 tmpNodeViewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
130
131 tmpNodeViewer.setContentProvider(nodeContentProvider);
132 tmpNodeViewer.setLabelProvider(new VersionLabelProvider());
133 tmpNodeViewer.addDoubleClickListener(new JcrDClickListener(tmpNodeViewer));
134 return tmpNodeViewer;
135 }
136
137 protected void createHistorySection(Composite parent) {
138
139 // Section Layout
140 Section section = tk.createSection(parent, Section.TWISTIE);
141 section.setLayoutData(new GridData(TableWrapData.FILL_GRAB));
142 TableWrapLayout twt = new TableWrapLayout();
143 section.setLayout(twt);
144
145 // Set title of the section
146 section.setText(WorkbenchUiPlugin.getMessage("versionHistorySectionTitle"));
147
148 final Text styledText = tk.createText(section, "",
149 SWT.FULL_SELECTION | SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
150 section.setClient(styledText);
151 styledText.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.FILL_GRAB));
152 refreshHistory(styledText);
153 styledText.setEditable(false);
154 section.setExpanded(false);
155
156 AbstractFormPart part = new AbstractFormPart() {
157 public void commit(boolean onSave) {
158 }
159
160 public void refresh() {
161 super.refresh();
162 refreshHistory(styledText);
163 }
164 };
165 getManagedForm().addPart(part);
166 }
167
168 protected void refreshHistory(Text styledText) {
169 try {
170 List<VersionDiff> lst = listHistoryDiff();
171 StringBuffer main = new StringBuffer("");
172
173 for (int i = lst.size() - 1; i >= 0; i--) {
174 if (i == 0)
175 main.append("Creation (");
176 else
177 main.append("Update " + i + " (");
178
179 if (lst.get(i).getUserId() != null)
180 main.append("UserId : " + lst.get(i).getUserId());
181
182 if (lst.get(i).getUserId() != null && lst.get(i).getUpdateTime() != null)
183 main.append(", ");
184
185 if (lst.get(i).getUpdateTime() != null)
186 main.append("Date : " + timeFormatter.format(lst.get(i).getUpdateTime().getTime()) + ")\n");
187
188 StringBuffer buf = new StringBuffer("");
189 Map<String, PropertyDiff> diffs = lst.get(i).getDiffs();
190 for (String prop : diffs.keySet()) {
191 PropertyDiff pd = diffs.get(prop);
192 // String propName = pd.getRelPath();
193 Value refValue = pd.getReferenceValue();
194 Value newValue = pd.getNewValue();
195 String refValueStr = "";
196 String newValueStr = "";
197
198 if (refValue != null) {
199 if (refValue.getType() == PropertyType.DATE) {
200 refValueStr = timeFormatter.format(refValue.getDate().getTime());
201 } else
202 refValueStr = refValue.getString();
203 }
204 if (newValue != null) {
205 if (newValue.getType() == PropertyType.DATE) {
206 newValueStr = timeFormatter.format(newValue.getDate().getTime());
207 } else
208 newValueStr = newValue.getString();
209 }
210
211 if (pd.getType() == PropertyDiff.MODIFIED) {
212 buf.append(prop).append(": ");
213 buf.append(refValueStr);
214 buf.append(" > ");
215 buf.append(newValueStr);
216 buf.append("\n");
217 } else if (pd.getType() == PropertyDiff.ADDED && !"".equals(newValueStr)) {
218 // we don't list property that have been added with an
219 // empty string as value
220 buf.append(prop).append(": ");
221 buf.append(" + ");
222 buf.append(newValueStr);
223 buf.append("\n");
224 } else if (pd.getType() == PropertyDiff.REMOVED) {
225 buf.append(prop).append(": ");
226 buf.append(" - ");
227 buf.append(refValueStr);
228 buf.append("\n");
229 }
230 }
231 buf.append("\n");
232 main.append(buf);
233 }
234 styledText.setText(main.toString());
235 } catch (RepositoryException e) {
236 throw new EclipseUiException("Cannot generate history for node", e);
237 }
238 }
239
240 public List<VersionDiff> listHistoryDiff() {
241 try {
242 List<VersionDiff> res = new ArrayList<VersionDiff>();
243 VersionManager versionManager = currentNode.getSession().getWorkspace().getVersionManager();
244 VersionHistory versionHistory = versionManager.getVersionHistory(currentNode.getPath());
245
246 VersionIterator vit = versionHistory.getAllLinearVersions();
247 while (vit.hasNext()) {
248 Version version = vit.nextVersion();
249 Node node = version.getFrozenNode();
250 Version predecessor = null;
251 try {
252 predecessor = version.getLinearPredecessor();
253 } catch (Exception e) {
254 // no predecessor seems to throw an exception even if it
255 // shouldn't...
256 }
257 if (predecessor == null) {// original
258 } else {
259 Map<String, PropertyDiff> diffs = JcrUtils.diffProperties(predecessor.getFrozenNode(), node);
260 if (!diffs.isEmpty()) {
261 String lastUserName = null;
262 Calendar lastUpdate = null;
263 try {
264 if (currentNode.isNodeType(NodeType.MIX_LAST_MODIFIED)) {
265 lastUserName = node.getProperty(Property.JCR_LAST_MODIFIED_BY).getString();
266 lastUpdate = node.getProperty(Property.JCR_LAST_MODIFIED).getDate();
267 } else
268 lastUpdate = version.getProperty(Property.JCR_CREATED).getDate();
269
270 } catch (Exception e) {
271 // Silent that info is optional
272 }
273 VersionDiff vd = new VersionDiff(lastUserName, lastUpdate, diffs);
274 res.add(vd);
275 }
276 }
277 }
278 return res;
279 } catch (RepositoryException e) {
280 throw new EclipseUiException("Cannot generate history for node ");
281 }
282
283 }
284
285 @Override
286 public void setActive(boolean active) {
287 super.setActive(active);
288 }
289 }