Improve ACR viewer.
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 20 Jun 2022 10:42:19 +0000 (12:42 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 20 Jun 2022 10:42:19 +0000 (12:42 +0200)
eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/AcrContentTreeView.java [deleted file]
eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/app/AcrContentTreeView.java [new file with mode: 0644]
eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/app/CmsUserApp.java
eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtTabularPart.java
jcr/org.argeo.cms.jcr/src/org/argeo/cms/jcr/acr/JcrContent.java
org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/Column.java [new file with mode: 0644]
org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/TabularPart.java
org.argeo.cms/src/org/argeo/cms/acr/AbstractContent.java
org.argeo.cms/src/org/argeo/cms/acr/directory/RoleContent.java
org.argeo.util/src/org/argeo/osgi/useradmin/LdifUser.java

diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/AcrContentTreeView.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/AcrContentTreeView.java
deleted file mode 100644 (file)
index 98fabf0..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.argeo.cms.swt.acr;
-
-import javax.xml.namespace.QName;
-
-import org.argeo.api.acr.Content;
-import org.argeo.cms.swt.CmsSwtUtils;
-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.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.TableItem;
-
-public class AcrContentTreeView extends Composite {
-       private static final long serialVersionUID = -3707881216246077323L;
-       private SwtContentHierarchicalPart hPart;
-//     private Tree tree;
-       private Table table;
-       private Content rootContent;
-
-       private Content selected;
-
-       public AcrContentTreeView(Composite parent, int style, Content content) {
-               super(parent, style);
-               this.rootContent = content;
-               this.selected = rootContent;
-               setLayout(new GridLayout(2, false));
-               initTree();
-               GridData treeGd = CmsSwtUtils.fillHeight();
-               treeGd.widthHint = 300;
-               hPart.getArea().setLayoutData(treeGd);
-               initTable();
-
-               table.setLayoutData(CmsSwtUtils.fillAll());
-       }
-
-       protected void initTree() {
-               hPart = new SwtContentHierarchicalPart(this, getStyle());
-               hPart.setInput(rootContent);
-               hPart.onSelected((o) -> {
-                       Content content = (Content) o;
-                       selected = content;
-                       refreshTable();
-
-               });
-//             tree = new Tree(this, 0);
-//             for (Content c : rootContent) {
-//                     TreeItem root = new TreeItem(tree, 0);
-//                     root.setText(c.getName().toString());
-//                     root.setData(c);
-//                     new TreeItem(root, 0);
-//             }
-//             tree.addListener(SWT.Expand, event -> {
-//                     final TreeItem root = (TreeItem) event.item;
-//                     TreeItem[] items = root.getItems();
-//                     for (TreeItem item : items) {
-//                             if (item.getData() != null)
-//                                     return;
-//                             item.dispose();
-//                     }
-//                     Content content = (Content) root.getData();
-//                     for (Content c : content) {
-//                             TreeItem item = new TreeItem(root, 0);
-//                             item.setText(c.getName().toString());
-//                             item.setData(c);
-//                             boolean hasChildren = true;
-//                             if (hasChildren) {
-//                                     new TreeItem(item, 0);
-//                             }
-//                     }
-//             });
-//             tree.addListener(SWT.Selection, event -> {
-//                     TreeItem item = (TreeItem) event.item;
-//                     selected = (Content) item.getData();
-//                     refreshTable();
-//             });
-       }
-
-       protected void initTable() {
-               table = new Table(this, 0);
-               table.setLinesVisible(true);
-               table.setHeaderVisible(true);
-               TableColumn keyCol = new TableColumn(table, SWT.NONE);
-               keyCol.setText("Attribute");
-               keyCol.setWidth(200);
-               TableColumn valueCol = new TableColumn(table, SWT.NONE);
-               valueCol.setText("Value");
-               keyCol.setWidth(300);
-               refreshTable();
-       }
-
-       protected void refreshTable() {
-               for (TableItem item : table.getItems()) {
-                       item.dispose();
-               }
-               for (QName key : selected.keySet()) {
-                       TableItem item = new TableItem(table, 0);
-                       item.setText(0, key.toString());
-                       Object value = selected.get(key);
-                       item.setText(1, value.toString());
-               }
-               table.getColumn(0).pack();
-               table.getColumn(1).pack();
-       }
-
-//     public static void main(String[] args) {
-//             Path basePath;
-//             if (args.length > 0) {
-//                     basePath = Paths.get(args[0]);
-//             } else {
-//                     basePath = Paths.get(System.getProperty("user.home"));
-//             }
-//
-//             final Display display = new Display();
-//             final Shell shell = new Shell(display);
-//             shell.setText(basePath.toString());
-//             shell.setLayout(new FillLayout());
-//
-//             FsContentProvider contentSession = new FsContentProvider("/", basePath);
-////           GcrContentTreeView treeView = new GcrContentTreeView(shell, 0, contentSession.get("/"));
-//
-//             shell.setSize(shell.computeSize(800, 600));
-//             shell.open();
-//             while (!shell.isDisposed()) {
-//                     if (!display.readAndDispatch())
-//                             display.sleep();
-//             }
-//             display.dispose();
-//     }
-}
diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/app/AcrContentTreeView.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/app/AcrContentTreeView.java
new file mode 100644 (file)
index 0000000..cfae59b
--- /dev/null
@@ -0,0 +1,152 @@
+package org.argeo.cms.swt.app;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.Content;
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.acr.SwtContentHierarchicalPart;
+import org.argeo.cms.swt.widgets.SwtTabularPart;
+import org.argeo.cms.ux.widgets.Column;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+
+public class AcrContentTreeView extends Composite {
+       private static final long serialVersionUID = -3707881216246077323L;
+
+       private Content rootContent;
+
+       private Content selected;
+
+       public AcrContentTreeView(Composite parent, int style, Content content) {
+               super(parent, style);
+               this.rootContent = content;
+               this.selected = rootContent;
+               setLayout(CmsSwtUtils.noSpaceGridLayout());
+
+               SashForm split = new SashForm(this, SWT.HORIZONTAL);
+               split.setLayoutData(CmsSwtUtils.fillAll());
+
+               SwtContentHierarchicalPart hPart = new SwtContentHierarchicalPart(split, getStyle());
+               Composite area = new Composite(split, SWT.NONE);
+               area.setLayout(CmsSwtUtils.noSpaceGridLayout(2));
+               split.setWeights(new int[] { 30, 70 });
+
+               // attributes
+               SwtTabularPart attributesPart = new SwtTabularPart(area, SWT.NONE) {
+                       List<QName> data;
+
+                       @Override
+                       protected Object getData(int row) {
+                               return data.get(row);
+                       }
+
+                       @Override
+                       protected int getItemCount() {
+                               data = new ArrayList<>(selected.keySet());
+                               return data.size();
+                       }
+               };
+               attributesPart.getArea().setLayoutData(CmsSwtUtils.fillHeight());
+
+               attributesPart.addColumn(new Column<QName>() {
+
+                       @Override
+                       public String getText(QName model) {
+                               return model.toString();
+                       }
+               });
+               attributesPart.addColumn(new Column<QName>() {
+
+                       @Override
+                       public String getText(QName model) {
+                               return selected.get(model).toString();
+                       }
+
+                       @Override
+                       public int getWidth() {
+                               return 400;
+                       }
+
+               });
+
+               // types
+               SwtTabularPart typesPart = new SwtTabularPart(area, SWT.NONE) {
+                       List<QName> data;
+
+                       @Override
+                       protected Object getData(int row) {
+                               return data.get(row);
+                       }
+
+                       @Override
+                       protected int getItemCount() {
+                               data = new ArrayList<>(selected.getTypes());
+                               return data.size();
+                       }
+               };
+               typesPart.addColumn(new Column<QName>() {
+
+                       @Override
+                       public String getText(QName model) {
+                               return model.toString();
+                       }
+               });
+               typesPart.getArea().setLayoutData(CmsSwtUtils.fillHeight());
+
+               // controller
+               hPart.setInput(rootContent);
+               hPart.onSelected((o) -> {
+                       Content c = (Content) o;
+                       selected = c;
+                       attributesPart.refresh();
+                       typesPart.refresh();
+               });
+
+               attributesPart.refresh();
+               typesPart.refresh();
+       }
+
+//     protected void refreshTable() {
+//             for (TableItem item : table.getItems()) {
+//                     item.dispose();
+//             }
+//             for (QName key : selected.keySet()) {
+//                     TableItem item = new TableItem(table, 0);
+//                     item.setText(0, key.toString());
+//                     Object value = selected.get(key);
+//                     item.setText(1, value.toString());
+//             }
+//             table.getColumn(0).pack();
+//             table.getColumn(1).pack();
+//     }
+
+//     public static void main(String[] args) {
+//             Path basePath;
+//             if (args.length > 0) {
+//                     basePath = Paths.get(args[0]);
+//             } else {
+//                     basePath = Paths.get(System.getProperty("user.home"));
+//             }
+//
+//             final Display display = new Display();
+//             final Shell shell = new Shell(display);
+//             shell.setText(basePath.toString());
+//             shell.setLayout(new FillLayout());
+//
+//             FsContentProvider contentSession = new FsContentProvider("/", basePath);
+////           GcrContentTreeView treeView = new GcrContentTreeView(shell, 0, contentSession.get("/"));
+//
+//             shell.setSize(shell.computeSize(800, 600));
+//             shell.open();
+//             while (!shell.isDisposed()) {
+//                     if (!display.readAndDispatch())
+//                             display.sleep();
+//             }
+//             display.dispose();
+//     }
+}
index 064c7e6864bf868fe6d41229820b95f541f28878..2eb2ce5dd029bd436879c72580117b4491abe821 100644 (file)
@@ -11,7 +11,6 @@ import org.argeo.api.cms.CmsView;
 import org.argeo.cms.AbstractCmsApp;
 import org.argeo.cms.swt.CmsSwtUi;
 import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.swt.acr.AcrContentTreeView;
 import org.argeo.cms.swt.auth.CmsLogin;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
index 02f2f815354e332d0c8617f9fd4f7173b37295e6..9872551be31546742f86287f520442915c53f43f 100644 (file)
@@ -3,12 +3,14 @@ package org.argeo.cms.swt.widgets;
 import java.util.function.Consumer;
 
 import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.ux.widgets.Column;
 import org.argeo.cms.ux.widgets.TabularPart;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.swt.widgets.TableItem;
 
 /** {@link TabularPart} implementation based on a {@link Table}. */
@@ -24,6 +26,7 @@ public class SwtTabularPart implements TabularPart {
                area = new Composite(parent, style);
                area.setLayout(CmsSwtUtils.noSpaceGridLayout());
                table = new Table(area, SWT.VIRTUAL | SWT.BORDER);
+               table.setLinesVisible(true);
        }
 
        @Override
@@ -67,13 +70,23 @@ public class SwtTabularPart implements TabularPart {
        }
 
        protected void refreshItem(TableItem item) {
-
+               int row = getTable().indexOf(item);
+               for (int i = 0; i < item.getParent().getColumnCount(); i++) {
+                       Column<Object> column = (Column<Object>) item.getParent().getColumn(i).getData();
+                       Object data = getData(row);
+                       String text = data != null ? column.getText(data) : "";
+                       item.setText(i, text);
+               }
        }
 
        protected int getItemCount() {
                return 0;
        }
 
+       protected Object getData(int row) {
+               return null;
+       }
+
        protected Table getTable() {
                return table;
        }
@@ -86,4 +99,16 @@ public class SwtTabularPart implements TabularPart {
                this.onAction = onAction;
        }
 
+       @Override
+       public void addColumn(Column<?> column) {
+               TableColumn swtColumn = new TableColumn(table, SWT.NONE);
+               swtColumn.setWidth(column.getWidth());
+               swtColumn.setData(column);
+
+       }
+
+       public Composite getArea() {
+               return area;
+       }
+
 }
