Improve terms framework.
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 2 Feb 2021 11:30:23 +0000 (12:30 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 2 Feb 2021 11:30:23 +0000 (12:30 +0100)
core/org.argeo.entity.api/src/org/argeo/entity/Term.java [new file with mode: 0644]
core/org.argeo.entity.api/src/org/argeo/entity/TermsManager.java
core/org.argeo.entity.api/src/org/argeo/entity/Typology.java [new file with mode: 0644]
core/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/AbstractTermsPart.java
core/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/MultiTermsPart.java
core/org.argeo.entity.ui/src/org/argeo/entity/ui/forms/SingleTermPart.java
core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTerm.java
core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTermsManager.java
core/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTypology.java

diff --git a/core/org.argeo.entity.api/src/org/argeo/entity/Term.java b/core/org.argeo.entity.api/src/org/argeo/entity/Term.java
new file mode 100644 (file)
index 0000000..3bf075a
--- /dev/null
@@ -0,0 +1,22 @@
+package org.argeo.entity;
+
+import java.util.List;
+
+/**
+ * A name within a {@link Typology}, used to qualify an entity (categories,
+ * keywords, etc.).
+ */
+public interface Term {
+       String getId();
+
+       String getName();
+
+//     String getRelativePath();
+
+       Typology getTypology();
+
+       List<? extends Term> getSubTerms();
+
+       Term getParentTerm();
+
+}
index a2b5951534b0c5b01b62641566f871ece669bc38..7564ff97821d1c8f98a0762c7d0570133721660f 100644 (file)
@@ -4,5 +4,10 @@ import java.util.List;
 
 /** Provides optimised access and utilities around terms typologies. */
 public interface TermsManager {
-       List<String> listAllTerms(String typology);
+       Typology getTypology(String typology);
+       
+       Term getTerm(String id);
+
+       List<Term> listAllTerms(String typology);
+
 }
diff --git a/core/org.argeo.entity.api/src/org/argeo/entity/Typology.java b/core/org.argeo.entity.api/src/org/argeo/entity/Typology.java
new file mode 100644 (file)
index 0000000..43431a0
--- /dev/null
@@ -0,0 +1,14 @@
+package org.argeo.entity;
+
+import java.util.List;
+
+/** A structured and exhaustive set of {@link Term}s. */
+public interface Typology {
+
+       String getId();
+
+       boolean isFlat();
+
+       List<? extends Term> getSubTerms();
+
+}
index f2ea75633019eb4bcd23d794d94d22cc0356279f..408a0bff2e828870357a972aff7fbce935504c92 100644 (file)
@@ -2,12 +2,15 @@ package org.argeo.entity.ui.forms;
 
 import javax.jcr.Item;
 
+import org.argeo.cms.Localized;
 import org.argeo.cms.ui.CmsTheme;
 import org.argeo.cms.ui.util.CmsIcon;
 import org.argeo.cms.ui.viewers.EditablePart;
 import org.argeo.cms.ui.widgets.ContextOverlay;
 import org.argeo.cms.ui.widgets.StyledControl;
+import org.argeo.entity.Term;
 import org.argeo.entity.TermsManager;
+import org.argeo.entity.Typology;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.layout.GridData;
@@ -20,7 +23,7 @@ import org.eclipse.swt.widgets.ToolItem;
 public abstract class AbstractTermsPart extends StyledControl implements EditablePart {
        private static final long serialVersionUID = -5497097995341927710L;
        protected final TermsManager termsManager;
-       protected final String typology;
+       protected final Typology typology;
 
        protected final boolean editable;
 
@@ -33,13 +36,12 @@ public abstract class AbstractTermsPart extends StyledControl implements Editabl
 
        protected final CmsTheme theme;
 
-       public AbstractTermsPart(Composite parent, int style, Item item, TermsManager termsManager,
-                       String typology) {
+       public AbstractTermsPart(Composite parent, int style, Item item, TermsManager termsManager, String typology) {
                super(parent, style, item);
-               if(item==null)
+               if (item == null)
                        throw new IllegalArgumentException("Item cannot be null");
                this.termsManager = termsManager;
-               this.typology = typology;
+               this.typology = termsManager.getTypology(typology);
                this.theme = CmsTheme.getCmsTheme(parent);
                editable = !(SWT.READ_ONLY == (style & SWT.READ_ONLY));
                highlightColor = parent.getDisplay().getSystemColor(SWT.COLOR_GRAY);
@@ -55,17 +57,21 @@ public abstract class AbstractTermsPart extends StyledControl implements Editabl
 
        }
 
-       protected String getTermLabel(String name) {
-               return name;
+       protected String getTermLabel(Term term) {
+               if (term instanceof Localized)
+                       return ((Localized) term).lead();
+               else
+                       return term.getName();
+
        }
 
        protected abstract void refresh(ContextOverlay contextArea, String filter, Text txt);
 
-       protected boolean isTermSelectable(String term) {
+       protected boolean isTermSelectable(Term term) {
                return true;
        }
 
-       protected void processTermListLabel(String term, Label label) {
+       protected void processTermListLabel(Term term, Label label) {
 
        }
 
index 1a12e90f2a5d458aaf6eb88ce5c65d603d417b96..457da70312233cb8039f74657d4df028f0906e81 100644 (file)
@@ -12,6 +12,7 @@ import org.argeo.cms.ui.widgets.ContextOverlay;
 import org.argeo.eclipse.ui.MouseDoubleClick;
 import org.argeo.eclipse.ui.MouseDown;
 import org.argeo.eclipse.ui.Selected;
+import org.argeo.entity.Term;
 import org.argeo.entity.TermsManager;
 import org.argeo.jcr.Jcr;
 import org.eclipse.swt.SWT;
@@ -39,9 +40,9 @@ public class MultiTermsPart extends AbstractTermsPart {
                Composite placeholder = new Composite(box, SWT.NONE);
                RowLayout rl = new RowLayout(SWT.HORIZONTAL | SWT.WRAP);
                placeholder.setLayout(rl);
-               List<String> currentValue = Jcr.getMultiple(getNode(), typology);
+               List<Term> currentValue = getValue();
                if (currentValue != null && !currentValue.isEmpty())
-                       for (String value : currentValue) {
+                       for (Term value : currentValue) {
                                Composite block = new Composite(placeholder, SWT.NONE);
                                block.setLayout(CmsUiUtils.noSpaceGridLayout(3));
                                Label lbl = new Label(block, SWT.SINGLE);
@@ -58,14 +59,13 @@ public class MultiTermsPart extends AbstractTermsPart {
                                        styleDelete(deleteItem);
                                        deleteItem.addSelectionListener((Selected) (e) -> {
                                                // we retrieve them again here because they may have changed
-                                               List<String> curr = Jcr.getMultiple(getNode(), typology);
-                                               List<String> newValue = new ArrayList<>();
-                                               for (String v : curr) {
+                                               List<Term> curr = getValue();
+                                               List<Term> newValue = new ArrayList<>();
+                                               for (Term v : curr) {
                                                        if (!v.equals(value))
                                                                newValue.add(v);
                                                }
-                                               Jcr.set(getNode(), typology, newValue);
-                                               Jcr.save(getNode());
+                                               setValue(newValue);
                                                block.dispose();
                                                layout(true, true);
                                        });
@@ -143,9 +143,9 @@ public class MultiTermsPart extends AbstractTermsPart {
        @Override
        protected void refresh(ContextOverlay contextArea, String filter, Text txt) {
                CmsUiUtils.clear(contextArea);
-               List<String> terms = termsManager.listAllTerms(typology);
-               List<String> currentValue = Jcr.getMultiple(getNode(), typology);
-               terms: for (String term : terms) {
+               List<? extends Term> terms = termsManager.listAllTerms(typology.getId());
+               List<Term> currentValue = getValue();
+               terms: for (Term term : terms) {
                        if (currentValue != null && currentValue.contains(term))
                                continue terms;
                        String display = getTermLabel(term);
@@ -156,13 +156,12 @@ public class MultiTermsPart extends AbstractTermsPart {
                        processTermListLabel(term, termL);
                        if (isTermSelectable(term))
                                termL.addMouseListener((MouseDown) (e) -> {
-                                       List<String> newValue = new ArrayList<>();
-                                       List<String> curr = Jcr.getMultiple(getNode(), typology);
+                                       List<Term> newValue = new ArrayList<>();
+                                       List<Term> curr = getValue();
                                        if (currentValue != null)
                                                newValue.addAll(curr);
                                        newValue.add(term);
-                                       Jcr.set(getNode(), typology, newValue);
-                                       Jcr.save(getNode());
+                                       setValue(newValue);
                                        contextArea.hide();
                                        stopEditing();
                                });
@@ -170,4 +169,26 @@ public class MultiTermsPart extends AbstractTermsPart {
                contextArea.show();
        }
 
+       protected List<Term> getValue() {
+               String property = typology.getId();
+               List<String> curr = Jcr.getMultiple(getNode(), property);
+               List<Term> res = new ArrayList<>();
+               if (curr != null)
+                       for (String str : curr) {
+                               Term term = termsManager.getTerm(str);
+                               res.add(term);
+                       }
+               return res;
+       }
+
+       protected void setValue(List<Term> value) {
+               String property = typology.getId();
+               List<String> ids = new ArrayList<>();
+               for (Term term : value) {
+                       ids.add(term.getId());
+               }
+               Jcr.set(getNode(), property, ids);
+               Jcr.save(getNode());
+       }
+
 }
index e9fad048f5aeabf7962c37d109b191fd3acdfda6..0dcf13d128c5e43659ceeff3950336d126dc500a 100644 (file)
@@ -11,6 +11,7 @@ import org.argeo.cms.ui.widgets.ContextOverlay;
 import org.argeo.eclipse.ui.MouseDoubleClick;
 import org.argeo.eclipse.ui.MouseDown;
 import org.argeo.eclipse.ui.Selected;
+import org.argeo.entity.Term;
 import org.argeo.entity.TermsManager;
 import org.argeo.jcr.Jcr;
 import org.eclipse.swt.SWT;
@@ -47,8 +48,7 @@ public class SingleTermPart extends AbstractTermsPart {
                        ToolItem deleteItem = new ToolItem(toolBar, SWT.PUSH);
                        styleDelete(deleteItem);
                        deleteItem.addSelectionListener((Selected) (e) -> {
-                               Jcr.set(getNode(), typology, null);
-                               Jcr.save(getNode());
+                               setValue(null);
                                stopEditing();
                        });
                        ToolItem cancelItem = new ToolItem(toolBar, SWT.PUSH);
@@ -95,7 +95,7 @@ public class SingleTermPart extends AbstractTermsPart {
                } else {
                        Composite block = new Composite(box, SWT.NONE);
                        block.setLayout(CmsUiUtils.noSpaceGridLayout(2));
-                       String currentValue = Jcr.get(getNode(), typology);
+                       Term currentValue = getValue();
                        if (currentValue != null) {
                                Label lbl = new Label(block, SWT.SINGLE);
                                String display = getTermLabel(currentValue);
@@ -120,8 +120,8 @@ public class SingleTermPart extends AbstractTermsPart {
        @Override
        protected void refresh(ContextOverlay contextArea, String filter, Text txt) {
                CmsUiUtils.clear(contextArea);
-               List<String> terms = termsManager.listAllTerms(typology);
-               terms: for (String term : terms) {
+               List<? extends Term> terms = termsManager.listAllTerms(typology.getId());
+               terms: for (Term term : terms) {
                        String display = getTermLabel(term);
                        if (filter != null && !display.toLowerCase().contains(filter))
                                continue terms;
@@ -130,8 +130,7 @@ public class SingleTermPart extends AbstractTermsPart {
                        processTermListLabel(term, termL);
                        if (isTermSelectable(term))
                                termL.addMouseListener((MouseDown) (e) -> {
-                                       Jcr.set(getNode(), typology, term);
-                                       Jcr.save(getNode());
+                                       setValue(term);
                                        contextArea.hide();
                                        stopEditing();
                                });
@@ -140,4 +139,17 @@ public class SingleTermPart extends AbstractTermsPart {
                // txt.setFocus();
        }
 
+       protected Term getValue() {
+               String property = typology.getId();
+               String id = Jcr.get(getNode(), property);
+               Term term = termsManager.getTerm(id);
+
+               return term;
+       }
+
+       protected void setValue(Term value) {
+               String property = typology.getId();
+               Jcr.set(getNode(), property, value != null ? value.getId() : null);
+               Jcr.save(getNode());
+       }
 }
index 0c03dc514826dae39dc2ed80cc10f782c2f37bfb..227b567c31f8b18248e80c0bd41effd65324cfef 100644 (file)
@@ -3,10 +3,12 @@ package org.argeo.suite.core;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.argeo.entity.Term;
+
 /**
  * A single term. Helper to optimise {@link SuiteTermsManager} implementation.
  */
-class SuiteTerm {
+class SuiteTerm implements Term {
        private final String name;
        private final String relativePath;
        private final SuiteTypology typology;
@@ -21,13 +23,19 @@ class SuiteTerm {
                this.relativePath = relativePath;
                int index = relativePath.lastIndexOf('/');
                if (index > 0) {
-                       this.name = relativePath.substring(index);
+                       this.name = relativePath.substring(index + 1);
                } else {
                        this.name = relativePath;
                }
                id = typology.getName() + '/' + relativePath;
        }
 
+       @Override
+       public String getId() {
+               return id;
+       }
+
+       @Override
        public String getName() {
                return name;
        }
@@ -36,19 +44,18 @@ class SuiteTerm {
                return relativePath;
        }
 
-       SuiteTypology getTypology() {
+       @Override
+       public SuiteTypology getTypology() {
                return typology;
        }
 
-       public String getId() {
-               return id;
-       }
-
-       List<SuiteTerm> getSubTerms() {
+       @Override
+       public List<SuiteTerm> getSubTerms() {
                return subTerms;
        }
 
-       SuiteTerm getParentTerm() {
+       @Override
+       public SuiteTerm getParentTerm() {
                return parentTerm;
        }
 
index 1362f946abf61caf3b278d55e7da363772f98d19..f8822f78c8b31a13909d07017e5f9a9081617279 100644 (file)
@@ -14,6 +14,7 @@ import org.argeo.api.NodeConstants;
 import org.argeo.api.NodeUtils;
 import org.argeo.entity.EntityNames;
 import org.argeo.entity.EntityType;
+import org.argeo.entity.Term;
 import org.argeo.entity.TermsManager;
 import org.argeo.jcr.Jcr;
 import org.argeo.jcr.JcrException;
@@ -32,16 +33,22 @@ public class SuiteTermsManager implements TermsManager {
        }
 
        @Override
-       public List<String> listAllTerms(String typology) {
-               List<String> res = new ArrayList<>();
+       public List<Term> listAllTerms(String typology) {
+               List<Term> res = new ArrayList<>();
                SuiteTypology t = getTypology(typology);
                for (SuiteTerm term : t.getAllTerms()) {
-                       res.add(term.getId());
+                       res.add(term);
                }
                return res;
        }
 
-       SuiteTypology getTypology(String typology) {
+       @Override
+       public SuiteTerm getTerm(String termId) {
+               return terms.get(termId);
+       }
+
+       @Override
+       public SuiteTypology getTypology(String typology) {
                SuiteTypology t = typologies.get(typology);
                if (t == null) {
                        Node termsNode = Jcr.getNode(adminSession, "SELECT * FROM [{0}] WHERE NAME()=\"{1}\"",
index e84066cfe43504c2796fb578ec4e601e1b20544e..d192ed7aef14a77509d9651632d8bd82c4f7cdd8 100644 (file)
@@ -5,10 +5,12 @@ import java.util.List;
 
 import javax.jcr.Node;
 
+import org.argeo.entity.Term;
+import org.argeo.entity.Typology;
 import org.argeo.jcr.Jcr;
 
 /** A typology. Helper to optimise {@link SuiteTermsManager} implementation. */
-class SuiteTypology {
+class SuiteTypology implements Typology {
        private final String name;
        private final Node node;
        private boolean isFlat = true;
@@ -20,6 +22,11 @@ class SuiteTypology {
                this.name = Jcr.getName(this.node);
        }
 
+       @Override
+       public String getId() {
+               return name;
+       }
+
        public String getName() {
                return name;
        }
@@ -33,10 +40,12 @@ class SuiteTypology {
                        isFlat = false;
        }
 
+       @Override
        public boolean isFlat() {
                return isFlat;
        }
 
+       @Override
        public List<SuiteTerm> getSubTerms() {
                return subTerms;
        }