Introduce terms content provider
authorMathieu Baudier <mbaudier@argeo.org>
Thu, 15 Jun 2023 08:33:56 +0000 (10:33 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Thu, 15 Jun 2023 08:33:56 +0000 (10:33 +0200)
org.argeo.app.api/src/org/argeo/app/api/EntityType.java
org.argeo.app.api/src/org/argeo/app/api/TermsManager.java
org.argeo.app.core/OSGI-INF/termsContentProvider.xml [new file with mode: 0644]
org.argeo.app.core/bnd.bnd
org.argeo.app.core/build.properties
org.argeo.app.core/src/org/argeo/app/acr/terms/TermContent.java [new file with mode: 0644]
org.argeo.app.core/src/org/argeo/app/acr/terms/TermsContentProvider.java [new file with mode: 0644]
org.argeo.app.core/src/org/argeo/app/acr/terms/TypologyContent.java [new file with mode: 0644]
org.argeo.app.jcr/src/org/argeo/app/jcr/terms/SuiteTermsManager.java
org.argeo.product.knowledge/OSGI-INF/termsEntryArea.xml
swt/org.argeo.app.swt/src/org/argeo/app/swt/terms/TermsEntryArea.java

index 8b9164a77d86aca468b0417d5712e0a6f4babd48..1e308214aecc99327e141c05d9648e082b5a7974 100644 (file)
@@ -19,31 +19,20 @@ public enum EntityType implements QNamed {
        // ldap
        person, user;
 
+       public final static String ENTITY_NAMESPACE_URI = "http://www.argeo.org/ns/entity";
+       public final static String ENTITY_DEFAULT_PREFIX = "entity";
+
        @Override
        public String getDefaultPrefix() {
-               return "entity";
+               return ENTITY_DEFAULT_PREFIX;
        }
 
-//     @Override
-//     public String getPrefix() {
-//             return getDefaultPrefix();
-//     }
-//
-//     public static String prefix() {
-//             return "entity";
-//     }
-
        public String basePath() {
                return '/' + name();
        }
 
        @Override
        public String getNamespace() {
-               return "http://www.argeo.org/ns/entity";
+               return ENTITY_NAMESPACE_URI;
        }
-
-//     public static String namespace() {
-//             return "http://www.argeo.org/ns/entity";
-//     }
-
 }
index decddd9b626989054c57582be5348dff63fe4c61..03e1150cd3c2a54832c41858bbf37fd5ba062a56 100644 (file)
@@ -1,11 +1,14 @@
 package org.argeo.app.api;
 
 import java.util.List;
+import java.util.Set;
 
 /** Provides optimised access and utilities around terms typologies. */
 public interface TermsManager {
        Typology getTypology(String typology);
-       
+
+       Set<Typology> getTypologies();
+
        Term getTerm(String id);
 
        List<Term> listAllTerms(String typology);
diff --git a/org.argeo.app.core/OSGI-INF/termsContentProvider.xml b/org.argeo.app.core/OSGI-INF/termsContentProvider.xml
new file mode 100644 (file)
index 0000000..4d5a1d2
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="start" name="org.argeo.app.termsContentProvider">
+   <implementation class="org.argeo.app.acr.terms.TermsContentProvider"/>
+   <reference bind="setService" cardinality="1..1" interface="org.argeo.app.api.TermsManager" name="TermsManager" policy="static"/>
+   <service>
+      <provide interface="org.argeo.api.acr.spi.ContentProvider"/>
+   </service>
+   <property name="acr.mount.path" type="String" value="/terms"/>
+</scr:component>
index 7a92b9b2d68c2505467145055966d034099d2570..c07e947376dfd6800c04940bfba22e25ea20da20 100644 (file)
@@ -2,6 +2,7 @@ Bundle-ActivationPolicy: lazy
 
 Service-Component:\
 OSGI-INF/suiteMaintenance.xml,\
+OSGI-INF/termsContentProvider.xml,\
 
 Import-Package:\
 tech.units.indriya.unit,\
index 4974d56f40c2ca9efc6f87e80f72414fb1d0a90a..741e8430b5de57b326d01434f06b4f27bafda16f 100644 (file)
@@ -2,7 +2,8 @@ bin.includes = META-INF/,\
                .,\
                OSGI-INF/,\
                OSGI-INF/appUserState.xml,\
-               OSGI-INF/suiteMaintenance.xml
+               OSGI-INF/suiteMaintenance.xml,\
+               OSGI-INF/termsContentProvider.xml
 additional.bundles = org.argeo.init
 source.. = src/
 output.. = bin/
diff --git a/org.argeo.app.core/src/org/argeo/app/acr/terms/TermContent.java b/org.argeo.app.core/src/org/argeo/app/acr/terms/TermContent.java
new file mode 100644 (file)
index 0000000..672f66f
--- /dev/null
@@ -0,0 +1,46 @@
+package org.argeo.app.acr.terms;
+
+import java.util.Iterator;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.Content;
+import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.api.acr.spi.ContentProvider;
+import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.app.api.Term;
+import org.argeo.cms.acr.AbstractContent;
+
+public class TermContent extends AbstractContent {
+       private TermsContentProvider provider;
+       private Term term;
+
+       public TermContent(ProvidedSession session, TermsContentProvider provider, Term term) {
+               super(session);
+               this.provider = provider;
+               this.term = term;
+       }
+
+       @Override
+       public Iterator<Content> iterator() {
+               return term.getSubTerms().stream().map((t) -> (Content) new TermContent(getSession(), provider, t)).iterator();
+       }
+
+       @Override
+       public ContentProvider getProvider() {
+               return provider;
+       }
+
+       @Override
+       public QName getName() {
+               return NamespaceUtils.unqualified(term.getName());
+       }
+
+       @Override
+       public Content getParent() {
+               Term parentTerm = term.getParentTerm();
+               return parentTerm == null ? new TypologyContent(getSession(), provider, term.getTypology())
+                               : new TermContent(getSession(), provider, parentTerm);
+       }
+
+}
diff --git a/org.argeo.app.core/src/org/argeo/app/acr/terms/TermsContentProvider.java b/org.argeo.app.core/src/org/argeo/app/acr/terms/TermsContentProvider.java
new file mode 100644 (file)
index 0000000..2d7a5d1
--- /dev/null
@@ -0,0 +1,69 @@
+package org.argeo.app.acr.terms;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.argeo.api.acr.Content;
+import org.argeo.api.acr.ContentNotFoundException;
+import org.argeo.api.acr.spi.ProvidedContent;
+import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.app.api.EntityType;
+import org.argeo.app.api.Term;
+import org.argeo.app.api.TermsManager;
+import org.argeo.app.api.Typology;
+import org.argeo.cms.acr.AbstractSimpleContentProvider;
+import org.argeo.cms.acr.ContentUtils;
+
+public class TermsContentProvider extends AbstractSimpleContentProvider<TermsManager> {
+
+       public TermsContentProvider() {
+               super(EntityType.ENTITY_NAMESPACE_URI, EntityType.ENTITY_DEFAULT_PREFIX);
+       }
+
+       @Override
+       protected Iterator<Content> firstLevel(ProvidedSession session) {
+               return getService().getTypologies().stream().map((t) -> (Content) new TypologyContent(session, this, t))
+                               .iterator();
+       }
+
+       @Override
+       public ProvidedContent get(ProvidedSession session, List<String> segments) {
+               String typologyName = segments.get(0);
+               Typology typology = getService().getTypology(typologyName);
+               if (segments.size() == 1)
+                       return new TypologyContent(session, this, typology);
+               Term currTerm = null;
+               terms: for (Term term : typology.getSubTerms()) {
+                       if (term.getName().equals(segments.get(1))) {
+                               currTerm = term;
+                               break terms;
+                       }
+               }
+               if (currTerm == null)
+                       throw new ContentNotFoundException(session,
+                                       getMountPath() + "/" + ContentUtils.toPath(segments) + " cannot be found");
+               if (segments.size() == 1)
+                       return new TermContent(session, this, currTerm);
+
+               for (int i = 2; i < segments.size(); i++) {
+                       String termName = segments.get(i);
+                       Term nextTerm = null;
+                       terms: for (Term term : currTerm.getSubTerms()) {
+                               if (term.getName().equals(termName)) {
+                                       nextTerm = term;
+                                       break terms;
+                               }
+                       }
+                       if (nextTerm == null)
+                               throw new ContentNotFoundException(session,
+                                               getMountPath() + "/" + ContentUtils.toPath(segments) + " cannot be found");
+                       currTerm = nextTerm;
+               }
+               return new TermContent(session, this, currTerm);
+       }
+
+       ServiceContent getRootContent(ProvidedSession session) {
+               return new ServiceContent(session);
+       }
+
+}
diff --git a/org.argeo.app.core/src/org/argeo/app/acr/terms/TypologyContent.java b/org.argeo.app.core/src/org/argeo/app/acr/terms/TypologyContent.java
new file mode 100644 (file)
index 0000000..63bb8a3
--- /dev/null
@@ -0,0 +1,45 @@
+package org.argeo.app.acr.terms;
+
+import java.util.Iterator;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.Content;
+import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.api.acr.spi.ContentProvider;
+import org.argeo.api.acr.spi.ProvidedSession;
+import org.argeo.app.api.Typology;
+import org.argeo.cms.acr.AbstractContent;
+
+public class TypologyContent extends AbstractContent {
+       private TermsContentProvider provider;
+       private Typology typology;
+
+       public TypologyContent(ProvidedSession session, TermsContentProvider provider, Typology typology) {
+               super(session);
+               this.provider = provider;
+               this.typology = typology;
+       }
+
+       @Override
+       public ContentProvider getProvider() {
+               return provider;
+       }
+
+       @Override
+       public QName getName() {
+               return NamespaceUtils.unqualified(typology.getId());
+       }
+
+       @Override
+       public Content getParent() {
+               return provider.getRootContent(getSession());
+       }
+
+       @Override
+       public Iterator<Content> iterator() {
+               return typology.getSubTerms().stream().map((t) -> (Content) new TermContent(getSession(), provider, t))
+                               .iterator();
+       }
+
+}
index 6327a552f9880cdfdb906b344058ef3a62d39d69..eba0529ac50c7d629e96bc88f3579d93cd9c03b8 100644 (file)
@@ -4,8 +4,11 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
 
 import javax.jcr.Node;
+import javax.jcr.NodeIterator;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -15,6 +18,7 @@ import org.argeo.app.api.EntityNames;
 import org.argeo.app.api.EntityType;
 import org.argeo.app.api.Term;
 import org.argeo.app.api.TermsManager;
+import org.argeo.app.api.Typology;
 import org.argeo.cms.jcr.CmsJcrUtils;
 import org.argeo.jcr.Jcr;
 import org.argeo.jcr.JcrException;
@@ -60,6 +64,16 @@ public class SuiteTermsManager implements TermsManager {
                return t;
        }
 
+       @Override
+       public Set<Typology> getTypologies() {
+               Set<Typology> res = new TreeSet<>((o1, o2) -> o1.getId().compareTo(o2.getId()));
+               NodeIterator termsNodes = Jcr.executeQuery(adminSession, "SELECT * FROM [{0}]", EntityType.terms.get());
+               for (Node termsNode : Jcr.iterate(termsNodes)) {
+                       res.add(loadTypology(termsNode));
+               }
+               return res;
+       }
+
        SuiteTypology loadTypology(Node termsNode) {
                try {
                        SuiteTypology typology = new SuiteTypology(termsNode);
index e241b11b2d092078eb5fce751e849cdb2cdfd8d2..404ebc36260f30afdbcc4c750661793ed21b27c4 100644 (file)
@@ -6,4 +6,5 @@
    </service>
    <property name="service.ranking" type="Integer" value="-1000"/>
    <properties entry="config/termsEntryArea.properties"/>
+   <reference bind="setTermsManager" cardinality="1..1" interface="org.argeo.app.api.TermsManager" name="TermsManager" policy="static"/>
 </scr:component>
index 2193a3cc581690303ecbe1ed66089da55682cb1a..7ae2531f413f048712f65cfb7aea6d7240c173e6 100644 (file)
@@ -1,22 +1,70 @@
 package org.argeo.app.swt.terms;
 
 import org.argeo.api.acr.Content;
+import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.api.acr.spi.ProvidedContent;
+import org.argeo.api.cms.ux.CmsView;
+import org.argeo.app.api.EntityType;
+import org.argeo.app.api.TermsManager;
+import org.argeo.app.ux.SuiteUxEvent;
+import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.swt.acr.SwtUiProvider;
-import org.eclipse.swt.SWT;
+import org.argeo.cms.swt.widgets.SwtTreeView;
+import org.argeo.cms.ux.acr.ContentHierarchicalPart;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
 
 /** Entry area for managing the typologies. */
 public class TermsEntryArea implements SwtUiProvider {
+       private TermsManager termsManager;
 
        @Override
        public Control createUiPart(Composite parent, Content content) {
+//             parent.setLayout(new GridLayout());
+//             Label lbl = new Label(parent, SWT.NONE);
+//             lbl.setText("Typologies");
+//
+//             Set<Typology> typologies = termsManager.getTypologies();
+//             for (Typology typology : typologies) {
+//                     new Label(parent, 0).setText(typology.getId());
+//             }
+//             
+//             
+//             return lbl;
+               CmsView cmsView = CmsSwtUtils.getCmsView(parent);
+
                parent.setLayout(new GridLayout());
-               Label lbl = new Label(parent, SWT.NONE);
-               lbl.setText("Typologies");
-               return lbl;
+               Content rootContent = ((ProvidedContent) content).getSession().getRepository().get().get("/terms");
+
+               ContentHierarchicalPart contentPart = new ContentHierarchicalPart() {
+
+                       @Override
+                       protected boolean isLeaf(Content content) {
+                               if (content.hasContentClass(EntityType.document.qName()))
+                                       return true;
+                               return super.isLeaf(content);
+                       }
+
+               };
+               contentPart.addColumn((c) -> NamespaceUtils.toPrefixedName(c.getName()));
+               contentPart.setInput(rootContent);
+
+               SwtTreeView<Content> view = new SwtTreeView<>(parent, 0, contentPart);
+               view.setLayoutData(CmsSwtUtils.fillAll());
+
+               contentPart.setInput(rootContent);
+//             contentPart.onSelected((o) -> {
+//                     Content c = (Content) o;
+////                   log.debug(c.getPath());
+//                     cmsView.sendEvent(SuiteUxEvent.refreshPart.topic(), SuiteUxEvent.eventProperties(c));
+//             });
+               return view;
+
+       }
+
+       public void setTermsManager(TermsManager termsManager) {
+               this.termsManager = termsManager;
        }
 
 }