X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=server%2Fplugins%2Forg.argeo.jcr.ui.explorer%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fjcr%2Fui%2Fexplorer%2Feditors%2FNodeVersionHistoryPage.java;h=8b5968fd8348046f3f98dba4d276a8ebfc6e424c;hb=1d5afdce3e91054f07ddd3c98309c363b4cf1d46;hp=dd888d12b0bcb448547e547415f4901c20a491a4;hpb=e20bb1ef1c9c03d5e704d1634f3c83a971d15df8;p=lgpl%2Fargeo-commons.git diff --git a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java index dd888d12b..8b5968fd8 100644 --- a/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java +++ b/server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/editors/NodeVersionHistoryPage.java @@ -1,27 +1,85 @@ +/* + * Copyright (C) 2007-2012 Mathieu Baudier + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.argeo.jcr.ui.explorer.editors; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Map; + import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.nodetype.NodeType; +import javax.jcr.version.Version; +import javax.jcr.version.VersionHistory; +import javax.jcr.version.VersionIterator; +import javax.jcr.version.VersionManager; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.PropertyDiff; +import org.argeo.jcr.VersionDiff; +import org.argeo.jcr.ui.explorer.JcrExplorerConstants; +import org.argeo.jcr.ui.explorer.JcrExplorerPlugin; +import org.argeo.jcr.ui.explorer.providers.FullVersioningTreeContentProvider; +import org.argeo.jcr.ui.explorer.providers.VersionLabelProvider; +import org.argeo.jcr.ui.explorer.utils.GenericNodeDoubleClickListener; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.AbstractFormPart; import org.eclipse.ui.forms.IManagedForm; import org.eclipse.ui.forms.editor.FormEditor; import org.eclipse.ui.forms.editor.FormPage; +import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; +import org.eclipse.ui.forms.widgets.Section; +import org.eclipse.ui.forms.widgets.TableWrapData; +import org.eclipse.ui.forms.widgets.TableWrapLayout; /** - * This page is only used at editor's creation time when current node has not - * yet been set - */ -public class NodeVersionHistoryPage extends FormPage { - private final static Log log = LogFactory - .getLog(NodeVersionHistoryPage.class); + * Offers two main sections : one to display a text area with a summary of all + * variations between a version and its predecessor and one tree view that + * enable browsing + * */ +public class NodeVersionHistoryPage extends FormPage implements + JcrExplorerConstants { + // private final static Log log = LogFactory + // .getLog(NodeVersionHistoryPage.class); + // Utils + protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT); + + // business objects private Node currentNode; + // this page UI components + private FullVersioningTreeContentProvider nodeContentProvider; + private TreeViewer nodesViewer; + private FormToolkit tk; + public NodeVersionHistoryPage(FormEditor editor, String title, Node currentNode) { super(editor, "NodeVersionHistoryPage", title); @@ -29,15 +87,233 @@ public class NodeVersionHistoryPage extends FormPage { } protected void createFormContent(IManagedForm managedForm) { + ScrolledForm form = managedForm.getForm(); + form.setText(JcrExplorerPlugin + .getMessage("nodeVersionHistoryPageTitle")); + tk = managedForm.getToolkit(); + GridLayout twt = new GridLayout(1, false); + twt.marginWidth = twt.marginHeight = 5; + Composite body = form.getBody(); + body.setLayout(twt); + + try { + if (!currentNode.isNodeType(NodeType.MIX_VERSIONABLE)) { + tk.createLabel(body, JcrExplorerPlugin + .getMessage("warningUnversionableNode")); + } else { + createHistorySection(form.getBody()); + createTreeSection(form.getBody()); + } + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected error while checking if node is versionable", e); + } + } + + protected void createTreeSection(Composite parent) { + // Section Layout & MetaData + Section section = tk.createSection(parent, Section.TWISTIE); + section.setLayoutData(new GridData(GridData.FILL_BOTH)); + section.setText(JcrExplorerPlugin.getMessage("versionTreeSectionTitle")); + + // Section Body + Composite body = tk.createComposite(section, SWT.FILL); + // WARNING : 2 following lines are compulsory or body won't be + // displayed. + body.setLayout(new GridLayout()); + section.setClient(body); + + body.setLayoutData(new GridData(GridData.FILL_BOTH)); + section.setExpanded(true); + + nodeContentProvider = new FullVersioningTreeContentProvider(); + nodesViewer = createNodeViewer(body, nodeContentProvider); + nodesViewer.setInput(currentNode); + } + + protected TreeViewer createNodeViewer(Composite parent, + final ITreeContentProvider nodeContentProvider) { + + final TreeViewer tmpNodeViewer = new TreeViewer(parent, SWT.MULTI); + + tmpNodeViewer.getTree().setLayoutData( + new GridData(SWT.FILL, SWT.FILL, true, true)); + + tmpNodeViewer.setContentProvider(nodeContentProvider); + tmpNodeViewer.setLabelProvider(new VersionLabelProvider()); + tmpNodeViewer + .addDoubleClickListener(new GenericNodeDoubleClickListener( + tmpNodeViewer)); + return tmpNodeViewer; + } + + protected void createHistorySection(Composite parent) { + + // Section Layout + Section section = tk.createSection(parent, Section.TWISTIE); + section.setLayoutData(new GridData(TableWrapData.FILL_GRAB)); + TableWrapLayout twt = new TableWrapLayout(); + section.setLayout(twt); + + // Set title of the section + section.setText(JcrExplorerPlugin + .getMessage("versionHistorySectionTitle")); + + final Text styledText = tk.createText(section, "", SWT.FULL_SELECTION + | SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL); + styledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + section.setClient(styledText); + refreshHistory(styledText); + styledText.setEditable(false); + section.setExpanded(false); + + AbstractFormPart part = new AbstractFormPart() { + public void commit(boolean onSave) { + } + + public void refresh() { + super.refresh(); + refreshHistory(styledText); + } + }; + getManagedForm().addPart(part); + } + + protected void refreshHistory(Text styledText) { + try { + List lst = listHistoryDiff(); + StringBuffer main = new StringBuffer(""); + + for (int i = lst.size() - 1; i >= 0; i--) { + if (i == 0) + main.append("Creation ("); + else + main.append("Update " + i + " ("); + + if (lst.get(i).getUserId() != null) + main.append("UserId : " + lst.get(i).getUserId()); + + if (lst.get(i).getUserId() != null + && lst.get(i).getUpdateTime() != null) + main.append(", "); + + if (lst.get(i).getUpdateTime() != null) + main.append("Date : " + + timeFormatter.format(lst.get(i).getUpdateTime() + .getTime()) + ")\n"); + + StringBuffer buf = new StringBuffer(""); + Map diffs = lst.get(i).getDiffs(); + for (String prop : diffs.keySet()) { + PropertyDiff pd = diffs.get(prop); + // String propName = pd.getRelPath(); + Value refValue = pd.getReferenceValue(); + Value newValue = pd.getNewValue(); + String refValueStr = ""; + String newValueStr = ""; + + if (refValue != null) { + if (refValue.getType() == PropertyType.DATE) { + refValueStr = timeFormatter.format(refValue + .getDate().getTime()); + } else + refValueStr = refValue.getString(); + } + if (newValue != null) { + if (newValue.getType() == PropertyType.DATE) { + newValueStr = timeFormatter.format(newValue + .getDate().getTime()); + } else + newValueStr = newValue.getString(); + } + + if (pd.getType() == PropertyDiff.MODIFIED) { + buf.append(prop).append(": "); + buf.append(refValueStr); + buf.append(" > "); + buf.append(newValueStr); + buf.append("\n"); + } else if (pd.getType() == PropertyDiff.ADDED + && !"".equals(newValueStr)) { + // we don't list property that have been added with an + // empty string as value + buf.append(prop).append(": "); + buf.append(" + "); + buf.append(newValueStr); + buf.append("\n"); + } else if (pd.getType() == PropertyDiff.REMOVED) { + buf.append(prop).append(": "); + buf.append(" - "); + buf.append(refValueStr); + buf.append("\n"); + } + } + buf.append("\n"); + main.append(buf); + } + styledText.setText(main.toString()); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot generate history for node", e); + } + + } + + public List listHistoryDiff() { try { - ScrolledForm form = managedForm.getForm(); - GridLayout twt = new GridLayout(1, false); - twt.marginWidth = twt.marginHeight = 0; - form.getBody().setLayout(twt); - Label lbl = new Label(form.getBody(), SWT.NONE); - lbl.setText("Implement this"); - } catch (Exception e) { - e.printStackTrace(); + List res = new ArrayList(); + VersionManager versionManager = currentNode.getSession() + .getWorkspace().getVersionManager(); + VersionHistory versionHistory = versionManager + .getVersionHistory(currentNode.getPath()); + + VersionIterator vit = versionHistory.getAllLinearVersions(); + while (vit.hasNext()) { + Version version = vit.nextVersion(); + Node node = version.getFrozenNode(); + Version predecessor = null; + try { + predecessor = version.getLinearPredecessor(); + } catch (Exception e) { + // no predecessor seems to throw an exception even if it + // shouldn't... + } + if (predecessor == null) {// original + } else { + Map diffs = JcrUtils.diffProperties( + predecessor.getFrozenNode(), node); + if (!diffs.isEmpty()) { + String lastUserName = null; + Calendar lastUpdate = null; + try { + if (currentNode + .isNodeType(NodeType.MIX_LAST_MODIFIED)) { + lastUserName = node.getProperty( + Property.JCR_LAST_MODIFIED_BY) + .getString(); + lastUpdate = node.getProperty( + Property.JCR_LAST_MODIFIED).getDate(); + } else + lastUpdate = version.getProperty( + Property.JCR_CREATED).getDate(); + + } catch (Exception e) { + // Silent that info is optional + } + VersionDiff vd = new VersionDiff(lastUserName, + lastUpdate, diffs); + res.add(vd); + } + } + } + return res; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot generate history for node "); } + + } + + @Override + public void setActive(boolean active) { + super.setActive(active); } }