+++ /dev/null
-package org.argeo.cms.jcr.acr;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.ForkJoinPool;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import javax.jcr.nodetype.NodeType;
-import javax.xml.namespace.QName;
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-
-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.api.cms.CmsConstants;
-import org.argeo.cms.acr.AbstractContent;
-import org.argeo.cms.acr.ContentUtils;
-import org.argeo.jcr.Jcr;
-import org.argeo.jcr.JcrException;
-import org.argeo.jcr.JcrUtils;
-
-/** A JCR {@link Node} accessed as {@link Content}. */
-public class JcrContent extends AbstractContent {
-// private Node jcrNode;
-
- private JcrContentProvider provider;
-
- private String jcrWorkspace;
- private String jcrPath;
-
- protected JcrContent(ProvidedSession session, JcrContentProvider provider, String jcrWorkspace, String jcrPath) {
- super(session);
- this.provider = provider;
- this.jcrWorkspace = jcrWorkspace;
- this.jcrPath = jcrPath;
- }
-
- @Override
- public QName getName() {
- String name = Jcr.getName(getJcrNode());
- if (name.equals("")) {// root
- String mountPath = provider.getMountPath();
- name = ContentUtils.getParentPath(mountPath)[1];
- // name = Jcr.getWorkspaceName(getJcrNode());
- }
- return NamespaceUtils.parsePrefixedName(provider, name);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <A> Optional<A> get(QName key, Class<A> clss) {
- if (isDefaultAttrTypeRequested(clss)) {
- return Optional.of((A) get(getJcrNode(), key.toString()));
- }
- return Optional.of((A) Jcr.get(getJcrNode(), key.toString()));
- }
-
- @Override
- public Iterator<Content> iterator() {
- try {
- return new JcrContentIterator(getJcrNode().getNodes());
- } catch (RepositoryException e) {
- throw new JcrException("Cannot list children of " + getJcrNode(), e);
- }
- }
-
- @Override
- protected Iterable<QName> keys() {
- try {
- Set<QName> keys = new HashSet<>();
- for (PropertyIterator propertyIterator = getJcrNode().getProperties(); propertyIterator.hasNext();) {
- Property property = propertyIterator.nextProperty();
- // TODO convert standard names
- // TODO skip technical properties
- QName name = NamespaceUtils.parsePrefixedName(provider, property.getName());
- keys.add(name);
- }
- return keys;
- } catch (RepositoryException e) {
- throw new JcrException("Cannot list properties of " + getJcrNode(), e);
- }
- }
-
- public Node getJcrNode() {
- try {
- // TODO caching?
- return provider.getJcrSession(getSession(), jcrWorkspace).getNode(jcrPath);
- } catch (RepositoryException e) {
- throw new JcrException("Cannot retrieve " + jcrPath + " from workspace " + jcrWorkspace, e);
- }
- }
-
- /** Cast to a standard Java object. */
- static Object get(Node node, String property) {
- try {
- Property p = node.getProperty(property);
- if (p.isMultiple()) {
- Value[] values = p.getValues();
- List<Object> lst = new ArrayList<>();
- for (Value value : values) {
- lst.add(convertSingleValue(value));
- }
- return lst;
- } else {
- Value value = node.getProperty(property).getValue();
- return convertSingleValue(value);
- }
- } catch (RepositoryException e) {
- throw new JcrException("Cannot cast value from " + property + " of node " + node, e);
- }
- }
-
- static Object convertSingleValue(Value value) throws RepositoryException {
- switch (value.getType()) {
- case PropertyType.STRING:
- return value.getString();
- case PropertyType.DOUBLE:
- return (Double) value.getDouble();
- case PropertyType.LONG:
- return (Long) value.getLong();
- case PropertyType.BOOLEAN:
- return (Boolean) value.getBoolean();
- case PropertyType.DATE:
- Calendar calendar = value.getDate();
- return calendar.toInstant();
- case PropertyType.BINARY:
- throw new IllegalArgumentException("Binary is not supported as an attribute");
- default:
- return value.getString();
- }
- }
-
- class JcrContentIterator implements Iterator<Content> {
- private final NodeIterator nodeIterator;
- // we keep track in order to be able to delete it
- private JcrContent current = null;
-
- protected JcrContentIterator(NodeIterator nodeIterator) {
- this.nodeIterator = nodeIterator;
- }
-
- @Override
- public boolean hasNext() {
- return nodeIterator.hasNext();
- }
-
- @Override
- public Content next() {
- current = new JcrContent(getSession(), provider, jcrWorkspace, Jcr.getPath(nodeIterator.nextNode()));
- return current;
- }
-
- @Override
- public void remove() {
- if (current != null) {
- Jcr.remove(current.getJcrNode());
- }
- }
-
- }
-
- @Override
- public String getPath() {
- try {
- // Note: it is important to to use the default way (recursing through parents),
- // since the session may not have access to parent nodes
- return ContentUtils.ROOT_SLASH + jcrWorkspace + getJcrNode().getPath();
- } catch (RepositoryException e) {
- throw new JcrException("Cannot get depth of " + getJcrNode(), e);
- }
- }
-
- @Override
- public int getDepth() {
- try {
- return getJcrNode().getDepth() + 1;
- } catch (RepositoryException e) {
- throw new JcrException("Cannot get depth of " + getJcrNode(), e);
- }
- }
-
- @Override
- public Content getParent() {
- if (Jcr.isRoot(getJcrNode())) // root
- return null;
- return new JcrContent(getSession(), provider, jcrWorkspace, Jcr.getParentPath(getJcrNode()));
- }
-
- @Override
- public Content add(QName name, QName... classes) {
- if (classes.length > 0) {
- QName primaryType = classes[0];
- Node child = Jcr.addNode(getJcrNode(), name.toString(), primaryType.toString());
- for (int i = 1; i < classes.length; i++) {
- try {
- child.addMixin(classes[i].toString());
- } catch (RepositoryException e) {
- throw new JcrException("Cannot add child to " + getJcrNode(), e);
- }
- }
-
- } else {
- Jcr.addNode(getJcrNode(), name.toString(), NodeType.NT_UNSTRUCTURED);
- }
- return null;
- }
-
- @Override
- public void remove() {
- Jcr.remove(getJcrNode());
- }
-
- @Override
- protected void removeAttr(QName key) {
- Property property = Jcr.getProperty(getJcrNode(), key.toString());
- if (property != null) {
- try {
- property.remove();
- } catch (RepositoryException e) {
- throw new JcrException("Cannot remove property " + key + " from " + getJcrNode(), e);
- }
- }
-
- }
-
- boolean exists() {
- try {
- return provider.getJcrSession(getSession(), jcrWorkspace).itemExists(jcrPath);
- } catch (RepositoryException e) {
- throw new JcrException("Cannot check whether " + jcrPath + " exists", e);
- }
- }
-
- /*
- * ADAPTERS
- */
- @SuppressWarnings("unchecked")
- public <A> A adapt(Class<A> clss) {
- if (Source.class.isAssignableFrom(clss)) {
-// try {
- PipedInputStream in = new PipedInputStream();
-
- ForkJoinPool.commonPool().execute(() -> {
- try (PipedOutputStream out = new PipedOutputStream(in)) {
- provider.getJcrSession(getSession(), jcrWorkspace).exportDocumentView(jcrPath, out, true, false);
- out.flush();
- } catch (IOException | RepositoryException e) {
- throw new RuntimeException("Cannot export " + jcrPath + " in workspace " + jcrWorkspace, e);
- }
-
- });
- return (A) new StreamSource(in);
-// } catch (IOException e) {
-// throw new RuntimeException("Cannot adapt " + JcrContent.this + " to " + clss, e);
-// }
- } else
-
- return super.adapt(clss);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <C extends Closeable> C open(Class<C> clss) throws IOException, IllegalArgumentException {
- if (InputStream.class.isAssignableFrom(clss)) {
- Node node = getJcrNode();
- if (Jcr.isNodeType(node, NodeType.NT_FILE)) {
- try {
- return (C) JcrUtils.getFileAsStream(node);
- } catch (RepositoryException e) {
- throw new JcrException("Cannot open " + jcrPath + " in workspace " + jcrWorkspace, e);
- }
- }
- }
- return super.open(clss);
- }
-
- @Override
- public ContentProvider getProvider() {
- return provider;
- }
-
- @Override
- public String getSessionLocalId() {
- try {
- return getJcrNode().getIdentifier();
- } catch (RepositoryException e) {
- throw new JcrException("Cannot get identifier for " + getJcrNode(), e);
- }
- }
-
- /*
- * TYPING
- */
- @Override
- public List<QName> getContentClasses() {
- try {
-// Node node = getJcrNode();
-// List<QName> res = new ArrayList<>();
-// res.add(nodeTypeToQName(node.getPrimaryNodeType()));
-// for (NodeType mixin : node.getMixinNodeTypes()) {
-// res.add(nodeTypeToQName(mixin));
-// }
-// return res;
- Node context = getJcrNode();
-
- List<QName> res = new ArrayList<>();
- // primary node type
- NodeType primaryType = context.getPrimaryNodeType();
- res.add(nodeTypeToQName(primaryType));
-
- Set<QName> secondaryTypes = new TreeSet<>(NamespaceUtils.QNAME_COMPARATOR);
- for (NodeType mixinType : context.getMixinNodeTypes()) {
- secondaryTypes.add(nodeTypeToQName(mixinType));
- }
- for (NodeType superType : primaryType.getDeclaredSupertypes()) {
- secondaryTypes.add(nodeTypeToQName(superType));
- }
- // mixins
- for (NodeType mixinType : context.getMixinNodeTypes()) {
- for (NodeType superType : mixinType.getDeclaredSupertypes()) {
- secondaryTypes.add(nodeTypeToQName(superType));
- }
- }
-// // entity type
-// if (context.isNodeType(EntityType.entity.get())) {
-// if (context.hasProperty(EntityNames.ENTITY_TYPE)) {
-// String entityTypeName = context.getProperty(EntityNames.ENTITY_TYPE).getString();
-// if (byType.containsKey(entityTypeName)) {
-// types.add(entityTypeName);
-// }
-// }
-// }
- res.addAll(secondaryTypes);
- return res;
- } catch (RepositoryException e) {
- throw new JcrException("Cannot list node types from " + getJcrNode(), e);
- }
- }
-
- private QName nodeTypeToQName(NodeType nodeType) {
- String name = nodeType.getName();
- return QName.valueOf(name);
- }
-
- @Override
- public int getSiblingIndex() {
- return Jcr.getIndex(getJcrNode());
- }
-
- /*
- * STATIC UTLITIES
- */
- public static Content nodeToContent(Node node) {
- if (node == null)
- return null;
- try {
- ProvidedSession contentSession = (ProvidedSession) node.getSession()
- .getAttribute(ProvidedSession.class.getName());
- if (contentSession == null)
- throw new IllegalArgumentException(
- "Cannot adapt " + node + " to content, because it was not loaded from a content session");
- return contentSession.get(ContentUtils.SLASH + CmsConstants.SYS_WORKSPACE + node.getPath());
- } catch (RepositoryException e) {
- throw new JcrException("Cannot adapt " + node + " to a content", e);
- }
- }
-
-}