/*
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.jcr.webdav.command;
import org.exoplatform.common.http.HTTPStatus;
import org.exoplatform.common.util.HierarchicalProperty;
import org.exoplatform.services.jcr.webdav.command.order.OrderMember;
import org.exoplatform.services.jcr.webdav.command.order.OrderPatchResponseEntity;
import org.exoplatform.services.jcr.webdav.util.TextUtil;
import org.exoplatform.services.jcr.webdav.xml.WebDavNamespaceContext;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import javax.jcr.AccessDeniedException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
import javax.ws.rs.core.Response;
import javax.xml.namespace.QName;
/**
* Created by The eXo Platform SAS.
* @author Vitaly Guly - gavrikvetal@gmail.com
*
* @version $Id: $
*/
public class OrderPatchCommand
{
/**
* logger.
*/
private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.webdav.OrderPatchCommand");
/**
* Constructor.
*/
public OrderPatchCommand()
{
}
/**
* Webdav OrderPatch method implementation.
*
* @param session current session
* @param path resource path
* @param body responce body
* @param baseURI base uri
* @return the instance of javax.ws.rs.core.Response
*/
public Response orderPatch(Session session, String path, HierarchicalProperty body, String baseURI)
{
try
{
Node node = (Node)session.getItem(path);
List<OrderMember> members = getMembers(body);
WebDavNamespaceContext nsContext = new WebDavNamespaceContext(session);
URI uri = new URI(TextUtil.escape(baseURI + node.getPath(), '%', true));
if (doOrder(node, members))
{
return Response.ok().build();
}
OrderPatchResponseEntity orderPatchEntity = new OrderPatchResponseEntity(nsContext, uri, node, members);
return Response.status(HTTPStatus.MULTISTATUS).entity(orderPatchEntity).build();
}
catch (PathNotFoundException exc)
{
return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
}
catch (LockException exc)
{
return Response.status(HTTPStatus.LOCKED).entity(exc.getMessage()).build();
}
catch (Exception exc)
{
LOG.error(exc.getMessage(), exc);
return Response.serverError().entity(exc.getMessage()).build();
}
}
/**
* Get oder members.
*
* @param body request body.
* @return list of members
*/
protected List<OrderMember> getMembers(HierarchicalProperty body)
{
ArrayList<OrderMember> members = new ArrayList<OrderMember>();
List<HierarchicalProperty> childs = body.getChildren();
for (int i = 0; i < childs.size(); i++)
{
OrderMember member = new OrderMember(childs.get(i));
members.add(member);
}
return members;
}
/**
* Order members.
*
* @param parentNode parent node
* @param members members
* @return true if can order
*/
protected boolean doOrder(Node parentNode, List<OrderMember> members)
{
boolean success = true;
for (int i = 0; i < members.size(); i++)
{
OrderMember member = members.get(i);
int status = HTTPStatus.OK;
try
{
parentNode.getSession().refresh(false);
String positionedNodeName = null;
if (!parentNode.hasNode(member.getSegment()))
{
throw new PathNotFoundException();
}
if (!new QName("DAV:", "last").equals(member.getPosition()))
{
NodeIterator nodeIter = parentNode.getNodes();
boolean finded = false;
while (nodeIter.hasNext())
{
Node curNode = nodeIter.nextNode();
if (new QName("DAV:", "first").equals(member.getPosition()))
{
positionedNodeName = curNode.getName();
finded = true;
break;
}
if (new QName("DAV:", "before").equals(member.getPosition())
&& curNode.getName().equals(member.getPositionSegment()))
{
positionedNodeName = curNode.getName();
finded = true;
break;
}
if (new QName("DAV:", "after").equals(member.getPosition())
&& curNode.getName().equals(member.getPositionSegment()))
{
if (nodeIter.hasNext())
{
positionedNodeName = nodeIter.nextNode().getName();
}
finded = true;
break;
}
}
if (!finded)
{
throw new AccessDeniedException();
}
}
parentNode.getSession().refresh(false);
parentNode.orderBefore(member.getSegment(), positionedNodeName);
parentNode.getSession().save();
}
catch (LockException exc)
{
status = HTTPStatus.LOCKED;
}
catch (PathNotFoundException exc)
{
status = HTTPStatus.FORBIDDEN;
}
catch (AccessDeniedException exc)
{
status = HTTPStatus.FORBIDDEN;
}
catch (RepositoryException exc)
{
LOG.error(exc.getMessage(), exc);
status = HTTPStatus.INTERNAL_ERROR;
}
member.setStatus(status);
if (status != HTTPStatus.OK)
{
success = false;
}
}
return success;
}
}