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.concurrent.ForkJoinPool;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
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.ContentUtils;
+import org.argeo.api.acr.NamespaceUtils;
import org.argeo.api.acr.spi.AbstractContent;
import org.argeo.api.acr.spi.ProvidedSession;
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 Node jcrNode;
private JcrContentProvider provider;
private ProvidedSession session;
- protected JcrContent(ProvidedSession session, JcrContentProvider provider, Node node) {
+ private String jcrWorkspace;
+ private String jcrPath;
+
+ protected JcrContent(ProvidedSession session, JcrContentProvider provider, String jcrWorkspace, String jcrPath) {
this.session = session;
this.provider = provider;
- this.jcrNode = node;
+ this.jcrWorkspace = jcrWorkspace;
+ this.jcrPath = jcrPath;
}
@Override
public QName getName() {
- return session.parsePrefixedName(Jcr.getName(jcrNode));
+ 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(jcrNode, key.toString()));
+ return Optional.of((A) get(getJcrNode(), key.toString()));
}
- return Optional.of((A) Jcr.get(jcrNode, key.toString()));
+ return Optional.of((A) Jcr.get(getJcrNode(), key.toString()));
}
@Override
public Iterator<Content> iterator() {
try {
- return new JcrContentIterator(jcrNode.getNodes());
+ return new JcrContentIterator(getJcrNode().getNodes());
} catch (RepositoryException e) {
- throw new JcrException("Cannot list children of " + jcrNode, e);
+ throw new JcrException("Cannot list children of " + getJcrNode(), e);
}
}
@Override
protected Iterable<QName> keys() {
- return new Iterable<QName>() {
-
- @Override
- public Iterator<QName> iterator() {
- try {
- PropertyIterator propertyIterator = jcrNode.getProperties();
- return new JcrKeyIterator(provider, propertyIterator);
- } catch (RepositoryException e) {
- throw new JcrException("Cannot retrive properties from " + jcrNode, e);
- }
+ 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() {
- return jcrNode;
+ try {
+ // TODO caching?
+ return provider.getJcrSession(session, 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 {
- Value value = node.getProperty(property).getValue();
- 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();
+ 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
@Override
public Content next() {
- current = new JcrContent(session, provider, nodeIterator.nextNode());
+ current = new JcrContent(session, provider, jcrWorkspace, Jcr.getPath(nodeIterator.nextNode()));
return current;
}
@Override
public Content getParent() {
- return new JcrContent(session, provider, Jcr.getParent(getJcrNode()));
+ return new JcrContent(session, provider, jcrWorkspace, Jcr.getParentPath(getJcrNode()));
}
@Override
}
- class JcrKeyIterator implements Iterator<QName> {
- private final JcrContentProvider contentSession;
- private final PropertyIterator propertyIterator;
+ /*
+ * ADAPTERS
+ */
+ public <A> A adapt(Class<A> clss) {
+ if (Source.class.isAssignableFrom(clss)) {
+// try {
+ PipedInputStream in = new PipedInputStream();
- protected JcrKeyIterator(JcrContentProvider contentSession, PropertyIterator propertyIterator) {
- this.contentSession = contentSession;
- this.propertyIterator = propertyIterator;
- }
+ ForkJoinPool.commonPool().execute(() -> {
+ try (PipedOutputStream out = new PipedOutputStream(in)) {
+ provider.getJcrSession(session, jcrWorkspace).exportDocumentView(jcrPath, out, true, false);
+ out.flush();
+ } catch (IOException | RepositoryException e) {
+ throw new RuntimeException("Cannot export " + jcrPath + " in workspace " + jcrWorkspace, e);
+ }
- @Override
- public boolean hasNext() {
- return propertyIterator.hasNext();
- }
+ });
+ return (A) new StreamSource(in);
+// } catch (IOException e) {
+// throw new RuntimeException("Cannot adapt " + JcrContent.this + " to " + clss, e);
+// }
+ } else
- @Override
- public QName next() {
- Property property = null;
- try {
- property = propertyIterator.nextProperty();
- // TODO map standard property names
- return session.parsePrefixedName(property.getName());
- } catch (RepositoryException e) {
- throw new JcrException("Cannot retrieve property " + property, null);
+ return super.adapt(clss);
+ }
+
+ @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);
}
+
+// class JcrKeyIterator implements Iterator<QName> {
+// private final PropertyIterator propertyIterator;
+//
+// protected JcrKeyIterator(PropertyIterator propertyIterator) {
+// this.propertyIterator = propertyIterator;
+// }
+//
+// @Override
+// public boolean hasNext() {
+// return propertyIterator.hasNext();
+// }
+//
+// @Override
+// public QName next() {
+// Property property = null;
+// try {
+// property = propertyIterator.nextProperty();
+// // TODO map standard property names
+// return NamespaceUtils.parsePrefixedName(provider, property.getName());
+// } catch (RepositoryException e) {
+// throw new JcrException("Cannot retrieve property " + property, null);
+// }
+// }
+//
+// }
}