From 25e4528153640a2e211e217468f8f5aa01607cf0 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sun, 22 Sep 2019 10:32:03 +0200 Subject: [PATCH] Introduce Jcr singleton, making using Jcr less verbose. --- org.argeo.jcr/src/org/argeo/jcr/Jcr.java | 317 ++++++++++++++++++ org.argeo.jcr/src/org/argeo/jcr/JcrUtils.java | 20 +- 2 files changed, 329 insertions(+), 8 deletions(-) create mode 100644 org.argeo.jcr/src/org/argeo/jcr/Jcr.java diff --git a/org.argeo.jcr/src/org/argeo/jcr/Jcr.java b/org.argeo.jcr/src/org/argeo/jcr/Jcr.java new file mode 100644 index 000000000..f8ad9c79c --- /dev/null +++ b/org.argeo.jcr/src/org/argeo/jcr/Jcr.java @@ -0,0 +1,317 @@ +package org.argeo.jcr; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.jcr.ItemNotFoundException; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.PropertyType; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.Value; + +/** + * Utility class whose purpose is to make using JCR less verbose by + * systematically using unchecked exceptions and returning null + * when something is not found. This is especially useful when writing user + * interfaces (such as with SWT) where listeners and callbacks expect unchecked + * exceptions. Loosely inspired by Java's Files singleton. + */ +public class Jcr { + + /** + * @see Node#isNodeType(String) + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static boolean isNodeType(Node node, String nodeTypeName) { + try { + return node.isNodeType(nodeTypeName); + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get whether " + node + " is of type " + nodeTypeName, e); + } + } + + /** + * @see Node#hasNodes() + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static boolean hasNodes(Node node) { + try { + return node.hasNodes(); + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get whether " + node + " has children.", e); + } + } + + /** + * @see Node#getParent() + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static Node getParent(Node node) { + try { + return isRoot(node) ? null : node.getParent(); + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get parent of " + node, e); + } + } + + /** + * Whether this node is the root node. + * + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static boolean isRoot(Node node) { + try { + return node.getDepth() == 0; + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get depth of " + node, e); + } + } + + /** + * @see Node#getPath() + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static String getPath(Node node) { + try { + return node.getPath(); + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get path of " + node, e); + } + } + + /** + * @see Node#getIdentifier() + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static String getIdentifier(Node node) { + try { + return node.getIdentifier(); + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get identifier of " + node, e); + } + } + + /** + * @see Node#getName() + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static String getName(Node node) { + try { + return node.getName(); + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get name of " + node, e); + } + } + + /** Accesses a {@link NodeIterator} as an {@link Iterable}. */ + @SuppressWarnings("unchecked") + public static Iterable iterate(NodeIterator nodeIterator) { + return new Iterable() { + + @Override + public Iterator iterator() { + return nodeIterator; + } + }; + } + + /** + * @return the children as an {@link Iterable} for use in for-each llops. + * @see Node#getNodes() + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static Iterable nodes(Node node) { + try { + return iterate(node.getNodes()); + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get children of " + node, e); + } + } + + /** + * @return the children as a (possibly empty) {@link List}. + * @see Node#getNodes() + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static List getNodes(Node node) { + List nodes = new ArrayList<>(); + try { + if (node.hasNodes()) { + NodeIterator nit = node.getNodes(); + while (nit.hasNext()) + nodes.add(nit.nextNode()); + return nodes; + } else + return nodes; + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get children of " + node, e); + } + } + + /** + * @return the child or null if not found + * @see Node#getNode(String) + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static Node getNode(Node node, String child) { + try { + if (node.hasNode(child)) + return node.getNode(child); + else + return null; + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get child of " + node, e); + } + } + + /** + * @return the node at this path or null if not found + * @see Session#getNode(String) + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static Node getNode(Session session, String path) { + try { + if (session.nodeExists(path)) + return session.getNode(path); + else + return null; + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get node " + path, e); + } + } + + /** + * @return the node with htis id or null if not found + * @see Session#getNodeByIdentifier(String) + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static Node getNodeById(Session session, String id) { + try { + return session.getNodeByIdentifier(id); + } catch (ItemNotFoundException e) { + return null; + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot get node with id " + id, e); + } + } + + /** + * Get property as {@link String}. + * + * @return the value of + * {@link Node#getProperty(String)}.{@link Property#getString()} or + * null if the property does not exist. + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static String get(Node node, String property) { + return get(node, property, null); + } + + /** + * Get property as a {@link String}. + * + * @return the value of + * {@link Node#getProperty(String)}.{@link Property#getString()} or + * defaultValue if the property does not exist. + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static String get(Node node, String property, String defaultValue) { + try { + if (node.hasProperty(property)) + return node.getProperty(property).getString(); + else + return defaultValue; + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot retrieve property " + property + " from " + node); + } + } + + /** + * Get property as a {@link Value}. + * + * @return {@link Node#getProperty(String)} or null if the property + * does not exist. + * @throws IllegalStateException caused by {@link RepositoryException} + */ + public static Value getValue(Node node, String property) { + try { + if (node.hasProperty(property)) + return node.getProperty(property).getValue(); + else + return null; + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot retrieve property " + property + " from " + node); + } + } + + /** + * Get property doing a best effort to cast it as the target object. + * + * @return the value of {@link Node#getProperty(String)} or + * defaultValue if the property does not exist. + * @throws IllegalArgumentException if the value could not be cast + * @throws IllegalStateException in case of unexpected + * {@link RepositoryException} + */ + @SuppressWarnings("unchecked") + public static T getAs(Node node, String property, T defaultValue) { + try { + if (node.hasProperty(property)) { + Property p = node.getProperty(property); + try { + switch (p.getType()) { + case PropertyType.STRING: + return (T) node.getProperty(property).getString(); + case PropertyType.DOUBLE: + return (T) (Double) node.getProperty(property).getDouble(); + case PropertyType.LONG: + return (T) (Long) node.getProperty(property).getLong(); + case PropertyType.BOOLEAN: + return (T) (Boolean) node.getProperty(property).getBoolean(); + case PropertyType.DATE: + return (T) node.getProperty(property).getDate(); + default: + return (T) node.getProperty(property).getString(); + } + } catch (ClassCastException e) { + throw new IllegalArgumentException( + "Cannot cast property of type " + PropertyType.nameFromValue(p.getType()), e); + } + } else { + return defaultValue; + } + } catch (RepositoryException e) { + throw new IllegalStateException("Cannot retrieve property " + property + " from " + node); + } + } + + /** Login to a JCR repository. */ + public static Session login(Repository repository, String workspace) { + try { + return repository.login(workspace); + } catch (RepositoryException e) { + throw new IllegalArgumentException("Cannot login to repository", e); + } + } + + /** Safely and silently logs out a session. */ + public static void logout(Session session) { + try { + if (session != null) + if (session.isLive()) + session.logout(); + } catch (Exception e) { + // silent + } + } + + /** Singleton. */ + private Jcr() { + + } +} diff --git a/org.argeo.jcr/src/org/argeo/jcr/JcrUtils.java b/org.argeo.jcr/src/org/argeo/jcr/JcrUtils.java index 5bbc207ea..331164cf2 100644 --- a/org.argeo.jcr/src/org/argeo/jcr/JcrUtils.java +++ b/org.argeo.jcr/src/org/argeo/jcr/JcrUtils.java @@ -1074,15 +1074,19 @@ public class JcrUtils { } } - /** Logs out the session, not throwing any exception, even if it is null. */ + /** + * Logs out the session, not throwing any exception, even if it is null. + * {@link Jcr#logout(Session)} should rather be used. + */ public static void logoutQuietly(Session session) { - try { - if (session != null) - if (session.isLive()) - session.logout(); - } catch (Exception e) { - // silent - } + Jcr.logout(session); +// try { +// if (session != null) +// if (session.isLive()) +// session.logout(); +// } catch (Exception e) { +// // silent +// } } /** -- 2.30.2