/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.jackrabbit.core.version;
import org.apache.jackrabbit.core.ItemManager;
import org.apache.jackrabbit.core.AbstractNodeData;
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.id.NodeId;
import org.apache.jackrabbit.core.session.SessionContext;
import org.apache.jackrabbit.core.NodeImpl;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.InvalidItemStateException;
import javax.jcr.Item;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Node;
import javax.jcr.nodetype.ConstraintViolationException;
import java.util.Calendar;
import java.util.List;
/**
* Base implementation of the {@link javax.jcr.version.Version} interface.
*/
public class VersionImpl extends NodeImpl implements Version {
/**
* Logger instance.
*/
private static Logger log = LoggerFactory.getLogger(VersionImpl.class);
/**
* Create a new instance of this class.
* @param itemMgr item manager
* @param sessionContext component context of the associated session
* @param data node data
*/
public VersionImpl(
ItemManager itemMgr, SessionContext sessionContext,
AbstractNodeData data) {
super(itemMgr, sessionContext, data);
}
/**
* Returns the internal version. Subclass responsibility.
* @return internal version
* @throws RepositoryException if the internal version is not available
*/
protected InternalVersion getInternalVersion() throws RepositoryException {
SessionImpl session = sessionContext.getSessionImpl();
InternalVersion version =
session.getInternalVersionManager().getVersion((NodeId) id);
if (version == null) {
throw new InvalidItemStateException(id + ": the item does not exist anymore");
}
return version;
}
/**
* {@inheritDoc}
*/
public Calendar getCreated() throws RepositoryException {
return getInternalVersion().getCreated();
}
/**
* {@inheritDoc}
*/
public javax.jcr.version.Version[] getSuccessors() throws RepositoryException {
// need to wrap it around proper node
List<InternalVersion> suc = getInternalVersion().getSuccessors();
Version[] ret = new Version[suc.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = (Version) sessionContext.getSessionImpl().getNodeById(
suc.get(i).getId());
}
return ret;
}
/**
* {@inheritDoc}
*/
public javax.jcr.version.Version[] getPredecessors() throws RepositoryException {
// need to wrap it around proper node
InternalVersion[] pred = getInternalVersion().getPredecessors();
Version[] ret = new Version[pred.length];
for (int i = 0; i < pred.length; i++) {
ret[i] = (Version) sessionContext.getSessionImpl().getNodeById(pred[i].getId());
}
return ret;
}
/**
* {@inheritDoc}
*/
public Version getLinearSuccessor() throws RepositoryException {
// get base version. this can certainly be optimized
SessionImpl session = sessionContext.getSessionImpl();
InternalVersionHistory vh = ((VersionHistoryImpl) getContainingHistory())
.getInternalVersionHistory();
Node vn = session.getNodeById(vh.getVersionableId());
InternalVersion base = ((VersionImpl) vn.getBaseVersion()).getInternalVersion();
InternalVersion suc = getInternalVersion().getLinearSuccessor(base);
return suc == null ? null : (Version) session.getNodeById(suc.getId());
}
/**
* {@inheritDoc}
*/
public javax.jcr.version.Version getLinearPredecessor() throws RepositoryException {
InternalVersion pred = getInternalVersion().getLinearPredecessor();
return (Version) sessionContext.getSessionImpl().getNodeById(pred.getId());
}
/**
* {@inheritDoc}
*/
public javax.jcr.version.VersionHistory getContainingHistory() throws RepositoryException {
return (VersionHistory) getParent();
}
/**
* Returns the frozen node of this version
*
* @return the internal frozen node
* @throws javax.jcr.RepositoryException if an error occurs
*/
public InternalFrozenNode getInternalFrozenNode() throws RepositoryException {
return getInternalVersion().getFrozenNode();
}
/**
* {@inheritDoc}
*/
public Node getFrozenNode() throws RepositoryException {
return sessionContext.getSessionImpl().getNodeById(getInternalVersion().getFrozenNodeId());
}
/**
* {@inheritDoc}
*/
@Override
public boolean isSame(Item otherItem) {
if (otherItem instanceof VersionImpl) {
// since all versions live in the same workspace, we can compare the uuids
try {
InternalVersion other = ((VersionImpl) otherItem).getInternalVersion();
return other.getId().equals(getInternalVersion().getId());
} catch (RepositoryException e) {
log.warn("Unable to retrieve internal version objects: " + e.getMessage());
log.debug("Stack dump:", e);
}
}
return false;
}
/**
* Checks if this version is more recent than the given version <code>v</code>.
* A version is more recent if and only if it is a successor (or a successor
* of a successor, etc., to any degree of separation) of the compared one.
*
* @param v the version to check
* @return <code>true</code> if the version is more recent;
* <code>false</code> otherwise.
* @throws RepositoryException if a repository error occurs
*/
public boolean isMoreRecent(VersionImpl v) throws RepositoryException {
return getInternalVersion().isMoreRecent(v.getInternalVersion());
}
/**
* Checks if this is the root version.
* @return <code>true</code> if this version is the root version;
* <code>false</code> otherwise.
* @throws RepositoryException if a repository error occurs
*/
public boolean isRootVersion() throws RepositoryException {
return getInternalVersion().isRootVersion();
}
//--------------------------------------< Overwrite "protected" methods >---
/**
* Always throws a {@link javax.jcr.nodetype.ConstraintViolationException} since this node
* is protected.
*
* @throws javax.jcr.nodetype.ConstraintViolationException
*/
@Override
public void update(String srcWorkspaceName) throws ConstraintViolationException {
String msg = "update operation not allowed: " + this;
log.debug(msg);
throw new ConstraintViolationException(msg);
}
/**
* Always throws a {@link javax.jcr.nodetype.ConstraintViolationException} since this node
* is protected.
*
* @throws javax.jcr.nodetype.ConstraintViolationException
*/
@Override
public NodeIterator merge(String srcWorkspace, boolean bestEffort)
throws ConstraintViolationException {
String msg = "merge operation not allowed: " + this;
log.debug(msg);
throw new ConstraintViolationException(msg);
}
//--------------------------------------------------------------< Object >
/**
* Return a string representation of this version node for diagnostic
* purposes.
*
* @return "version node /path/to/item"
*/
public String toString() {
return "version " + super.toString();
}
}