index a7a9ecce0746f85a9e7967112c93b425e46a2b89..41672a0e9e24b68ca9ca0a49f64776330d2948d7 100644 (file)
@@ -307,7 +307,7 @@ public class JcrContent extends AbstractContent {
                        NodeType primaryType = context.getPrimaryNodeType();
                        res.add(nodeTypeToQName(primaryType));
 
-                       Set<QName> secondaryTypes = new TreeSet<>();
+                       Set<QName> secondaryTypes = new TreeSet<>(NamespaceUtils.QNAME_COMPARATOR);
                        for (NodeType mixinType : context.getMixinNodeTypes()) {
                                secondaryTypes.add(nodeTypeToQName(mixinType));
                        }
diff --git a/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/Column.java b/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/Column.java
new file mode 100644 (file)
index 0000000..5890fc4
--- /dev/null
@@ -0,0 +1,9 @@
+package org.argeo.cms.ux.widgets;
+
+public interface Column<T> {
+       String getText(T model);
+
+       default int getWidth() {
+               return 200;
+       }
+}
index 40a56eb525704c1aaea9b2a8ec15f38cd7ee5f06..4c9320268f874141185d7490b92b1d0f429de73b 100644 (file)
@@ -1,5 +1,5 @@
 package org.argeo.cms.ux.widgets;
 
 public interface TabularPart extends ColumnsPart {
-
+       void addColumn(Column<?> column);
 }
index 18c6724ace740d6a5df99e5cf43e9126cd6c9eaf..c8ba7311daaa4206a14de8be12a032ed40644c7d 100644 (file)
@@ -16,6 +16,7 @@ import org.argeo.api.acr.Content;
 import org.argeo.api.acr.CrName;
 import org.argeo.api.acr.spi.ProvidedContent;
 import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.util.LangUtils;
 
 /** Partial reference implementation of a {@link ProvidedContent}. */
 public abstract class AbstractContent extends AbstractMap<QName, Object> implements ProvidedContent {
@@ -152,9 +153,9 @@ public abstract class AbstractContent extends AbstractMap<QName, Object> impleme
        /*
         * DEFAULTS
         */
-       //      - no children
-       //      - no attributes
-       //      - cannot be modified
+       // - no children
+       // - no attributes
+       // - cannot be modified
        @Override
        public Iterator<Content> iterator() {
                return Collections.emptyIterator();
@@ -226,12 +227,7 @@ public abstract class AbstractContent extends AbstractMap<QName, Object> impleme
 
                @Override
                public int size() {
-
-                       int count = 0;
-                       for (Iterator<QName> it = keys().iterator(); it.hasNext();) {
-                               count++;
-                       }
-                       return count;
+                       return LangUtils.size(keys());
                }
 
        }
index 344dede76d52c7a1ddce15c02c2a601a4828ec8a..bf3b319f40bd4aa5f248e2cdb637b5cca74028e4 100644 (file)
@@ -79,17 +79,16 @@ class RoleContent extends AbstractContent {
        @Override
        public List<QName> getTypes() {
                List<QName> contentClasses = new ArrayList<>();
-               keys: for (Enumeration<String> it = role.getProperties().keys(); it.hasMoreElements();) {
-                       String key = it.nextElement();
-                       if (key.equalsIgnoreCase(LdapAttrs.objectClass.name())) {
-                               String[] objectClasses = role.getProperties().get(key).toString().split("\\n");
-                               objectClasses: for (String objectClass : objectClasses) {
-                                       if (LdapObjs.top.name().equalsIgnoreCase(objectClass))
-                                               continue objectClasses;
-                                       contentClasses.add(new ContentName(CrName.LDAP_NAMESPACE_URI, objectClass, provider));
-                               }
-                               break keys;
-                       }
+               String objectClass = role.getProperties().get(LdapAttrs.objectClass.name()).toString();
+               contentClasses.add(new ContentName(CrName.LDAP_NAMESPACE_URI, objectClass, provider));
+
+               String[] objectClasses = role.getProperties().get(LdapAttrs.objectClasses.name()).toString().split("\\n");
+               objectClasses: for (String oc : objectClasses) {
+                       if (LdapObjs.top.name().equalsIgnoreCase(oc))
+                               continue objectClasses;
+                       if (objectClass.equalsIgnoreCase(oc))
+                               continue objectClasses;
+                       contentClasses.add(new ContentName(CrName.LDAP_NAMESPACE_URI, oc, provider));
                }
                return contentClasses;
        }
index 552bfdc8da8bfbeaac3d20c608abbb64e2d2d63d..1eb4067d7a036e4bc1bd2cd372c74a87e70d565c 100644 (file)
@@ -243,21 +243,23 @@ class LdifUser implements DirectoryUser {
                private final List<String> attrFilter;
                private final Boolean includeFilter;
 
-               public AttributeDictionary(Boolean includeFilter) {
+               public AttributeDictionary(Boolean credentials) {
                        this.attrFilter = userAdmin.getCredentialAttributeIds();
-                       this.includeFilter = includeFilter;
+                       this.includeFilter = credentials;
                        try {
                                NamingEnumeration<String> ids = getAttributes().getIDs();
                                while (ids.hasMore()) {
                                        String id = ids.next();
-                                       if (includeFilter && attrFilter.contains(id))
+                                       if (credentials && attrFilter.contains(id))
                                                effectiveKeys.add(id);
-                                       else if (!includeFilter && !attrFilter.contains(id))
+                                       else if (!credentials && !attrFilter.contains(id))
                                                effectiveKeys.add(id);
                                }
                        } catch (NamingException e) {
                                throw new UserDirectoryException("Cannot initialise attribute dictionary", e);
                        }
+                       if (!credentials)
+                               effectiveKeys.add(LdapAttrs.objectClasses.name());
                }
 
                @Override
@@ -297,7 +299,8 @@ class LdifUser implements DirectoryUser {
                @Override
                public Object get(Object key) {
                        try {
-                               Attribute attr = getAttributes().get(key.toString());
+                               Attribute attr = !key.equals(LdapAttrs.objectClasses.name()) ? getAttributes().get(key.toString())
+                                               : getAttributes().get(LdapAttrs.objectClass.name());
                                if (attr == null)
                                        return null;
                                Object value = attr.get();
@@ -310,7 +313,7 @@ class LdifUser implements DirectoryUser {
                                if (attr.size() == 1)
                                        return value;
                                // special case for object class
-                               if (attr.getID().equals(LdapAttrs.objectClass.name())) {
+                               if (key.equals(LdapAttrs.objectClass.name())) {
                                        // TODO support multiple object classes
                                        NamingEnumeration<?> en = attr.getAll();
                                        String first = null;