/*
* (C) Copyright 2013-2017 Nuxeo (http://nuxeo.com/) and others.
*
* 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.
*
* Contributors:
* dmetzler
*/
package org.nuxeo.ecm.restapi.server.jaxrs;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentRef;
import org.nuxeo.ecm.core.api.NuxeoException;
import org.nuxeo.ecm.core.api.PathRef;
import org.nuxeo.ecm.core.api.VersioningOption;
import org.nuxeo.ecm.core.io.marshallers.json.document.DocumentModelJsonReader;
import org.nuxeo.ecm.core.rest.DocumentObject;
import org.nuxeo.ecm.core.versioning.VersioningService;
import org.nuxeo.ecm.restapi.jaxrs.io.RestConstants;
import org.nuxeo.ecm.webengine.WebException;
import org.nuxeo.ecm.webengine.model.WebObject;
/**
* This object basically overrides the default DocumentObject that doesn't know how to produce/consume JSON
*
* @since 5.7.2
*/
@WebObject(type = "Document")
@Produces({ "application/json+nxentity", "application/json+esentity", MediaType.APPLICATION_JSON })
public class JSONDocumentObject extends DocumentObject {
private static final String APPLICATION_JSON_NXENTITY = "application/json+nxentity";
protected static final Log log = LogFactory.getLog(JSONDocumentObject.class);
private boolean isVersioning;
@Override
@GET
public DocumentModel doGet() {
return doc;
}
/**
* @return the document or the last version document in case of versioning handled
*/
@PUT
@Consumes({ APPLICATION_JSON_NXENTITY, "application/json" })
public DocumentModel doPut(DocumentModel inputDoc, @Context HttpHeaders headers) {
DocumentModelJsonReader.applyPropertyValues(inputDoc, doc);
CoreSession session = ctx.getCoreSession();
versioningDocFromHeaderIfExists(headers);
doc = session.saveDocument(doc);
session.save();
return isVersioning ? session.getLastDocumentVersion(doc.getRef()) : doc;
}
@POST
@Consumes({ APPLICATION_JSON_NXENTITY, "application/json" })
public Response doPost(DocumentModel inputDoc) {
CoreSession session = ctx.getCoreSession();
if (StringUtils.isBlank(inputDoc.getType()) || StringUtils.isBlank(inputDoc.getName())) {
return Response.status(Status.BAD_REQUEST).entity("type or name property is missing").build();
}
DocumentModel createdDoc = session.createDocumentModel(doc.getPathAsString(), inputDoc.getName(),
inputDoc.getType());
DocumentModelJsonReader.applyPropertyValues(inputDoc, createdDoc);
createdDoc = session.createDocument(createdDoc);
session.save();
return Response.ok(createdDoc).status(Status.CREATED).build();
}
@DELETE
public Response doDelete() {
super.doDelete();
return Response.noContent().build();
}
@Override
@Path("@search")
public Object search() {
return ctx.newAdapter(this, "search");
}
@Override
public DocumentObject newDocument(String path) {
try {
PathRef pathRef = new PathRef(doc.getPath().append(path).toString());
DocumentModel doc = ctx.getCoreSession().getDocument(pathRef);
return (DocumentObject) ctx.newObject("Document", doc);
} catch (NuxeoException e) {
throw WebException.wrap(e);
}
}
@Override
public DocumentObject newDocument(DocumentRef ref) {
try {
DocumentModel doc = ctx.getCoreSession().getDocument(ref);
return (DocumentObject) ctx.newObject("Document", doc);
} catch (NuxeoException e) {
throw WebException.wrap(e);
}
}
@Override
public DocumentObject newDocument(DocumentModel doc) {
return (DocumentObject) ctx.newObject("Document", doc);
}
/**
* In case of version option header presence, checkin the related document
*
* @param headers X-Versioning-Option or Source (for automatic versioning) Header
*/
private void versioningDocFromHeaderIfExists(HttpHeaders headers) {
isVersioning = false;
List<String> versionHeader = headers.getRequestHeader(RestConstants.X_VERSIONING_OPTION);
List<String> sourceHeader = headers.getRequestHeader(RestConstants.SOURCE);
if (versionHeader != null && !versionHeader.isEmpty()) {
VersioningOption versioningOption = VersioningOption.valueOf(versionHeader.get(0).toUpperCase());
if (versioningOption != null && !versioningOption.equals(VersioningOption.NONE)) {
doc.putContextData(VersioningService.VERSIONING_OPTION, versioningOption);
isVersioning = true;
}
} else if (sourceHeader != null && !sourceHeader.isEmpty()) {
doc.putContextData(CoreSession.SOURCE, sourceHeader.get(0));
isVersioning = true;
}
}
}