package org.argeo.cms.jcr.gcr;
import java.util.Calendar;
import java.util.Iterator;
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 org.argeo.api.gcr.Content;
import org.argeo.api.gcr.spi.AbstractContent;
import org.argeo.api.gcr.spi.ProvidedSession;
import org.argeo.jcr.Jcr;
import org.argeo.jcr.JcrException;
public class JcrContent extends AbstractContent {
private Node jcrNode;
private JcrContentProvider provider;
private ProvidedSession session;
protected JcrContent(ProvidedSession session, JcrContentProvider provider, Node node) {
this.session = session;
this.provider = provider;
this.jcrNode = node;
}
@Override
public QName getName() {
return session.parsePrefixedName(Jcr.getName(jcrNode));
}
@Override
public A get(QName key, Class clss) {
if (isDefaultAttrTypeRequested(clss)) {
return (A) get(jcrNode, key.toString());
}
return (A) Jcr.get(jcrNode, key.toString());
}
@Override
public Iterator iterator() {
try {
return new JcrContentIterator(jcrNode.getNodes());
} catch (RepositoryException e) {
throw new JcrException("Cannot list children of " + jcrNode, e);
}
}
@Override
protected Iterable keys() {
return new Iterable() {
@Override
public Iterator iterator() {
try {
PropertyIterator propertyIterator = jcrNode.getProperties();
return new JcrKeyIterator(provider, propertyIterator);
} catch (RepositoryException e) {
throw new JcrException("Cannot retrive properties from " + jcrNode, e);
}
}
};
}
public Node getJcrNode() {
return jcrNode;
}
/** 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();
}
} catch (RepositoryException e) {
throw new JcrException("Cannot cast value from " + property + " of node " + node, e);
}
}
class JcrContentIterator implements Iterator {
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(session, provider, nodeIterator.nextNode());
return current;
}
@Override
public void remove() {
if (current != null) {
Jcr.remove(current.getJcrNode());
}
}
}
@Override
public Content getParent() {
return new JcrContent(session, provider, Jcr.getParent(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);
}
}
}
class JcrKeyIterator implements Iterator {
private final JcrContentProvider contentSession;
private final PropertyIterator propertyIterator;
protected JcrKeyIterator(JcrContentProvider contentSession, PropertyIterator propertyIterator) {
this.contentSession = contentSession;
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 session.parsePrefixedName(property.getName());
} catch (RepositoryException e) {
throw new JcrException("Cannot retrieve property " + property, null);
}
}
}
}