package com.thinkbiganalytics.metadata.modeshape.support;
/*-
* #%L
* thinkbig-metadata-modeshape
* %%
* Copyright (C) 2017 ThinkBig Analytics
* %%
* 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.
* #L%
*/
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.thinkbiganalytics.metadata.modeshape.MetadataRepositoryException;
import com.thinkbiganalytics.metadata.modeshape.common.JcrObject;
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.lock.LockManager;
import javax.jcr.nodetype.NodeType;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
import javax.jcr.version.VersionIterator;
import javax.jcr.version.VersionManager;
/**
*/
public class JcrVersionUtil {
/**
* Returns the LockManager object from the given session.
*
* @param session {@link Session}
* @return a {@link LockManager} object
*/
public static LockManager getLockManager(Session session) throws RepositoryException {
LockManager lockMgr = session.getWorkspace().getLockManager();
return lockMgr;
}
/**
* Returns the VersionManager object from the given session.
*
* @param session {@link Session}
* @return a {@link VersionManager} object
*/
public static VersionManager getVersionManager(Session session) throws RepositoryException {
VersionManager versionMgr = session.getWorkspace().getVersionManager();
return versionMgr;
}
/**
* Sets the given node to checked-out status.
*
* @param node node to check-out
*/
public static void checkout(Node node) throws RepositoryException {
//getVersionManager(node.getSession()).checkout(node.getPath());
}
/**
* Creates for the given node a new version and returns that version. Put the node into the checked-in state.
*
* @param node node to checkin
* @return the created version
*/
public static Version checkin(Node node) throws RepositoryException {
if (node.getSession().isLive()) {
//return getVersionManager(node.getSession()).checkin(node.getPath());
return null;
} else {
return null;
}
}
public static void checkinRecursively(Node node) {
try {
NodeIterator it = node.getNodes();
while (it.hasNext()) {
checkinRecursively(it.nextNode());
}
if (node.isCheckedOut() && node.isNodeType(NodeType.MIX_VERSIONABLE)) {
//node.checkin();
checkin(node);
}
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Could not perform check-in", e);
}
}
public static void checkoutRecursively(Node node) {
try {
NodeIterator it = node.getNodes();
while (it.hasNext()) {
checkoutRecursively(it.nextNode());
}
if (!node.isCheckedOut() && node.isNodeType(NodeType.MIX_VERSIONABLE)) {
//node.checkout();
checkout(node);
}
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Could not perform check-out", e);
}
}
/**
* Places a lock on the given node.
*
* @param node the node to be locked
* @param isDeep if <code>true</code> this lock will apply to this node and all its descendants; if <code>false</code>, it applies only to this node.
* @param isSessionScoped if <code>true</code>, this lock expires with the current session; if <code>false</code> it expires when explicitly or automatically unlocked for some other reason.
* @param timeoutHint desired lock timeout in seconds (servers are free to ignore this value); specify Long.MAX_VALUE for no timeout.
* @param ownerInfo a string containing owner information supplied by the client; servers are free to ignore this value.
* @see javax.jcr.lock.LockManager#lock(String, boolean, boolean, long, String)
*/
public static void lock(Node node, boolean isDeep, boolean isSessionScoped, long timeoutHint, String ownerInfo) {
try {
getLockManager(node.getSession()).lock(node.getPath(), isDeep, isSessionScoped, timeoutHint, ownerInfo);
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Could not perform lock", e);
}
}
/**
* Removes the lock on the given node.
*
* @param node the node unlock
* @see javax.jcr.lock.LockManager#unlock(String)
*/
public static void unlock(Node node) {
try {
getLockManager(node.getSession()).unlock(node.getPath());
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Could not perform unlock", e);
}
}
public static Version getBaseVersion(Node node) {
String nodeName = null;
if (!JcrUtil.isVersionable(node)) {
return null;
}
try {
nodeName = node.getName();
return JcrVersionUtil.getVersionManager(node.getSession()).getBaseVersion(node.getPath());
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to find Base Version for " + nodeName, e);
}
}
public static List<Version> getVersions(Node node) {
String nodeName = null;
if (!JcrUtil.isVersionable(node)) {
return null;
}
try {
nodeName = node.getName();
List<Version> versions = new ArrayList<>();
VersionHistory history = JcrVersionUtil.getVersionManager(node.getSession()).getVersionHistory(node.getPath());
VersionIterator itr = history.getAllVersions();
String id = history.getVersionableIdentifier();
while (itr.hasNext()) {
Version version = itr.nextVersion();
versions.add(version);
}
return versions;
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to find Version History for " + nodeName, e);
}
}
public static <T extends JcrObject> T getVersionedNode(Version version, Class<T> type, Object[] constructorArgs) {
String nodeName = null;
String versionName = null;
try {
versionName = version.getName();
Node node = version.getFrozenNode();
nodeName = node.getName();
String entityId = version.getContainingHistory().getVersionableIdentifier();
T obj = JcrUtil.constructNodeObject(node, type, constructorArgs);
obj.setVersionName(versionName);
obj.setVersionableIdentifier(entityId);
return obj;
} catch (RepositoryException e) {
throw new MetadataRepositoryException("Unable to find Version " + versionName + " for Node " + nodeName, e);
}
}
public static Version findVersion(Node node, final String versionName) {
if (!JcrUtil.isVersionable(node)) {
return null;
}
Version version = Iterables.tryFind(getVersions(node), new Predicate<Version>() {
@Override
public boolean apply(Version version) {
try {
String identifier = node.getIdentifier();
String frozenIdentifer = JcrPropertyUtil.getString(version.getFrozenNode(), "jcr:frozenUuid");
return version.getName().equalsIgnoreCase(versionName) && frozenIdentifer.equalsIgnoreCase(identifier);
} catch (RepositoryException e) {
}
return false;
}
}).orNull();
return version;
}
public static <T extends JcrObject> T getVersionedNode(Version version, Class<T> type) {
return getVersionedNode(version, type, null);
}
public static <T extends JcrObject> T getVersionedNode(JcrObject node, String versionNumber, Class<T> type) {
Version version = findVersion(node.getNode(), versionNumber);
if (version != null) {
return getVersionedNode(version, type);
}
throw new MetadataRepositoryException("Unable to find Version " + versionNumber + " for Node " + node.getNodeName());
}
}