From 678186f16393cdafbd5430adbad98359179c96bd Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sat, 16 Jan 2021 09:53:52 +0100 Subject: [PATCH] Introduce Terms manager service. --- .../src/org/argeo/entity/TermsManager.java | 8 ++ .../OSGI-INF/termsManager.xml | 8 ++ org.argeo.suite.core/bnd.bnd | 1 + .../suite/core/CustomMaintenanceService.java | 3 + .../src/org/argeo/suite/core/SuiteTerm.java | 55 +++++++++++ .../argeo/suite/core/SuiteTermsManager.java | 94 +++++++++++++++++++ .../org/argeo/suite/core/SuiteTypology.java | 64 +++++++++++++ 7 files changed, 233 insertions(+) create mode 100644 org.argeo.entity.api/src/org/argeo/entity/TermsManager.java create mode 100644 org.argeo.suite.core/OSGI-INF/termsManager.xml create mode 100644 org.argeo.suite.core/src/org/argeo/suite/core/SuiteTerm.java create mode 100644 org.argeo.suite.core/src/org/argeo/suite/core/SuiteTermsManager.java create mode 100644 org.argeo.suite.core/src/org/argeo/suite/core/SuiteTypology.java diff --git a/org.argeo.entity.api/src/org/argeo/entity/TermsManager.java b/org.argeo.entity.api/src/org/argeo/entity/TermsManager.java new file mode 100644 index 0000000..a2b5951 --- /dev/null +++ b/org.argeo.entity.api/src/org/argeo/entity/TermsManager.java @@ -0,0 +1,8 @@ +package org.argeo.entity; + +import java.util.List; + +/** Provides optimised access and utilities around terms typologies. */ +public interface TermsManager { + List listAllTerms(String typology); +} diff --git a/org.argeo.suite.core/OSGI-INF/termsManager.xml b/org.argeo.suite.core/OSGI-INF/termsManager.xml new file mode 100644 index 0000000..3e6d4c6 --- /dev/null +++ b/org.argeo.suite.core/OSGI-INF/termsManager.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/org.argeo.suite.core/bnd.bnd b/org.argeo.suite.core/bnd.bnd index fe90533..1b9efff 100644 --- a/org.argeo.suite.core/bnd.bnd +++ b/org.argeo.suite.core/bnd.bnd @@ -1,6 +1,7 @@ Bundle-ActivationPolicy: lazy Service-Component:\ +OSGI-INF/termsManager.xml,\ OSGI-INF/maintenanceService.xml Import-Package:\ diff --git a/org.argeo.suite.core/src/org/argeo/suite/core/CustomMaintenanceService.java b/org.argeo.suite.core/src/org/argeo/suite/core/CustomMaintenanceService.java index 8847032..b6e997a 100644 --- a/org.argeo.suite.core/src/org/argeo/suite/core/CustomMaintenanceService.java +++ b/org.argeo.suite.core/src/org/argeo/suite/core/CustomMaintenanceService.java @@ -42,6 +42,9 @@ public abstract class CustomMaintenanceService extends AbstractMaintenanceServic protected void loadTerms(Node termsBase, String name) throws IOException, RepositoryException { try { + if (termsBase.hasNode(name)) + return; + String termsLoadPath = getTypologiesLoadBase() + '/' + name + ".xml"; URL termsUrl = getClass().getClassLoader().getResource(termsLoadPath); if (termsUrl == null) diff --git a/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTerm.java b/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTerm.java new file mode 100644 index 0000000..0c03dc5 --- /dev/null +++ b/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTerm.java @@ -0,0 +1,55 @@ +package org.argeo.suite.core; + +import java.util.ArrayList; +import java.util.List; + +/** + * A single term. Helper to optimise {@link SuiteTermsManager} implementation. + */ +class SuiteTerm { + private final String name; + private final String relativePath; + private final SuiteTypology typology; + private final String id; + + private final SuiteTerm parentTerm; + private final List subTerms = new ArrayList<>(); + + SuiteTerm(SuiteTypology typology, String relativePath, SuiteTerm parentTerm) { + this.typology = typology; + this.parentTerm = parentTerm; + this.relativePath = relativePath; + int index = relativePath.lastIndexOf('/'); + if (index > 0) { + this.name = relativePath.substring(index); + } else { + this.name = relativePath; + } + id = typology.getName() + '/' + relativePath; + } + + public String getName() { + return name; + } + + public String getRelativePath() { + return relativePath; + } + + SuiteTypology getTypology() { + return typology; + } + + public String getId() { + return id; + } + + List getSubTerms() { + return subTerms; + } + + SuiteTerm getParentTerm() { + return parentTerm; + } + +} diff --git a/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTermsManager.java b/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTermsManager.java new file mode 100644 index 0000000..3c5a59f --- /dev/null +++ b/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTermsManager.java @@ -0,0 +1,94 @@ +package org.argeo.suite.core; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.api.NodeConstants; +import org.argeo.api.NodeUtils; +import org.argeo.entity.EntityNames; +import org.argeo.entity.EntityType; +import org.argeo.entity.TermsManager; +import org.argeo.jcr.Jcr; +import org.argeo.jcr.JcrException; + +/** Argeo Suite implementation of terms manager. */ +public class SuiteTermsManager implements TermsManager { + private final Map terms = new HashMap<>(); + private final Map typologies = new HashMap<>(); + + // JCR + private Repository repository; + private Session adminSession; + + public void init() { + adminSession = NodeUtils.openDataAdminSession(repository, NodeConstants.SYS_WORKSPACE); + } + + @Override + public List listAllTerms(String typology) { + List res = new ArrayList<>(); + SuiteTypology t = getTypology(typology); + for (SuiteTerm term : t.getAllTerms()) { + res.add(term.getId()); + } + return res; + } + + SuiteTypology getTypology(String typology) { + SuiteTypology t = typologies.get(typology); + if (t == null) { + Node termsNode = Jcr.getNode(adminSession, "SELECT * FROM [{0}] WHERE NAME()=\"{1}\"", + EntityType.terms.get(), typology); + t = loadTypology(termsNode); + } + return t; + } + + SuiteTypology loadTypology(Node termsNode) { + try { + SuiteTypology typology = new SuiteTypology(termsNode); + for (Node termNode : Jcr.iterate(termsNode.getNodes())) { + if (termNode.isNodeType(EntityType.term.get())) { + SuiteTerm term = loadTerm(typology, termNode, null); + if (!term.getSubTerms().isEmpty()) + typology.markNotFlat(); + typology.getSubTerms().add(term); + } + } + typologies.put(typology.getName(), typology); + return typology; + } catch (RepositoryException e) { + throw new JcrException("Cannot load typology from " + termsNode, e); + } + } + + SuiteTerm loadTerm(SuiteTypology typology, Node termNode, SuiteTerm parentTerm) throws RepositoryException { + String name = termNode.getProperty(EntityNames.NAME).getString(); + String relativePath = parentTerm == null ? name : parentTerm.getRelativePath() + '/' + name; + SuiteTerm term = new SuiteTerm(typology, relativePath, parentTerm); + terms.put(term.getId(), term); + for (Node subTermNode : Jcr.iterate(termNode.getNodes())) { + if (termNode.isNodeType(EntityType.term.get())) { + SuiteTerm subTerm = loadTerm(typology, subTermNode, term); + term.getSubTerms().add(subTerm); + } + } + return term; + } + + public void destroy() { + Jcr.logout(adminSession); + } + + public void setRepository(Repository repository) { + this.repository = repository; + } + +} diff --git a/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTypology.java b/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTypology.java new file mode 100644 index 0000000..e84066c --- /dev/null +++ b/org.argeo.suite.core/src/org/argeo/suite/core/SuiteTypology.java @@ -0,0 +1,64 @@ +package org.argeo.suite.core; + +import java.util.ArrayList; +import java.util.List; + +import javax.jcr.Node; + +import org.argeo.jcr.Jcr; + +/** A typology. Helper to optimise {@link SuiteTermsManager} implementation. */ +class SuiteTypology { + private final String name; + private final Node node; + private boolean isFlat = true; + + private final List subTerms = new ArrayList<>(); + + public SuiteTypology(Node node) { + this.node = node; + this.name = Jcr.getName(this.node); + } + + public String getName() { + return name; + } + + public Node getNode() { + return node; + } + + void markNotFlat() { + if (isFlat) + isFlat = false; + } + + public boolean isFlat() { + return isFlat; + } + + public List getSubTerms() { + return subTerms; + } + + public List getAllTerms() { + if (isFlat) + return subTerms; + else { + List terms = new ArrayList<>(); + for (SuiteTerm subTerm : subTerms) { + terms.add(subTerm); + collectSubTerms(terms, subTerm); + } + return terms; + } + } + + private void collectSubTerms(List terms, SuiteTerm term) { + for (SuiteTerm subTerm : term.getSubTerms()) { + terms.add(subTerm); + collectSubTerms(terms, subTerm); + } + } + +} -- 2.30.2