--- /dev/null
+package org.argeo.jcr.ui.explorer.editors;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ui.explorer.JcrExplorerConstants;
+import org.argeo.jcr.ui.explorer.JcrExplorerPlugin;
+import org.argeo.jcr.ui.explorer.providers.PropertyLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+/**
+ * Generic editor property page. Lists all properties of current node as a
+ * complex tree. TODO: enable editing
+ */
+
+public class GenericPropertyPage extends FormPage implements
+ JcrExplorerConstants {
+ private final static Log log = LogFactory.getLog(GenericPropertyPage.class);
+
+ // local constants
+ private final static String JCR_PROPERTY_NAME = "jcr:name";
+
+ // Main business Objects
+ private Node currentNode;
+
+ // This page widgets
+ private FormToolkit tk;
+ private TreeViewer complexTree;
+
+ public GenericPropertyPage(FormEditor editor, String title, Node currentNode) {
+ super(editor, "id", title);
+ this.currentNode = currentNode;
+ }
+
+ protected void createFormContent(IManagedForm managedForm) {
+ tk = managedForm.getToolkit();
+ ScrolledForm form = managedForm.getForm();
+ form.setText(JcrExplorerPlugin
+ .getMessage("genericNodePageTitle"));
+ FillLayout layout = new FillLayout();
+ layout.marginHeight = 5;
+ layout.marginWidth = 5;
+ form.getBody().setLayout(layout);
+
+ complexTree = createComplexTree(form.getBody());
+
+ // TODO remove following
+ // createPropertiesPart(form.getBody());
+ }
+
+ private TreeViewer createComplexTree(Composite parent) {
+ int style = SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION;
+ Tree tree = new Tree(parent, style);
+ createColumn(tree, "Property", SWT.LEFT, 200);
+ createColumn(tree, "Value(s)", SWT.LEFT, 300);
+ createColumn(tree, "Attributes", SWT.LEFT, 65);
+ tree.setLinesVisible(true);
+ tree.setHeaderVisible(true);
+
+ TreeViewer result = new TreeViewer(tree);
+ result.setContentProvider(new TreeContentProvider());
+ result.setLabelProvider(new PropertyLabelProvider());
+ result.setInput(currentNode);
+ result.expandAll();
+ return result;
+ }
+
+ 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;
+ }
+
+ //
+ // private void createPropertiesPart(Composite parent) {
+ // try {
+ //
+ // PropertyIterator pi = currentNode.getProperties();
+ //
+ // // Initializes form part
+ // AbstractFormPart part = new AbstractFormPart() {
+ // public void commit(boolean onSave) {
+ // try {
+ // if (onSave) {
+ // ListIterator<Control> it = modifyableProperties
+ // .listIterator();
+ // while (it.hasNext()) {
+ // // we only support Text controls for the time
+ // // being
+ // Text curControl = (Text) it.next();
+ // String value = curControl.getText();
+ // currentNode.setProperty((String) curControl
+ // .getData(JCR_PROPERTY_NAME), value);
+ // }
+ //
+ // // We only commit when onSave = true,
+ // // thus it is still possible to save after a tab
+ // // change.
+ // super.commit(onSave);
+ // }
+ // } catch (RepositoryException re) {
+ // throw new ArgeoException(
+ // "Unexpected error while saving properties", re);
+ // }
+ // }
+ // };
+ //
+ // while (pi.hasNext()) {
+ // Property prop = pi.nextProperty();
+ // addPropertyLine(parent, part, prop);
+ // }
+ //
+ // getManagedForm().addPart(part);
+ // } catch (RepositoryException re) {
+ // throw new ArgeoException(
+ // "Error during creation of network details section", re);
+ // }
+ //
+ // }
+ //
+ // private void addPropertyLine(Composite parent, AbstractFormPart part,
+ // Property prop) {
+ // try {
+ // tk.createLabel(parent, prop.getName());
+ // tk.createLabel(parent,
+ // "[" + JcrUtils.getPropertyDefinitionAsString(prop) + "]");
+ //
+ // if (prop.getDefinition().isProtected()) {
+ // tk.createLabel(parent, formatReadOnlyPropertyValue(prop));
+ // } else
+ // addModifyableValueWidget(parent, part, prop);
+ // } catch (RepositoryException re) {
+ // throw new ArgeoException("Cannot get property " + prop, re);
+ // }
+ // }
+ //
+ // private String formatReadOnlyPropertyValue(Property prop) {
+ // try {
+ // String strValue;
+ //
+ // if (prop.getType() == PropertyType.BINARY)
+ // strValue = "<binary>";
+ // else if (prop.isMultiple())
+ // strValue = Arrays.asList(prop.getValues()).toString();
+ // else if (prop.getType() == PropertyType.DATE)
+ // strValue = timeFormatter.format(prop.getValue().getDate()
+ // .getTime());
+ // else
+ // strValue = prop.getValue().getString();
+ //
+ // return strValue;
+ // } catch (RepositoryException re) {
+ // throw new ArgeoException(
+ // "Unexpected error while formatting read only property value",
+ // re);
+ // }
+ // }
+ //
+ // private Control addModifyableValueWidget(Composite parent,
+ // AbstractFormPart part, Property prop) {
+ // GridData gd;
+ // try {
+ // if (prop.getType() == PropertyType.STRING) {
+ // Text txt = tk.createText(parent, prop.getString());
+ // gd = new GridData(GridData.FILL_HORIZONTAL);
+ // txt.setLayoutData(gd);
+ // txt.addModifyListener(new ModifiedFieldListener(part));
+ // txt.setData(JCR_PROPERTY_NAME, prop.getName());
+ // modifyableProperties.add(txt);
+ // } else {
+ // // unsupported property type for editing, we create a read only
+ // // label.
+ // return tk
+ // .createLabel(parent, formatReadOnlyPropertyValue(prop));
+ // }
+ // return null;
+ // } catch (RepositoryException re) {
+ // throw new ArgeoException(
+ // "Unexpected error while formatting read only property value",
+ // re);
+ // }
+ //
+ // }
+
+ // Multiple Value Model
+ // protected class MultipleValueItem {
+ // private int index;
+ // private Value value;
+ //
+ // public MultipleValueItem(int index, Value value) {
+ // this.index = index;
+ // this.value = value;
+ // }
+ //
+ // public int getIndex() {
+ // return index;
+ // }
+ //
+ // public Object getValue() {
+ // return value;
+ // }
+ // }
+
+ private class TreeContentProvider implements ITreeContentProvider {
+ public Object[] getElements(Object parent) {
+ Object[] props = null;
+ try {
+
+ if (parent instanceof Node) {
+ Node node = (Node) parent;
+ PropertyIterator pi;
+ pi = node.getProperties();
+ List<Property> propList = new ArrayList<Property>();
+ while (pi.hasNext()) {
+ propList.add(pi.nextProperty());
+ }
+ props = propList.toArray();
+ }
+ } catch (RepositoryException e) {
+ throw new ArgeoException(
+ "Unexpected exception while listing node properties", e);
+ }
+ return props;
+ }
+
+ public Object getParent(Object child) {
+ return null;
+ }
+
+ public Object[] getChildren(Object parent) {
+ Object[] result = null;
+ if (parent instanceof Property) {
+ Property prop = (Property) parent;
+ try {
+
+ if (prop.isMultiple()) {
+ Value[] values = prop.getValues();
+ // List<MultipleValueItem> list = new
+ // ArrayList<MultipleValueItem>();
+ // for (int i = 0; i < values.length; i++) {
+ // MultipleValueItem mvi = new MultipleValueItem(i,
+ // values[i]);
+ // list.add(mvi);
+ // }
+
+ return values;
+ }
+ } catch (RepositoryException e) {
+ throw new ArgeoException(
+ "Unexpected error getting multiple values property.",
+ e);
+ }
+ }
+ return result;
+ }
+
+ public boolean hasChildren(Object parent) {
+ try {
+ if (parent instanceof Property
+ && ((Property) parent).isMultiple()) {
+ 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() {
+ }
+ }
+}
--- /dev/null
+package org.argeo.jcr.ui.explorer.providers;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+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.jcr.ui.explorer.JcrExplorerConstants;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ViewerCell;
+
+public class PropertyLabelProvider extends ColumnLabelProvider implements
+ JcrExplorerConstants {
+
+ // To be able to change column order easily
+ public static final int COLUMN_PROPERTY = 0;
+ public static final int COLUMN_VALUE = 1;
+ public static final int COLUMN_ATTRIBUTES = 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 Property) {
+ Property prop = (Property) element;
+ if (prop.isMultiple()) {
+ switch (columnIndex) {
+ case COLUMN_PROPERTY:
+ return prop.getName();
+ case COLUMN_VALUE:
+ // Corresponding values are listed on children
+ return "";
+ case COLUMN_ATTRIBUTES:
+ return JcrUtils.getPropertyDefinitionAsString(prop);
+ }
+ } else {
+ switch (columnIndex) {
+ case COLUMN_PROPERTY:
+ return prop.getName();
+ case COLUMN_VALUE:
+ return formatValueAsString(prop.getValue());
+ case COLUMN_ATTRIBUTES:
+ return JcrUtils.getPropertyDefinitionAsString(prop);
+ }
+ }
+ } else if (element instanceof Value) {
+ Value val = (Value) element;
+
+ switch (columnIndex) {
+ case COLUMN_PROPERTY:
+ // Nothing to show
+ return "";
+ case COLUMN_VALUE:
+ return formatValueAsString(val);
+ case COLUMN_ATTRIBUTES:
+ // Corresponding attributes are listed on the parent
+ return "";
+ }
+ }
+
+ } 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 = "<binary>";
+ 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);
+ }
+ }
+}