modified version without this exception; this exception also makes it possible
to release a modified version which carries forward this exception.
+# Apache License Permission
+
+Linking Argeo JCR statically or dynamically with other modules is making a
+combined work based on Argeo JCR. Thus, the terms and conditions of the GNU
+General Public License cover the whole combination when this license becomes
+applicable.
+
+In addition, as a special exception, the copyright holders of Argeo JCR give
+you permission to combine Argeo JCR with any program released under the
+terms and conditions of the Apache License v2.0 or any later version of this
+license. You may copy and distribute such a system following the terms of
+the GNU GPL for Argeo JCR and the licenses of the other code concerned,
+provided that you include the source code of that other code when and as
+the GNU GPL requires distribution of source code.
+
+Note that people who make modified versions of Argeo JCR are not obligated
+to grant this special exception for their modified versions; it is their choice
+whether to do so. The GNU General Public License gives permission to release a
+modified version without this exception; this exception also makes it possible
+to release a modified version which carries forward this exception.
+
# Java Content Repository API version 2.0 Permission
Linking Argeo JCR statically or dynamically with other modules is making a
package org.argeo.cms.jcr.acr;
+import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO;
+
import java.util.ArrayList;
import java.util.List;
+import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.query.QueryManager;
import javax.xml.namespace.QName;
import org.apache.jackrabbit.commons.query.sql2.QOMFormatter;
+import org.argeo.api.acr.DName;
import org.argeo.api.acr.NamespaceUtils;
import org.argeo.api.acr.search.BasicSearch;
import org.argeo.api.acr.search.Constraint;
import org.argeo.api.acr.search.ContentFilter;
-import org.argeo.api.acr.search.ContentFilter.Eq;
-import org.argeo.api.acr.search.ContentFilter.IsContentClass;
-import org.argeo.api.acr.search.ContentFilter.Not;
+import org.argeo.api.acr.search.Eq;
+import org.argeo.api.acr.search.Gt;
+import org.argeo.api.acr.search.Gte;
+import org.argeo.api.acr.search.IsContentClass;
+import org.argeo.api.acr.search.IsDefined;
+import org.argeo.api.acr.search.Like;
+import org.argeo.api.acr.search.Lt;
+import org.argeo.api.acr.search.Lte;
+import org.argeo.api.acr.search.Not;
+import org.argeo.api.acr.search.PropertyValueContraint;
import org.argeo.api.cms.CmsLog;
/** Convert an ACR basic search to a JCR query. */
private Session session;
private QueryManager queryManager;
private BasicSearch basicSearch;
- QueryObjectModelFactory factory;
+ private QueryObjectModelFactory factory;
+
+ private String relPath;
- QName contentClass = null;
+ private QName contentClass = null;
- String selectorName = "content";
+ private String selectorName = "content";
public BasicSearchToQom(Session session, BasicSearch basicSearch, String relPath) throws RepositoryException {
this.session = session;
this.queryManager = session.getWorkspace().getQueryManager();
this.basicSearch = basicSearch;
+ this.relPath = relPath;
factory = queryManager.getQOMFactory();
}
if (contentClass == null)
throw new IllegalArgumentException("No content class specified");
+ if (relPath != null) {
+ qomConstraint = factory.and(qomConstraint, factory.descendantNode(selectorName, "/" + relPath));
+ }
+
Selector source = factory.selector(NamespaceUtils.toPrefixedName(contentClass), selectorName);
QueryObjectModel qom = factory.createQuery(source, qomConstraint, null, null);
}
private javax.jcr.query.qom.Constraint toQomConstraint(Constraint constraint) throws RepositoryException {
- javax.jcr.query.qom.Constraint qomConstraint;
+// javax.jcr.query.qom.Constraint qomConstraint;
if (constraint instanceof ContentFilter<?> where) {
List<Constraint> constraints = new ArrayList<>();
for (Constraint c : where.getConstraints()) {
}
if (constraints.isEmpty()) {
- qomConstraint = null;
+ return null;
} else if (constraints.size() == 1) {
- qomConstraint = toQomConstraint(constraints.get(0));
+ return toQomConstraint(constraints.get(0));
} else {
javax.jcr.query.qom.Constraint currQomConstraint = toQomConstraint(constraints.get(0));
+ // QOM constraint may be null because only content classes where specified
+ while (currQomConstraint == null) {
+ constraints.remove(0);
+ if (constraints.isEmpty())
+ return null;
+ currQomConstraint = toQomConstraint(constraints.get(0));
+ }
+ assert currQomConstraint != null : "currQomConstraint is null : " + constraints.get(0);
for (int i = 1; i < constraints.size(); i++) {
Constraint c = constraints.get(i);
- if (where.isUnion()) {
- currQomConstraint = factory.or(currQomConstraint, toQomConstraint(c));
- } else {
- currQomConstraint = factory.and(currQomConstraint, toQomConstraint(c));
+ javax.jcr.query.qom.Constraint subQomConstraint = toQomConstraint(c);
+ if (subQomConstraint != null) { // isContentClass leads to null QOM constraint
+ assert subQomConstraint != null : "subQomConstraint";
+ if (where.isUnion()) {
+ currQomConstraint = factory.or(currQomConstraint, subQomConstraint);
+ } else {
+ currQomConstraint = factory.and(currQomConstraint, subQomConstraint);
+ }
}
}
- qomConstraint = currQomConstraint;
+ return currQomConstraint;
}
- } else if (constraint instanceof Eq comp) {
- DynamicOperand dynamicOperand = factory.propertyValue(selectorName,
- NamespaceUtils.toPrefixedName(comp.getProp()));
+ } else if (constraint instanceof PropertyValueContraint comp) {
+ QName prop = comp.getProp();
+ if (DName.creationdate.equals(prop))
+ prop = JcrName.created.qName();
+ else if (DName.getlastmodified.equals(prop))
+ prop = JcrName.lastModified.qName();
+
+ DynamicOperand dynamicOperand = factory.propertyValue(selectorName, NamespaceUtils.toPrefixedName(prop));
// TODO better convert attribute value
StaticOperand staticOperand = factory
- .literal(session.getValueFactory().createValue(comp.getValue().toString()));
- qomConstraint = factory.comparison(dynamicOperand, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO,
- staticOperand);
+ .literal(JcrContent.convertSingleObject(session.getValueFactory(), comp.getValue()));
+ javax.jcr.query.qom.Constraint res;
+ if (comp instanceof Eq)
+ res = factory.comparison(dynamicOperand, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO,
+ staticOperand);
+ else if (comp instanceof Lt)
+ res = factory.comparison(dynamicOperand, QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN,
+ staticOperand);
+ else if (comp instanceof Lte)
+ res = factory.comparison(dynamicOperand, QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO,
+ staticOperand);
+ else if (comp instanceof Gt)
+ res = factory.comparison(dynamicOperand, QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN,
+ staticOperand);
+ else if (comp instanceof Gte)
+ res = factory.comparison(dynamicOperand,
+ QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO, staticOperand);
+ else if (comp instanceof Like)
+ res = factory.comparison(dynamicOperand, QueryObjectModelConstants.JCR_OPERATOR_LIKE, staticOperand);
+ else
+ throw new UnsupportedOperationException("Constraint of type " + comp.getClass() + " is not supported");
+ return res;
} else if (constraint instanceof Not not) {
- qomConstraint = factory.not(toQomConstraint(not.getNegated()));
+ return factory.not(toQomConstraint(not.getNegated()));
+ } else if (constraint instanceof IsDefined comp) {
+ QName prop = comp.getProp();
+ if (DName.checkedIn.equals(prop) || DName.checkedOut.equals(prop)) {
+ DynamicOperand dynamicOperand = factory.propertyValue(selectorName, Property.JCR_IS_CHECKED_OUT);
+ StaticOperand staticOperand = factory
+ .literal(session.getValueFactory().createValue(DName.checkedOut.equals(prop)));
+ return factory.comparison(dynamicOperand, JCR_OPERATOR_EQUAL_TO, staticOperand);
+ } else {
+ return factory.propertyExistence(selectorName, NamespaceUtils.toPrefixedName(prop));
+ }
} else {
throw new IllegalArgumentException("Constraint " + constraint.getClass() + " is not supported");
}
- return qomConstraint;
+// return qomConstraint;
}
}
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.time.Instant;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.ForkJoinPool;
+import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import org.argeo.api.acr.Content;
import org.argeo.api.acr.CrAttributeType;
+import org.argeo.api.acr.DName;
import org.argeo.api.acr.NamespaceUtils;
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.cms.util.AsyncPipedOutputStream;
import org.argeo.jcr.Jcr;
import org.argeo.jcr.JcrException;
import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.JcrxApi;
/** A JCR {@link Node} accessed as {@link Content}. */
public class JcrContent extends AbstractContent {
/* OPTIMISATIONS */
/**
- * While we want to support thread-safe access, it is very likely that only
- * thread and only one sesssion will be used (typically from a single-threaded
+ * While we want to support thread-safe access, it is very likely that only one
+ * thread and only one session will be used (typically from a single-threaded
* UI). We therefore cache was long as the same thread is calling.
*/
private Thread lastRetrievingThread = null;
@SuppressWarnings("unchecked")
@Override
public <A> Optional<A> get(QName key, Class<A> clss) {
- Object value = get(getJcrNode(), key.toString());
- if (value instanceof List<?> lst)
- return Optional.of((A) lst);
- // TODO check other collections?
- return CrAttributeType.cast(clss, value);
+ try {
+ Node node = getJcrNode();
+ if (DName.creationdate.equals(key))
+ key = JcrName.created.qName();
+ else if (DName.getlastmodified.equals(key))
+ key = JcrName.lastModified.qName();
+ else if (DName.getcontenttype.equals(key)) {
+ String contentType = null;
+ if (node.isNodeType(NodeType.NT_FILE)) {
+ Node content = node.getNode(Node.JCR_CONTENT);
+ if (content.isNodeType(NodeType.MIX_MIMETYPE)) {
+ contentType = content.getProperty(Property.JCR_MIMETYPE).getString();
+ if (content.hasProperty(Property.JCR_ENCODING))
+ contentType = contentType + ";encoding="
+ + content.getProperty(Property.JCR_ENCODING).getString();
+ }
+ }
+ if (contentType == null)
+ contentType = "application/octet-stream";
+ return CrAttributeType.cast(clss, contentType);
+ } else if (DName.checkedOut.equals(key)) {
+ if (!node.hasProperty(Property.JCR_IS_CHECKED_OUT))
+ return Optional.empty();
+ boolean isCheckedOut = node.getProperty(Property.JCR_IS_CHECKED_OUT).getBoolean();
+ if (!isCheckedOut)
+ return Optional.empty();
+ // FIXME return URI
+ return (Optional<A>) Optional.of(new Object());
+ } else if (DName.checkedIn.equals(key)) {
+ if (!node.hasProperty(Property.JCR_IS_CHECKED_OUT))
+ return Optional.empty();
+ boolean isCheckedOut = node.getProperty(Property.JCR_IS_CHECKED_OUT).getBoolean();
+ if (isCheckedOut)
+ return Optional.empty();
+ // FIXME return URI
+ return (Optional<A>) Optional.of(new Object());
+ }
+
+ Object value = get(node, key.toString());
+ if (value instanceof List<?> lst)
+ return Optional.of((A) lst);
+ // TODO check other collections?
+ return CrAttributeType.cast(clss, value);
+ } catch (RepositoryException e) {
+ throw new JcrException(e);
+ }
}
@Override
@Override
protected Iterable<QName> keys() {
try {
+ Node node = getJcrNode();
Set<QName> keys = new HashSet<>();
- for (PropertyIterator propertyIterator = getJcrNode().getProperties(); propertyIterator.hasNext();) {
+ for (PropertyIterator propertyIterator = node.getProperties(); propertyIterator.hasNext();) {
Property property = propertyIterator.nextProperty();
+ QName name = NamespaceUtils.parsePrefixedName(provider, property.getName());
+
// TODO convert standard names
+ if (property.getName().equals(Property.JCR_CREATED))
+ name = DName.creationdate.qName();
+ else if (property.getName().equals(Property.JCR_LAST_MODIFIED))
+ name = DName.getlastmodified.qName();
+ else if (property.getName().equals(Property.JCR_MIMETYPE))
+ name = DName.getcontenttype.qName();
+ else if (property.getName().equals(Property.JCR_IS_CHECKED_OUT)) {
+ boolean isCheckedOut = node.getProperty(Property.JCR_IS_CHECKED_OUT).getBoolean();
+ name = isCheckedOut ? DName.checkedOut.qName() : DName.checkedIn.qName();
+ }
+
// TODO skip technical properties
- QName name = NamespaceUtils.parsePrefixedName(provider, property.getName());
keys.add(name);
}
return keys;
}
} catch (RepositoryException e) {
throw new JcrException(
- "Cannot check multiplicityof property " + p + " of " + jcrPath + " in " + jcrWorkspace, e);
+ "Cannot check multiplicity of property " + p + " of " + jcrPath + " in " + jcrWorkspace, e);
}
}
return Jcr.getIndex(getJcrNode());
}
+ @Override
+ public String getText() {
+ return JcrxApi.getXmlValue(getJcrNode());
+ }
+
/*
* MAP OPTIMISATIONS
*/
@Override
public Content add(QName name, QName... classes) {
- if (classes.length > 0) {
- QName primaryType = classes[0];
+ try {
Node node = openForEdit();
- Node child = Jcr.addNode(node, name.toString(), primaryType.toString());
- for (int i = 1; i < classes.length; i++) {
- try {
+ Node child;
+ if (classes.length > 0) {
+ classes: for (int i = 0; i < classes.length; i++) {
+ if (classes[i].equals(DName.collection.qName())) {
+ List<QName> lst = new ArrayList<>(Arrays.asList(classes));
+ lst.add(0, NtType.folder.qName());
+ lst.remove(DName.collection.qName());
+ classes = lst.toArray(new QName[lst.size()]);
+ break classes;
+ }
+ }
+ QName primaryType = classes[0];
+ child = Jcr.addNode(node, name.toString(), primaryType.toString());
+
+ for (int i = 1; i < classes.length; i++)
child.addMixin(classes[i].toString());
- } catch (RepositoryException e) {
- throw new JcrException("Cannot add child to " + getJcrNode(), e);
+
+ if (NtType.file.qName().equals(primaryType)) {
+ // TODO optimise when we have a proper save mechanism
+ child.addNode(Node.JCR_CONTENT, NodeType.NT_UNSTRUCTURED);
}
+ } else {
+ child = Jcr.addNode(node, name.toString(), NodeType.NT_UNSTRUCTURED);
}
+ saveEditedNode(node);
+ return new JcrContent(getSession(), provider, jcrWorkspace, child.getPath());
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot add child to " + jcrPath + " in " + jcrWorkspace, e);
+ }
+ }
- } else {
- Jcr.addNode(getJcrNode(), name.toString(), NodeType.NT_UNSTRUCTURED);
+ @Override
+ public Content add(QName name, Map<QName, Object> attrs, QName... classes) {
+ if (attrs.containsKey(DName.getcontenttype.qName())) {
+ List<QName> lst = new ArrayList<>(Arrays.asList(classes));
+ lst.add(0, NtType.file.qName());
+ classes = lst.toArray(new QName[lst.size()]);
}
- return null;
+
+ Content child = add(name, classes);
+ child.putAll(attrs);
+ return child;
}
@Override
public void remove() {
Node node = openForEdit();
Jcr.remove(node);
+ saveEditedNode(node);
+ }
+
+ private void saveEditedNode(Node node) {
+ try {
+ node.getSession().save();
+ getJcrSession().refresh(true);
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot persist " + jcrPath + " in " + jcrWorkspace, e);
+ }
}
@Override
throw new JcrException("Cannot remove property " + key + " from " + getJcrNode(), e);
}
}
-
+ saveEditedNode(node);
}
@Override
public Object put(QName key, Object value) {
+ Objects.requireNonNull(value, "Value cannot be null");
+ Node node = openForEdit();
try {
- String property = NamespaceUtils.toFullyQualified(key);
- Node node = openForEdit();
+ if (DName.checkedIn.equals(key) || DName.checkedOut.equals(key))
+ throw new IllegalArgumentException(
+ key + " cannot be set, use the openForEdit/freeze methods of the related content provider.");
+
Object old = null;
- if (node.hasProperty(property)) {
- old = convertSingleValue(node.getProperty(property).getValue());
+ String property;
+ if (DName.creationdate.equals(key))
+ property = Property.JCR_CREATED;
+ else if (DName.getlastmodified.equals(key))
+ property = Property.JCR_LAST_MODIFIED;
+ else if (DName.getcontenttype.equals(key)) {
+ if (!node.isNodeType(NodeType.NT_FILE))
+ throw new IllegalStateException(DName.getcontenttype + " can only be set on a file");
+ Node content = node.getNode(Node.JCR_CONTENT);
+ old = Jcr.get(content, Property.JCR_MIMETYPE);
+ if (old != null && Jcr.hasProperty(content, Property.JCR_ENCODING))
+ old = old + ";encoding=" + Jcr.get(content, Property.JCR_ENCODING);
+ String[] str = value.toString().split(";");
+ String mimeType = str[0].trim();
+ String encoding = null;
+ if (str.length > 1) {
+ value = str[0].trim();
+ String[] eq = str[1].split("=");
+ assert eq.length == 2;
+ if ("encoding".equals(eq[0].trim()))
+ encoding = eq[1];
+ }
+ content.setProperty(Property.JCR_MIMETYPE, mimeType);
+ if (encoding != null)
+ content.setProperty(Property.JCR_ENCODING, encoding);
+ property = null;
+ } else
+ property = NamespaceUtils.toFullyQualified(key);
+
+ if (property != null) {
+ if (node.hasProperty(property)) {
+ old = convertSingleValue(node.getProperty(property).getValue());
+ }
+ Value newValue = convertSingleObject(node.getSession().getValueFactory(), value);
+ node.setProperty(property, newValue);
}
- Value newValue = convertSingleObject(node.getSession().getValueFactory(), value);
- node.setProperty(property, newValue);
// FIXME proper edition
- node.getSession().save();
+ saveEditedNode(node);
return old;
} catch (RepositoryException e) {
throw new JcrException("Cannot set property " + key + " on " + jcrPath + " in " + jcrWorkspace, e);
node.addMixin(nodeType.getName());
}
// FIXME proper edition
- node.getSession().save();
+ saveEditedNode(node);
} catch (RepositoryException e) {
throw new JcrException(
"Cannot add content classes " + contentClass + " to " + jcrPath + " in " + jcrWorkspace, e);
@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 {
+ try {
+ if (InputStream.class.isAssignableFrom(clss)) {
+ Node node = getJcrNode();
+// System.out.println(node.getSession());
+ if (Jcr.isNodeType(node, NodeType.NT_FILE)) {
return (C) JcrUtils.getFileAsStream(node);
- } catch (RepositoryException e) {
- throw new JcrException("Cannot open " + jcrPath + " in workspace " + jcrWorkspace, e);
+ }
+ } else if (OutputStream.class.isAssignableFrom(clss)) {
+ Node node = openForEdit();
+// System.out.println(node.getSession());
+ if (Jcr.isNodeType(node, NodeType.NT_FILE)) {
+ Node content = node.getNode(Node.JCR_CONTENT);
+ AsyncPipedOutputStream out = new AsyncPipedOutputStream();
+
+ ValueFactory valueFactory = getJcrSession().getValueFactory();
+ out.asyncRead((in) -> {
+ try {
+ Binary binary = valueFactory.createBinary(in);
+ content.setProperty(Property.JCR_DATA, binary);
+ saveEditedNode(node);
+ } catch (RepositoryException e) {
+ throw new JcrException(
+ "Cannot create binary in " + jcrPath + " in workspace " + jcrWorkspace, e);
+ }
+ });
+ return (C) out;
}
}
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot open " + jcrPath + " in workspace " + jcrWorkspace, e);
}
return super.open(clss);
}
// primary node type
NodeType primaryType = context.getPrimaryNodeType();
res.add(nodeTypeToQName(primaryType));
+ if (primaryType.getName().equals(NodeType.NT_FOLDER))
+ res.add(DName.collection.qName());
Set<QName> secondaryTypes = new TreeSet<>(NamespaceUtils.QNAME_COMPARATOR);
for (NodeType mixinType : context.getMixinNodeTypes()) {
* COMMON UTILITIES
*/
protected Session getJcrSession() {
- return provider.getJcrSession(getSession(), jcrWorkspace);
+ Session s = provider.getJcrSession(getSession(), jcrWorkspace);
+// if (getSession().isEditing())
+// try {
+// s.refresh(false);
+// } catch (RepositoryException e) {
+// throw new JcrException("Cannot refresh session", e);
+// }
+ return s;
}
protected Node getJcrNode() {
--- /dev/null
+package org.argeo.cms.jcr.acr;
+
+import org.argeo.api.acr.QNamed;
+
+public enum JcrName implements QNamed {
+ created, lastModified, isCheckedOut;
+
+ @Override
+ public String getNamespace() {
+ return JcrContentNamespace.JCR.getNamespaceURI();
+ }
+
+ @Override
+ public String getDefaultPrefix() {
+ return JcrContentNamespace.JCR.getDefaultPrefix();
+ }
+
+}
public synchronized Node openForEdit(String workspace, String jcrPath) throws RepositoryException {
Session session = getWriteSession(workspace);
Node node = session.getNode(jcrPath);
- if (node.isNodeType(NodeType.MIX_SIMPLE_VERSIONABLE)) {
- VersionManager versionManager = session.getWorkspace().getVersionManager();
- if (versionManager.isCheckedOut(jcrPath)) {
+ VersionManager versionManager = session.getWorkspace().getVersionManager();
+
+ Node versionedAncestor = findVersionedAncestor(node);
+ boolean checkedOut = versionManager.isCheckedOut(jcrPath);
+
+ if (versionedAncestor != null) {
+ if (checkedOut) {
if (!checkedOutModified.containsKey(workspace))
checkedOutModified.put(workspace, new TreeSet<>());
- checkedOutModified.get(workspace).add(jcrPath);
+ checkedOutModified.get(workspace).add(versionedAncestor.getPath());
} else {
if (!checkedInModified.containsKey(workspace))
checkedInModified.put(workspace, new TreeSet<>());
- checkedInModified.get(workspace).add(jcrPath);
- versionManager.checkout(jcrPath);
+ checkedInModified.get(workspace).add(versionedAncestor.getPath());
+ versionManager.checkout(versionedAncestor.getPath());
}
}
return node;
}
+ private Node findVersionedAncestor(Node node) throws RepositoryException {
+ if (node.isNodeType(NodeType.MIX_SIMPLE_VERSIONABLE))
+ return node;
+ Node parent = node.getParent();
+ if (parent == null)
+ return null;
+ return findVersionedAncestor(parent);
+ }
+
public synchronized Node freeze(String workspace, String jcrPath) throws RepositoryException {
Session session = getWriteSession(workspace);
Node node = session.getNode(jcrPath);
--- /dev/null
+package org.argeo.cms.jcr.acr;
+
+import org.argeo.api.acr.QNamed;
+
+public enum MixInType implements QNamed {
+ mimeType;
+
+ @Override
+ public String getNamespace() {
+ return JcrContentNamespace.JCR_MIX.getNamespaceURI();
+ }
+
+ @Override
+ public String getDefaultPrefix() {
+ return JcrContentNamespace.JCR_MIX.getDefaultPrefix();
+ }
+}
--- /dev/null
+package org.argeo.cms.jcr.acr;
+
+import org.argeo.api.acr.QNamed;
+
+public enum NtType implements QNamed {
+ file, folder;
+
+ @Override
+ public String getNamespace() {
+ return JcrContentNamespace.JCR_NT.getNamespaceURI();
+ }
+
+ @Override
+ public String getDefaultPrefix() {
+ return JcrContentNamespace.JCR_NT.getDefaultPrefix();
+ }
+}
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import javax.jcr.Binary;
import javax.jcr.ItemNotFoundException;
*/
@SuppressWarnings("unchecked")
public static <T> T getAs(Node node, String property, T defaultValue) {
+ Objects.requireNonNull(defaultValue);
try {
// TODO deal with multiple
if (node.hasProperty(property)) {
@SuppressWarnings("unchecked")
public static <T> T getAs(Node node, String property, Class<T> clss) {
- if (String.class.isAssignableFrom(clss)) {
- return (T) get(node, property);
- } else if (Long.class.isAssignableFrom(clss)) {
- return (T) get(node, property);
- } else {
- throw new IllegalArgumentException("Unsupported format " + clss);
+ try {
+ Property p = node.getProperty(property);
+ try {
+ if (p.isMultiple()) {
+ throw new UnsupportedOperationException("Multiple values properties are not supported");
+ }
+ Value value = p.getValue();
+ return (T) get(value);
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException(
+ "Cannot cast property of type " + PropertyType.nameFromValue(p.getType()), e);
+ }
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot retrieve property " + property + " from " + node, e);
}
+// if (String.class.isAssignableFrom(clss)) {
+// return (T) get(node, property);
+// } else if (Long.class.isAssignableFrom(clss)) {
+// return (T) get(node, property);
+// } else if (Boolean.class.isAssignableFrom(clss)) {
+// return (T) get(node, property);
+// } else {
+// throw new IllegalArgumentException("Unsupported format " + clss);
+// }
}
/**
-Subproject commit d9cae87d811258d5a13e43eea8492f3792377ce4
+Subproject commit d5943f556d6fba9db0dd63d4c4cfceef89e4888e
major=2
minor=3
-micro=15
+micro=18
qualifier=
Bundle-Copyright= \
SPDX-License-Identifier= \
GPL-2.0-or-later \
-OR LicenseRef-argeo2-GPL-2.0-or-later-with-EPL-and-JCR-permissions
+OR LicenseRef-argeo2-GPL-2.0-or-later-with-EPL-and-Apache-and-JCR-permissions
+++ /dev/null
-package org.argeo.cms.ui;
-
-/** Commons constants */
-@Deprecated
-public interface CmsUiConstants {
- // DATAKEYS
-// public final static String STYLE = EclipseUiConstants.CSS_CLASS;
-// public final static String MARKUP = EclipseUiConstants.MARKUP_SUPPORT;
- @Deprecated
- /* RWT.CUSTOM_ITEM_HEIGHT */
- public final static String ITEM_HEIGHT = "org.eclipse.rap.rwt.customItemHeight";
-
- // EVENT DETAILS
- @Deprecated
- /* RWT.HYPERLINK */
- public final static int HYPERLINK = 1 << 26;
-
- // STANDARD RESOURCES
- public final static String LOADING_IMAGE = "icons/loading.gif";
-
- // MISCEALLENEOUS
- String DATE_TIME_FORMAT = "dd/MM/yyyy, HH:mm";
-}
package org.argeo.cms.ui.util;
-import java.io.IOException;
-import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import org.argeo.api.cms.CmsConstants;
import org.argeo.api.cms.ux.Cms2DSize;
import org.argeo.api.cms.ux.CmsView;
+import org.argeo.cms.acr.ContentUtils;
import org.argeo.cms.jcr.CmsJcrUtils;
import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.ui.CmsUiConstants;
import org.argeo.cms.ux.AbstractImageManager;
import org.argeo.cms.ux.CmsUxUtils;
import org.argeo.jcr.JcrUtils;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.service.ResourceManager;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
/** Clean reserved URL characters for use in HTTP links. */
public static String getDataPathForUrl(Node node) {
- return CmsSwtUtils.cleanPathForUrl(getDataPath(node));
+ return ContentUtils.cleanPathForUrl(getDataPath(node));
}
/** @deprecated Use rowData16px() instead. GridData should not be reused. */
@Deprecated
public static RowData ROW_DATA_16px = new RowData(16, 16);
-
-
/*
* FORM LAYOUT
*/
-
+ public final static String ITEM_HEIGHT = "org.eclipse.rap.rwt.customItemHeight";
@Deprecated
public static void setItemHeight(Table table, int height) {
- table.setData(CmsUiConstants.ITEM_HEIGHT, height);
+ table.setData(ITEM_HEIGHT, height);
}
//
import javax.jcr.Item;
import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.ui.CmsUiConstants;
import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.widgets.Control;
/** Editable text part displaying styled text. */
-public abstract class StyledControl extends JcrComposite implements CmsUiConstants {
+public abstract class StyledControl extends JcrComposite {
private static final long serialVersionUID = -6372283442330912755L;
private Control control;