/** * This file is part of the JCROM project. * Copyright (C) 2008-2014 - All rights reserved. * Authors: Olafur Gauti Gudmundsson, Nicolas Dos Santos * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jcrom.dao; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.List; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.nodetype.NodeType; import javax.jcr.query.Query; import javax.jcr.query.QueryManager; import javax.jcr.query.QueryResult; import javax.jcr.query.qom.Column; import javax.jcr.query.qom.Constraint; import javax.jcr.query.qom.Ordering; import javax.jcr.query.qom.QueryObjectModelFactory; import javax.jcr.query.qom.Source; import javax.jcr.version.Version; import javax.jcr.version.VersionHistory; import javax.jcr.version.VersionIterator; import org.jcrom.JcrMappingException; import org.jcrom.Jcrom; import org.jcrom.annotations.JcrNode; import org.jcrom.callback.JcromCallback; import org.jcrom.util.JcrUtils; import org.jcrom.util.NodeFilter; import org.jcrom.util.PathUtils; import org.jcrom.util.ReflectionUtils; /** * An abstract implementation of the JcrDAO interface. This should be extended * for specific entity implementations. * This class implements all the methods defined in the JcrDAO interface, and * provides a few protected methods that are useful for implementing custom * finder methods. * <br/><br/> * * The constructor takes a JCR session, so an instance should be created per * session. The constructor also takes a Jcrom instance that can be shared * across multiple DAOs. * <br/><br/> * * This implementation encapsulates exceptions in JcrMappingException, which * is a RuntimeException. * * @author Olafur Gauti Gudmundsson * @author Nicolas Dos Santos */ public abstract class AbstractJcrDAO<T> implements JcrDAO<T> { protected final Jcrom jcrom; protected final Session session; protected final Class<T> entityClass; protected final String[] mixinTypes; protected final boolean isVersionable; /** * <p> * Use this constructor when you intend to override the getSession() * method to provide your own session management (for example via * Guice providers). You can also use the other constructors and just * pass null as the session. * </p> * <p>The entityClass is retrieved from {@link ParameterizedType} in the superclass.</p> * * @param jcrom the Jcrom instance to use for object mapping */ public AbstractJcrDAO(Jcrom jcrom) { this(null, null, jcrom, new String[0]); } /** * Constructor. The entityClass is retrieved from {@link ParameterizedType} in the superclass. * * @param session the current JCR session * @param jcrom the Jcrom instance to use for object mapping */ public AbstractJcrDAO(Session session, Jcrom jcrom) { this(null, session, jcrom, new String[0]); } /** * Use this constructor when you intend to override the getSession() * method to provide your own session management (for example via * Guice providers). You can also use the other constructors and just * pass null as the session. * * @param entityClass the class handled by this DAO implementation * @param jcrom the Jcrom instance to use for object mapping */ public AbstractJcrDAO(Class<T> entityClass, Jcrom jcrom) { this(entityClass, null, jcrom, new String[0]); } /** * Constructor. * * @param entityClass the class handled by this DAO implementation * @param session the current JCR session * @param jcrom the Jcrom instance to use for object mapping */ public AbstractJcrDAO(Class<T> entityClass, Session session, Jcrom jcrom) { this(entityClass, session, jcrom, new String[0]); } /** * Constructor. * * @param entityClass the class handled by this DAO implementation. If entityClass is <code>null</code>, the entityClass is retrieved from {@link ParameterizedType} in the superclass * @param session the current JCR session * @param jcrom the Jcrom instance to use for object mapping * @param mixinTypes an array of mixin types to apply to new nodes */ @SuppressWarnings("unchecked") public AbstractJcrDAO(Class<T> entityClass, Session session, Jcrom jcrom, String[] mixinTypes) { if (entityClass == null) { Class<?> clazz = getClass(); while (!(clazz.getGenericSuperclass() instanceof ParameterizedType)) { clazz = clazz.getSuperclass(); } this.entityClass = (Class<T>) ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0]; } else { this.entityClass = entityClass; } this.session = session; this.jcrom = jcrom; this.mixinTypes = new String[mixinTypes.length]; System.arraycopy(mixinTypes, 0, this.mixinTypes, 0, mixinTypes.length); this.isVersionable = checkIfVersionable(); } protected Class<T> getEntityClass() { return entityClass; } protected Session getSession() { return session; } protected Jcrom getJcrom() { return jcrom; } protected String[] getMixinTypes() { return mixinTypes; } private boolean checkIfVersionable() { // check mixin type array for (String mixinType : getMixinTypes()) { if (mixinType.equals("mix:versionable") || mixinType.equals(NodeType.MIX_VERSIONABLE)) { return true; } } // check the class annotation JcrNode jcrNode = ReflectionUtils.getJcrNodeAnnotation(getEntityClass()); if (jcrNode != null && jcrNode.mixinTypes() != null) { for (String mixinType : jcrNode.mixinTypes()) { if (mixinType.equals("mix:versionable") || mixinType.equals(NodeType.MIX_VERSIONABLE)) { return true; } } } return false; } protected Node getNodeById(String id) throws RepositoryException { // return getSession().getNodeByUUID(uuid); return getSession().getNodeByIdentifier(id); } protected Node getNode(String absolutePath) throws RepositoryException { return PathUtils.getNode(absolutePath, getSession()); } protected NodeIterator getNodes(String absolutePath) throws RepositoryException { return PathUtils.getNodes(absolutePath, getSession()); } @Override public T create(T entity) { return create(getParentPath(entity), entity, null); } @Override public T create(T entity, JcromCallback action) { return create(getParentPath(entity), entity, action); } private String getParentPath(T entity) { try { // Set the parent path with a default value, the entity path if it is not null, otherwise the root path "/" String entityPath = getJcrom().getPath(entity); String parentPath = entityPath != null ? entityPath : "/"; // Search the parent object annotated with JcrParentNode Object parentObject = getJcrom().getParentObject(entity); if (parentObject != null) { // Retrieve the parent path and check if the parent node exists parentPath = getJcrom().getPath(parentObject); if (!exists(parentPath)) { throw new JcrMappingException("the parent with path '" + parentPath + "' is not created!"); } Node parentNode = getNode(parentPath); // Search a child container path annotated with JcrChildNode and the type is the same as 'entity' clazz String childContainerPath = getJcrom().getChildContainerPath(entity, parentObject, parentNode); if (childContainerPath != null) { parentPath = childContainerPath; } } return parentPath; } catch (RepositoryException e) { throw new JcrMappingException("Could not retrieve parent path", e); } } @Override public T create(String parentNodePath, T entity) { return create(parentNodePath, entity, null); } @Override public T create(String parentNodePath, T entity, JcromCallback action) { try { String entityName = getJcrom().getName(entity); if (entityName == null || entityName.equals("")) { throw new JcrMappingException("The name of the entity being created is empty!"); } if (parentNodePath == null || parentNodePath.equals("")) { throw new JcrMappingException("The parent path of the entity being created is empty!"); } Node parentNode = getNode(parentNodePath); if (isVersionable) { // if this is a versionable node, then we need to check out parent before moving the node if (JcrUtils.hasMixinType(parentNode, "mix:versionable") || JcrUtils.hasMixinType(parentNode, NodeType.MIX_VERSIONABLE)) { JcrUtils.checkout(parentNode); } } Node newNode = getJcrom().addNode(parentNode, entity, getMixinTypes(), action); newNode.getSession().save(); if (isVersionable) { //newNode.checkin(); JcrUtils.checkinRecursively(newNode); // check in the parent node if ((JcrUtils.hasMixinType(parentNode, "mix:versionable") || JcrUtils.hasMixinType(parentNode, NodeType.MIX_VERSIONABLE)) && parentNode.isCheckedOut()) { JcrUtils.checkin(parentNode); } } //return (T)getJcrom().fromNode(getEntityClass(), newNode); return entity; } catch (RepositoryException e) { throw new JcrMappingException("Could not create node", e); } } @Override public T update(T entity) { return update(entity, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE), null); } @Override public T update(T entity, JcromCallback action) { return update(entity, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE), action); } @Override @Deprecated public T update(T entity, String childNameFilter, int maxDepth) { return update(entity, new NodeFilter(childNameFilter, maxDepth), null); } @Override public T update(T entity, NodeFilter nodeFilter) { return update(entity, nodeFilter, null); } @Override public T update(T entity, NodeFilter nodeFilter, JcromCallback action) { Node node; try { node = getNode(getJcrom().getPath(entity)); } catch (RepositoryException e) { throw new JcrMappingException("Could not update node", e); } return update(node, entity, nodeFilter, action); } @Override @Deprecated public T updateByUUID(T entity, String uuid) { return updateById(entity, uuid, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE), null); } @Override public T updateById(T entity, String id) { return updateById(entity, id, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE), null); } @Override public T updateById(T entity, String id, JcromCallback action) { return updateById(entity, id, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE), action); } @Override @Deprecated public T updateByUUID(T entity, String uuid, String childNameFilter, int maxDepth) { return updateById(entity, uuid, childNameFilter, maxDepth); } @Override @Deprecated public T updateById(T entity, String id, String childNameFilter, int maxDepth) { return updateById(entity, id, new NodeFilter(childNameFilter, maxDepth), null); } @Override public T updateById(T entity, String id, NodeFilter nodeFilter) { return updateById(entity, id, nodeFilter, null); } @Override public T updateById(T entity, String id, NodeFilter nodeFilter, JcromCallback action) { Node node; try { node = getNodeById(id); } catch (RepositoryException e) { throw new JcrMappingException("Could not update node", e); } return update(node, entity, nodeFilter, action); } protected T update(Node node, T entity, NodeFilter nodeFilter, JcromCallback action) { try { if (isVersionable) { //node.checkout(); JcrUtils.checkoutRecursively(node); } Node updatedNode = getJcrom().updateNode(node, entity, nodeFilter, action); updatedNode.getSession().save(); if (isVersionable) { //node.checkin(); JcrUtils.checkinRecursively(updatedNode); } return entity; } catch (RepositoryException e) { throw new JcrMappingException("Could not update node", e); } } @Override public void move(T entity, String newParentPath) { // if this is a versionable node, then we need to check out both // the old parent and the new parent before moving the node try { String sourcePath = getJcrom().getPath(entity); String entityName = getJcrom().getName(entity); Node oldParent = null; Node newParent = null; if (isVersionable) { oldParent = getNode(sourcePath).getParent(); newParent = getNode(newParentPath); if (JcrUtils.hasMixinType(oldParent, "mix:versionable") || JcrUtils.hasMixinType(oldParent, NodeType.MIX_VERSIONABLE)) { //oldParent.checkout(); JcrUtils.checkout(oldParent); } if (JcrUtils.hasMixinType(newParent, "mix:versionable") || JcrUtils.hasMixinType(newParent, NodeType.MIX_VERSIONABLE)) { //newParent.checkout(); JcrUtils.checkout(newParent); } } Session session = getSession(); if (newParentPath.equals("/")) { // special case, moving to root session.move(sourcePath, newParentPath + entityName); } else { session.move(sourcePath, newParentPath + "/" + entityName); } session.save(); if (isVersionable) { if ((JcrUtils.hasMixinType(oldParent, "mix:versionable") || JcrUtils.hasMixinType(oldParent, NodeType.MIX_VERSIONABLE)) && oldParent.isCheckedOut()) { //oldParent.checkin(); JcrUtils.checkin(oldParent); } if ((JcrUtils.hasMixinType(newParent, "mix:versionable") || JcrUtils.hasMixinType(newParent, NodeType.MIX_VERSIONABLE)) && newParent.isCheckedOut()) { //newParent.checkin(); JcrUtils.checkin(newParent); } } } catch (RepositoryException e) { throw new JcrMappingException("Could not move node", e); } } @Override public void remove(String path) { try { Node parent = null; if (isVersionable) { parent = getNode(path).getParent(); if (JcrUtils.hasMixinType(parent, "mix:versionable") || JcrUtils.hasMixinType(parent, NodeType.MIX_VERSIONABLE)) { //parent.checkout(); JcrUtils.checkout(parent); } } Node node = getNode(path); node.remove(); node.getSession().save(); if (isVersionable) { if ((JcrUtils.hasMixinType(parent, "mix:versionable") || JcrUtils.hasMixinType(parent, NodeType.MIX_VERSIONABLE)) && parent.isCheckedOut()) { //parent.checkin(); JcrUtils.checkin(parent); } } } catch (RepositoryException e) { throw new JcrMappingException("Could not remove node", e); } } @Override @Deprecated public void removeByUUID(String uuid) { removeById(uuid); } @Override public void removeById(String id) { try { Node node = getNodeById(id); Node parent = null; if (isVersionable) { parent = node.getParent(); if (JcrUtils.hasMixinType(parent, "mix:versionable") || JcrUtils.hasMixinType(parent, NodeType.MIX_VERSIONABLE)) { //parent.checkout(); JcrUtils.checkout(parent); } } node.remove(); node.getSession().save(); if (isVersionable) { if ((JcrUtils.hasMixinType(parent, "mix:versionable") || JcrUtils.hasMixinType(parent, NodeType.MIX_VERSIONABLE)) && parent.isCheckedOut()) { //parent.checkin(); JcrUtils.checkin(parent); } } } catch (RepositoryException e) { throw new JcrMappingException("Could not remove node", e); } } @Override public boolean exists(String path) { try { return getSession().getRootNode().hasNode(PathUtils.relativePath(path)); } catch (RepositoryException e) { throw new JcrMappingException("Could not check if node exists", e); } } @Override public T get(String path) { return get(path, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE)); } @Override @Deprecated public T get(String path, String childNameFilter, int maxDepth) { return get(path, new NodeFilter(childNameFilter, maxDepth)); } @Override public T get(String path, NodeFilter nodeFilter) { if (exists(path)) { Node node; try { node = getNode(path); } catch (RepositoryException e) { throw new JcrMappingException("Could not get node", e); } return getJcrom().fromNode(getEntityClass(), node, nodeFilter); } else { return null; } } @Override public List<T> getAll(String path) { return getAll(path, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE)); } @Override public List<T> getAll(String path, long startIndex, long resultSize) { return getAll(path, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE), startIndex, resultSize); } @Override @Deprecated public List<T> getAll(String path, String childNameFilter, int maxDepth) { return getAll(path, new NodeFilter(childNameFilter, maxDepth)); } @Override public List<T> getAll(String path, NodeFilter nodeFilter) { try { return toList(getNodes(path), nodeFilter); } catch (RepositoryException e) { throw new JcrMappingException("Could not get nodes", e); } } @Override @Deprecated public List<T> getAll(String path, String childNameFilter, int maxDepth, long startIndex, long resultSize) { return getAll(path, new NodeFilter(childNameFilter, maxDepth), startIndex, resultSize); } @Override public List<T> getAll(String path, NodeFilter nodeFilter, long startIndex, long resultSize) { try { NodeIterator nodeIterator = getNodes(path); nodeIterator.skip(startIndex); return toList(nodeIterator, nodeFilter, resultSize); } catch (RepositoryException e) { throw new JcrMappingException("Could not get nodes", e); } } @Override @Deprecated public T loadByUUID(String uuid) { return loadById(uuid, NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE); } @Override public T loadById(String id) { return loadById(id, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE)); } @Override @Deprecated public T loadByUUID(String uuid, String childNameFilter, int maxDepth) { return loadById(uuid, childNameFilter, maxDepth); } @Override @Deprecated public T loadById(String id, String childNameFilter, int maxDepth) { return loadById(id, new NodeFilter(childNameFilter, maxDepth)); } @Override public T loadById(String id, NodeFilter nodeFilter) { Node node; try { node = getNodeById(id); } catch (RepositoryException e) { throw new JcrMappingException("Could not load node", e); } return getJcrom().fromNode(getEntityClass(), node, nodeFilter); } @Override public T getVersion(String path, String versionName) { return getVersion(path, versionName, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE)); } @Override @Deprecated public T getVersion(String path, String versionName, String childNameFilter, int maxDepth) { return getVersion(path, versionName, new NodeFilter(childNameFilter, maxDepth)); } @Override public T getVersion(String path, String versionName, NodeFilter nodeFilter) { try { return getVersion(getNode(path), versionName, nodeFilter); } catch (RepositoryException e) { throw new JcrMappingException("Could not get version", e); } } @Override @Deprecated public T getVersionByUUID(String uuid, String versionName) { return getVersionById(uuid, versionName, NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE); } @Override public T getVersionById(String id, String versionName) { return getVersionById(id, versionName, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE)); } @Override @Deprecated public T getVersionByUUID(String uuid, String versionName, String childNameFilter, int maxDepth) { return getVersionById(uuid, versionName, childNameFilter, maxDepth); } @Override @Deprecated public T getVersionById(String id, String versionName, String childNameFilter, int maxDepth) { return getVersionById(id, versionName, new NodeFilter(childNameFilter, maxDepth)); } @Override public T getVersionById(String id, String versionName, NodeFilter nodeFilter) { try { Node node = getNodeById(id); return getVersion(node, versionName, nodeFilter); } catch (RepositoryException e) { throw new JcrMappingException("Could not get version", e); } } protected T getVersion(Node node, String versionName, NodeFilter nodeFilter) { try { //VersionHistory versionHistory = node.getVersionHistory(); VersionHistory versionHistory = JcrUtils.getVersionManager(node.getSession()).getVersionHistory(node.getPath()); Version version = versionHistory.getVersion(versionName); return getJcrom().fromNode(getEntityClass(), version.getNodes().nextNode(), nodeFilter); } catch (RepositoryException e) { throw new JcrMappingException("Could not get version", e); } } @Override public void restoreVersion(String path, String versionName) { restoreVersion(path, versionName, true); } @Override @Deprecated public void restoreVersionByUUID(String uuid, String versionName) { restoreVersionById(uuid, versionName, true); } @Override public void restoreVersionById(String id, String versionName) { restoreVersionById(id, versionName, true); } @Override public void restoreVersion(String path, String versionName, boolean removeExisting) { try { restoreVersion(getNode(path), versionName, removeExisting); } catch (RepositoryException e) { throw new JcrMappingException("Could not restore version", e); } } @Override @Deprecated public void restoreVersionByUUID(String uuid, String versionName, boolean removeExisting) { restoreVersionById(uuid, versionName, removeExisting); } @Override public void restoreVersionById(String id, String versionName, boolean removeExisting) { try { Node node = getNodeById(id); restoreVersion(node, versionName, removeExisting); } catch (RepositoryException e) { throw new JcrMappingException("Could not restore version", e); } } protected void restoreVersion(Node node, String versionName, boolean removeExisting) { try { //node.checkout(); JcrUtils.checkout(node); //node.restore(versionName, removeExisting); JcrUtils.getVersionManager(node.getSession()).restore(node.getPath(), versionName, removeExisting); } catch (RepositoryException e) { throw new JcrMappingException("Could not restore version", e); } } @Override public void removeVersion(String path, String versionName) { try { removeVersion(getNode(path), versionName); } catch (RepositoryException e) { throw new JcrMappingException("Could not remove version", e); } } @Override @Deprecated public void removeVersionByUUID(String uuid, String versionName) { removeVersionById(uuid, versionName); } @Override public void removeVersionById(String id, String versionName) { try { Node node = getNodeById(id); removeVersion(node, versionName); } catch (RepositoryException e) { throw new JcrMappingException("Could not remove version", e); } } protected void removeVersion(Node node, String versionName) { try { //VersionHistory versionHistory = node.getVersionHistory(); VersionHistory versionHistory = JcrUtils.getVersionManager(node.getSession()).getVersionHistory(node.getPath()); versionHistory.removeVersion(versionName); } catch (RepositoryException e) { throw new JcrMappingException("Could not remove version", e); } } @Override public long getVersionSize(String path) { try { return getVersionSize(getNode(path)); } catch (RepositoryException e) { throw new JcrMappingException("Could not get version history size", e); } } @Override @Deprecated public long getVersionSizeByUUID(String uuid) { return getVersionSizeById(uuid); } @Override public long getVersionSizeById(String id) { try { Node node = getNodeById(id); return getVersionSize(node); } catch (RepositoryException e) { throw new JcrMappingException("Could not get version history size", e); } } protected long getVersionSize(Node node) { try { //VersionHistory versionHistory = node.getVersionHistory(); VersionHistory versionHistory = JcrUtils.getVersionManager(node.getSession()).getVersionHistory(node.getPath()); return versionHistory.getAllVersions().getSize() - 1; } catch (RepositoryException e) { throw new JcrMappingException("Could not get version history size", e); } } @Override public List<T> getVersionList(String path) { try { return getVersionList(getNode(path), new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE)); } catch (RepositoryException e) { throw new JcrMappingException("Could not get version list", e); } } @Override @Deprecated public List<T> getVersionList(String path, String childNameFilter, int maxDepth) { return getVersionList(path, new NodeFilter(childNameFilter, maxDepth)); } @Override public List<T> getVersionList(String path, NodeFilter nodeFilter) { try { return getVersionList(getNode(path), nodeFilter); } catch (RepositoryException e) { throw new JcrMappingException("Could not get version list", e); } } @Override @Deprecated public List<T> getVersionList(String path, String childNameFilter, int maxDepth, long startIndex, long resultSize) { return getVersionList(path, new NodeFilter(childNameFilter, maxDepth), startIndex, resultSize); } @Override public List<T> getVersionList(String path, NodeFilter nodeFilter, long startIndex, long resultSize) { try { return getVersionList(getNode(path), nodeFilter, startIndex, resultSize); } catch (RepositoryException e) { throw new JcrMappingException("Could not get version list", e); } } @Override @Deprecated public List<T> getVersionListByUUID(String uuid) { return getVersionListById(uuid); } @Override public List<T> getVersionListById(String id) { try { Node node = getNodeById(id); return getVersionList(node, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE)); } catch (RepositoryException e) { throw new JcrMappingException("Could not get version list", e); } } @Override @Deprecated public List<T> getVersionListByUUID(String uuid, String childNameFilter, int maxDepth) { return getVersionListById(uuid, new NodeFilter(childNameFilter, maxDepth)); } @Override @Deprecated public List<T> getVersionListById(String id, String childNameFilter, int maxDepth) { return getVersionListById(id, new NodeFilter(childNameFilter, maxDepth)); } @Override public List<T> getVersionListById(String id, NodeFilter nodeFilter) { try { Node node = getNodeById(id); return getVersionList(node, nodeFilter); } catch (RepositoryException e) { throw new JcrMappingException("Could not get version list", e); } } @Override @Deprecated public List<T> getVersionListByUUID(String uuid, String childNameFilter, int maxDepth, long startIndex, long resultSize) { return getVersionListById(uuid, new NodeFilter(childNameFilter, maxDepth), startIndex, resultSize); } @Override @Deprecated public List<T> getVersionListById(String id, String childNameFilter, int maxDepth, long startIndex, long resultSize) { return getVersionListById(id, new NodeFilter(childNameFilter, maxDepth), startIndex, resultSize); } @Override public List<T> getVersionListById(String id, NodeFilter nodeFilter, long startIndex, long resultSize) { try { Node node = getNodeById(id); return getVersionList(node, nodeFilter, startIndex, resultSize); } catch (RepositoryException e) { throw new JcrMappingException("Could not get version list", e); } } protected List<T> getVersionList(Node node, NodeFilter nodeFilter) { try { List<T> versionList = new ArrayList<T>(); //VersionHistory versionHistory = node.getVersionHistory(); VersionHistory versionHistory = JcrUtils.getVersionManager(node.getSession()).getVersionHistory(node.getPath()); VersionIterator versionIterator = versionHistory.getAllVersions(); versionIterator.skip(1); while (versionIterator.hasNext()) { Version version = versionIterator.nextVersion(); NodeIterator nodeIterator = version.getNodes(); while (nodeIterator.hasNext()) { T entityVersion = getJcrom().fromNode(getEntityClass(), nodeIterator.nextNode(), nodeFilter); //Version baseVersion = node.getBaseVersion(); Version baseVersion = JcrUtils.getVersionManager(node.getSession()).getBaseVersion(node.getPath()); getJcrom().setBaseVersionInfo(entityVersion, baseVersion.getName(), baseVersion.getCreated()); versionList.add(entityVersion); } } return versionList; } catch (RepositoryException e) { throw new JcrMappingException("Could not get version list", e); } } protected List<T> getVersionList(Node node, NodeFilter nodeFilter, long startIndex, long resultSize) { try { List<T> versionList = new ArrayList<T>(); //VersionHistory versionHistory = node.getVersionHistory(); VersionHistory versionHistory = JcrUtils.getVersionManager(node.getSession()).getVersionHistory(node.getPath()); VersionIterator versionIterator = versionHistory.getAllVersions(); versionIterator.skip(1 + startIndex); long counter = 0; while (versionIterator.hasNext()) { if (counter == resultSize) { break; } Version version = versionIterator.nextVersion(); NodeIterator nodeIterator = version.getNodes(); while (nodeIterator.hasNext()) { versionList.add(getJcrom().fromNode(getEntityClass(), nodeIterator.nextNode(), nodeFilter)); } counter++; } return versionList; } catch (RepositoryException e) { throw new JcrMappingException("Could not get version list", e); } } @Override public long getSize(String rootPath) { try { NodeIterator nodeIterator = getNode(rootPath).getNodes(); return nodeIterator.getSize(); } catch (RepositoryException e) { throw new JcrMappingException("Could not get list size", e); } } @Override public List<T> findAll(String rootPath) { return findAll(rootPath, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE)); } @Override public List<T> findAll(String rootPath, long startIndex, long resultSize) { return findAll(rootPath, new NodeFilter(NodeFilter.INCLUDE_ALL, NodeFilter.DEPTH_INFINITE), startIndex, resultSize); } @Override @Deprecated public List<T> findAll(String rootPath, String childNameFilter, int maxDepth) { return findAll(rootPath, new NodeFilter(childNameFilter, maxDepth)); } @Override public List<T> findAll(String rootPath, NodeFilter nodeFilter) { try { return toList(getNode(rootPath).getNodes(), nodeFilter); } catch (RepositoryException e) { throw new JcrMappingException("Could not find nodes", e); } } @Override @Deprecated public List<T> findAll(String rootPath, String childNameFilter, int maxDepth, long startIndex, long resultSize) { return findAll(rootPath, new NodeFilter(childNameFilter, maxDepth), startIndex, resultSize); } @Override public List<T> findAll(String rootPath, NodeFilter nodeFilter, long startIndex, long resultSize) { try { NodeIterator nodeIterator = getNode(rootPath).getNodes(); nodeIterator.skip(startIndex); return toList(nodeIterator, nodeFilter, resultSize); } catch (RepositoryException e) { throw new JcrMappingException("Could not find nodes", e); } } /** * Find JCR nodes that match the xpath supplied, and map to objects. * * @param xpath the XPath for finding the nodes * @param nodeFilter the NodeFilter to apply when updating child nodes and references * @param startIndex the zero based index of the first item to return * @param resultSize the number of items to return * @return a list of all objects found */ protected List<T> findByXPath(String xpath, NodeFilter nodeFilter, long startIndex, long resultSize) { try { QueryManager queryManager = getSession().getWorkspace().getQueryManager(); Query query = queryManager.createQuery(xpath, Query.XPATH); QueryResult result = query.execute(); NodeIterator nodeIterator = result.getNodes(); nodeIterator.skip(startIndex); return toList(nodeIterator, nodeFilter, resultSize); } catch (RepositoryException e) { throw new JcrMappingException("Could not find nodes by XPath", e); } } /** * Find JCR nodes that match the xpath supplied, and map to objects. * * @param xpath the XPath for finding the nodes * @param nodeFilter the NodeFilter to apply when updating child nodes and references * @return a list of all objects found */ protected List<T> findByXPath(String xpath, NodeFilter nodeFilter) { try { QueryManager queryManager = getSession().getWorkspace().getQueryManager(); Query query = queryManager.createQuery(xpath, Query.XPATH); QueryResult result = query.execute(); return toList(result.getNodes(), nodeFilter); } catch (RepositoryException e) { throw new JcrMappingException("Could not find nodes by XPath", e); } } /** * Find JCR nodes that match the SQL supplied, and map to objects. * * @param sql the SQL for finding the nodes * @param nodeFilter the NodeFilter to apply when updating child nodes and references * @param startIndex the zero based index of the first item to return * @param resultSize the number of items to return * @return a list of all objects found */ protected List<T> findBySql(String sql, NodeFilter nodeFilter, long startIndex, long resultSize) { try { QueryManager queryManager = getSession().getWorkspace().getQueryManager(); Query query = queryManager.createQuery(sql, Query.JCR_SQL2); QueryResult result = query.execute(); NodeIterator nodeIterator = result.getNodes(); nodeIterator.skip(startIndex); return toList(nodeIterator, nodeFilter, resultSize); } catch (RepositoryException e) { throw new JcrMappingException("Could not find nodes by SQL", e); } } /** * Find JCR nodes that match the SQL supplied, and map to objects. * * @param sql the SQL for finding the nodes * @param nodeFilter the NodeFilter to apply when updating child nodes and references * @return a list of all objects found */ protected List<T> findBySql(String sql, NodeFilter nodeFilter) { try { QueryManager queryManager = getSession().getWorkspace().getQueryManager(); Query query = queryManager.createQuery(sql, Query.JCR_SQL2); QueryResult result = query.execute(); return toList(result.getNodes(), nodeFilter); } catch (RepositoryException e) { throw new JcrMappingException("Could not find nodes by SQL", e); } } /** * Find JCR nodes with one or more selectors, and map to objects. * * @param source the node-tuple source; non-null * @param constraint the constraint, or null if none * @param orderings zero or more orderings; null is equivalent to a zero-length array * @param columns the columns; null is equivalent to a zero-length array * @param nodeFilter the NodeFilter to apply when updating child nodes and references * @return a list of objects mapped from the nodes */ protected List<T> findByQOM(Source source, Constraint constraint, Ordering orderings[], Column columns[], NodeFilter nodeFilter) { try { QueryObjectModelFactory factory = getSession().getWorkspace().getQueryManager().getQOMFactory(); Query query = factory.createQuery(source, constraint, orderings, columns); QueryResult result = query.execute(); return toList(result.getNodes(), nodeFilter); } catch (RepositoryException e) { throw new JcrMappingException("Could not find nodes by QOM", e); } } /** * Maps JCR nodes to a List of JcrEntity implementations. * * @param nodeIterator the iterator pointing to the nodes * @param nodeFilter the NodeFilter to apply when updating child nodes and references * @return a list of objects mapped from the nodes */ protected List<T> toList(NodeIterator nodeIterator, NodeFilter nodeFilter) { List<T> objects = new ArrayList<T>(); while (nodeIterator.hasNext()) { objects.add(getJcrom().fromNode(getEntityClass(), nodeIterator.nextNode(), nodeFilter)); } return objects; } /** * Maps JCR nodes to a List of JcrEntity implementations. * * @param nodeIterator the iterator pointing to the nodes * @param nodeFilter the NodeFilter to apply when updating child nodes and references * @param resultSize the number of items to retrieve from the iterator * @return a list of objects mapped from the nodes */ protected List<T> toList(NodeIterator nodeIterator, NodeFilter nodeFilter, long resultSize) { List<T> objects = new ArrayList<T>(); long counter = 0; while (nodeIterator.hasNext()) { if (counter == resultSize) { break; } objects.add(getJcrom().fromNode(getEntityClass(), nodeIterator.nextNode(), nodeFilter)); counter++; } return objects; } }