org.argeo.node.repo.jackrabbit,\
org.argeo.security.dao.os,\
-org.argeo.security.ui.initialPerspective=org.argeo.slc.akb.ui.akbEnvPerspective
+org.argeo.security.ui.initialPerspective=org.argeo.slc.akb.ui.akbTemplatesPerspective
eclipse.application=org.argeo.security.ui.rcp.secureUi
log4j.configuration=file:../../log4j.properties
<property name="repository" ref="repository" />
<property name="akbService" ref="akbService" />
</bean>
+
+ <!-- deletes an AKB specific node-->
+ <bean id="deleteAkbNodes" class="org.argeo.slc.akb.ui.commands.DeleteAkbNodes"
+ scope="prototype">
+ <property name="repository" ref="repository" />
+ </bean>
</beans>
<bean id="akbConnectorAliasEditor" class="org.argeo.slc.akb.ui.editors.AkbConnectorAliasEditor"
scope="prototype">
<property name="repository" ref="repository" />
+ <property name="akbService" ref="akbService" />
</bean>
</beans>
\ No newline at end of file
name="The Parent Node JCR ID if needed">
</commandParameter>
</command>
+ <command
+ defaultHandler="org.argeo.eclipse.spring.SpringExtensionFactory"
+ id="org.argeo.slc.akb.ui.deleteAkbNodes"
+ name="Delete Akb Node(s) and close corresponding editors">
+ <commandParameter
+ id="param.nodeJcrId"
+ name="The Node JCR ID if needed">
+ </commandParameter>
+ </command>
</extension>
<!-- Menus -->
<extension
--- /dev/null
+package org.argeo.slc.akb.ui;
+
+import java.util.Calendar;
+
+import javax.jcr.Node;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import org.argeo.slc.akb.AkbException;
+import org.argeo.slc.akb.utils.AkbJcrUtils;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.AbstractFormPart;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+/** Some helper methods that factorize widely used snippets in people UI */
+public class AkbUiUtils {
+
+ /**
+ * Shortcut to refresh the value of a <code>Text</code> given a Node and a
+ * property Name
+ */
+ public static String refreshTextWidgetValue(Text text, Node entity,
+ String propName) {
+ String tmpStr = AkbJcrUtils.get(entity, propName);
+ if (AkbJcrUtils.checkNotEmptyString(tmpStr))
+ text.setText(tmpStr);
+ return tmpStr;
+ }
+
+ /**
+ * Shortcut to refresh a <code>Text</code> widget given a Node in a form and
+ * a property Name. Also manages its enable state
+ */
+ public static String refreshFormTextWidget(Text text, Node entity,
+ String propName) {
+ String tmpStr = AkbJcrUtils.get(entity, propName);
+ if (AkbJcrUtils.checkNotEmptyString(tmpStr))
+ text.setText(tmpStr);
+ text.setEnabled(AkbJcrUtils.isNodeCheckedOutByMe(entity));
+ return tmpStr;
+ }
+
+ /**
+ * Shortcut to refresh a Check box <code>Button</code> widget given a Node
+ * in a form and a property Name.
+ */
+ public static boolean refreshCheckBoxWidget(Button button, Node entity,
+ String propName) {
+ Boolean tmp = null;
+ try {
+ if (entity.hasProperty(propName)) {
+ tmp = entity.getProperty(propName).getBoolean();
+ button.setSelection(tmp);
+ }
+ } catch (RepositoryException re) {
+ throw new AkbException("unable get boolean value for property "
+ + propName);
+ }
+ return tmp;
+ }
+
+ /**
+ * Shortcut to add a default modify listeners to a <code>Text</code> widget
+ * that is bound a JCR String Property. Any change in the text is
+ * immediately stored in the active session, but no save is done.
+ */
+ public static void addTextModifyListener(final Text text, final Node node,
+ final String propName, final AbstractFormPart part) {
+ text.addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent event) {
+ if (setJcrProperty(node, propName, PropertyType.STRING,
+ text.getText()))
+ part.markDirty();
+ }
+ });
+ }
+
+ /**
+ * 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 {
+ // int propertyType = getPic().getProperty(propName).getType();
+ 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 AkbException("Unimplemented save for property type: "
+ + propertyType + " - property: " + propName);
+
+ }
+ } catch (RepositoryException re) {
+ throw new AkbException("Error while setting property" + propName
+ + " - propertyType: " + propertyType, re);
+ }
+ }
+
+ // ////////////////////////
+ // LAYOUTS AND STYLES
+
+ /** shortcut to set form data while dealing with switching panel */
+ public static void setSwitchingFormData(Composite composite) {
+ FormData fdLabel = new FormData();
+ fdLabel.top = new FormAttachment(0, 0);
+ fdLabel.left = new FormAttachment(0, 0);
+ fdLabel.right = new FormAttachment(100, 0);
+ fdLabel.bottom = new FormAttachment(100, 0);
+ composite.setLayoutData(fdLabel);
+ }
+
+ public static void setTableDefaultStyle(TableViewer viewer,
+ int customItemHeight) {
+ Table table = viewer.getTable();
+ table.setLinesVisible(true);
+ table.setHeaderVisible(false);
+ }
+
+ /**
+ * Shortcut to provide a gridlayout with no margin and no spacing (dafault
+ * are normally 5 px)
+ */
+ public static GridLayout gridLayoutNoBorder() {
+ return gridLayoutNoBorder(1);
+ }
+
+ /**
+ * Shortcut to provide a gridlayout with no margin and no spacing (default
+ * are normally 5 px) with the given column number (equals width is false).
+ */
+ public static GridLayout gridLayoutNoBorder(int nbOfCol) {
+ GridLayout gl = new GridLayout(nbOfCol, false);
+ gl.marginWidth = gl.marginHeight = gl.horizontalSpacing = gl.verticalSpacing = 0;
+ return gl;
+ }
+
+ /** Creates a text widget with RowData already set */
+ public static Text createRDText(FormToolkit toolkit, Composite parent,
+ String msg, String toolTip, int width) {
+ Text text = toolkit.createText(parent, "", SWT.BORDER | SWT.SINGLE
+ | SWT.LEFT);
+ text.setMessage(msg);
+ text.setToolTipText(toolTip);
+ text.setLayoutData(new RowData(width, SWT.DEFAULT));
+ return text;
+ }
+
+ /**
+ * Creates a text widget with GridData already set
+ *
+ * @param toolkit
+ * @param parent
+ * @param msg
+ * @param toolTip
+ * @param width
+ * @param colSpan
+ * @return
+ */
+ public static Text createGDText(FormToolkit toolkit, Composite parent,
+ String msg, String toolTip, int width, int colSpan) {
+ Text text = toolkit.createText(parent, "", SWT.BORDER | SWT.SINGLE
+ | SWT.LEFT);
+ text.setMessage(msg);
+ text.setToolTipText(toolTip);
+ GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
+ gd.widthHint = width;
+ gd.horizontalSpan = colSpan;
+ text.setLayoutData(gd);
+ return text;
+ }
+
+ /**
+ * Shortcut to quickly get a FormData object with configured FormAttachment
+ *
+ * @param left
+ * @param top
+ * @param right
+ * @param bottom
+ * @return
+ */
+ public static FormData createformData(int left, int top, int right,
+ int bottom) {
+ FormData formData = new FormData();
+ formData.left = new FormAttachment(left, 0);
+ formData.top = new FormAttachment(top, 0);
+ formData.right = new FormAttachment(right, 0);
+ formData.bottom = new FormAttachment(bottom, 0);
+ return formData;
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.argeo.slc.akb.ui.commands;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.akb.AkbException;
+import org.argeo.slc.akb.ui.AkbUiPlugin;
+import org.argeo.slc.akb.ui.editors.AkbNodeEditorInput;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Deletes one or more akb nodes also closing the corresponding editors if
+ * needed
+ */
+public class DeleteAkbNodes extends AbstractHandler {
+ public final static String ID = AkbUiPlugin.PLUGIN_ID + ".deleteAkbNodes";
+
+ /* DEPENDENCY INJECTION */
+ private Repository repository;
+
+ public final static String PARAM_NODE_JCR_ID = "param.nodeJcrId";
+
+ // public final static String PARAM_NODE_TYPE = "param.nodeType";
+
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ // String nodeType = event.getParameter(PARAM_NODE_TYPE);
+ String nodeJcrId = event.getParameter(PARAM_NODE_JCR_ID);
+
+ Session session = null;
+ try {
+ // caches current Page
+ IWorkbenchPage currentPage = HandlerUtil.getActiveWorkbenchWindow(
+ event).getActivePage();
+
+ session = repository.login();
+ Node node = null;
+
+ if (nodeJcrId != null)
+ node = session.getNodeByIdentifier(nodeJcrId);
+
+ // no node has been found or created, return silently
+ if (node == null)
+ return null;
+
+ IEditorPart currPart = currentPage
+ .findEditor(new AkbNodeEditorInput(nodeJcrId));
+ if (currPart != null)
+ currPart.dispose();
+ } catch (RepositoryException e) {
+ throw new AkbException("JCR error while deleting node" + nodeJcrId
+ + " editor", e);
+ } finally {
+ JcrUtils.logoutQuietly(session);
+ }
+ return null;
+ }
+
+ /* DEPENDENCY INJECTION */
+ public void setRepository(Repository repository) {
+ this.repository = repository;
+ }
+}
\ No newline at end of file
package org.argeo.slc.akb.ui.commands;
import javax.jcr.Node;
+import javax.jcr.Property;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
String editorId = getEditorForNode(node);
- // no editor has been found, return
+ // no editor has been found, return silently
if (editorId == null)
return null;
private Node createNewNode(Session session, String nodeType,
String parentNodeJcrId) throws RepositoryException {
Node node = null;
+ String name = SingleValue.ask("New name", "Create AKB item");
+
+ if (name == null)
+ return null;
if (AkbTypes.AKB_ENV_TEMPLATE.equals(nodeType)) {
- String name = SingleValue.ask("Template name",
- "Please give a name to the template to create");
- if (name != null)
- node = akbService.createAkbTemplate(
- session.getNodeByIdentifier(parentNodeJcrId), name);
- else
- return null;
+ node = akbService.createAkbTemplate(
+ session.getNodeByIdentifier(parentNodeJcrId), name);
} else {
Node parentNode = session.getNodeByIdentifier(parentNodeJcrId);
- node = parentNode.addNode("new", nodeType);
+ node = parentNode.addNode(name, nodeType);
+ node.setProperty(Property.JCR_TITLE, name);
}
// corresponding node is saved but not checked in, in order to ease
// cancel actions.
editorId = AkbConnectorAliasEditor.ID;
else if (node.isNodeType(AkbTypes.AKB_ENV_TEMPLATE))
editorId = AkbEnvTemplateEditor.ID;
- else
- throw new AkbException("Editor is undefined for node " + node);
+ // else
+ // throw new AkbException("Editor is undefined for node " + node);
return editorId;
}
--- /dev/null
+package org.argeo.slc.akb.ui.composites;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+
+import org.argeo.slc.akb.ui.AkbUiUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.AbstractFormPart;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+public class MixTitleComposite extends Composite {
+ // private final static Log log =
+ // LogFactory.getLog(MixTitleComposite.class);
+
+ private final Node akbNode;
+ private final FormToolkit toolkit;
+ private final IManagedForm form;
+ // Don't forget to unregister on dispose
+ private AbstractFormPart formPart;
+
+ // To enable set focus
+ private Text titleTxt;
+
+ public MixTitleComposite(Composite parent, int style, FormToolkit toolkit,
+ IManagedForm form, Node akbNode) {
+ super(parent, style);
+ this.akbNode = akbNode;
+ this.toolkit = toolkit;
+ this.form = form;
+ populate();
+ toolkit.adapt(this);
+ }
+
+ private void populate() {
+ // Initialization
+ Composite parent = this;
+
+ parent.setLayout(new GridLayout(2, false));
+
+ // first line: connector type and name
+ toolkit.createLabel(parent, "Name");
+ titleTxt = toolkit.createText(parent, "", SWT.BORDER);
+ GridData gd = new GridData(SWT.FILL, SWT.TOP, true, false);
+ titleTxt.setLayoutData(gd);
+
+ // 2nd line: description
+ Label lbl = toolkit.createLabel(parent, "Description");
+ lbl.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
+ final Text descTxt = toolkit.createText(parent, "", SWT.BORDER
+ | SWT.MULTI | SWT.WRAP);
+ gd = new GridData(SWT.FILL, SWT.FILL, true, true);
+ descTxt.setLayoutData(gd);
+
+ // Part Management
+ final AbstractFormPart part = new AbstractFormPart() {
+ public void refresh() {
+ super.refresh();
+ // update display value
+ AkbUiUtils.refreshFormTextWidget(titleTxt, akbNode,
+ Property.JCR_TITLE);
+ AkbUiUtils.refreshFormTextWidget(descTxt, akbNode,
+ Property.JCR_DESCRIPTION);
+ }
+ };
+ // Listeners
+ AkbUiUtils.addTextModifyListener(titleTxt, akbNode, Property.JCR_TITLE,
+ part);
+ AkbUiUtils.addTextModifyListener(descTxt, akbNode,
+ Property.JCR_DESCRIPTION, part);
+ form.addPart(part);
+ }
+
+ @Override
+ public boolean setFocus() {
+ return titleTxt.setFocus();
+ }
+
+ protected void disposePart(AbstractFormPart part) {
+ if (part != null) {
+ form.removePart(part);
+ part.dispose();
+ }
+ }
+
+ @Override
+ public void dispose() {
+ disposePart(formPart);
+ super.dispose();
+ }
+}
import org.argeo.jcr.JcrUtils;
import org.argeo.slc.akb.AkbException;
+import org.argeo.slc.akb.AkbService;
import org.argeo.slc.akb.utils.AkbJcrUtils;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.part.EditorPart;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
/**
* Parent Abstract Node editor for AKB. Manage life cycle of the JCR session
* that is bound to it.
*/
-public abstract class AbstractAkbNodeEditor extends EditorPart {
+public abstract class AbstractAkbNodeEditor extends FormEditor {
// private final static Log log = LogFactory
// .getLog(AbstractEntityEditor.class);
// changes life cycle
private Repository repository;
private Session session;
+ private AkbService akbService;
// Business Objects
private Node akbNode;
// Some constants
private final static int SHORT_NAME_LENGHT = 10;
- // LIFE CYCLE
+ // to implement methods
+ protected abstract String getEditorId();
+
+ protected abstract void populateMainPage(Composite parent,
+ IManagedForm managedForm);
+
public void init(IEditorSite site, IEditorInput input)
throws PartInitException {
setSite(site);
setTitleToolTip("Display and edit " + name);
}
+ /* Pages management */
+ @Override
+ protected void addPages() {
+ try {
+ addPage(new ConnectorAliasPage(this, "mainPage", "Main"));
+ // TODO Add history page
+ // addPage(new ConnectorAliasPage(this, "mainPage", "Main"));
+ } catch (PartInitException e) {
+ throw new AkbException("Unable to initialise pages for editor "
+ + getEditorId(), e);
+ }
+ }
+
+ /**
+ * Display and edit info
+ */
+ private class ConnectorAliasPage extends FormPage {
+
+ public ConnectorAliasPage(FormEditor editor, String id, String title) {
+ super(editor, id, title);
+ }
+
+ protected void createFormContent(IManagedForm managedForm) {
+ super.createFormContent(managedForm);
+ ScrolledForm form = managedForm.getForm();
+ form.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ populateMainPage(form.getBody(), managedForm);
+ }
+ }
+
/* EXPOSES TO CHILDREN CLASSES */
protected Session getSession() {
return session;
}
+ protected AkbService getAkbService() {
+ return akbService;
+ }
+
+ protected Node getAkbNode() {
+ return akbNode;
+ }
+
+ /* LIFE CYCLE MANAGEMENT */
@Override
public void dispose() {
try {
@Override
public void doSave(IProgressMonitor monitor) {
- throw new AkbException("Implement this");
+ try {
+ if (getSession().hasPendingChanges())
+ JcrUtils.updateLastModified(getAkbNode());
+ getSession().save();
+ updatePartNameAndToolTip();
+ this.firePropertyChange(PROP_DIRTY);
+ } catch (Exception e) {
+ throw new AkbException("Error getting session status.", e);
+ }
}
@Override
public void setRepository(Repository repository) {
this.repository = repository;
}
+
+ public void setAkbService(AkbService akbService) {
+ this.akbService = akbService;
+ }
}
\ No newline at end of file
package org.argeo.slc.akb.ui.editors;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+
+import org.argeo.slc.akb.AkbException;
+import org.argeo.slc.akb.AkbNames;
+import org.argeo.slc.akb.AkbTypes;
import org.argeo.slc.akb.ui.AkbUiPlugin;
+import org.argeo.slc.akb.ui.AkbUiUtils;
+import org.argeo.slc.akb.utils.AkbJcrUtils;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.AbstractFormPart;
+import org.eclipse.ui.forms.IManagedForm;
/**
* Display and edit a connector Alias
*/
public class AkbConnectorAliasEditor extends AbstractAkbNodeEditor {
+ // private final static Log log = LogFactory
+ // .getLog(AkbConnectorAliasEditor.class);
public final static String ID = AkbUiPlugin.PLUGIN_ID
+ ".akbConnectorAliasEditor";
+ private String[] connectorTypesLbl = new String[] { "JDBC", "SSH", "JCR" };
+ private String[] connectorTypes = new String[] {
+ AkbTypes.AKB_JDBC_CONNECTOR, AkbTypes.AKB_SSH_CONNECTOR,
+ AkbTypes.AKB_JCR_CONNECTOR };
+
+ private IManagedForm managedForm;
+
/* CONTENT CREATION */
@Override
- public void createPartControl(Composite parent) {
+ public void populateMainPage(Composite parent, IManagedForm managedForm) {
+ parent.setLayout(AkbUiUtils.gridLayoutNoBorder());
+ this.managedForm = managedForm;
+
+ // First line main info
+ Composite firstLine = getToolkit()
+ .createComposite(parent, SWT.NO_FOCUS);
+ firstLine.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ createConnectorAliasInfoCmp(firstLine);
+
+ // Second line define defaut connector and test abilities
+ Composite secondLine = getToolkit().createComposite(parent,
+ SWT.NO_FOCUS);
+ secondLine.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ createDefaultTestConnectorCmp(secondLine);
+
+ }
+
+ private void createConnectorAliasInfoCmp(Composite parent) {
+ parent.setLayout(new GridLayout(4, false));
+
+ // first line: connector type and name
+ getToolkit().createLabel(parent, "Connector Type");
+ final Combo typeCmb = new Combo(parent, SWT.READ_ONLY);
+ typeCmb.setItems(connectorTypesLbl);
+
+ getToolkit().createLabel(parent, "Name");
+ final Text titleTxt = getToolkit().createText(parent, "", SWT.BORDER);
+ GridData gd = new GridData(SWT.FILL, SWT.TOP, true, false);
+ titleTxt.setLayoutData(gd);
+
+ // 2nd line: description
+ getToolkit().createLabel(parent, "Short Description");
+ final Text descTxt = getToolkit().createText(parent, "", SWT.BORDER);
+ gd = new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1);
+ descTxt.setLayoutData(gd);
+
+ // Part Management
+ final AbstractFormPart part = new AbstractFormPart() {
+ public void refresh() {
+ super.refresh();
+ // update display value
+ AkbUiUtils.refreshFormTextWidget(titleTxt, getAkbNode(),
+ Property.JCR_TITLE);
+ AkbUiUtils.refreshFormTextWidget(descTxt, getAkbNode(),
+ Property.JCR_DESCRIPTION);
+ }
+ };
+ // Listeners
+ AkbUiUtils.addTextModifyListener(titleTxt, getAkbNode(),
+ Property.JCR_TITLE, part);
+ AkbUiUtils.addTextModifyListener(descTxt, getAkbNode(),
+ Property.JCR_DESCRIPTION, part);
+
+ typeCmb.addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent event) {
+
+ try { // TODO enhance this
+
+ // retrieve old and new node type
+ int oldIndex = -1;
+ for (int i = 0; i < connectorTypes.length; i++) {
+ if (getAkbNode().isNodeType(connectorTypes[i])) {
+ oldIndex = i;
+ break;
+ }
+ }
+ int selIndex = typeCmb.getSelectionIndex();
+
+ // insure something has really been modified
+ if (selIndex < 0 || oldIndex == selIndex)
+ return;
+
+ // remove old mixin, add new and notify form
+ if (oldIndex > -1)
+ getAkbNode().removeMixin(connectorTypes[oldIndex]);
+ getAkbNode().addMixin(connectorTypes[selIndex]);
+ part.markDirty();
+ } catch (RepositoryException e) {
+ throw new AkbException(
+ "Error while updating connector type", e);
+ }
+ }
+ });
+
+ managedForm.addPart(part);
+ }
+
+ private void createDefaultTestConnectorCmp(Composite parent) {
+ String groupTitle = "Default test instance";
+ parent.setLayout(new GridLayout());
+ Group group = new Group(parent, SWT.NONE);
+ group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ getToolkit().adapt(group, false, false);
+
+ group.setText(groupTitle);
+ group.setLayout(AkbUiUtils.gridLayoutNoBorder());
+ // 1st line: the URL
+
+ Composite firstLine = getToolkit().createComposite(group);
+ firstLine.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ firstLine.setLayout(new GridLayout(3, false));
+
+ getToolkit().createLabel(firstLine, "URL");
+ final Text urlTxt = getToolkit().createText(firstLine, "", SWT.BORDER);
+ urlTxt.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ final Button testBtn = getToolkit().createButton(firstLine,
+ "Test connection", SWT.PUSH);
+ // testBtn.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false,
+ // false));
+
+ // Part Management
+ final AbstractFormPart part = new AbstractFormPart() {
+ public void refresh() {
+ super.refresh();
+ // update display value
+ AkbUiUtils.refreshFormTextWidget(urlTxt, getAkbNode(),
+ AkbNames.AKB_CONNECTOR_URL);
+ }
+ };
+ // Listeners
+ AkbUiUtils.addTextModifyListener(urlTxt, getAkbNode(),
+ AkbNames.AKB_CONNECTOR_URL, part);
+
+ testBtn.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ boolean testSuccesfull = getAkbService().testConnector(
+ getAkbNode());
+
+ String name = AkbJcrUtils.get(getAkbNode(), Property.JCR_TITLE);
+ String url = AkbJcrUtils.get(getAkbNode(),
+ AkbNames.AKB_CONNECTOR_URL);
+
+ String msg = "to " + name + " (" + url + ")";
+ if (testSuccesfull)
+ MessageDialog.openInformation(getSite().getShell(),
+ "Test successful", "Successfully connected " + msg);
+ else
+ MessageDialog.openError(getSite().getShell(),
+ "Test failure", "Unable to connect" + msg);
+ }
+ });
+
+ managedForm.addPart(part);
+
+ }
+
+ @Override
+ protected String getEditorId() {
+ return ID;
}
}
\ No newline at end of file
package org.argeo.slc.akb.ui.editors;
import org.argeo.slc.akb.ui.AkbUiPlugin;
+import org.argeo.slc.akb.ui.AkbUiUtils;
+import org.argeo.slc.akb.ui.composites.MixTitleComposite;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.IManagedForm;
/**
* Display and edit a connector Alias
/* CONTENT CREATION */
@Override
- public void createPartControl(Composite parent) {
+ public void populateMainPage(Composite parent, IManagedForm managedForm) {
+ parent.setLayout(AkbUiUtils.gridLayoutNoBorder());
+ // First line main info
+ MixTitleComposite mixTitleCmp = new MixTitleComposite(parent,
+ SWT.NO_FOCUS, getToolkit(), managedForm, getAkbNode());
+ mixTitleCmp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ }
+
+ @Override
+ protected String getEditorId() {
+ return ID;
}
}
\ No newline at end of file
public Object getParent(Object child) {
try {
- return ((Node) child).getParent();
+ Node node = (Node) child;
+ if (node.getDepth() == 0)
+ return null;
+ else
+ return node.getParent();
} catch (RepositoryException e) {
throw new AkbException("Error while getting parent node", e);
}
// + "session for view " + ID, e);
// }
}
- }
\ No newline at end of file
+}
\ No newline at end of file
import javax.jcr.Repository;\r
import javax.jcr.RepositoryException;\r
import javax.jcr.Session;\r
+import javax.jcr.observation.Event;\r
+import javax.jcr.observation.EventListener;\r
+import javax.jcr.observation.ObservationManager;\r
\r
+import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;\r
import org.argeo.eclipse.ui.utils.CommandUtils;\r
import org.argeo.jcr.JcrUtils;\r
import org.argeo.slc.akb.AkbException;\r
import org.argeo.slc.akb.AkbNames;\r
import org.argeo.slc.akb.AkbTypes;\r
import org.argeo.slc.akb.ui.AkbUiPlugin;\r
+import org.argeo.slc.akb.ui.commands.DeleteAkbNodes;\r
import org.argeo.slc.akb.ui.commands.OpenAkbNodeEditor;\r
import org.argeo.slc.akb.ui.providers.AkbTreeLabelProvider;\r
import org.argeo.slc.akb.ui.providers.TemplatesTreeContentProvider;\r
+import org.eclipse.jface.action.IContributionItem;\r
import org.eclipse.jface.action.IMenuListener;\r
import org.eclipse.jface.action.IMenuManager;\r
import org.eclipse.jface.action.MenuManager;\r
+import org.eclipse.jface.resource.ImageDescriptor;\r
import org.eclipse.jface.viewers.DoubleClickEvent;\r
import org.eclipse.jface.viewers.IDoubleClickListener;\r
import org.eclipse.jface.viewers.IStructuredSelection;\r
import org.eclipse.swt.SWT;\r
import org.eclipse.swt.layout.GridData;\r
import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
import org.eclipse.swt.widgets.Menu;\r
import org.eclipse.ui.IWorkbenchWindow;\r
+import org.eclipse.ui.menus.CommandContributionItem;\r
+import org.eclipse.ui.menus.CommandContributionItemParameter;\r
import org.eclipse.ui.part.ViewPart;\r
+import org.eclipse.ui.services.IServiceLocator;\r
\r
/** SLC generic JCR Result tree view. */\r
public class AkbTemplatesTreeView extends ViewPart {\r
// Usefull business objects\r
private Node templatesParentNode;\r
\r
+ // Observer\r
+ private EventListener allResultsObserver = null;\r
+ private final static String[] observedNodeTypesUnderAllResults = {\r
+ AkbTypes.AKB_ENV_TEMPLATE, AkbTypes.AKB_CONNECTOR_ALIAS,\r
+ AkbTypes.AKB_ITEM, AkbTypes.AKB_ITEM_FOLDER };\r
+\r
// private EventListener myResultsObserver = null;\r
// private EventListener allResultsObserver = null;\r
//\r
\r
getSite().registerContextMenu(menuManager, viewer);\r
\r
+ // Initialize observer\r
+ try {\r
+ ObservationManager observationManager = session.getWorkspace()\r
+ .getObservationManager();\r
+\r
+ allResultsObserver = new AllResultsObserver(viewer.getTree()\r
+ .getDisplay());\r
+\r
+ // observe tree changes under All results\r
+ observationManager.addEventListener(allResultsObserver,\r
+ Event.NODE_ADDED | Event.NODE_REMOVED,\r
+ templatesParentNode.getPath(), true, null,\r
+ observedNodeTypesUnderAllResults, false);\r
+ } catch (RepositoryException e) {\r
+ throw new AkbException("Cannot register listeners", e);\r
+ }\r
+\r
// add change listener to display TestResult information in the property\r
// viewer\r
// viewer.addSelectionChangedListener(new MySelectionChangedListener());\r
return viewer;\r
}\r
\r
+ class AllResultsObserver extends AsyncUiEventListener {\r
+\r
+ public AllResultsObserver(Display display) {\r
+ super(display);\r
+ }\r
+\r
+ @Override\r
+ protected Boolean willProcessInUiThread(List<Event> events)\r
+ throws RepositoryException {\r
+ // unfiltered for the time being\r
+ return true;\r
+ }\r
+\r
+ protected void onEventInUiThread(List<Event> events)\r
+ throws RepositoryException {\r
+ resultTreeViewer.setInput(initializeResultTree());\r
+ // if (lastSelectedSourceElementParent != null)\r
+ // refresh(lastSelectedSourceElementParent);\r
+ }\r
+ }\r
+\r
// Detailed property viewer\r
// protected TableViewer createPropertiesViewer(Composite parent) {\r
// }\r
IWorkbenchWindow window = AkbUiPlugin.getDefault().getWorkbench()\r
.getActiveWorkbenchWindow();\r
try {\r
+\r
+ // Build conditions\r
+ Node selected = (Node) ((IStructuredSelection) resultTreeViewer\r
+ .getSelection()).getFirstElement();\r
+\r
+ boolean hasSelection = selected != null;\r
+ boolean isParentItemsFolder = hasSelection ? selected\r
+ .isNodeType(AkbTypes.AKB_ITEM_FOLDER) : false;\r
+ boolean isParentConnectorsFolder = hasSelection ? selected\r
+ .isNodeType(AkbTypes.AKB_CONNECTOR_FOLDER) : false;\r
+ boolean isDeletable = hasSelection ? !(selected.getParent()\r
+ .isNodeType(AkbTypes.AKB_ENV_TEMPLATE)) : false;\r
+\r
+ // Add Connector Alias\r
Map<String, String> params = new HashMap<String, String>();\r
+ if (hasSelection)\r
+ params.put(OpenAkbNodeEditor.PARAM_PARENT_NODE_JCR_ID,\r
+ selected.getIdentifier());\r
+ params.put(OpenAkbNodeEditor.PARAM_NODE_TYPE,\r
+ AkbTypes.AKB_CONNECTOR_ALIAS);\r
+ refreshParameterizedCommand(menuManager, window,\r
+ "cmd.addConnector", OpenAkbNodeEditor.ID,\r
+ "Add connector Alias", null, isParentConnectorsFolder,\r
+ params);\r
+\r
+ // Add Item\r
+ params = new HashMap<String, String>();\r
+ if (hasSelection)\r
+ params.put(OpenAkbNodeEditor.PARAM_PARENT_NODE_JCR_ID,\r
+ selected.getIdentifier());\r
+ params.put(OpenAkbNodeEditor.PARAM_NODE_TYPE, AkbTypes.AKB_ITEM);\r
+ refreshParameterizedCommand(menuManager, window, "cmd.addItem",\r
+ OpenAkbNodeEditor.ID, "Add item", null,\r
+ isParentItemsFolder, params);\r
+\r
+ // Add Item Folder\r
+ params = new HashMap<String, String>();\r
+ if (hasSelection)\r
+ params.put(OpenAkbNodeEditor.PARAM_PARENT_NODE_JCR_ID,\r
+ selected.getIdentifier());\r
+ params.put(OpenAkbNodeEditor.PARAM_NODE_TYPE,\r
+ AkbTypes.AKB_ITEM_FOLDER);\r
+ refreshParameterizedCommand(menuManager, window,\r
+ "cmd.addItemFolder", OpenAkbNodeEditor.ID,\r
+ "Add item folder", null, isParentItemsFolder, params);\r
+\r
+ // Delete Item\r
+ params = new HashMap<String, String>();\r
+ if (hasSelection)\r
+ params.put(DeleteAkbNodes.PARAM_NODE_JCR_ID,\r
+ selected.getIdentifier());\r
+ refreshParameterizedCommand(menuManager, window, "cmd.deleteItem",\r
+ DeleteAkbNodes.ID, "Delete selected item(s)", null,\r
+ isDeletable, params);\r
+\r
+ // create template\r
+ params = new HashMap<String, String>();\r
params.put(OpenAkbNodeEditor.PARAM_PARENT_NODE_JCR_ID,\r
templatesParentNode.getIdentifier());\r
params.put(OpenAkbNodeEditor.PARAM_NODE_TYPE,\r
AkbTypes.AKB_ENV_TEMPLATE);\r
-\r
- // Effective Refresh\r
- CommandUtils.refreshParametrizedCommand(menuManager, window,\r
- OpenAkbNodeEditor.ID, "Create new template...", null, true,\r
- params);\r
+ refreshParameterizedCommand(menuManager, window,\r
+ "cmd.createTemplate", OpenAkbNodeEditor.ID,\r
+ "Create new template...", null, true, params);\r
\r
} catch (RepositoryException re) {\r
throw new AkbException("Error while refreshing context menu", re);\r
}\r
}\r
\r
+ /**\r
+ * Commodities the refresh of a single command with a map of parameters in a\r
+ * Menu.aboutToShow method to simplify further development\r
+ * \r
+ * @param menuManager\r
+ * @param locator\r
+ * @param cmdId\r
+ * @param label\r
+ * @param iconPath\r
+ * @param showCommand\r
+ */\r
+ private void refreshParameterizedCommand(IMenuManager menuManager,\r
+ IServiceLocator locator, String itemId, String cmdId, String label,\r
+ ImageDescriptor icon, boolean showCommand,\r
+ Map<String, String> params) {\r
+ IContributionItem ici = menuManager.find(itemId);\r
+ if (ici != null)\r
+ menuManager.remove(ici);\r
+ CommandContributionItemParameter contributionItemParameter = new CommandContributionItemParameter(\r
+ locator, itemId, cmdId, SWT.PUSH);\r
+\r
+ if (showCommand) {\r
+ // Set Params\r
+ contributionItemParameter.label = label;\r
+ contributionItemParameter.icon = icon;\r
+\r
+ if (params != null)\r
+ contributionItemParameter.parameters = params;\r
+\r
+ CommandContributionItem cci = new CommandContributionItem(\r
+ contributionItemParameter);\r
+ menuManager.add(cci);\r
+ }\r
+ }\r
+\r
/* INNER CLASSES */\r
class ViewDoubleClickListener implements IDoubleClickListener {\r
public void doubleClick(DoubleClickEvent evt) {\r
public interface AkbService {
/** Creates a preconfigured AKB Template */
- public Node createAkbTemplate(Node parent, String name) throws RepositoryException;
+ public Node createAkbTemplate(Node parent, String name)
+ throws RepositoryException;
+
+ /**
+ * Shortcut to perform whatever test on a given connector only to check if
+ * URL is correctly defined, if the target system is there and if the
+ * current user has the sufficient credentials to connect
+ */
+ public boolean testConnector(Node connector);
}
package org.argeo.slc.akb;
-/** Maps AKB specific JCR node types with java constants */
+/** Maps AKB specific JCR node types with java constants */
public interface AkbTypes {
public final static String ARGEO_NOTE = "argeo:note";
- // Env and templates
+ // Env and templates
public final static String AKB_ENV_TEMPLATE = "akb:envTemplate";
- public final static String AKB_ENV= "akb:env";
+ public final static String AKB_ENV = "akb:env";
// Connectors
- public final static String AKB_CONNECTOR = "akb:connector";
- public final static String AKB_CONNECTOR_ALIAS = "akb:connectorAlias";
+
+ public final static String AKB_CONNECTOR_FOLDER = "akb:connectorFolder";
+ public final static String AKB_CONNECTOR = "akb:connector";
+ public final static String AKB_CONNECTOR_ALIAS = "akb:connectorAlias";
// Various connector mixin types
- public final static String AKB_SSH_CONNECTOR = "akb:sshConnector";
- public final static String AKB_JDBC_CONNECTOR = "akb:jdbcConnector";
-
- // Item tree
+ public final static String AKB_SSH_CONNECTOR = "akb:sshConnector";
+ public final static String AKB_JDBC_CONNECTOR = "akb:jdbcConnector";
+ public final static String AKB_JCR_CONNECTOR = "akb:jcrConnector";
+
+ // Item tree
public final static String AKB_ITEM_FOLDER = "akb:itemsFolder";
public final static String AKB_ITEM = "akb:item";
-
+
// Various items types
public final static String AKB_SSH_FILE = "akb:sshFile";
public final static String AKB_SSH_COMMAND = "akb:sshCommand";
public final static String AKB_JDBC_QUERY = "akb:jdbcQuery";
public final static String AKB_NOTE = "akb:note";
-
}
\ No newline at end of file
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
Node newTemplate = parentNode.addNode(name, AkbTypes.AKB_ENV_TEMPLATE);
newTemplate.setProperty(Property.JCR_TITLE, name);
- Node connectorParent = newTemplate.addNode(connectorParentName,
- NodeType.NT_UNSTRUCTURED);
- connectorParent.addMixin(NodeType.MIX_TITLE);
+ Node connectorParent = newTemplate.addNode(
+ AkbTypes.AKB_CONNECTOR_FOLDER, AkbTypes.AKB_CONNECTOR_FOLDER);
connectorParent.setProperty(Property.JCR_TITLE, connectorParentName);
- Node itemsParent = newTemplate.addNode(itemsParentName,
- NodeType.NT_UNSTRUCTURED);
- itemsParent.addMixin(NodeType.MIX_TITLE);
+ Node itemsParent = newTemplate.addNode(AkbTypes.AKB_ITEM_FOLDER,
+ AkbTypes.AKB_ITEM_FOLDER);
itemsParent.setProperty(Property.JCR_TITLE, itemsParentName);
return newTemplate;
}
+ // ///////////////////////////////////////
+ // / CONNECTORS
+
+ public boolean testConnector(Node connector) {
+ // TODO Implement this.
+ return false;
+ }
+
// /** Expose injected repository */
// public Repository getRepository() {
// return repository;
- akb:connectorUrl (STRING)
// add argeo keyring
-[akb:connectorAlias] > nt:unstructured, mix:title
+// ease retrieval and enable adding alias specific properties
+[akb:connectorAlias] > akb:connector
+// Use akb:connectorUrl property to define default test connector
+
+
+// HELPER
+[akb:connectorFolder] > nt:unstructured, mix:title
++ * (akb:connector, akb:connectorAlias) *
+
// Various connector types as mixin
[akb:jdbcConnector]
mixin
+[akb:jcrConnector]
+mixin
+
//
//
// GENERIC ITEM FOLDER
//
-[akb:itemsFolder] > nt:unstructured
+[akb:itemsFolder] > nt:unstructured, mix:title
+ * (akb:item) *
++ * (akb:itemsFolder) *
//
// SSH FILE