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