From 49080f09ed17e6331c95594b012cf1dd5bded8f6 Mon Sep 17 00:00:00 2001 From: Bruno Sinou Date: Thu, 13 Oct 2011 10:02:19 +0000 Subject: [PATCH] First draft of some views to browse the Slc Repo git-svn-id: https://svn.argeo.org/slc/trunk@4818 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- demo/log4j.properties | 1 + demo/slc_demo_rap.properties | 1 + .../META-INF/MANIFEST.MF | 26 +- .../META-INF/spring/editors.xml | 2 +- .../META-INF/spring/jcr.xml | 3 +- .../META-INF/spring/osgi.xml | 6 +- .../META-INF/spring/views.xml | 33 ++- .../org.argeo.slc.client.ui.dist/plugin.xml | 26 +- .../slc/client/ui/dist/DistConstants.java | 15 ++ .../argeo/slc/client/ui/dist/DistPlugin.java | 1 + .../ui/dist/DistributionPerspective.java | 12 +- .../dist/providers/ArtifactLabelProvider.java | 85 +++++++ .../ArtifactsTreeContentProvider.java | 60 +++++ .../dist/utils/ArtifactsTableConfigurer.java | 227 ++++++++++++++++++ .../utils/GenericDoubleClickListener.java | 66 +++++ .../views/AbstractQueryArtifactsView.java | 168 +++++++++++++ .../ui/dist/views/ArtifactsBrowser.java | 111 +++++++++ .../ui/dist/views/QueryArtifactsForm.java | 144 +++++++++++ .../ui/dist/views/QueryArtifactsText.java | 99 ++++++++ 19 files changed, 1056 insertions(+), 30 deletions(-) create mode 100644 eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistConstants.java create mode 100644 eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/providers/ArtifactLabelProvider.java create mode 100644 eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/providers/ArtifactsTreeContentProvider.java create mode 100644 eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/ArtifactsTableConfigurer.java create mode 100644 eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/GenericDoubleClickListener.java create mode 100644 eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/AbstractQueryArtifactsView.java create mode 100644 eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/ArtifactsBrowser.java create mode 100644 eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/QueryArtifactsForm.java create mode 100644 eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/QueryArtifactsText.java diff --git a/demo/log4j.properties b/demo/log4j.properties index 05da4c948..7b62f3a48 100644 --- a/demo/log4j.properties +++ b/demo/log4j.properties @@ -5,6 +5,7 @@ log4j.rootLogger=WARN, development log4j.logger.org.argeo=DEBUG log4j.logger.org.argeo.jackrabbit.remote.ExtendedDispatcherServlet=WARN log4j.logger.org.argeo.server.webextender.TomcatDeployer=WARN +log4j.logger.org.argeo.slc.client.ui.dist=TRACE log4j.logger.org.apache.jackrabbit.webdav=DEBUG log4j.logger.org.apache.jackrabbit.jcr2spi=DEBUG diff --git a/demo/slc_demo_rap.properties b/demo/slc_demo_rap.properties index e2f435113..53fac9f6b 100644 --- a/demo/slc_demo_rap.properties +++ b/demo/slc_demo_rap.properties @@ -34,6 +34,7 @@ org.argeo.slc.demo.basic,\ #org.argeo.elgis.rpmfactory,\ org.argeo.security.ui.initialPerspective=org.argeo.slc.client.ui.slcExecutionPerspective +#org.argeo.security.ui.initialPerspective=org.argeo.slc.client.ui.dist.distributionPerspective # JCR argeo.node.repo.home=data/noderepo diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/MANIFEST.MF b/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/MANIFEST.MF index 29d4774b8..5bde12239 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/MANIFEST.MF +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/MANIFEST.MF @@ -4,17 +4,35 @@ Bundle-Name: Dist Bundle-SymbolicName: org.argeo.slc.client.ui.dist;singleton:=true Bundle-Version: 0.13.1.SNAPSHOT Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-Activator: org.argeo.slc.client.ui.dist.DistPlugin +Bundle-ActivationPolicy: lazy Require-Bundle: org.eclipse.ui;resolution:=optional, org.eclipse.rap.ui;resolution:=optional, - org.eclipse.core.runtime -Bundle-Activator: org.argeo.slc.client.ui.dist.DistPlugin + org.eclipse.core.runtime;resolution:=optional, + org.eclipse.rap.ui.workbench;resolution:=optional Import-Package: aQute.lib.osgi;resolution:=optional, javax.jcr;version="[2.0.0,3.0.0)", + javax.jcr.query, org.apache.commons.logging;version="1.1.1", + org.argeo, org.argeo.eclipse.spring, org.argeo.eclipse.ui, + org.argeo.eclipse.ui.dialogs, + org.argeo.eclipse.ui.jcr, org.argeo.eclipse.ui.jcr.commands, org.argeo.eclipse.ui.jcr.editors, + org.argeo.eclipse.ui.jcr.utils, org.argeo.eclipse.ui.jcr.views, - org.argeo.jcr -Bundle-ActivationPolicy: lazy + org.argeo.eclipse.ui.specific, + org.argeo.eclipse.ui.utils, + org.argeo.jcr, + org.argeo.jcr.security, + org.argeo.jcr.spring, + org.argeo.jcr.ui.explorer.utils, + org.argeo.slc.jcr, + org.argeo.slc.repo, + org.eclipse.ui.forms, + org.eclipse.ui.forms.editor, + org.eclipse.ui.forms.events, + org.eclipse.ui.forms.widgets + diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/editors.xml b/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/editors.xml index 3f97af1e3..069bb1559 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/editors.xml +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/editors.xml @@ -7,6 +7,6 @@ - + diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/jcr.xml b/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/jcr.xml index 2701948bd..e92d2fd85 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/jcr.xml +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/jcr.xml @@ -5,6 +5,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd"> - + + diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/osgi.xml b/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/osgi.xml index 0e87da8c0..0b82c900f 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/osgi.xml +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/osgi.xml @@ -8,8 +8,6 @@ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" osgi:default-timeout="30000"> - - - + \ No newline at end of file diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/views.xml b/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/views.xml index 5e790d1a9..3fe3fdd09 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/views.xml +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/views.xml @@ -1,19 +1,32 @@ + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/util + http://www.springframework.org/schema/util/spring-util-2.5.xsd"> - - - - + + + + + + - - - - - + + + + + + + + + + diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/plugin.xml b/eclipse/plugins/org.argeo.slc.client.ui.dist/plugin.xml index 9d600acf5..39e7a4639 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui.dist/plugin.xml +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/plugin.xml @@ -1,6 +1,7 @@ + + + class="org.argeo.eclipse.spring.SpringExtensionFactory" + id="org.argeo.slc.client.ui.dist.artifactsBrowser" + name="Artifacts browser"> + + + + + - + + - - + --> diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistConstants.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistConstants.java new file mode 100644 index 000000000..062113eb2 --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistConstants.java @@ -0,0 +1,15 @@ +package org.argeo.slc.client.ui.dist; + +/** Constants used across the application. */ +public interface DistConstants { + /* + * MISCEALLENEOUS + */ + public final static String DATE_TIME_FORMAT = "MM/dd/yyyy, HH:mm"; + public final static String DATE_FORMAT = "MM/dd/yyyy"; + + /* + * Architecture specific constants + */ + public final static String BASE_ARTIFACTS_NODE_PATH = "/slc/repo/artifacts"; +} diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistPlugin.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistPlugin.java index c651aba21..fa98f18a2 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistPlugin.java +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistPlugin.java @@ -5,6 +5,7 @@ import org.osgi.framework.BundleContext; public class DistPlugin extends AbstractUIPlugin { private static BundleContext bundleContext; + public final static String ID = "org.argeo.slc.client.ui.dist"; @Override public void start(BundleContext context) throws Exception { diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistributionPerspective.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistributionPerspective.java index bbdca1071..9d36aedfc 100644 --- a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistributionPerspective.java +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/DistributionPerspective.java @@ -1,11 +1,16 @@ package org.argeo.slc.client.ui.dist; +import org.argeo.slc.client.ui.dist.views.ArtifactsBrowser; +import org.argeo.slc.client.ui.dist.views.QueryArtifactsForm; +import org.argeo.slc.client.ui.dist.views.QueryArtifactsText; import org.eclipse.ui.IFolderLayout; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.IPerspectiveFactory; public class DistributionPerspective implements IPerspectiveFactory { + public final static String ID = DistPlugin.ID + ".distributionPerspective"; + public void createInitialLayout(IPageLayout layout) { String editorArea = layout.getEditorArea(); layout.setEditorAreaVisible(true); @@ -13,9 +18,8 @@ public class DistributionPerspective implements IPerspectiveFactory { IFolderLayout main = layout.createFolder("main", IPageLayout.LEFT, 0.5f, editorArea); - //main.addView("org.argeo.slc.client.ui.dist.distributionView"); - main.addView("org.argeo.slc.client.ui.dist.modulesView"); - + main.addView(ArtifactsBrowser.ID); + main.addView(QueryArtifactsForm.ID); + main.addView(QueryArtifactsText.ID); } - } diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/providers/ArtifactLabelProvider.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/providers/ArtifactLabelProvider.java new file mode 100644 index 000000000..ec4728d88 --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/providers/ArtifactLabelProvider.java @@ -0,0 +1,85 @@ +package org.argeo.slc.client.ui.dist.providers; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; + +import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; +import org.argeo.slc.client.ui.dist.DistConstants; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ViewerCell; + +public class ArtifactLabelProvider extends ColumnLabelProvider implements + DistConstants { + + // To be able to change column order easily + public static final int COLUMN_TREE = 0; + public static final int COLUMN_DATE = 1; + public static final int COLUMN_SIZE = 2; + + // Utils + protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT); + + public void update(ViewerCell cell) { + Object element = cell.getElement(); + cell.setText(getColumnText(element, cell.getColumnIndex())); + // Image image = getImage(element); + // cell.setImage(image); + // cell.setBackground(getBackground(element)); + // cell.setForeground(getForeground(element)); + // cell.setFont(getFont(element)); + } + + public String getColumnText(Object element, int columnIndex) { + try { + if (element instanceof Node) { + Node node = (Node) element; + switch (columnIndex) { + case COLUMN_TREE: + return node.getName(); + case COLUMN_SIZE: + long size = JcrUtils.getNodeApproxSize(node) / 1024; + if (size > 1024) + return size / 1024 + " MB"; + else + return size + " KB"; + case COLUMN_DATE: + if (node.hasProperty(Property.JCR_CREATED)) + return timeFormatter.format(node + .getProperty(Property.JCR_CREATED).getDate() + .getTime()); + else + return null; + } + } + } catch (RepositoryException re) { + throw new ArgeoException( + "Unexepected error while getting property values", re); + } + return null; + } + + private String formatValueAsString(Value value) { + // TODO enhance this method + try { + String strValue; + + if (value.getType() == PropertyType.BINARY) + strValue = ""; + else if (value.getType() == PropertyType.DATE) + strValue = timeFormatter.format(value.getDate().getTime()); + else + strValue = value.getString(); + return strValue; + } catch (RepositoryException e) { + throw new ArgeoException("unexpected error while formatting value", + e); + } + } +} diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/providers/ArtifactsTreeContentProvider.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/providers/ArtifactsTreeContentProvider.java new file mode 100644 index 000000000..289fef5e0 --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/providers/ArtifactsTreeContentProvider.java @@ -0,0 +1,60 @@ +package org.argeo.slc.client.ui.dist.providers; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; + +import org.argeo.ArgeoException; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +public class ArtifactsTreeContentProvider implements ITreeContentProvider { + public Object[] getElements(Object parent) { + return getChildren(parent); + } + + public Object getParent(Object child) { + return null; + } + + public Object[] getChildren(Object parent) { + Object[] elements = null; + try { + if (parent instanceof Node) { + Node node = (Node) parent; + NodeIterator ni = node.getNodes(); + List nodesList = new ArrayList(); + while (ni.hasNext()) { + nodesList.add(ni.nextNode()); + } + elements = nodesList.toArray(); + } + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected exception while listing node properties", e); + } + return elements; + } + + public boolean hasChildren(Object parent) { + try { + if (parent instanceof Node && ((Node) parent).hasNodes()) { + return true; + } + } catch (RepositoryException e) { + throw new ArgeoException( + "Unexpected exception while checking if property is multiple", + e); + } + return false; + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + public void dispose() { + } +} \ No newline at end of file diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/ArtifactsTableConfigurer.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/ArtifactsTableConfigurer.java new file mode 100644 index 000000000..f213b3dd2 --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/ArtifactsTableConfigurer.java @@ -0,0 +1,227 @@ +package org.argeo.slc.client.ui.dist.utils; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.query.Row; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.GenericTableComparator; +import org.argeo.slc.client.ui.dist.DistConstants; +import org.argeo.slc.jcr.SlcNames; +import org.argeo.slc.jcr.SlcTypes; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.TableColumn; + +/** + * Centralizes and factorizes useful methods to create and manage tables that + * display artifacts for both editors and views. + */ +public class ArtifactsTableConfigurer implements SlcNames, SlcTypes, + DistConstants { + private final static Log log = LogFactory + .getLog(ArtifactsTableConfigurer.class); + // Used in the comparator to be able to retrieve the value from a row + // knowing the corresponding column index. + private Map indexToName = new HashMap(); + + private CurrentTableComparator comparator; + private TableViewer viewer; + + protected DateFormat timeFormatter = new SimpleDateFormat(DATE_TIME_FORMAT); + + /** + * Create and initialize the table configurer. + */ + public ArtifactsTableConfigurer(TableViewer viewer, + int defaultSortColumnIndex, int direction) { + this.viewer = viewer; + comparator = new CurrentTableComparator(defaultSortColumnIndex, + direction); + } + + public GenericTableComparator getComparator() { + return comparator; + } + + /** + * Configure column width and header label depending on the value that will + * be displayed in the current column. + * + * @param jcrColumnName + * @param column + * @param columnIndex + */ + public void configureColumn(String jcrColumnName, TableViewerColumn column, + int columnIndex) { + + if (columnIndex != -1 + && getSelectionAdapter(column.getColumn(), columnIndex) != null) { + column.getColumn().addSelectionListener( + getSelectionAdapter(column.getColumn(), columnIndex)); + indexToName.put(new Integer(columnIndex), jcrColumnName); + } + Object[] objs = getColumnLabelAndWidth(jcrColumnName); + column.getColumn().setWidth((Integer) objs[0]); + column.getColumn().setText((String) objs[1]); + } + + /** + * Returns corresponding default width ( (int) object[0] ) and the header + * label ( (String) object[1] ) depending on the property name. + */ + public static Object[] getColumnLabelAndWidth(String propertyName) { + // to avoid npe : + if (propertyName == null) + return new Object[] { 60, "(No name)" }; + + if (propertyName.equals(SLC_ARTIFACT + "." + SLC_ARTIFACT_ID)) { + return new Object[] { 140, "Artifact ID" }; + } else if (propertyName.equals(SLC_ARTIFACT + "." + SLC_GROUP_ID)) { + return new Object[] { 120, "Group ID" }; + } else if (propertyName.equals(SLC_ARTIFACT + "." + + SLC_ARTIFACT_VERSION)) { + return new Object[] { 60, "Version" }; + } else if (propertyName.equals(SLC_ARTIFACT + "." + + SLC_ARTIFACT_CLASSIFIER)) { + return new Object[] { 60, "Classifier" }; + } else if (propertyName.equals(SLC_ARTIFACT + "." + + SLC_ARTIFACT_EXTENSION)) { + return new Object[] { 40, "Type" }; + } else if (propertyName.equals(SLC_ARTIFACT + ".jcr:uuid")) { + return new Object[] { 20, "UUID" }; + } else { + if (log.isTraceEnabled()) + log.trace("No Column label provider defined for property: [" + + propertyName + "]"); + return new Object[] { 60, propertyName }; + } + } + + /** + * Might be used by client classes to sort columns. + * + * @param column + * @param index + * @return + */ + public SelectionAdapter getSelectionAdapter(final TableColumn column, + final int index) { + + // A comparator must be define + if (comparator == null) + return null; + + SelectionAdapter selectionAdapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + + try { + + comparator.setColumn(index); + int dir = viewer.getTable().getSortDirection(); + if (viewer.getTable().getSortColumn() == column) { + dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; + } else { + + dir = SWT.DOWN; + } + viewer.getTable().setSortDirection(dir); + viewer.getTable().setSortColumn(column); + viewer.refresh(); + } catch (Exception exc) { + exc.printStackTrace(); + } + } + }; + return selectionAdapter; + } + + /** + * provides a label provider that returns the content of a specific cell. + * Specific treatment is done for some columns when the query returns a code + * that must be translated to the corresponding value at display time. + */ + public ColumnLabelProvider getLabelProvider(final String columnName) { + boolean test = false; + + if (test) { + return new ColumnLabelProvider() { + public String getText(Object element) { + return null; + } + + public Image getImage(Object element) { + return null; + } + }; + } else + return new ColumnLabelProvider() { + public String getText(Object element) { + Row row = (Row) element; + try { + return row.getValue(columnName).getString(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot display row " + row, e); + } + } + + public Image getImage(Object element) { + return null; + } + }; + } + + /** Implements comparator for various types of Artifact Table row */ + private class CurrentTableComparator extends GenericTableComparator { + + public CurrentTableComparator(int colIndex, int direction) { + super(colIndex, direction); + } + + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + int rc = 0; + + if (e1 instanceof Row) { + try { + + Value v1 = ((Row) e1).getValue(indexToName + .get(propertyIndex)); + Value v2 = ((Row) e2).getValue(indexToName + .get(propertyIndex)); + + if (v1.getType() == PropertyType.STRING) + rc = v1.getString().compareTo(v2.getString()); + else if (v1.getType() == PropertyType.DATE) + rc = v1.getDate().compareTo(v2.getDate()); + else + throw new ArgeoException("comparator for object type " + + v1.getType() + " is not yet implemented"); + } catch (Exception e) { + throw new ArgeoException("rows cannot be compared ", e); + } + } else + throw new ArgeoException("Unsupported row type"); + // If descending order, flip the direction + if (direction == DESCENDING) { + rc = -rc; + } + return rc; + } + } +} diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/GenericDoubleClickListener.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/GenericDoubleClickListener.java new file mode 100644 index 000000000..e053146d8 --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/GenericDoubleClickListener.java @@ -0,0 +1,66 @@ +package org.argeo.slc.client.ui.dist.utils; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; + +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.specific.FileHandler; +import org.argeo.jcr.ui.explorer.utils.JcrFileProvider; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; + +/** + * Centralizes the management of double click on an ArtifactTreeViewer + */ +public class GenericDoubleClickListener implements IDoubleClickListener { + + // private final static Log log = LogFactory + // .getLog(GenericNodeDoubleClickListener.class); + + private TreeViewer viewer; + private JcrFileProvider jfp; + private FileHandler fileHandler; + + public GenericDoubleClickListener(TreeViewer viewer) { + this.viewer = viewer; + jfp = new JcrFileProvider(); + fileHandler = new FileHandler(jfp); + } + + public void doubleClick(DoubleClickEvent event) { + if (event.getSelection() == null || event.getSelection().isEmpty()) + return; + Object obj = ((IStructuredSelection) event.getSelection()) + .getFirstElement(); + if (obj instanceof Node) { + Node node = (Node) obj; + try { + if (node.isNodeType(NodeType.NT_FILE)) { + // double click on a file node triggers its opening + String name = node.getName(); + String id = node.getIdentifier(); + + // For the file provider to be able to browse the + // various + // repository. + // TODO : enhanced that. + // ITreeContentProvider itcp = (ITreeContentProvider) + // nodeViewer + // .getContentProvider(); + // jfp.setRootNodes((Object[]) itcp.getElements(null)); + fileHandler.openFile(name, id); + } + } catch (RepositoryException re) { + throw new ArgeoException( + "Repository error while getting node info", re); + } + // catch (PartInitException pie) { + // throw new ArgeoException( + // "Unexepected exception while opening node editor", pie); + // } + } + } +} diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/AbstractQueryArtifactsView.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/AbstractQueryArtifactsView.java new file mode 100644 index 000000000..c8f5e4ac5 --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/AbstractQueryArtifactsView.java @@ -0,0 +1,168 @@ +package org.argeo.slc.client.ui.dist.views; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.List; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.query.Query; +import javax.jcr.query.QueryResult; +import javax.jcr.query.Row; +import javax.jcr.query.RowIterator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.eclipse.ui.GenericTableComparator; +import org.argeo.slc.client.ui.dist.utils.ArtifactsTableConfigurer; +import org.argeo.slc.jcr.SlcTypes; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.part.ViewPart; + +/** Factorizes useful methods to build a query view in a sashForm */ +public abstract class AbstractQueryArtifactsView extends ViewPart implements + SlcTypes { + private static final Log log = LogFactory + .getLog(AbstractQueryArtifactsView.class); + + /* DEPENDENCY INJECTION */ + private Session session; + + // This page widgets + private TableViewer viewer; + private List tableViewerColumns = new ArrayList(); + private ArtifactsTableConfigurer tableConfigurer; + private GenericTableComparator comparator; + + protected void createResultPart(Composite parent) { + viewer = new TableViewer(parent); + Table table = viewer.getTable(); + table.getParent().setLayout(new GridLayout(1, false)); + table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + viewer.getTable().setHeaderVisible(true); + viewer.getTable().setLinesVisible(true); + + viewer.setLabelProvider(new ViewLabelProvider()); + viewer.setContentProvider(new ViewContentProvider()); + // viewer.addDoubleClickListener(new ViewDoubleClickListener()); + tableConfigurer = new ArtifactsTableConfigurer(viewer, 1, + GenericTableComparator.DESCENDING); + + comparator = tableConfigurer.getComparator(); + viewer.setComparator(comparator); + } + + protected void executeQuery(String statement) { + try { + Calendar stStamp = new GregorianCalendar(); + if (log.isDebugEnabled()) { + log.debug("Executed query: " + statement); + } + QueryResult qr = session.getWorkspace().getQueryManager() + .createQuery(statement, Query.JCR_SQL2).execute(); + + if (log.isDebugEnabled()) { + Calendar enStamp = new GregorianCalendar(); + long duration = enStamp.getTimeInMillis() + - stStamp.getTimeInMillis(); + log.debug("Query executed in : " + duration / 1000 + "s."); + } + + // remove previous columns + for (TableViewerColumn tvc : tableViewerColumns) + tvc.getColumn().dispose(); + int i = 0; + for (final String columnName : qr.getColumnNames()) { + TableViewerColumn tvc = new TableViewerColumn(viewer, SWT.NONE); + tableConfigurer.configureColumn(columnName, tvc, i); + tvc.setLabelProvider(tableConfigurer + .getLabelProvider(columnName)); + tableViewerColumns.add(tvc); + i++; + } + + // We must create a local list because query result can be read only + // once. + try { + List rows = new ArrayList(); + RowIterator rit = qr.getRows(); + while (rit.hasNext()) { + rows.add(rit.nextRow()); + } + viewer.setInput(rows); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot read query result", e); + } + + } catch (RepositoryException e) { + ErrorDialog.openError(null, "Error", "Cannot execute JCR query: " + + statement, new Status(IStatus.ERROR, + "org.argeo.eclipse.ui.jcr", e.getMessage())); + } + } + + // Can be overridden by subclasses. + protected String generateSelectStatement() { + StringBuffer sb = new StringBuffer("select * "); + return sb.toString(); + } + + protected String generateFromStatement() { + StringBuffer sb = new StringBuffer(" from ["); + sb.append(SLC_ARTIFACT); + sb.append("] "); + return sb.toString(); + } + + // Providers + protected class ViewContentProvider implements IStructuredContentProvider { + + public void inputChanged(Viewer arg0, Object arg1, Object arg2) { + } + + public void dispose() { + } + + @SuppressWarnings("unchecked") + public Object[] getElements(Object obj) { + return ((List) obj).toArray(); + } + } + + protected class ViewLabelProvider extends LabelProvider implements + ITableLabelProvider { + public String getColumnText(Object obj, int index) { + if (!(obj instanceof String[])) + return "Object is not properly formatted "; + + String[] value = (String[]) obj; + + return value[index]; + } + + public Image getColumnImage(Object obj, int index) { + return null; + } + } + + /* DEPENDENCY INJECTION */ + public void setSession(Session session) { + this.session = session; + } +} \ No newline at end of file diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/ArtifactsBrowser.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/ArtifactsBrowser.java new file mode 100644 index 000000000..8c1da64dc --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/ArtifactsBrowser.java @@ -0,0 +1,111 @@ +package org.argeo.slc.client.ui.dist.views; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.slc.client.ui.dist.DistConstants; +import org.argeo.slc.client.ui.dist.DistPlugin; +import org.argeo.slc.client.ui.dist.providers.ArtifactLabelProvider; +import org.argeo.slc.client.ui.dist.providers.ArtifactsTreeContentProvider; +import org.argeo.slc.client.ui.dist.utils.GenericDoubleClickListener; +import org.argeo.slc.repo.RepoConstants; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.ui.part.ViewPart; + +/** + * Basic View to browse a maven base repository + */ + +public class ArtifactsBrowser extends ViewPart implements DistConstants, + RepoConstants { + private final static Log log = LogFactory.getLog(ArtifactsBrowser.class); + public final static String ID = DistPlugin.ID + ".artifactsBrowser"; + + /* DEPENDENCY INJECTION */ + private Session jcrSession; + // Business objects + private Node rootNode; + + // This page widgets + private TreeViewer artifactTreeViewer; + + @Override + public void createPartControl(Composite parent) { + GridLayout gl = new GridLayout(1, false); + parent.setLayout(gl); + artifactTreeViewer = createArtifactsTreeViewer(parent); + + // context menu : it is completely defined in the plugin.xml file. + + // Nothing in the context menu for the time being + // MenuManager menuManager = new MenuManager(); + // Menu menu = + // menuManager.createContextMenu(artifactTreeViewer.getTree()); + // artifactTreeViewer.getTree().setMenu(menu); + // getSite().registerContextMenu(menuManager, artifactTreeViewer); + + getSite().setSelectionProvider(artifactTreeViewer); + // packagesViewer.setComparer(new NodeViewerComparer()); + + // Model initialisation + if (jcrSession != null) { + try { + rootNode = jcrSession.getNode(ARTIFACTS_BASE_PATH); + artifactTreeViewer.setInput(rootNode); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot load base artifact nodes", e); + } + } + } + + protected TreeViewer createArtifactsTreeViewer(Composite parent) { + int style = SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION; + Tree tree = new Tree(parent, style); + createColumn(tree, "Artifacts", SWT.LEFT, 300); + createColumn(tree, "Date created", SWT.LEFT, 105); + createColumn(tree, "Size", SWT.RIGHT, 55); + tree.setLinesVisible(true); + tree.setHeaderVisible(true); + + TreeViewer viewer = new TreeViewer(tree); + + viewer.setContentProvider(new ArtifactsTreeContentProvider()); + viewer.setLabelProvider(new ArtifactLabelProvider()); + viewer.addDoubleClickListener(new GenericDoubleClickListener(viewer)); + viewer.setInput(rootNode); + return viewer; + } + + private static TreeColumn createColumn(Tree parent, String name, int style, + int width) { + TreeColumn result = new TreeColumn(parent, style); + result.setText(name); + result.setWidth(width); + result.setMoveable(true); + result.setResizable(true); + return result; + } + + protected TreeViewer getArtifactTreeViewer() { + return artifactTreeViewer; + } + + @Override + public void setFocus() { + // TODO Auto-generated method stub + } + + /* DEPENDENCY INJECTION */ + public void setJcrSession(Session jcrSession) { + this.jcrSession = jcrSession; + } +} diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/QueryArtifactsForm.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/QueryArtifactsForm.java new file mode 100644 index 000000000..7baddb358 --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/QueryArtifactsForm.java @@ -0,0 +1,144 @@ +package org.argeo.slc.client.ui.dist.views; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.slc.client.ui.dist.DistPlugin; +import org.argeo.slc.jcr.SlcNames; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; + +/** Query SLC Repo to get some artifacts given some predefined parameters */ +public class QueryArtifactsForm extends AbstractQueryArtifactsView implements + SlcNames { + private static final Log log = LogFactory.getLog(QueryArtifactsForm.class); + public static final String ID = DistPlugin.ID + ".queryArtifactsForm"; + + // widgets + private Button executeBtn; + private Text groupId; + private Text artifactId; + private Text version; + private SashForm sashForm; + + private Composite top, bottom; + + @Override + public void createPartControl(Composite parent) { + + sashForm = new SashForm(parent, SWT.VERTICAL); + sashForm.setSashWidth(4); + sashForm.setLayout(new GridLayout(1, false)); + + top = new Composite(sashForm, SWT.NONE); + top.setLayout(new GridLayout(1, false)); + + bottom = new Composite(sashForm, SWT.NONE); + bottom.setLayout(new GridLayout(1, false)); + + sashForm.setWeights(new int[] { 25, 75 }); + + createQueryForm(top); + createResultPart(bottom); + } + + public void createQueryForm(Composite parent) { + Label lbl; + GridData gd; + + GridLayout gl = new GridLayout(2, false); + gl.marginTop = 5; + parent.setLayout(gl); + + lbl = new Label(parent, SWT.SINGLE); + lbl.setText("Query by Categories"); + gd = new GridData(); + gd.horizontalSpan = 2; + lbl.setLayoutData(gd); + + // Group ID + lbl = new Label(parent, SWT.SINGLE); + lbl.setText("Group ID:"); + groupId = new Text(parent, SWT.SINGLE | SWT.BORDER); + + // Artifact ID + lbl = new Label(parent, SWT.SINGLE); + lbl.setText("Artifact ID:"); + artifactId = new Text(parent, SWT.SINGLE | SWT.BORDER); + + // Version + lbl = new Label(parent, SWT.SINGLE); + lbl.setText("Version:"); + version = new Text(parent, SWT.SINGLE | SWT.BORDER); + + executeBtn = new Button(parent, SWT.PUSH); + executeBtn.setText("Search"); + gd = new GridData(); + gd.horizontalSpan = 2; + executeBtn.setLayoutData(gd); + + Listener executeListener = new Listener() { + public void handleEvent(Event event) { + refreshQuery(); + } + }; + executeBtn.addListener(SWT.Selection, executeListener); + } + + public void refreshQuery() { + String queryStr = generateSelectStatement() + generateFromStatement() + + generateWhereStatement(); + executeQuery(queryStr); + bottom.layout(); + sashForm.layout(); + } + + private String generateWhereStatement() { + try { + boolean hasFirstClause = false; + StringBuffer sb = new StringBuffer(" where "); + + if (groupId.getText() != null + && !groupId.getText().trim().equals("")) { + sb.append("[" + SLC_GROUP_ID + "] like '" + + groupId.getText().replace('*', '%') + "'"); + hasFirstClause = true; + } + + if (artifactId.getText() != null + && !artifactId.getText().trim().equals("")) { + if (hasFirstClause) + sb.append(" AND "); + sb.append("[" + SLC_ARTIFACT_ID + "] like '" + + artifactId.getText().replace('*', '%') + "'"); + hasFirstClause = true; + } + + if (version.getText() != null + && !version.getText().trim().equals("")) { + if (hasFirstClause) + sb.append(" AND "); + sb.append("[" + SLC_ARTIFACT_VERSION + "] like '" + + version.getText().replace('*', '%') + "'"); + } + + return sb.toString(); + } catch (Exception e) { + throw new ArgeoException( + "Cannot generate where statement to get artifacts", e); + } + } + + @Override + public void setFocus() { + executeBtn.setFocus(); + } +} \ No newline at end of file diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/QueryArtifactsText.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/QueryArtifactsText.java new file mode 100644 index 000000000..c73dcbeca --- /dev/null +++ b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/QueryArtifactsText.java @@ -0,0 +1,99 @@ +package org.argeo.slc.client.ui.dist.views; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.client.ui.dist.DistPlugin; +import org.argeo.slc.jcr.SlcNames; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; + +/** Query SLC Repo to get some artifacts with a JCR SQL 2 request. */ +public class QueryArtifactsText extends AbstractQueryArtifactsView implements + SlcNames { + private static final Log log = LogFactory.getLog(QueryArtifactsText.class); + public static final String ID = DistPlugin.ID + ".queryArtifactsText"; + + // widgets + private Button executeBtn; + private Text queryText; + private SashForm sashForm; + + private Composite top, bottom; + + @Override + public void createPartControl(Composite parent) { + + sashForm = new SashForm(parent, SWT.VERTICAL); + sashForm.setSashWidth(4); + sashForm.setLayout(new GridLayout(1, false)); + + top = new Composite(sashForm, SWT.NONE); + top.setLayout(new GridLayout(1, false)); + + bottom = new Composite(sashForm, SWT.NONE); + bottom.setLayout(new GridLayout(1, false)); + + sashForm.setWeights(new int[] { 25, 75 }); + + createQueryForm(top); + createResultPart(bottom); + } + + public void createQueryForm(Composite parent) { + Label lbl; + GridData gd; + + GridLayout gl = new GridLayout(2, false); + gl.marginTop = 5; + parent.setLayout(gl); + + lbl = new Label(parent, SWT.SINGLE); + lbl.setText("Enter a JCR:SQL2 Query"); + + executeBtn = new Button(parent, SWT.PUSH); + executeBtn.setText("Search"); + + queryText = new Text(parent, SWT.MULTI | SWT.WRAP | SWT.BORDER); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.grabExcessHorizontalSpace = true; + gd.heightHint = 100; + gd.horizontalSpan = 2; + queryText.setLayoutData(gd); + + String query = generateSelectStatement() + generateFromStatement() + + generateWhereStatement(); + queryText.setText(query); + + Listener executeListener = new Listener() { + public void handleEvent(Event event) { + refreshQuery(); + } + }; + executeBtn.addListener(SWT.Selection, executeListener); + } + + public void refreshQuery() { + String queryStr = queryText.getText(); + executeQuery(queryStr); + bottom.layout(); + sashForm.layout(); + } + + private String generateWhereStatement() { + StringBuffer sb = new StringBuffer(" where "); + return sb.toString(); + } + + @Override + public void setFocus() { + executeBtn.setFocus(); + } +} \ No newline at end of file -- 2.39.2