/*
* 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.session;
import javax.jcr.AccessDeniedException;
import javax.jcr.ItemExistsException;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.ConstraintViolationException;
import org.apache.jackrabbit.core.ItemManager;
import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.id.NodeId;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.commons.conversion.NameException;
import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
/**
* Session operation for adding a new node.
*/
public class AddNodeOperation implements SessionWriteOperation<Node> {
private final NodeImpl node;
private final String relPath;
private final String nodeTypeName;
private final String uuid;
public AddNodeOperation(
NodeImpl node, String relPath,
String nodeTypeName, String uuid) {
this.node = node;
this.relPath = relPath;
this.nodeTypeName = nodeTypeName;
this.uuid = uuid;
}
public Node perform(SessionContext context) throws RepositoryException {
ItemManager itemMgr = context.getItemManager();
// Get the canonical path of the new node
Path path;
try {
path = PathFactoryImpl.getInstance().create(
node.getPrimaryPath(), context.getQPath(relPath), true);
} catch (NameException e) {
throw new RepositoryException(
"Failed to resolve path " + relPath
+ " relative to " + node, e);
}
// Check that the last path element is a simple name
if (!path.denotesName() || path.getIndex() != Path.INDEX_UNDEFINED) {
throw new RepositoryException(
"Invalid last path element for adding node "
+ relPath + " relative to " + node);
}
// Get the parent node instance
NodeImpl parentNode;
Path parentPath = path.getAncestor(1);
try {
parentNode = itemMgr.getNode(parentPath);
} catch (PathNotFoundException e) {
if (itemMgr.propertyExists(parentPath)) {
throw new ConstraintViolationException(
"Unable to add a child node to property "
+ context.getJCRPath(parentPath));
}
throw e;
} catch (AccessDeniedException ade) {
throw new PathNotFoundException(
"Failed to resolve path " + relPath
+ " relative to " + node);
}
// Resolve node type name (if any)
Name typeName = null;
if (nodeTypeName != null) {
typeName = context.getQName(nodeTypeName);
}
// Check that the given UUID (if any) does not already exist
NodeId id = null;
if (uuid != null) {
id = new NodeId(uuid);
if (itemMgr.itemExists(id)) {
throw new ItemExistsException(
"A node with this UUID already exists: " + uuid);
}
}
return parentNode.addNode(path.getName(), typeName, id);
}
//--------------------------------------------------------------< Object >
/**
* Returns a string representation of this operation.
*/
public String toString() {
return "node.addNode(" + relPath + ", " + nodeTypeName + ", " + uuid + ")";
}
}