From: Mathieu Baudier Date: Sun, 5 Dec 2021 07:18:43 +0000 (+0100) Subject: Move Eclipse components which are JCR specific. X-Git-Tag: argeo-commons-2.3.5~133 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=d169026cb1939009fd90ac46a11f480cb3d803c0;p=lgpl%2Fargeo-commons.git Move Eclipse components which are JCR specific. --- diff --git a/org.argeo.cms.ui/pom.xml b/org.argeo.cms.ui/pom.xml index 60eb6203f..d2dd775e0 100644 --- a/org.argeo.cms.ui/pom.xml +++ b/org.argeo.cms.ui/pom.xml @@ -16,6 +16,11 @@ org.argeo.cms 2.3-SNAPSHOT + + org.argeo.commons + org.argeo.cms.jcr + 2.3-SNAPSHOT + org.argeo.commons diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java new file mode 100644 index 000000000..8f7c2f99a --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java @@ -0,0 +1,139 @@ +package org.argeo.eclipse.ui.jcr; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.eclipse.ui.AbstractTreeContentProvider; +import org.argeo.eclipse.ui.EclipseUiException; + +/** Canonical implementation of tree content provider manipulating JCR nodes. */ +public abstract class AbstractNodeContentProvider extends + AbstractTreeContentProvider { + private static final long serialVersionUID = -4905836490027272569L; + + private final static Log log = LogFactory + .getLog(AbstractNodeContentProvider.class); + + private Session session; + + public AbstractNodeContentProvider(Session session) { + this.session = session; + } + + /** + * Whether this path is a base path (and thus has no parent). By default it + * returns true if path is '/' (root node) + */ + protected Boolean isBasePath(String path) { + // root node + return path.equals("/"); + } + + @Override + public Object[] getChildren(Object element) { + Object[] children; + if (element instanceof Node) { + try { + Node node = (Node) element; + children = getChildren(node); + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot get children of " + element, e); + } + } else if (element instanceof WrappedNode) { + WrappedNode wrappedNode = (WrappedNode) element; + try { + children = getChildren(wrappedNode.getNode()); + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot get children of " + + wrappedNode, e); + } + } else if (element instanceof NodesWrapper) { + NodesWrapper node = (NodesWrapper) element; + children = node.getChildren(); + } else { + children = super.getChildren(element); + } + + children = sort(element, children); + return children; + } + + /** Do not sort by default. To be overidden to provide custom sort. */ + protected Object[] sort(Object parent, Object[] children) { + return children; + } + + /** + * To be overridden in order to filter out some nodes. Does nothing by + * default. The provided list is a temporary one and can thus be modified + * directly . (e.g. via an iterator) + */ + protected List filterChildren(List children) + throws RepositoryException { + return children; + } + + protected Object[] getChildren(Node node) throws RepositoryException { + List nodes = new ArrayList(); + for (NodeIterator nit = node.getNodes(); nit.hasNext();) + nodes.add(nit.nextNode()); + nodes = filterChildren(nodes); + return nodes.toArray(); + } + + @Override + public Object getParent(Object element) { + if (element instanceof Node) { + Node node = (Node) element; + try { + String path = node.getPath(); + if (isBasePath(path)) + return null; + else + return node.getParent(); + } catch (RepositoryException e) { + log.warn("Cannot get parent of " + element + ": " + e); + return null; + } + } else if (element instanceof WrappedNode) { + WrappedNode wrappedNode = (WrappedNode) element; + return wrappedNode.getParent(); + } else if (element instanceof NodesWrapper) { + NodesWrapper nodesWrapper = (NodesWrapper) element; + return this.getParent(nodesWrapper.getNode()); + } + return super.getParent(element); + } + + @Override + public boolean hasChildren(Object element) { + try { + if (element instanceof Node) { + Node node = (Node) element; + return node.hasNodes(); + } else if (element instanceof WrappedNode) { + WrappedNode wrappedNode = (WrappedNode) element; + return wrappedNode.getNode().hasNodes(); + } else if (element instanceof NodesWrapper) { + NodesWrapper nodesWrapper = (NodesWrapper) element; + return nodesWrapper.hasChildren(); + } + + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot check whether " + element + + " has children", e); + } + return super.hasChildren(element); + } + + public Session getSession() { + return session; + } +} \ No newline at end of file diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java new file mode 100644 index 000000000..ae5c2936d --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java @@ -0,0 +1,84 @@ +package org.argeo.eclipse.ui.jcr; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.RepositoryException; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventIterator; +import javax.jcr.observation.EventListener; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.eclipse.ui.EclipseUiException; +import org.eclipse.swt.widgets.Display; + +/** + * {@link EventListener} which simplifies running actions within the UI thread. + */ +public abstract class AsyncUiEventListener implements EventListener { + // private final static Log logSuper = LogFactory + // .getLog(AsyncUiEventListener.class); + private final Log logThis = LogFactory.getLog(getClass()); + + private final Display display; + + public AsyncUiEventListener(Display display) { + super(); + this.display = display; + } + + /** Called asynchronously in the UI thread. */ + protected abstract void onEventInUiThread(List events) throws RepositoryException; + + /** + * Whether these events should be processed in the UI or skipped with no UI + * job created. + */ + protected Boolean willProcessInUiThread(List events) throws RepositoryException { + return true; + } + + protected Log getLog() { + return logThis; + } + + public final void onEvent(final EventIterator eventIterator) { + final List events = new ArrayList(); + while (eventIterator.hasNext()) + events.add(eventIterator.nextEvent()); + + if (logThis.isTraceEnabled()) + logThis.trace("Received " + events.size() + " events"); + + try { + if (!willProcessInUiThread(events)) + return; + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot test skip events " + events, e); + } + + // Job job = new Job("JCR Events") { + // protected IStatus run(IProgressMonitor monitor) { + // if (display.isDisposed()) { + // logSuper.warn("Display is disposed cannot update UI"); + // return Status.CANCEL_STATUS; + // } + + if (!display.isDisposed()) + display.asyncExec(new Runnable() { + public void run() { + try { + onEventInUiThread(events); + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot process events " + events, e); + } + } + }); + + // return Status.OK_STATUS; + // } + // }; + // job.schedule(); + } +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java new file mode 100644 index 000000000..22ffeafc6 --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java @@ -0,0 +1,82 @@ +package org.argeo.eclipse.ui.jcr; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; + +import org.argeo.eclipse.ui.EclipseUiException; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.swt.graphics.Image; + +/** + * Default label provider to manage node and corresponding UI objects. It + * provides reasonable overwrite-able default for known JCR types. + */ +public class DefaultNodeLabelProvider extends ColumnLabelProvider { + private static final long serialVersionUID = 1216182332792151235L; + + public String getText(Object element) { + try { + if (element instanceof Node) { + return getText((Node) element); + } else if (element instanceof WrappedNode) { + return getText(((WrappedNode) element).getNode()); + } else if (element instanceof NodesWrapper) { + return getText(((NodesWrapper) element).getNode()); + } + return super.getText(element); + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot get text for of " + element, e); + } + } + + protected String getText(Node node) throws RepositoryException { + if (node.isNodeType(NodeType.MIX_TITLE) + && node.hasProperty(Property.JCR_TITLE)) + return node.getProperty(Property.JCR_TITLE).getString(); + else + return node.getName(); + } + + @Override + public Image getImage(Object element) { + try { + if (element instanceof Node) { + return getImage((Node) element); + } else if (element instanceof WrappedNode) { + return getImage(((WrappedNode) element).getNode()); + } else if (element instanceof NodesWrapper) { + return getImage(((NodesWrapper) element).getNode()); + } + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot retrieve image for " + element, e); + } + return super.getImage(element); + } + + protected Image getImage(Node node) throws RepositoryException { + // FIXME who uses that? + return null; + } + + @Override + public String getToolTipText(Object element) { + try { + if (element instanceof Node) { + return getToolTipText((Node) element); + } else if (element instanceof WrappedNode) { + return getToolTipText(((WrappedNode) element).getNode()); + } else if (element instanceof NodesWrapper) { + return getToolTipText(((NodesWrapper) element).getNode()); + } + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot get tooltip for " + element, e); + } + return super.getToolTipText(element); + } + + protected String getToolTipText(Node node) throws RepositoryException { + return null; + } +} \ No newline at end of file diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/EclipseJcrMonitor.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/EclipseJcrMonitor.java new file mode 100644 index 000000000..b83aaa25a --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/EclipseJcrMonitor.java @@ -0,0 +1,44 @@ +package org.argeo.eclipse.ui.jcr; + +import org.argeo.jcr.JcrMonitor; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * Wraps an Eclipse {@link IProgressMonitor} so that it can be passed to + * framework agnostic Argeo routines. + */ +public class EclipseJcrMonitor implements JcrMonitor { + private final IProgressMonitor progressMonitor; + + public EclipseJcrMonitor(IProgressMonitor progressMonitor) { + this.progressMonitor = progressMonitor; + } + + public void beginTask(String name, int totalWork) { + progressMonitor.beginTask(name, totalWork); + } + + public void done() { + progressMonitor.done(); + } + + public boolean isCanceled() { + return progressMonitor.isCanceled(); + } + + public void setCanceled(boolean value) { + progressMonitor.setCanceled(value); + } + + public void setTaskName(String name) { + progressMonitor.setTaskName(name); + } + + public void subTask(String name) { + progressMonitor.subTask(name); + } + + public void worked(int work) { + progressMonitor.worked(work); + } +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/JcrUiUtils.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/JcrUiUtils.java new file mode 100644 index 000000000..420154b83 --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/JcrUiUtils.java @@ -0,0 +1,149 @@ +package org.argeo.eclipse.ui.jcr; + +import java.util.Calendar; + +import javax.jcr.Node; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; + +import org.argeo.eclipse.ui.EclipseUiException; +import org.argeo.eclipse.ui.jcr.lists.NodeViewerComparator; +import org.argeo.eclipse.ui.jcr.lists.RowViewerComparator; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Table; + +/** Utility methods to simplify UI development using SWT (or RWT), jface and JCR. */ +public class JcrUiUtils { + + /** + * Centralizes management of updating property value. Among other to avoid + * infinite loop when the new value is the same as the ones that is already + * stored in JCR. + * + * @return true if the value as changed + */ + public static boolean setJcrProperty(Node node, String propName, + int propertyType, Object value) { + try { + switch (propertyType) { + case PropertyType.STRING: + if ("".equals((String) value) + && (!node.hasProperty(propName) || node + .hasProperty(propName) + && "".equals(node.getProperty(propName) + .getString()))) + // workaround the fact that the Text widget value cannot be + // set to null + return false; + else if (node.hasProperty(propName) + && node.getProperty(propName).getString() + .equals((String) value)) + // nothing changed yet + return false; + else { + node.setProperty(propName, (String) value); + return true; + } + case PropertyType.BOOLEAN: + if (node.hasProperty(propName) + && node.getProperty(propName).getBoolean() == (Boolean) value) + // nothing changed yet + return false; + else { + node.setProperty(propName, (Boolean) value); + return true; + } + case PropertyType.DATE: + if (node.hasProperty(propName) + && node.getProperty(propName).getDate() + .equals((Calendar) value)) + // nothing changed yet + return false; + else { + node.setProperty(propName, (Calendar) value); + return true; + } + case PropertyType.LONG: + Long lgValue = (Long) value; + + if (lgValue == null) + lgValue = 0L; + + if (node.hasProperty(propName) + && node.getProperty(propName).getLong() == lgValue) + // nothing changed yet + return false; + else { + node.setProperty(propName, lgValue); + return true; + } + + default: + throw new EclipseUiException("Unimplemented property save"); + } + } catch (RepositoryException re) { + throw new EclipseUiException("Unexpected error while setting property", + re); + } + } + + /** + * Creates a new selection adapter in order to provide sorting abitily on a + * SWT Table that display a row list + **/ + public static SelectionAdapter getRowSelectionAdapter(final int index, + final int propertyType, final String selectorName, + final String propertyName, final RowViewerComparator comparator, + final TableViewer viewer) { + SelectionAdapter selectionAdapter = new SelectionAdapter() { + private static final long serialVersionUID = -5738918304901437720L; + + @Override + public void widgetSelected(SelectionEvent e) { + Table table = viewer.getTable(); + comparator.setColumn(propertyType, selectorName, propertyName); + int dir = table.getSortDirection(); + if (table.getSortColumn() == table.getColumn(index)) { + dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; + } else { + dir = SWT.DOWN; + } + table.setSortDirection(dir); + table.setSortColumn(table.getColumn(index)); + viewer.refresh(); + } + }; + return selectionAdapter; + } + + /** + * Creates a new selection adapter in order to provide sorting abitily on a + * swt table that display a row list + **/ + public static SelectionAdapter getNodeSelectionAdapter(final int index, + final int propertyType, final String propertyName, + final NodeViewerComparator comparator, final TableViewer viewer) { + SelectionAdapter selectionAdapter = new SelectionAdapter() { + private static final long serialVersionUID = -1683220869195484625L; + + @Override + public void widgetSelected(SelectionEvent e) { + Table table = viewer.getTable(); + comparator.setColumn(propertyType, propertyName); + int dir = table.getSortDirection(); + if (table.getSortColumn() == table.getColumn(index)) { + dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; + } else { + dir = SWT.DOWN; + } + table.setSortDirection(dir); + table.setSortColumn(table.getColumn(index)); + viewer.refresh(); + } + }; + return selectionAdapter; + } +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/NodeColumnLabelProvider.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/NodeColumnLabelProvider.java new file mode 100644 index 000000000..7e12becd8 --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/NodeColumnLabelProvider.java @@ -0,0 +1,123 @@ +package org.argeo.eclipse.ui.jcr; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; + +/** Simplifies writing JCR-based column label provider. */ +public class NodeColumnLabelProvider extends ColumnLabelProvider { + private static final long serialVersionUID = -6586692836928505358L; + + protected String getNodeText(Node node) throws RepositoryException { + return super.getText(node); + } + + protected String getNodeToolTipText(Node node) throws RepositoryException { + return super.getToolTipText(node); + } + + protected Image getNodeImage(Node node) throws RepositoryException { + return super.getImage(node); + } + + protected Font getNodeFont(Node node) throws RepositoryException { + return super.getFont(node); + } + + public Color getNodeBackground(Node node) throws RepositoryException { + return super.getBackground(node); + } + + public Color getNodeForeground(Node node) throws RepositoryException { + return super.getForeground(node); + } + + @Override + public String getText(Object element) { + try { + if (element instanceof Node) + return getNodeText((Node) element); + else if (element instanceof NodeElement) + return getNodeText(((NodeElement) element).getNode()); + else + throw new IllegalArgumentException("Unsupported element type " + element.getClass()); + } catch (RepositoryException e) { + throw new IllegalStateException("Repository exception when accessing " + element, e); + } + } + + @Override + public Image getImage(Object element) { + try { + if (element instanceof Node) + return getNodeImage((Node) element); + else if (element instanceof NodeElement) + return getNodeImage(((NodeElement) element).getNode()); + else + throw new IllegalArgumentException("Unsupported element type " + element.getClass()); + } catch (RepositoryException e) { + throw new IllegalStateException("Repository exception when accessing " + element, e); + } + } + + @Override + public String getToolTipText(Object element) { + try { + if (element instanceof Node) + return getNodeToolTipText((Node) element); + else if (element instanceof NodeElement) + return getNodeToolTipText(((NodeElement) element).getNode()); + else + throw new IllegalArgumentException("Unsupported element type " + element.getClass()); + } catch (RepositoryException e) { + throw new IllegalStateException("Repository exception when accessing " + element, e); + } + } + + @Override + public Font getFont(Object element) { + try { + if (element instanceof Node) + return getNodeFont((Node) element); + else if (element instanceof NodeElement) + return getNodeFont(((NodeElement) element).getNode()); + else + throw new IllegalArgumentException("Unsupported element type " + element.getClass()); + } catch (RepositoryException e) { + throw new IllegalStateException("Repository exception when accessing " + element, e); + } + } + + @Override + public Color getBackground(Object element) { + try { + if (element instanceof Node) + return getNodeBackground((Node) element); + else if (element instanceof NodeElement) + return getNodeBackground(((NodeElement) element).getNode()); + else + throw new IllegalArgumentException("Unsupported element type " + element.getClass()); + } catch (RepositoryException e) { + throw new IllegalStateException("Repository exception when accessing " + element, e); + } + } + + @Override + public Color getForeground(Object element) { + try { + if (element instanceof Node) + return getNodeForeground((Node) element); + else if (element instanceof NodeElement) + return getNodeForeground(((NodeElement) element).getNode()); + else + throw new IllegalArgumentException("Unsupported element type " + element.getClass()); + } catch (RepositoryException e) { + throw new IllegalStateException("Repository exception when accessing " + element, e); + } + } + +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/NodeElement.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/NodeElement.java new file mode 100644 index 000000000..787c92ed5 --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/NodeElement.java @@ -0,0 +1,8 @@ +package org.argeo.eclipse.ui.jcr; + +import javax.jcr.Node; + +/** An element which is related to a JCR {@link Node}. */ +public interface NodeElement { + Node getNode(); +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/NodeElementComparer.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/NodeElementComparer.java new file mode 100644 index 000000000..2f3d64d6b --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/NodeElementComparer.java @@ -0,0 +1,36 @@ +package org.argeo.eclipse.ui.jcr; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.eclipse.ui.EclipseUiException; +import org.eclipse.jface.viewers.IElementComparer; + +/** Element comparer for JCR node, to be used in JFace viewers. */ +public class NodeElementComparer implements IElementComparer { + + public boolean equals(Object a, Object b) { + try { + if ((a instanceof Node) && (b instanceof Node)) { + Node nodeA = (Node) a; + Node nodeB = (Node) b; + return nodeA.getIdentifier().equals(nodeB.getIdentifier()); + } else { + return a.equals(b); + } + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot compare nodes", e); + } + } + + public int hashCode(Object element) { + try { + if (element instanceof Node) + return ((Node) element).getIdentifier().hashCode(); + return element.hashCode(); + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot get hash code", e); + } + } + +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/NodesWrapper.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/NodesWrapper.java new file mode 100644 index 000000000..2f808a51f --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/NodesWrapper.java @@ -0,0 +1,71 @@ +package org.argeo.eclipse.ui.jcr; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; + +import org.argeo.eclipse.ui.EclipseUiException; + +/** + * Element of tree which is based on a node, but whose children are not + * necessarily this node children. + */ +public class NodesWrapper { + private final Node node; + + public NodesWrapper(Node node) { + super(); + this.node = node; + } + + protected NodeIterator getNodeIterator() throws RepositoryException { + return node.getNodes(); + } + + protected List getWrappedNodes() throws RepositoryException { + List nodes = new ArrayList(); + for (NodeIterator nit = getNodeIterator(); nit.hasNext();) + nodes.add(new WrappedNode(this, nit.nextNode())); + return nodes; + } + + public Object[] getChildren() { + try { + return getWrappedNodes().toArray(); + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot get wrapped children", e); + } + } + + /** + * @return true by default because we don't want to compute the wrapped + * nodes twice + */ + public Boolean hasChildren() { + return true; + } + + public Node getNode() { + return node; + } + + @Override + public int hashCode() { + return node.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof NodesWrapper) + return node.equals(((NodesWrapper) obj).getNode()); + else + return false; + } + + public String toString() { + return "nodes wrapper based on " + node; + } +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/QueryTableContentProvider.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/QueryTableContentProvider.java new file mode 100644 index 000000000..934fa6781 --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/QueryTableContentProvider.java @@ -0,0 +1,35 @@ +package org.argeo.eclipse.ui.jcr; + +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.query.Query; + +import org.argeo.jcr.JcrException; +import org.argeo.jcr.JcrUtils; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; + +/** Content provider based on a JCR {@link Query}. */ +public class QueryTableContentProvider implements IStructuredContentProvider { + private static final long serialVersionUID = 760371460907204722L; + + @Override + public void dispose() { + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + @Override + public Object[] getElements(Object inputElement) { + Query query = (Query) inputElement; + try { + NodeIterator nit = query.execute().getNodes(); + return JcrUtils.nodeIteratorToList(nit).toArray(); + } catch (RepositoryException e) { + throw new JcrException(e); + } + } + +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java new file mode 100644 index 000000000..cb235d76b --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java @@ -0,0 +1,59 @@ +package org.argeo.eclipse.ui.jcr; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.eclipse.ui.EclipseUiException; +import org.argeo.jcr.JcrUtils; + +/** Simple JCR node content provider taking a list of String as base path. */ +public class SimpleNodeContentProvider extends AbstractNodeContentProvider { + private static final long serialVersionUID = -8245193308831384269L; + private final List basePaths; + private Boolean mkdirs = false; + + public SimpleNodeContentProvider(Session session, String... basePaths) { + this(session, Arrays.asList(basePaths)); + } + + public SimpleNodeContentProvider(Session session, List basePaths) { + super(session); + this.basePaths = basePaths; + } + + @Override + protected Boolean isBasePath(String path) { + if (basePaths.contains(path)) + return true; + return super.isBasePath(path); + } + + public Object[] getElements(Object inputElement) { + try { + List baseNodes = new ArrayList(); + for (String basePath : basePaths) + if (mkdirs && !getSession().itemExists(basePath)) + baseNodes.add(JcrUtils.mkdirs(getSession(), basePath)); + else + baseNodes.add(getSession().getNode(basePath)); + return baseNodes.toArray(); + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot get base nodes for " + basePaths, + e); + } + } + + public List getBasePaths() { + return basePaths; + } + + public void setMkdirs(Boolean mkdirs) { + this.mkdirs = mkdirs; + } + +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/VersionColumnLabelProvider.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/VersionColumnLabelProvider.java new file mode 100644 index 000000000..1ce315429 --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/VersionColumnLabelProvider.java @@ -0,0 +1,80 @@ +package org.argeo.eclipse.ui.jcr; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.version.Version; + +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.swt.graphics.Image; + +/** Simplifies writing JCR-based column label provider. */ +public class VersionColumnLabelProvider extends ColumnLabelProvider { + private static final long serialVersionUID = -6117690082313161159L; + + protected String getVersionText(Version version) throws RepositoryException { + return super.getText(version); + } + + protected String getVersionToolTipText(Version version) throws RepositoryException { + return super.getToolTipText(version); + } + + protected Image getVersionImage(Version version) throws RepositoryException { + return super.getImage(version); + } + + protected String getUserName(Version version) throws RepositoryException { + Node node = version.getFrozenNode(); + if(node.hasProperty(Property.JCR_LAST_MODIFIED_BY)) + return node.getProperty(Property.JCR_LAST_MODIFIED_BY).getString(); + if(node.hasProperty(Property.JCR_CREATED_BY)) + return node.getProperty(Property.JCR_CREATED_BY).getString(); + return null; + } + +// protected String getActivityTitle(Version version) throws RepositoryException { +// Node activity = getActivity(version); +// if (activity == null) +// return null; +// if (activity.hasProperty("jcr:activityTitle")) +// return activity.getProperty("jcr:activityTitle").getString(); +// else +// return activity.getName(); +// } +// +// protected Node getActivity(Version version) throws RepositoryException { +// if (version.hasProperty(Property.JCR_ACTIVITY)) { +// return version.getProperty(Property.JCR_ACTIVITY).getNode(); +// } else +// return null; +// } + + @Override + public String getText(Object element) { + try { + return getVersionText((Version) element); + } catch (RepositoryException e) { + throw new RuntimeException("Runtime repository exception when accessing " + element, e); + } + } + + @Override + public Image getImage(Object element) { + try { + return getVersionImage((Version) element); + } catch (RepositoryException e) { + throw new RuntimeException("Runtime repository exception when accessing " + element, e); + } + } + + @Override + public String getToolTipText(Object element) { + try { + return getVersionToolTipText((Version) element); + } catch (RepositoryException e) { + throw new RuntimeException("Runtime repository exception when accessing " + element, e); + } + } + +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/VersionHistoryContentProvider.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/VersionHistoryContentProvider.java new file mode 100644 index 000000000..32e5d30c1 --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/VersionHistoryContentProvider.java @@ -0,0 +1,27 @@ +package org.argeo.eclipse.ui.jcr; + +import javax.jcr.version.VersionHistory; + +import org.argeo.jcr.Jcr; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; + +/** Content provider based on a {@link VersionHistory}. */ +public class VersionHistoryContentProvider implements IStructuredContentProvider { + private static final long serialVersionUID = -4921107883428887012L; + + @Override + public void dispose() { + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + @Override + public Object[] getElements(Object inputElement) { + VersionHistory versionHistory = (VersionHistory) inputElement; + return Jcr.getLinearVersions(versionHistory).toArray(); + } + +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/WrappedNode.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/WrappedNode.java new file mode 100644 index 000000000..43df1fe01 --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/WrappedNode.java @@ -0,0 +1,41 @@ +package org.argeo.eclipse.ui.jcr; + +import javax.jcr.Node; + +/** Wrap a node (created from a {@link NodesWrapper}) */ +public class WrappedNode { + private final NodesWrapper parent; + private final Node node; + + public WrappedNode(NodesWrapper parent, Node node) { + super(); + this.parent = parent; + this.node = node; + } + + public NodesWrapper getParent() { + return parent; + } + + public Node getNode() { + return node; + } + + public String toString() { + return "wrapped " + node; + } + + @Override + public int hashCode() { + return node.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof WrappedNode) + return node.equals(((WrappedNode) obj).getNode()); + else + return false; + } + +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/JcrColumnDefinition.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/JcrColumnDefinition.java new file mode 100644 index 000000000..c5dd73317 --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/JcrColumnDefinition.java @@ -0,0 +1,116 @@ +package org.argeo.eclipse.ui.jcr.lists; + +import javax.jcr.Node; +import javax.jcr.query.Row; + +import org.argeo.eclipse.ui.ColumnDefinition; + +/** + * Utility object to manage column in various tables and extracts displaying + * data from JCR + */ +public class JcrColumnDefinition extends ColumnDefinition { + private final static int DEFAULT_COLUMN_SIZE = 120; + + private String selectorName; + private String propertyName; + private int propertyType; + private int columnSize; + + /** + * Use this kind of columns to configure a table that displays JCR + * {@link Row} + * + * @param selectorName + * @param propertyName + * @param propertyType + * @param headerLabel + */ + public JcrColumnDefinition(String selectorName, String propertyName, + int propertyType, String headerLabel) { + super(new SimpleJcrRowLabelProvider(selectorName, propertyName), + headerLabel); + this.selectorName = selectorName; + this.propertyName = propertyName; + this.propertyType = propertyType; + this.columnSize = DEFAULT_COLUMN_SIZE; + } + + /** + * Use this kind of columns to configure a table that displays JCR + * {@link Row} + * + * @param selectorName + * @param propertyName + * @param propertyType + * @param headerLabel + * @param columnSize + */ + public JcrColumnDefinition(String selectorName, String propertyName, + int propertyType, String headerLabel, int columnSize) { + super(new SimpleJcrRowLabelProvider(selectorName, propertyName), + headerLabel, columnSize); + this.selectorName = selectorName; + this.propertyName = propertyName; + this.propertyType = propertyType; + this.columnSize = columnSize; + } + + /** + * Use this kind of columns to configure a table that displays JCR + * {@link Node} + * + * @param propertyName + * @param propertyType + * @param headerLabel + * @param columnSize + */ + public JcrColumnDefinition(String propertyName, int propertyType, + String headerLabel, int columnSize) { + super(new SimpleJcrNodeLabelProvider(propertyName), headerLabel, + columnSize); + this.propertyName = propertyName; + this.propertyType = propertyType; + this.columnSize = columnSize; + } + + public String getSelectorName() { + return selectorName; + } + + public void setSelectorName(String selectorName) { + this.selectorName = selectorName; + } + + public String getPropertyName() { + return propertyName; + } + + public void setPropertyName(String propertyName) { + this.propertyName = propertyName; + } + + public int getPropertyType() { + return propertyType; + } + + public void setPropertyType(int propertyType) { + this.propertyType = propertyType; + } + + public int getColumnSize() { + return columnSize; + } + + public void setColumnSize(int columnSize) { + this.columnSize = columnSize; + } + + public String getHeaderLabel() { + return super.getLabel(); + } + + public void setHeaderLabel(String headerLabel) { + super.setLabel(headerLabel); + } +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java new file mode 100644 index 000000000..341b3abee --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java @@ -0,0 +1,190 @@ +package org.argeo.eclipse.ui.jcr.lists; + +import java.math.BigDecimal; +import java.util.Calendar; + +import javax.jcr.Node; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFormatException; + +import org.argeo.eclipse.ui.EclipseUiException; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; + +/** + * Base comparator to enable ordering on Table or Tree viewer that display Jcr + * Nodes. + * + * Note that the following snippet must be added before setting the comparator + * to the corresponding control: + * // IMPORTANT: initialize comparator before setting it + * JcrColumnDefinition firstCol = colDefs.get(0); + * comparator.setColumn(firstCol.getPropertyType(), + * firstCol.getPropertyName()); + * viewer.setComparator(comparator); + */ +public class NodeViewerComparator extends ViewerComparator { + private static final long serialVersionUID = -7782916140737279027L; + + protected String propertyName; + + protected int propertyType; + public static final int ASCENDING = 0, DESCENDING = 1; + protected int direction = DESCENDING; + + public NodeViewerComparator() { + } + + /** + * e1 and e2 must both be Jcr nodes. + * + * @param viewer + * @param e1 + * @param e2 + * @return + */ + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + int rc = 0; + long lc = 0; + + try { + Node n1 = (Node) e1; + Node n2 = (Node) e2; + + Value v1 = null; + Value v2 = null; + if (n1.hasProperty(propertyName)) + v1 = n1.getProperty(propertyName).getValue(); + if (n2.hasProperty(propertyName)) + v2 = n2.getProperty(propertyName).getValue(); + + if (v2 == null && v1 == null) + return 0; + else if (v2 == null) + return -1; + else if (v1 == null) + return 1; + + switch (propertyType) { + case PropertyType.STRING: + rc = v1.getString().compareTo(v2.getString()); + break; + case PropertyType.BOOLEAN: + boolean b1 = v1.getBoolean(); + boolean b2 = v2.getBoolean(); + if (b1 == b2) + rc = 0; + else + // we assume true is greater than false + rc = b1 ? 1 : -1; + break; + case PropertyType.DATE: + Calendar c1 = v1.getDate(); + Calendar c2 = v2.getDate(); + if (c1 == null || c2 == null) + // log.trace("undefined date"); + ; + lc = c1.getTimeInMillis() - c2.getTimeInMillis(); + if (lc < Integer.MIN_VALUE) + rc = -1; + else if (lc > Integer.MAX_VALUE) + rc = 1; + else + rc = (int) lc; + break; + case PropertyType.LONG: + long l1; + long l2; + // TODO Sometimes an empty string is set instead of a long + try { + l1 = v1.getLong(); + } catch (ValueFormatException ve) { + l1 = 0; + } + try { + l2 = v2.getLong(); + } catch (ValueFormatException ve) { + l2 = 0; + } + + lc = l1 - l2; + if (lc < Integer.MIN_VALUE) + rc = -1; + else if (lc > Integer.MAX_VALUE) + rc = 1; + else + rc = (int) lc; + break; + case PropertyType.DECIMAL: + BigDecimal bd1 = v1.getDecimal(); + BigDecimal bd2 = v2.getDecimal(); + rc = bd1.compareTo(bd2); + break; + case PropertyType.DOUBLE: + Double d1 = v1.getDouble(); + Double d2 = v2.getDouble(); + rc = d1.compareTo(d2); + break; + default: + throw new EclipseUiException( + "Unimplemented comparaison for PropertyType " + + propertyType); + } + // If descending order, flip the direction + if (direction == DESCENDING) { + rc = -rc; + } + + } catch (RepositoryException re) { + throw new EclipseUiException("Unexpected error " + + "while comparing nodes", re); + } + return rc; + } + + /** + * @param propertyType + * Corresponding JCR type + * @param propertyName + * name of the property to use. + */ + public void setColumn(int propertyType, String propertyName) { + if (this.propertyName != null && this.propertyName.equals(propertyName)) { + // Same column as last sort; toggle the direction + direction = 1 - direction; + } else { + // New column; do an ascending sort + this.propertyType = propertyType; + this.propertyName = propertyName; + direction = ASCENDING; + } + } + + // Getters and setters + protected String getPropertyName() { + return propertyName; + } + + protected void setPropertyName(String propertyName) { + this.propertyName = propertyName; + } + + protected int getPropertyType() { + return propertyType; + } + + protected void setPropertyType(int propertyType) { + this.propertyType = propertyType; + } + + protected int getDirection() { + return direction; + } + + protected void setDirection(int direction) { + this.direction = direction; + } +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java new file mode 100644 index 000000000..455fb0dcd --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java @@ -0,0 +1,62 @@ +package org.argeo.eclipse.ui.jcr.lists; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.query.Row; + +import org.argeo.eclipse.ui.EclipseUiException; +import org.eclipse.jface.viewers.Viewer; + +/** + * Base comparator to enable ordering on Table or Tree viewer that display Jcr + * rows + */ +public class RowViewerComparator extends NodeViewerComparator { + private static final long serialVersionUID = 7020939505172625113L; + protected String selectorName; + + public RowViewerComparator() { + } + + /** + * e1 and e2 must both be Jcr rows. + * + * @param viewer + * @param e1 + * @param e2 + * @return + */ + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + try { + Node n1 = ((Row) e1).getNode(selectorName); + Node n2 = ((Row) e2).getNode(selectorName); + return super.compare(viewer, n1, n2); + } catch (RepositoryException re) { + throw new EclipseUiException("Unexpected error " + + "while comparing nodes", re); + } + } + + /** + * @param propertyType + * Corresponding JCR type + * @param propertyName + * name of the property to use. + */ + public void setColumn(int propertyType, String selectorName, + String propertyName) { + if (this.selectorName != null && getPropertyName() != null + && this.selectorName.equals(selectorName) + && this.getPropertyName().equals(propertyName)) { + // Same column as last sort; toggle the direction + setDirection(1 - getDirection()); + } else { + // New column; do a descending sort + setPropertyType(propertyType); + setPropertyName(propertyName); + this.selectorName = selectorName; + setDirection(NodeViewerComparator.ASCENDING); + } + } +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java new file mode 100644 index 000000000..aa2e3375c --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java @@ -0,0 +1,120 @@ +package org.argeo.eclipse.ui.jcr.lists; + +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; + +import javax.jcr.Node; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; + +import org.argeo.eclipse.ui.EclipseUiException; +import org.eclipse.jface.viewers.ColumnLabelProvider; + +/** Base implementation of a label provider for controls that display JCR Nodes */ +public class SimpleJcrNodeLabelProvider extends ColumnLabelProvider { + private static final long serialVersionUID = -5215787695436221993L; + + private final static String DEFAULT_DATE_FORMAT = "EEE, dd MMM yyyy"; + private final static String DEFAULT_NUMBER_FORMAT = "#,##0.0"; + + private DateFormat dateFormat; + private NumberFormat numberFormat; + + final private String propertyName; + + /** + * Default Label provider for a given property of a node. Using default + * pattern for date and number formating + */ + public SimpleJcrNodeLabelProvider(String propertyName) { + this.propertyName = propertyName; + dateFormat = new SimpleDateFormat(DEFAULT_DATE_FORMAT); + numberFormat = DecimalFormat.getInstance(); + ((DecimalFormat) numberFormat).applyPattern(DEFAULT_NUMBER_FORMAT); + } + + /** + * Label provider for a given property of a node optionally precising date + * and/or number format patterns + */ + public SimpleJcrNodeLabelProvider(String propertyName, + String dateFormatPattern, String numberFormatPattern) { + this.propertyName = propertyName; + dateFormat = new SimpleDateFormat( + dateFormatPattern == null ? DEFAULT_DATE_FORMAT + : dateFormatPattern); + numberFormat = DecimalFormat.getInstance(); + ((DecimalFormat) numberFormat) + .applyPattern(numberFormatPattern == null ? DEFAULT_NUMBER_FORMAT + : numberFormatPattern); + } + + @Override + public String getText(Object element) { + try { + Node currNode = (Node) element; + + if (currNode.hasProperty(propertyName)) { + if (currNode.getProperty(propertyName).isMultiple()) { + StringBuilder builder = new StringBuilder(); + for (Value value : currNode.getProperty(propertyName) + .getValues()) { + String currStr = getSingleValueAsString(value); + if (notEmptyString(currStr)) + builder.append(currStr).append("; "); + } + if (builder.length() > 0) + builder.deleteCharAt(builder.length() - 2); + + return builder.toString(); + } else + return getSingleValueAsString(currNode.getProperty( + propertyName).getValue()); + } else + return ""; + } catch (RepositoryException re) { + throw new EclipseUiException("Unable to get text from row", re); + } + } + + private String getSingleValueAsString(Value value) + throws RepositoryException { + switch (value.getType()) { + case PropertyType.STRING: + return value.getString(); + case PropertyType.BOOLEAN: + return "" + value.getBoolean(); + case PropertyType.DATE: + return dateFormat.format(value.getDate().getTime()); + case PropertyType.LONG: + return "" + value.getLong(); + case PropertyType.DECIMAL: + return numberFormat.format(value.getDecimal()); + case PropertyType.DOUBLE: + return numberFormat.format(value.getDouble()); + case PropertyType.NAME: + return value.getString(); + default: + throw new EclipseUiException("Unimplemented label provider " + + "for property type " + value.getType() + + " while getting property " + propertyName + " - value: " + + value.getString()); + + } + } + + private boolean notEmptyString(String string) { + return string != null && !"".equals(string.trim()); + } + + public void setDateFormat(String dateFormatPattern) { + dateFormat = new SimpleDateFormat(dateFormatPattern); + } + + public void setNumberFormat(String numberFormatPattern) { + ((DecimalFormat) numberFormat).applyPattern(numberFormatPattern); + } +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java new file mode 100644 index 000000000..5d421f64b --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java @@ -0,0 +1,47 @@ +package org.argeo.eclipse.ui.jcr.lists; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.query.Row; + +import org.argeo.eclipse.ui.EclipseUiException; + +/** + * Base implementation of a label provider for widgets that display JCR Rows. + */ +public class SimpleJcrRowLabelProvider extends SimpleJcrNodeLabelProvider { + private static final long serialVersionUID = -3414654948197181740L; + + final private String selectorName; + + /** + * Default Label provider for a given property of a row. Using default + * pattern for date and number formating + */ + public SimpleJcrRowLabelProvider(String selectorName, String propertyName) { + super(propertyName); + this.selectorName = selectorName; + } + + /** + * Label provider for a given property of a node optionally precising date + * and/or number format patterns + */ + public SimpleJcrRowLabelProvider(String selectorName, String propertyName, + String dateFormatPattern, String numberFormatPattern) { + super(propertyName, dateFormatPattern, numberFormatPattern); + this.selectorName = selectorName; + } + + @Override + public String getText(Object element) { + try { + Row currRow = (Row) element; + Node currNode = currRow.getNode(selectorName); + return super.getText(currNode); + } catch (RepositoryException re) { + throw new EclipseUiException("Unable to get Node " + selectorName + + " from row " + element, re); + } + } +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/package-info.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/package-info.java new file mode 100644 index 000000000..3678aab88 --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/lists/package-info.java @@ -0,0 +1,2 @@ +/** Generic SWT/JFace JCR utilities for lists. */ +package org.argeo.eclipse.ui.jcr.lists; \ No newline at end of file diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/package-info.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/package-info.java new file mode 100644 index 000000000..19e3cc3ff --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/package-info.java @@ -0,0 +1,2 @@ +/** Generic SWT/JFace JCR utilities. */ +package org.argeo.eclipse.ui.jcr; \ No newline at end of file diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/JcrFileProvider.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/JcrFileProvider.java new file mode 100644 index 000000000..c82e666d1 --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/JcrFileProvider.java @@ -0,0 +1,129 @@ +package org.argeo.eclipse.ui.jcr.util; + +import java.io.InputStream; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; + +import org.apache.commons.io.IOUtils; +import org.argeo.eclipse.ui.EclipseUiException; +import org.argeo.eclipse.ui.FileProvider; + +/** + * Implements a FileProvider for UI purposes. Note that it might not be very + * reliable as long as we have not fixed login and multi repository issues that + * will be addressed in the next version. + * + * NOTE: id used here is the real id of the JCR Node, not the JCR Path + * + * Relies on common approach for JCR file handling implementation. + * + */ +@SuppressWarnings("deprecation") +public class JcrFileProvider implements FileProvider { + + // private Object[] rootNodes; + private Node refNode; + + /** + * Must be set in order for the provider to be able to get current session + * and thus have the ability to get the file node corresponding to a given + * file ID + * + * @param refNode + */ + public void setReferenceNode(Node refNode) { + // FIXME : this introduces some concurrency ISSUES. + this.refNode = refNode; + } + + public byte[] getByteArrayFileFromId(String fileId) { + InputStream fis = null; + byte[] ba = null; + Node child = getFileNodeFromId(fileId); + try { + fis = (InputStream) child.getProperty(Property.JCR_DATA).getBinary().getStream(); + ba = IOUtils.toByteArray(fis); + + } catch (Exception e) { + throw new EclipseUiException("Stream error while opening file", e); + } finally { + IOUtils.closeQuietly(fis); + } + return ba; + } + + public InputStream getInputStreamFromFileId(String fileId) { + try { + InputStream fis = null; + + Node child = getFileNodeFromId(fileId); + fis = (InputStream) child.getProperty(Property.JCR_DATA).getBinary().getStream(); + return fis; + } catch (RepositoryException re) { + throw new EclipseUiException("Cannot get stream from file node for Id " + fileId, re); + } + } + + /** + * Throws an exception if the node is not found in the current repository (a + * bit like a FileNotFoundException) + * + * @param fileId + * @return Returns the child node of the nt:file node. It is the child node + * that have the jcr:data property where actual file is stored. + * never null + */ + private Node getFileNodeFromId(String fileId) { + try { + Node result = refNode.getSession().getNodeByIdentifier(fileId); + + // rootNodes: for (int j = 0; j < rootNodes.length; j++) { + // // in case we have a classic JCR Node + // if (rootNodes[j] instanceof Node) { + // Node curNode = (Node) rootNodes[j]; + // if (result != null) + // break rootNodes; + // } // Case of a repository Node + // else if (rootNodes[j] instanceof RepositoryNode) { + // Object[] nodes = ((RepositoryNode) rootNodes[j]) + // .getChildren(); + // for (int i = 0; i < nodes.length; i++) { + // Node node = (Node) nodes[i]; + // result = node.getSession().getNodeByIdentifier(fileId); + // if (result != null) + // break rootNodes; + // } + // } + // } + + // Sanity checks + if (result == null) + throw new EclipseUiException("File node not found for ID" + fileId); + + Node child = null; + + boolean isValid = true; + if (!result.isNodeType(NodeType.NT_FILE)) + // useless: mandatory child node + // || !result.hasNode(Property.JCR_CONTENT)) + isValid = false; + else { + child = result.getNode(Property.JCR_CONTENT); + if (!(child.isNodeType(NodeType.NT_RESOURCE) || child.hasProperty(Property.JCR_DATA))) + isValid = false; + } + + if (!isValid) + throw new EclipseUiException("ERROR: In the current implemented model, '" + NodeType.NT_FILE + + "' file node must have a child node named jcr:content " + + "that has a BINARY Property named jcr:data " + "where the actual data is stored"); + return child; + + } catch (RepositoryException re) { + throw new EclipseUiException("Erreur while getting file node of ID " + fileId, re); + } + } +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/JcrItemsComparator.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/JcrItemsComparator.java new file mode 100644 index 000000000..fb123992f --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/JcrItemsComparator.java @@ -0,0 +1,21 @@ +package org.argeo.eclipse.ui.jcr.util; + +import java.util.Comparator; + +import javax.jcr.Item; +import javax.jcr.RepositoryException; + +import org.argeo.eclipse.ui.EclipseUiException; + +/** Compares two JCR items (node or properties) based on their names. */ +public class JcrItemsComparator implements Comparator { + public int compare(Item o1, Item o2) { + try { + // TODO: put folder before files + return o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase()); + } catch (RepositoryException e) { + throw new EclipseUiException("Cannot compare " + o1 + " and " + o2, e); + } + } + +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/NodeViewerComparer.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/NodeViewerComparer.java new file mode 100644 index 000000000..54b795f3b --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/NodeViewerComparer.java @@ -0,0 +1,36 @@ +package org.argeo.eclipse.ui.jcr.util; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.eclipse.ui.EclipseUiException; +import org.eclipse.jface.viewers.IElementComparer; + +/** Compare JCR nodes based on their JCR identifiers, for use in JFace viewers. */ +public class NodeViewerComparer implements IElementComparer { + + // force comparison on Node IDs only. + public boolean equals(Object elementA, Object elementB) { + if (!(elementA instanceof Node) || !(elementB instanceof Node)) { + return elementA == null ? elementB == null : elementA + .equals(elementB); + } else { + + boolean result = false; + try { + String idA = ((Node) elementA).getIdentifier(); + String idB = ((Node) elementB).getIdentifier(); + result = idA == null ? idB == null : idA.equals(idB); + } catch (RepositoryException re) { + throw new EclipseUiException("cannot compare nodes", re); + } + + return result; + } + } + + public int hashCode(Object element) { + // TODO enhanced this method. + return element.getClass().toString().hashCode(); + } +} \ No newline at end of file diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/SingleSessionFileProvider.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/SingleSessionFileProvider.java new file mode 100644 index 000000000..291d579ac --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/SingleSessionFileProvider.java @@ -0,0 +1,98 @@ +package org.argeo.eclipse.ui.jcr.util; + +import java.io.InputStream; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; + +import org.apache.commons.io.IOUtils; +import org.argeo.eclipse.ui.EclipseUiException; +import org.argeo.eclipse.ui.FileProvider; + +/** + * Implements a FileProvider for UI purposes. Unlike the + * JcrFileProvider , it relies on a single session and manages + * nodes with path only. + * + * Note that considered id is the JCR path + * + * Relies on common approach for JCR file handling implementation. + */ +@SuppressWarnings("deprecation") +public class SingleSessionFileProvider implements FileProvider { + + private Session session; + + public SingleSessionFileProvider(Session session) { + this.session = session; + } + + public byte[] getByteArrayFileFromId(String fileId) { + InputStream fis = null; + byte[] ba = null; + Node child = getFileNodeFromId(fileId); + try { + fis = (InputStream) child.getProperty(Property.JCR_DATA) + .getBinary().getStream(); + ba = IOUtils.toByteArray(fis); + + } catch (Exception e) { + throw new EclipseUiException("Stream error while opening file", e); + } finally { + IOUtils.closeQuietly(fis); + } + return ba; + } + + public InputStream getInputStreamFromFileId(String fileId) { + try { + InputStream fis = null; + + Node child = getFileNodeFromId(fileId); + fis = (InputStream) child.getProperty(Property.JCR_DATA) + .getBinary().getStream(); + return fis; + } catch (RepositoryException re) { + throw new EclipseUiException("Cannot get stream from file node for Id " + + fileId, re); + } + } + + /** + * + * @param fileId + * @return Returns the child node of the nt:file node. It is the child node + * that have the jcr:data property where actual file is stored. + * never null + */ + private Node getFileNodeFromId(String fileId) { + try { + Node result = null; + result = session.getNode(fileId); + + // Sanity checks + if (result == null) + throw new EclipseUiException("File node not found for ID" + fileId); + + // Ensure that the node have the correct type. + if (!result.isNodeType(NodeType.NT_FILE)) + throw new EclipseUiException( + "Cannot open file children Node that are not of " + + NodeType.NT_RESOURCE + " type."); + + Node child = result.getNodes().nextNode(); + if (child == null || !child.isNodeType(NodeType.NT_RESOURCE)) + throw new EclipseUiException( + "ERROR: IN the current implemented model, " + + NodeType.NT_FILE + + " file node must have one and only one child of the nt:ressource, where actual data is stored"); + return child; + } catch (RepositoryException re) { + throw new EclipseUiException("Erreur while getting file node of ID " + + fileId, re); + } + } +} diff --git a/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/package-info.java b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/package-info.java new file mode 100644 index 000000000..016348cda --- /dev/null +++ b/org.argeo.cms.ui/src/org/argeo/eclipse/ui/jcr/util/package-info.java @@ -0,0 +1,2 @@ +/** Generic SWT/JFace JCR helpers. */ +package org.argeo.eclipse.ui.jcr.util; \ No newline at end of file diff --git a/org.argeo.cms/build.properties b/org.argeo.cms/build.properties index 55f4d9ae5..c5d6b5045 100644 --- a/org.argeo.cms/build.properties +++ b/org.argeo.cms/build.properties @@ -6,5 +6,4 @@ bin.includes = META-INF/,\ source.. = src/,\ ext/test/ additional.bundles = org.apache.jackrabbit.data,\ - org.argeo.jcr,\ org.junit diff --git a/org.argeo.eclipse.ui/bnd.bnd b/org.argeo.eclipse.ui/bnd.bnd index b836fc0e9..ad8e58178 100644 --- a/org.argeo.eclipse.ui/bnd.bnd +++ b/org.argeo.eclipse.ui/bnd.bnd @@ -1,5 +1,4 @@ -Import-Package: javax.jcr.nodetype,\ - org.eclipse.swt,\ +Import-Package: org.eclipse.swt,\ org.eclipse.jface.window,\ org.eclipse.core.commands.common,\ * diff --git a/org.argeo.eclipse.ui/pom.xml b/org.argeo.eclipse.ui/pom.xml index 1574da881..9a97ad070 100644 --- a/org.argeo.eclipse.ui/pom.xml +++ b/org.argeo.eclipse.ui/pom.xml @@ -17,7 +17,7 @@ org.argeo.commons - org.argeo.jcr + org.argeo.cms.jcr 2.3-SNAPSHOT diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/EclipseJcrMonitor.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/EclipseJcrMonitor.java deleted file mode 100644 index ffc50adad..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/EclipseJcrMonitor.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.argeo.eclipse.ui; - -import org.argeo.jcr.JcrMonitor; -import org.eclipse.core.runtime.IProgressMonitor; - -/** - * Wraps an Eclipse {@link IProgressMonitor} so that it can be passed to - * framework agnostic Argeo routines. - */ -public class EclipseJcrMonitor implements JcrMonitor { - private final IProgressMonitor progressMonitor; - - public EclipseJcrMonitor(IProgressMonitor progressMonitor) { - this.progressMonitor = progressMonitor; - } - - public void beginTask(String name, int totalWork) { - progressMonitor.beginTask(name, totalWork); - } - - public void done() { - progressMonitor.done(); - } - - public boolean isCanceled() { - return progressMonitor.isCanceled(); - } - - public void setCanceled(boolean value) { - progressMonitor.setCanceled(value); - } - - public void setTaskName(String name) { - progressMonitor.setTaskName(name); - } - - public void subTask(String name) { - progressMonitor.subTask(name); - } - - public void worked(int work) { - progressMonitor.worked(work); - } -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java deleted file mode 100644 index 8f7c2f99a..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/AbstractNodeContentProvider.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.eclipse.ui.AbstractTreeContentProvider; -import org.argeo.eclipse.ui.EclipseUiException; - -/** Canonical implementation of tree content provider manipulating JCR nodes. */ -public abstract class AbstractNodeContentProvider extends - AbstractTreeContentProvider { - private static final long serialVersionUID = -4905836490027272569L; - - private final static Log log = LogFactory - .getLog(AbstractNodeContentProvider.class); - - private Session session; - - public AbstractNodeContentProvider(Session session) { - this.session = session; - } - - /** - * Whether this path is a base path (and thus has no parent). By default it - * returns true if path is '/' (root node) - */ - protected Boolean isBasePath(String path) { - // root node - return path.equals("/"); - } - - @Override - public Object[] getChildren(Object element) { - Object[] children; - if (element instanceof Node) { - try { - Node node = (Node) element; - children = getChildren(node); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get children of " + element, e); - } - } else if (element instanceof WrappedNode) { - WrappedNode wrappedNode = (WrappedNode) element; - try { - children = getChildren(wrappedNode.getNode()); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get children of " - + wrappedNode, e); - } - } else if (element instanceof NodesWrapper) { - NodesWrapper node = (NodesWrapper) element; - children = node.getChildren(); - } else { - children = super.getChildren(element); - } - - children = sort(element, children); - return children; - } - - /** Do not sort by default. To be overidden to provide custom sort. */ - protected Object[] sort(Object parent, Object[] children) { - return children; - } - - /** - * To be overridden in order to filter out some nodes. Does nothing by - * default. The provided list is a temporary one and can thus be modified - * directly . (e.g. via an iterator) - */ - protected List filterChildren(List children) - throws RepositoryException { - return children; - } - - protected Object[] getChildren(Node node) throws RepositoryException { - List nodes = new ArrayList(); - for (NodeIterator nit = node.getNodes(); nit.hasNext();) - nodes.add(nit.nextNode()); - nodes = filterChildren(nodes); - return nodes.toArray(); - } - - @Override - public Object getParent(Object element) { - if (element instanceof Node) { - Node node = (Node) element; - try { - String path = node.getPath(); - if (isBasePath(path)) - return null; - else - return node.getParent(); - } catch (RepositoryException e) { - log.warn("Cannot get parent of " + element + ": " + e); - return null; - } - } else if (element instanceof WrappedNode) { - WrappedNode wrappedNode = (WrappedNode) element; - return wrappedNode.getParent(); - } else if (element instanceof NodesWrapper) { - NodesWrapper nodesWrapper = (NodesWrapper) element; - return this.getParent(nodesWrapper.getNode()); - } - return super.getParent(element); - } - - @Override - public boolean hasChildren(Object element) { - try { - if (element instanceof Node) { - Node node = (Node) element; - return node.hasNodes(); - } else if (element instanceof WrappedNode) { - WrappedNode wrappedNode = (WrappedNode) element; - return wrappedNode.getNode().hasNodes(); - } else if (element instanceof NodesWrapper) { - NodesWrapper nodesWrapper = (NodesWrapper) element; - return nodesWrapper.hasChildren(); - } - - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot check whether " + element - + " has children", e); - } - return super.hasChildren(element); - } - - public Session getSession() { - return session; - } -} \ No newline at end of file diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java deleted file mode 100644 index ae5c2936d..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/AsyncUiEventListener.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.RepositoryException; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventIterator; -import javax.jcr.observation.EventListener; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.swt.widgets.Display; - -/** - * {@link EventListener} which simplifies running actions within the UI thread. - */ -public abstract class AsyncUiEventListener implements EventListener { - // private final static Log logSuper = LogFactory - // .getLog(AsyncUiEventListener.class); - private final Log logThis = LogFactory.getLog(getClass()); - - private final Display display; - - public AsyncUiEventListener(Display display) { - super(); - this.display = display; - } - - /** Called asynchronously in the UI thread. */ - protected abstract void onEventInUiThread(List events) throws RepositoryException; - - /** - * Whether these events should be processed in the UI or skipped with no UI - * job created. - */ - protected Boolean willProcessInUiThread(List events) throws RepositoryException { - return true; - } - - protected Log getLog() { - return logThis; - } - - public final void onEvent(final EventIterator eventIterator) { - final List events = new ArrayList(); - while (eventIterator.hasNext()) - events.add(eventIterator.nextEvent()); - - if (logThis.isTraceEnabled()) - logThis.trace("Received " + events.size() + " events"); - - try { - if (!willProcessInUiThread(events)) - return; - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot test skip events " + events, e); - } - - // Job job = new Job("JCR Events") { - // protected IStatus run(IProgressMonitor monitor) { - // if (display.isDisposed()) { - // logSuper.warn("Display is disposed cannot update UI"); - // return Status.CANCEL_STATUS; - // } - - if (!display.isDisposed()) - display.asyncExec(new Runnable() { - public void run() { - try { - onEventInUiThread(events); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot process events " + events, e); - } - } - }); - - // return Status.OK_STATUS; - // } - // }; - // job.schedule(); - } -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java deleted file mode 100644 index 22ffeafc6..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/DefaultNodeLabelProvider.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.swt.graphics.Image; - -/** - * Default label provider to manage node and corresponding UI objects. It - * provides reasonable overwrite-able default for known JCR types. - */ -public class DefaultNodeLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = 1216182332792151235L; - - public String getText(Object element) { - try { - if (element instanceof Node) { - return getText((Node) element); - } else if (element instanceof WrappedNode) { - return getText(((WrappedNode) element).getNode()); - } else if (element instanceof NodesWrapper) { - return getText(((NodesWrapper) element).getNode()); - } - return super.getText(element); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get text for of " + element, e); - } - } - - protected String getText(Node node) throws RepositoryException { - if (node.isNodeType(NodeType.MIX_TITLE) - && node.hasProperty(Property.JCR_TITLE)) - return node.getProperty(Property.JCR_TITLE).getString(); - else - return node.getName(); - } - - @Override - public Image getImage(Object element) { - try { - if (element instanceof Node) { - return getImage((Node) element); - } else if (element instanceof WrappedNode) { - return getImage(((WrappedNode) element).getNode()); - } else if (element instanceof NodesWrapper) { - return getImage(((NodesWrapper) element).getNode()); - } - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot retrieve image for " + element, e); - } - return super.getImage(element); - } - - protected Image getImage(Node node) throws RepositoryException { - // FIXME who uses that? - return null; - } - - @Override - public String getToolTipText(Object element) { - try { - if (element instanceof Node) { - return getToolTipText((Node) element); - } else if (element instanceof WrappedNode) { - return getToolTipText(((WrappedNode) element).getNode()); - } else if (element instanceof NodesWrapper) { - return getToolTipText(((NodesWrapper) element).getNode()); - } - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get tooltip for " + element, e); - } - return super.getToolTipText(element); - } - - protected String getToolTipText(Node node) throws RepositoryException { - return null; - } -} \ No newline at end of file diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/JcrUiUtils.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/JcrUiUtils.java deleted file mode 100644 index 420154b83..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/JcrUiUtils.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import java.util.Calendar; - -import javax.jcr.Node; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.jcr.lists.NodeViewerComparator; -import org.argeo.eclipse.ui.jcr.lists.RowViewerComparator; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.widgets.Table; - -/** Utility methods to simplify UI development using SWT (or RWT), jface and JCR. */ -public class JcrUiUtils { - - /** - * Centralizes management of updating property value. Among other to avoid - * infinite loop when the new value is the same as the ones that is already - * stored in JCR. - * - * @return true if the value as changed - */ - public static boolean setJcrProperty(Node node, String propName, - int propertyType, Object value) { - try { - switch (propertyType) { - case PropertyType.STRING: - if ("".equals((String) value) - && (!node.hasProperty(propName) || node - .hasProperty(propName) - && "".equals(node.getProperty(propName) - .getString()))) - // workaround the fact that the Text widget value cannot be - // set to null - return false; - else if (node.hasProperty(propName) - && node.getProperty(propName).getString() - .equals((String) value)) - // nothing changed yet - return false; - else { - node.setProperty(propName, (String) value); - return true; - } - case PropertyType.BOOLEAN: - if (node.hasProperty(propName) - && node.getProperty(propName).getBoolean() == (Boolean) value) - // nothing changed yet - return false; - else { - node.setProperty(propName, (Boolean) value); - return true; - } - case PropertyType.DATE: - if (node.hasProperty(propName) - && node.getProperty(propName).getDate() - .equals((Calendar) value)) - // nothing changed yet - return false; - else { - node.setProperty(propName, (Calendar) value); - return true; - } - case PropertyType.LONG: - Long lgValue = (Long) value; - - if (lgValue == null) - lgValue = 0L; - - if (node.hasProperty(propName) - && node.getProperty(propName).getLong() == lgValue) - // nothing changed yet - return false; - else { - node.setProperty(propName, lgValue); - return true; - } - - default: - throw new EclipseUiException("Unimplemented property save"); - } - } catch (RepositoryException re) { - throw new EclipseUiException("Unexpected error while setting property", - re); - } - } - - /** - * Creates a new selection adapter in order to provide sorting abitily on a - * SWT Table that display a row list - **/ - public static SelectionAdapter getRowSelectionAdapter(final int index, - final int propertyType, final String selectorName, - final String propertyName, final RowViewerComparator comparator, - final TableViewer viewer) { - SelectionAdapter selectionAdapter = new SelectionAdapter() { - private static final long serialVersionUID = -5738918304901437720L; - - @Override - public void widgetSelected(SelectionEvent e) { - Table table = viewer.getTable(); - comparator.setColumn(propertyType, selectorName, propertyName); - int dir = table.getSortDirection(); - if (table.getSortColumn() == table.getColumn(index)) { - dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; - } else { - dir = SWT.DOWN; - } - table.setSortDirection(dir); - table.setSortColumn(table.getColumn(index)); - viewer.refresh(); - } - }; - return selectionAdapter; - } - - /** - * Creates a new selection adapter in order to provide sorting abitily on a - * swt table that display a row list - **/ - public static SelectionAdapter getNodeSelectionAdapter(final int index, - final int propertyType, final String propertyName, - final NodeViewerComparator comparator, final TableViewer viewer) { - SelectionAdapter selectionAdapter = new SelectionAdapter() { - private static final long serialVersionUID = -1683220869195484625L; - - @Override - public void widgetSelected(SelectionEvent e) { - Table table = viewer.getTable(); - comparator.setColumn(propertyType, propertyName); - int dir = table.getSortDirection(); - if (table.getSortColumn() == table.getColumn(index)) { - dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; - } else { - dir = SWT.DOWN; - } - table.setSortDirection(dir); - table.setSortColumn(table.getColumn(index)); - viewer.refresh(); - } - }; - return selectionAdapter; - } -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/NodeColumnLabelProvider.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/NodeColumnLabelProvider.java deleted file mode 100644 index 7e12becd8..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/NodeColumnLabelProvider.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.Image; - -/** Simplifies writing JCR-based column label provider. */ -public class NodeColumnLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = -6586692836928505358L; - - protected String getNodeText(Node node) throws RepositoryException { - return super.getText(node); - } - - protected String getNodeToolTipText(Node node) throws RepositoryException { - return super.getToolTipText(node); - } - - protected Image getNodeImage(Node node) throws RepositoryException { - return super.getImage(node); - } - - protected Font getNodeFont(Node node) throws RepositoryException { - return super.getFont(node); - } - - public Color getNodeBackground(Node node) throws RepositoryException { - return super.getBackground(node); - } - - public Color getNodeForeground(Node node) throws RepositoryException { - return super.getForeground(node); - } - - @Override - public String getText(Object element) { - try { - if (element instanceof Node) - return getNodeText((Node) element); - else if (element instanceof NodeElement) - return getNodeText(((NodeElement) element).getNode()); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public Image getImage(Object element) { - try { - if (element instanceof Node) - return getNodeImage((Node) element); - else if (element instanceof NodeElement) - return getNodeImage(((NodeElement) element).getNode()); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public String getToolTipText(Object element) { - try { - if (element instanceof Node) - return getNodeToolTipText((Node) element); - else if (element instanceof NodeElement) - return getNodeToolTipText(((NodeElement) element).getNode()); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public Font getFont(Object element) { - try { - if (element instanceof Node) - return getNodeFont((Node) element); - else if (element instanceof NodeElement) - return getNodeFont(((NodeElement) element).getNode()); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public Color getBackground(Object element) { - try { - if (element instanceof Node) - return getNodeBackground((Node) element); - else if (element instanceof NodeElement) - return getNodeBackground(((NodeElement) element).getNode()); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - - @Override - public Color getForeground(Object element) { - try { - if (element instanceof Node) - return getNodeForeground((Node) element); - else if (element instanceof NodeElement) - return getNodeForeground(((NodeElement) element).getNode()); - else - throw new IllegalArgumentException("Unsupported element type " + element.getClass()); - } catch (RepositoryException e) { - throw new IllegalStateException("Repository exception when accessing " + element, e); - } - } - -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/NodeElement.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/NodeElement.java deleted file mode 100644 index 787c92ed5..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/NodeElement.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; - -/** An element which is related to a JCR {@link Node}. */ -public interface NodeElement { - Node getNode(); -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/NodeElementComparer.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/NodeElementComparer.java deleted file mode 100644 index 2f3d64d6b..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/NodeElementComparer.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.IElementComparer; - -/** Element comparer for JCR node, to be used in JFace viewers. */ -public class NodeElementComparer implements IElementComparer { - - public boolean equals(Object a, Object b) { - try { - if ((a instanceof Node) && (b instanceof Node)) { - Node nodeA = (Node) a; - Node nodeB = (Node) b; - return nodeA.getIdentifier().equals(nodeB.getIdentifier()); - } else { - return a.equals(b); - } - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot compare nodes", e); - } - } - - public int hashCode(Object element) { - try { - if (element instanceof Node) - return ((Node) element).getIdentifier().hashCode(); - return element.hashCode(); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get hash code", e); - } - } - -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/NodesWrapper.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/NodesWrapper.java deleted file mode 100644 index 2f808a51f..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/NodesWrapper.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import java.util.ArrayList; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; - -import org.argeo.eclipse.ui.EclipseUiException; - -/** - * Element of tree which is based on a node, but whose children are not - * necessarily this node children. - */ -public class NodesWrapper { - private final Node node; - - public NodesWrapper(Node node) { - super(); - this.node = node; - } - - protected NodeIterator getNodeIterator() throws RepositoryException { - return node.getNodes(); - } - - protected List getWrappedNodes() throws RepositoryException { - List nodes = new ArrayList(); - for (NodeIterator nit = getNodeIterator(); nit.hasNext();) - nodes.add(new WrappedNode(this, nit.nextNode())); - return nodes; - } - - public Object[] getChildren() { - try { - return getWrappedNodes().toArray(); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get wrapped children", e); - } - } - - /** - * @return true by default because we don't want to compute the wrapped - * nodes twice - */ - public Boolean hasChildren() { - return true; - } - - public Node getNode() { - return node; - } - - @Override - public int hashCode() { - return node.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof NodesWrapper) - return node.equals(((NodesWrapper) obj).getNode()); - else - return false; - } - - public String toString() { - return "nodes wrapper based on " + node; - } -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/QueryTableContentProvider.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/QueryTableContentProvider.java deleted file mode 100644 index 934fa6781..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/QueryTableContentProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.query.Query; - -import org.argeo.jcr.JcrException; -import org.argeo.jcr.JcrUtils; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** Content provider based on a JCR {@link Query}. */ -public class QueryTableContentProvider implements IStructuredContentProvider { - private static final long serialVersionUID = 760371460907204722L; - - @Override - public void dispose() { - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - @Override - public Object[] getElements(Object inputElement) { - Query query = (Query) inputElement; - try { - NodeIterator nit = query.execute().getNodes(); - return JcrUtils.nodeIteratorToList(nit).toArray(); - } catch (RepositoryException e) { - throw new JcrException(e); - } - } - -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java deleted file mode 100644 index cb235d76b..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/SimpleNodeContentProvider.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.jcr.JcrUtils; - -/** Simple JCR node content provider taking a list of String as base path. */ -public class SimpleNodeContentProvider extends AbstractNodeContentProvider { - private static final long serialVersionUID = -8245193308831384269L; - private final List basePaths; - private Boolean mkdirs = false; - - public SimpleNodeContentProvider(Session session, String... basePaths) { - this(session, Arrays.asList(basePaths)); - } - - public SimpleNodeContentProvider(Session session, List basePaths) { - super(session); - this.basePaths = basePaths; - } - - @Override - protected Boolean isBasePath(String path) { - if (basePaths.contains(path)) - return true; - return super.isBasePath(path); - } - - public Object[] getElements(Object inputElement) { - try { - List baseNodes = new ArrayList(); - for (String basePath : basePaths) - if (mkdirs && !getSession().itemExists(basePath)) - baseNodes.add(JcrUtils.mkdirs(getSession(), basePath)); - else - baseNodes.add(getSession().getNode(basePath)); - return baseNodes.toArray(); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot get base nodes for " + basePaths, - e); - } - } - - public List getBasePaths() { - return basePaths; - } - - public void setMkdirs(Boolean mkdirs) { - this.mkdirs = mkdirs; - } - -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/VersionColumnLabelProvider.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/VersionColumnLabelProvider.java deleted file mode 100644 index 1ce315429..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/VersionColumnLabelProvider.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.version.Version; - -import org.eclipse.jface.viewers.ColumnLabelProvider; -import org.eclipse.swt.graphics.Image; - -/** Simplifies writing JCR-based column label provider. */ -public class VersionColumnLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = -6117690082313161159L; - - protected String getVersionText(Version version) throws RepositoryException { - return super.getText(version); - } - - protected String getVersionToolTipText(Version version) throws RepositoryException { - return super.getToolTipText(version); - } - - protected Image getVersionImage(Version version) throws RepositoryException { - return super.getImage(version); - } - - protected String getUserName(Version version) throws RepositoryException { - Node node = version.getFrozenNode(); - if(node.hasProperty(Property.JCR_LAST_MODIFIED_BY)) - return node.getProperty(Property.JCR_LAST_MODIFIED_BY).getString(); - if(node.hasProperty(Property.JCR_CREATED_BY)) - return node.getProperty(Property.JCR_CREATED_BY).getString(); - return null; - } - -// protected String getActivityTitle(Version version) throws RepositoryException { -// Node activity = getActivity(version); -// if (activity == null) -// return null; -// if (activity.hasProperty("jcr:activityTitle")) -// return activity.getProperty("jcr:activityTitle").getString(); -// else -// return activity.getName(); -// } -// -// protected Node getActivity(Version version) throws RepositoryException { -// if (version.hasProperty(Property.JCR_ACTIVITY)) { -// return version.getProperty(Property.JCR_ACTIVITY).getNode(); -// } else -// return null; -// } - - @Override - public String getText(Object element) { - try { - return getVersionText((Version) element); - } catch (RepositoryException e) { - throw new RuntimeException("Runtime repository exception when accessing " + element, e); - } - } - - @Override - public Image getImage(Object element) { - try { - return getVersionImage((Version) element); - } catch (RepositoryException e) { - throw new RuntimeException("Runtime repository exception when accessing " + element, e); - } - } - - @Override - public String getToolTipText(Object element) { - try { - return getVersionToolTipText((Version) element); - } catch (RepositoryException e) { - throw new RuntimeException("Runtime repository exception when accessing " + element, e); - } - } - -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/VersionHistoryContentProvider.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/VersionHistoryContentProvider.java deleted file mode 100644 index 32e5d30c1..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/VersionHistoryContentProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.version.VersionHistory; - -import org.argeo.jcr.Jcr; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.Viewer; - -/** Content provider based on a {@link VersionHistory}. */ -public class VersionHistoryContentProvider implements IStructuredContentProvider { - private static final long serialVersionUID = -4921107883428887012L; - - @Override - public void dispose() { - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - @Override - public Object[] getElements(Object inputElement) { - VersionHistory versionHistory = (VersionHistory) inputElement; - return Jcr.getLinearVersions(versionHistory).toArray(); - } - -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/WrappedNode.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/WrappedNode.java deleted file mode 100644 index 43df1fe01..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/WrappedNode.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.argeo.eclipse.ui.jcr; - -import javax.jcr.Node; - -/** Wrap a node (created from a {@link NodesWrapper}) */ -public class WrappedNode { - private final NodesWrapper parent; - private final Node node; - - public WrappedNode(NodesWrapper parent, Node node) { - super(); - this.parent = parent; - this.node = node; - } - - public NodesWrapper getParent() { - return parent; - } - - public Node getNode() { - return node; - } - - public String toString() { - return "wrapped " + node; - } - - @Override - public int hashCode() { - return node.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof WrappedNode) - return node.equals(((WrappedNode) obj).getNode()); - else - return false; - } - -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/JcrColumnDefinition.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/JcrColumnDefinition.java deleted file mode 100644 index c5dd73317..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/JcrColumnDefinition.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import javax.jcr.Node; -import javax.jcr.query.Row; - -import org.argeo.eclipse.ui.ColumnDefinition; - -/** - * Utility object to manage column in various tables and extracts displaying - * data from JCR - */ -public class JcrColumnDefinition extends ColumnDefinition { - private final static int DEFAULT_COLUMN_SIZE = 120; - - private String selectorName; - private String propertyName; - private int propertyType; - private int columnSize; - - /** - * Use this kind of columns to configure a table that displays JCR - * {@link Row} - * - * @param selectorName - * @param propertyName - * @param propertyType - * @param headerLabel - */ - public JcrColumnDefinition(String selectorName, String propertyName, - int propertyType, String headerLabel) { - super(new SimpleJcrRowLabelProvider(selectorName, propertyName), - headerLabel); - this.selectorName = selectorName; - this.propertyName = propertyName; - this.propertyType = propertyType; - this.columnSize = DEFAULT_COLUMN_SIZE; - } - - /** - * Use this kind of columns to configure a table that displays JCR - * {@link Row} - * - * @param selectorName - * @param propertyName - * @param propertyType - * @param headerLabel - * @param columnSize - */ - public JcrColumnDefinition(String selectorName, String propertyName, - int propertyType, String headerLabel, int columnSize) { - super(new SimpleJcrRowLabelProvider(selectorName, propertyName), - headerLabel, columnSize); - this.selectorName = selectorName; - this.propertyName = propertyName; - this.propertyType = propertyType; - this.columnSize = columnSize; - } - - /** - * Use this kind of columns to configure a table that displays JCR - * {@link Node} - * - * @param propertyName - * @param propertyType - * @param headerLabel - * @param columnSize - */ - public JcrColumnDefinition(String propertyName, int propertyType, - String headerLabel, int columnSize) { - super(new SimpleJcrNodeLabelProvider(propertyName), headerLabel, - columnSize); - this.propertyName = propertyName; - this.propertyType = propertyType; - this.columnSize = columnSize; - } - - public String getSelectorName() { - return selectorName; - } - - public void setSelectorName(String selectorName) { - this.selectorName = selectorName; - } - - public String getPropertyName() { - return propertyName; - } - - public void setPropertyName(String propertyName) { - this.propertyName = propertyName; - } - - public int getPropertyType() { - return propertyType; - } - - public void setPropertyType(int propertyType) { - this.propertyType = propertyType; - } - - public int getColumnSize() { - return columnSize; - } - - public void setColumnSize(int columnSize) { - this.columnSize = columnSize; - } - - public String getHeaderLabel() { - return super.getLabel(); - } - - public void setHeaderLabel(String headerLabel) { - super.setLabel(headerLabel); - } -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java deleted file mode 100644 index 341b3abee..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/NodeViewerComparator.java +++ /dev/null @@ -1,190 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import java.math.BigDecimal; -import java.util.Calendar; - -import javax.jcr.Node; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; -import javax.jcr.ValueFormatException; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerComparator; - -/** - * Base comparator to enable ordering on Table or Tree viewer that display Jcr - * Nodes. - * - * Note that the following snippet must be added before setting the comparator - * to the corresponding control: - * // IMPORTANT: initialize comparator before setting it - * JcrColumnDefinition firstCol = colDefs.get(0); - * comparator.setColumn(firstCol.getPropertyType(), - * firstCol.getPropertyName()); - * viewer.setComparator(comparator); - */ -public class NodeViewerComparator extends ViewerComparator { - private static final long serialVersionUID = -7782916140737279027L; - - protected String propertyName; - - protected int propertyType; - public static final int ASCENDING = 0, DESCENDING = 1; - protected int direction = DESCENDING; - - public NodeViewerComparator() { - } - - /** - * e1 and e2 must both be Jcr nodes. - * - * @param viewer - * @param e1 - * @param e2 - * @return - */ - @Override - public int compare(Viewer viewer, Object e1, Object e2) { - int rc = 0; - long lc = 0; - - try { - Node n1 = (Node) e1; - Node n2 = (Node) e2; - - Value v1 = null; - Value v2 = null; - if (n1.hasProperty(propertyName)) - v1 = n1.getProperty(propertyName).getValue(); - if (n2.hasProperty(propertyName)) - v2 = n2.getProperty(propertyName).getValue(); - - if (v2 == null && v1 == null) - return 0; - else if (v2 == null) - return -1; - else if (v1 == null) - return 1; - - switch (propertyType) { - case PropertyType.STRING: - rc = v1.getString().compareTo(v2.getString()); - break; - case PropertyType.BOOLEAN: - boolean b1 = v1.getBoolean(); - boolean b2 = v2.getBoolean(); - if (b1 == b2) - rc = 0; - else - // we assume true is greater than false - rc = b1 ? 1 : -1; - break; - case PropertyType.DATE: - Calendar c1 = v1.getDate(); - Calendar c2 = v2.getDate(); - if (c1 == null || c2 == null) - // log.trace("undefined date"); - ; - lc = c1.getTimeInMillis() - c2.getTimeInMillis(); - if (lc < Integer.MIN_VALUE) - rc = -1; - else if (lc > Integer.MAX_VALUE) - rc = 1; - else - rc = (int) lc; - break; - case PropertyType.LONG: - long l1; - long l2; - // TODO Sometimes an empty string is set instead of a long - try { - l1 = v1.getLong(); - } catch (ValueFormatException ve) { - l1 = 0; - } - try { - l2 = v2.getLong(); - } catch (ValueFormatException ve) { - l2 = 0; - } - - lc = l1 - l2; - if (lc < Integer.MIN_VALUE) - rc = -1; - else if (lc > Integer.MAX_VALUE) - rc = 1; - else - rc = (int) lc; - break; - case PropertyType.DECIMAL: - BigDecimal bd1 = v1.getDecimal(); - BigDecimal bd2 = v2.getDecimal(); - rc = bd1.compareTo(bd2); - break; - case PropertyType.DOUBLE: - Double d1 = v1.getDouble(); - Double d2 = v2.getDouble(); - rc = d1.compareTo(d2); - break; - default: - throw new EclipseUiException( - "Unimplemented comparaison for PropertyType " - + propertyType); - } - // If descending order, flip the direction - if (direction == DESCENDING) { - rc = -rc; - } - - } catch (RepositoryException re) { - throw new EclipseUiException("Unexpected error " - + "while comparing nodes", re); - } - return rc; - } - - /** - * @param propertyType - * Corresponding JCR type - * @param propertyName - * name of the property to use. - */ - public void setColumn(int propertyType, String propertyName) { - if (this.propertyName != null && this.propertyName.equals(propertyName)) { - // Same column as last sort; toggle the direction - direction = 1 - direction; - } else { - // New column; do an ascending sort - this.propertyType = propertyType; - this.propertyName = propertyName; - direction = ASCENDING; - } - } - - // Getters and setters - protected String getPropertyName() { - return propertyName; - } - - protected void setPropertyName(String propertyName) { - this.propertyName = propertyName; - } - - protected int getPropertyType() { - return propertyType; - } - - protected void setPropertyType(int propertyType) { - this.propertyType = propertyType; - } - - protected int getDirection() { - return direction; - } - - protected void setDirection(int direction) { - this.direction = direction; - } -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java deleted file mode 100644 index 455fb0dcd..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/RowViewerComparator.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.query.Row; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.Viewer; - -/** - * Base comparator to enable ordering on Table or Tree viewer that display Jcr - * rows - */ -public class RowViewerComparator extends NodeViewerComparator { - private static final long serialVersionUID = 7020939505172625113L; - protected String selectorName; - - public RowViewerComparator() { - } - - /** - * e1 and e2 must both be Jcr rows. - * - * @param viewer - * @param e1 - * @param e2 - * @return - */ - @Override - public int compare(Viewer viewer, Object e1, Object e2) { - try { - Node n1 = ((Row) e1).getNode(selectorName); - Node n2 = ((Row) e2).getNode(selectorName); - return super.compare(viewer, n1, n2); - } catch (RepositoryException re) { - throw new EclipseUiException("Unexpected error " - + "while comparing nodes", re); - } - } - - /** - * @param propertyType - * Corresponding JCR type - * @param propertyName - * name of the property to use. - */ - public void setColumn(int propertyType, String selectorName, - String propertyName) { - if (this.selectorName != null && getPropertyName() != null - && this.selectorName.equals(selectorName) - && this.getPropertyName().equals(propertyName)) { - // Same column as last sort; toggle the direction - setDirection(1 - getDirection()); - } else { - // New column; do a descending sort - setPropertyType(propertyType); - setPropertyName(propertyName); - this.selectorName = selectorName; - setDirection(NodeViewerComparator.ASCENDING); - } - } -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java deleted file mode 100644 index aa2e3375c..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrNodeLabelProvider.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; - -import javax.jcr.Node; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.Value; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.ColumnLabelProvider; - -/** Base implementation of a label provider for controls that display JCR Nodes */ -public class SimpleJcrNodeLabelProvider extends ColumnLabelProvider { - private static final long serialVersionUID = -5215787695436221993L; - - private final static String DEFAULT_DATE_FORMAT = "EEE, dd MMM yyyy"; - private final static String DEFAULT_NUMBER_FORMAT = "#,##0.0"; - - private DateFormat dateFormat; - private NumberFormat numberFormat; - - final private String propertyName; - - /** - * Default Label provider for a given property of a node. Using default - * pattern for date and number formating - */ - public SimpleJcrNodeLabelProvider(String propertyName) { - this.propertyName = propertyName; - dateFormat = new SimpleDateFormat(DEFAULT_DATE_FORMAT); - numberFormat = DecimalFormat.getInstance(); - ((DecimalFormat) numberFormat).applyPattern(DEFAULT_NUMBER_FORMAT); - } - - /** - * Label provider for a given property of a node optionally precising date - * and/or number format patterns - */ - public SimpleJcrNodeLabelProvider(String propertyName, - String dateFormatPattern, String numberFormatPattern) { - this.propertyName = propertyName; - dateFormat = new SimpleDateFormat( - dateFormatPattern == null ? DEFAULT_DATE_FORMAT - : dateFormatPattern); - numberFormat = DecimalFormat.getInstance(); - ((DecimalFormat) numberFormat) - .applyPattern(numberFormatPattern == null ? DEFAULT_NUMBER_FORMAT - : numberFormatPattern); - } - - @Override - public String getText(Object element) { - try { - Node currNode = (Node) element; - - if (currNode.hasProperty(propertyName)) { - if (currNode.getProperty(propertyName).isMultiple()) { - StringBuilder builder = new StringBuilder(); - for (Value value : currNode.getProperty(propertyName) - .getValues()) { - String currStr = getSingleValueAsString(value); - if (notEmptyString(currStr)) - builder.append(currStr).append("; "); - } - if (builder.length() > 0) - builder.deleteCharAt(builder.length() - 2); - - return builder.toString(); - } else - return getSingleValueAsString(currNode.getProperty( - propertyName).getValue()); - } else - return ""; - } catch (RepositoryException re) { - throw new EclipseUiException("Unable to get text from row", re); - } - } - - private String getSingleValueAsString(Value value) - throws RepositoryException { - switch (value.getType()) { - case PropertyType.STRING: - return value.getString(); - case PropertyType.BOOLEAN: - return "" + value.getBoolean(); - case PropertyType.DATE: - return dateFormat.format(value.getDate().getTime()); - case PropertyType.LONG: - return "" + value.getLong(); - case PropertyType.DECIMAL: - return numberFormat.format(value.getDecimal()); - case PropertyType.DOUBLE: - return numberFormat.format(value.getDouble()); - case PropertyType.NAME: - return value.getString(); - default: - throw new EclipseUiException("Unimplemented label provider " - + "for property type " + value.getType() - + " while getting property " + propertyName + " - value: " - + value.getString()); - - } - } - - private boolean notEmptyString(String string) { - return string != null && !"".equals(string.trim()); - } - - public void setDateFormat(String dateFormatPattern) { - dateFormat = new SimpleDateFormat(dateFormatPattern); - } - - public void setNumberFormat(String numberFormatPattern) { - ((DecimalFormat) numberFormat).applyPattern(numberFormatPattern); - } -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java deleted file mode 100644 index 5d421f64b..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/SimpleJcrRowLabelProvider.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.argeo.eclipse.ui.jcr.lists; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.query.Row; - -import org.argeo.eclipse.ui.EclipseUiException; - -/** - * Base implementation of a label provider for widgets that display JCR Rows. - */ -public class SimpleJcrRowLabelProvider extends SimpleJcrNodeLabelProvider { - private static final long serialVersionUID = -3414654948197181740L; - - final private String selectorName; - - /** - * Default Label provider for a given property of a row. Using default - * pattern for date and number formating - */ - public SimpleJcrRowLabelProvider(String selectorName, String propertyName) { - super(propertyName); - this.selectorName = selectorName; - } - - /** - * Label provider for a given property of a node optionally precising date - * and/or number format patterns - */ - public SimpleJcrRowLabelProvider(String selectorName, String propertyName, - String dateFormatPattern, String numberFormatPattern) { - super(propertyName, dateFormatPattern, numberFormatPattern); - this.selectorName = selectorName; - } - - @Override - public String getText(Object element) { - try { - Row currRow = (Row) element; - Node currNode = currRow.getNode(selectorName); - return super.getText(currNode); - } catch (RepositoryException re) { - throw new EclipseUiException("Unable to get Node " + selectorName - + " from row " + element, re); - } - } -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/package-info.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/package-info.java deleted file mode 100644 index 3678aab88..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/lists/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Generic SWT/JFace JCR utilities for lists. */ -package org.argeo.eclipse.ui.jcr.lists; \ No newline at end of file diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/package-info.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/package-info.java deleted file mode 100644 index 19e3cc3ff..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Generic SWT/JFace JCR utilities. */ -package org.argeo.eclipse.ui.jcr; \ No newline at end of file diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/JcrFileProvider.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/JcrFileProvider.java deleted file mode 100644 index c82e666d1..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/JcrFileProvider.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.argeo.eclipse.ui.jcr.util; - -import java.io.InputStream; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NodeType; - -import org.apache.commons.io.IOUtils; -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.FileProvider; - -/** - * Implements a FileProvider for UI purposes. Note that it might not be very - * reliable as long as we have not fixed login and multi repository issues that - * will be addressed in the next version. - * - * NOTE: id used here is the real id of the JCR Node, not the JCR Path - * - * Relies on common approach for JCR file handling implementation. - * - */ -@SuppressWarnings("deprecation") -public class JcrFileProvider implements FileProvider { - - // private Object[] rootNodes; - private Node refNode; - - /** - * Must be set in order for the provider to be able to get current session - * and thus have the ability to get the file node corresponding to a given - * file ID - * - * @param refNode - */ - public void setReferenceNode(Node refNode) { - // FIXME : this introduces some concurrency ISSUES. - this.refNode = refNode; - } - - public byte[] getByteArrayFileFromId(String fileId) { - InputStream fis = null; - byte[] ba = null; - Node child = getFileNodeFromId(fileId); - try { - fis = (InputStream) child.getProperty(Property.JCR_DATA).getBinary().getStream(); - ba = IOUtils.toByteArray(fis); - - } catch (Exception e) { - throw new EclipseUiException("Stream error while opening file", e); - } finally { - IOUtils.closeQuietly(fis); - } - return ba; - } - - public InputStream getInputStreamFromFileId(String fileId) { - try { - InputStream fis = null; - - Node child = getFileNodeFromId(fileId); - fis = (InputStream) child.getProperty(Property.JCR_DATA).getBinary().getStream(); - return fis; - } catch (RepositoryException re) { - throw new EclipseUiException("Cannot get stream from file node for Id " + fileId, re); - } - } - - /** - * Throws an exception if the node is not found in the current repository (a - * bit like a FileNotFoundException) - * - * @param fileId - * @return Returns the child node of the nt:file node. It is the child node - * that have the jcr:data property where actual file is stored. - * never null - */ - private Node getFileNodeFromId(String fileId) { - try { - Node result = refNode.getSession().getNodeByIdentifier(fileId); - - // rootNodes: for (int j = 0; j < rootNodes.length; j++) { - // // in case we have a classic JCR Node - // if (rootNodes[j] instanceof Node) { - // Node curNode = (Node) rootNodes[j]; - // if (result != null) - // break rootNodes; - // } // Case of a repository Node - // else if (rootNodes[j] instanceof RepositoryNode) { - // Object[] nodes = ((RepositoryNode) rootNodes[j]) - // .getChildren(); - // for (int i = 0; i < nodes.length; i++) { - // Node node = (Node) nodes[i]; - // result = node.getSession().getNodeByIdentifier(fileId); - // if (result != null) - // break rootNodes; - // } - // } - // } - - // Sanity checks - if (result == null) - throw new EclipseUiException("File node not found for ID" + fileId); - - Node child = null; - - boolean isValid = true; - if (!result.isNodeType(NodeType.NT_FILE)) - // useless: mandatory child node - // || !result.hasNode(Property.JCR_CONTENT)) - isValid = false; - else { - child = result.getNode(Property.JCR_CONTENT); - if (!(child.isNodeType(NodeType.NT_RESOURCE) || child.hasProperty(Property.JCR_DATA))) - isValid = false; - } - - if (!isValid) - throw new EclipseUiException("ERROR: In the current implemented model, '" + NodeType.NT_FILE - + "' file node must have a child node named jcr:content " - + "that has a BINARY Property named jcr:data " + "where the actual data is stored"); - return child; - - } catch (RepositoryException re) { - throw new EclipseUiException("Erreur while getting file node of ID " + fileId, re); - } - } -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/JcrItemsComparator.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/JcrItemsComparator.java deleted file mode 100644 index fb123992f..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/JcrItemsComparator.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.argeo.eclipse.ui.jcr.util; - -import java.util.Comparator; - -import javax.jcr.Item; -import javax.jcr.RepositoryException; - -import org.argeo.eclipse.ui.EclipseUiException; - -/** Compares two JCR items (node or properties) based on their names. */ -public class JcrItemsComparator implements Comparator { - public int compare(Item o1, Item o2) { - try { - // TODO: put folder before files - return o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase()); - } catch (RepositoryException e) { - throw new EclipseUiException("Cannot compare " + o1 + " and " + o2, e); - } - } - -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/NodeViewerComparer.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/NodeViewerComparer.java deleted file mode 100644 index 54b795f3b..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/NodeViewerComparer.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.argeo.eclipse.ui.jcr.util; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.eclipse.ui.EclipseUiException; -import org.eclipse.jface.viewers.IElementComparer; - -/** Compare JCR nodes based on their JCR identifiers, for use in JFace viewers. */ -public class NodeViewerComparer implements IElementComparer { - - // force comparison on Node IDs only. - public boolean equals(Object elementA, Object elementB) { - if (!(elementA instanceof Node) || !(elementB instanceof Node)) { - return elementA == null ? elementB == null : elementA - .equals(elementB); - } else { - - boolean result = false; - try { - String idA = ((Node) elementA).getIdentifier(); - String idB = ((Node) elementB).getIdentifier(); - result = idA == null ? idB == null : idA.equals(idB); - } catch (RepositoryException re) { - throw new EclipseUiException("cannot compare nodes", re); - } - - return result; - } - } - - public int hashCode(Object element) { - // TODO enhanced this method. - return element.getClass().toString().hashCode(); - } -} \ No newline at end of file diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/SingleSessionFileProvider.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/SingleSessionFileProvider.java deleted file mode 100644 index 291d579ac..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/SingleSessionFileProvider.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.argeo.eclipse.ui.jcr.util; - -import java.io.InputStream; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; - -import org.apache.commons.io.IOUtils; -import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.FileProvider; - -/** - * Implements a FileProvider for UI purposes. Unlike the - * JcrFileProvider , it relies on a single session and manages - * nodes with path only. - * - * Note that considered id is the JCR path - * - * Relies on common approach for JCR file handling implementation. - */ -@SuppressWarnings("deprecation") -public class SingleSessionFileProvider implements FileProvider { - - private Session session; - - public SingleSessionFileProvider(Session session) { - this.session = session; - } - - public byte[] getByteArrayFileFromId(String fileId) { - InputStream fis = null; - byte[] ba = null; - Node child = getFileNodeFromId(fileId); - try { - fis = (InputStream) child.getProperty(Property.JCR_DATA) - .getBinary().getStream(); - ba = IOUtils.toByteArray(fis); - - } catch (Exception e) { - throw new EclipseUiException("Stream error while opening file", e); - } finally { - IOUtils.closeQuietly(fis); - } - return ba; - } - - public InputStream getInputStreamFromFileId(String fileId) { - try { - InputStream fis = null; - - Node child = getFileNodeFromId(fileId); - fis = (InputStream) child.getProperty(Property.JCR_DATA) - .getBinary().getStream(); - return fis; - } catch (RepositoryException re) { - throw new EclipseUiException("Cannot get stream from file node for Id " - + fileId, re); - } - } - - /** - * - * @param fileId - * @return Returns the child node of the nt:file node. It is the child node - * that have the jcr:data property where actual file is stored. - * never null - */ - private Node getFileNodeFromId(String fileId) { - try { - Node result = null; - result = session.getNode(fileId); - - // Sanity checks - if (result == null) - throw new EclipseUiException("File node not found for ID" + fileId); - - // Ensure that the node have the correct type. - if (!result.isNodeType(NodeType.NT_FILE)) - throw new EclipseUiException( - "Cannot open file children Node that are not of " - + NodeType.NT_RESOURCE + " type."); - - Node child = result.getNodes().nextNode(); - if (child == null || !child.isNodeType(NodeType.NT_RESOURCE)) - throw new EclipseUiException( - "ERROR: IN the current implemented model, " - + NodeType.NT_FILE - + " file node must have one and only one child of the nt:ressource, where actual data is stored"); - return child; - } catch (RepositoryException re) { - throw new EclipseUiException("Erreur while getting file node of ID " - + fileId, re); - } - } -} diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/package-info.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/package-info.java deleted file mode 100644 index 016348cda..000000000 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/jcr/util/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Generic SWT/JFace JCR helpers. */ -package org.argeo.eclipse.ui.jcr.util; \ No newline at end of file