/** * This Source Code Form is subject to the terms of the Mozilla Public License, * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. * * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS * graphic logo is a trademark of OpenMRS Inc. */ package org.openmrs.module.webservices.rest.web.v1_0.controller; import org.openmrs.module.webservices.rest.SimpleObject; import org.openmrs.module.webservices.rest.web.RequestContext; import org.openmrs.module.webservices.rest.web.RestConstants; import org.openmrs.module.webservices.rest.web.RestUtil; import org.openmrs.module.webservices.rest.web.api.RestService; import org.openmrs.module.webservices.rest.web.representation.Representation; import org.openmrs.module.webservices.rest.web.resource.api.Converter; import org.openmrs.module.webservices.rest.web.resource.api.Creatable; import org.openmrs.module.webservices.rest.web.resource.api.CrudResource; import org.openmrs.module.webservices.rest.web.resource.api.Deletable; import org.openmrs.module.webservices.rest.web.resource.api.Listable; import org.openmrs.module.webservices.rest.web.resource.api.Purgeable; import org.openmrs.module.webservices.rest.web.resource.api.Resource; import org.openmrs.module.webservices.rest.web.resource.api.Retrievable; import org.openmrs.module.webservices.rest.web.resource.api.SearchHandler; import org.openmrs.module.webservices.rest.web.resource.api.Searchable; import org.openmrs.module.webservices.rest.web.resource.api.Updatable; import org.openmrs.module.webservices.rest.web.resource.api.Uploadable; import org.openmrs.module.webservices.rest.web.response.ResourceDoesNotSupportOperationException; import org.openmrs.module.webservices.rest.web.response.ResponseException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Enumeration; /** * Base controller that handles exceptions (via {@link BaseRestController}) and also standard CRUD * operations based on a {@link CrudResource}. */ @Controller @RequestMapping(value = "/rest/" + RestConstants.VERSION_1) public class MainResourceController extends BaseRestController { @Autowired RestService restService; @Autowired BaseUriSetup baseUriSetup; /** * @param uuid * @param request * @return * @throws ResponseException */ @RequestMapping(value = "/{resource}/{uuid}", method = RequestMethod.GET) @ResponseBody public Object retrieve(@PathVariable("resource") String resource, @PathVariable("uuid") String uuid, HttpServletRequest request, HttpServletResponse response) throws ResponseException { baseUriSetup.setup(request); RequestContext context = RestUtil.getRequestContext(request, response); Retrievable res = (Retrievable) restService.getResourceByName(buildResourceName(resource)); return res.retrieve(uuid, context); } /** * @param post * @param request * @param response * @return * @throws Exception */ @RequestMapping(value = "/{resource}", method = RequestMethod.POST) @ResponseBody public Object create(@PathVariable("resource") String resource, @RequestBody SimpleObject post, HttpServletRequest request, HttpServletResponse response) throws ResponseException { baseUriSetup.setup(request); RequestContext context = RestUtil.getRequestContext(request, response); Creatable res = (Creatable) restService.getResourceByName(buildResourceName(resource)); Object created = res.create(post, context); return RestUtil.created(response, created); } @RequestMapping(value = "/{resource}", method = RequestMethod.POST, headers = "Content-Type=multipart/form-data") @ResponseBody public Object upload(@PathVariable("resource") String resource, @RequestParam("file") MultipartFile file, HttpServletRequest request, HttpServletResponse response) throws IOException, ResponseException { baseUriSetup.setup(request); RequestContext context = RestUtil.getRequestContext(request, response); Resource res = restService.getResourceByName(buildResourceName(resource)); if (res instanceof Uploadable) { Object updated = ((Uploadable) res).upload(file, context); return RestUtil.created(response, updated); } else { throw new ResourceDoesNotSupportOperationException(res.getClass().getSimpleName() + "is not uploadable"); } } /** * @param uuid * @param post * @param request * @param response * @return * @throws Exception */ @RequestMapping(value = "/{resource}/{uuid}", method = RequestMethod.POST) @ResponseBody public Object update(@PathVariable("resource") String resource, @PathVariable("uuid") String uuid, @RequestBody SimpleObject post, HttpServletRequest request, HttpServletResponse response) throws ResponseException { baseUriSetup.setup(request); RequestContext context = RestUtil.getRequestContext(request, response); Updatable res = (Updatable) restService.getResourceByName(buildResourceName(resource)); Object updated = res.update(uuid, post, context); return RestUtil.updated(response, updated); } /** * @param uuid * @param reason * @param request * @throws Exception */ @RequestMapping(value = "/{resource}/{uuid}", method = RequestMethod.DELETE, params = "!purge") @ResponseBody public Object delete(@PathVariable("resource") String resource, @PathVariable("uuid") String uuid, @RequestParam(value = "reason", defaultValue = "web service call") String reason, HttpServletRequest request, HttpServletResponse response) throws ResponseException { baseUriSetup.setup(request); RequestContext context = RestUtil.getRequestContext(request, response); Deletable res = (Deletable) restService.getResourceByName(buildResourceName(resource)); res.delete(uuid, reason, context); return RestUtil.noContent(response); } /** * @param uuid * @param request * @param response * @throws Exception */ @RequestMapping(value = "/{resource}/{uuid}", method = RequestMethod.DELETE, params = "purge") @ResponseBody public Object purge(@PathVariable("resource") String resource, @PathVariable("uuid") String uuid, HttpServletRequest request, HttpServletResponse response) throws ResponseException { baseUriSetup.setup(request); RequestContext context = RestUtil.getRequestContext(request, response); Purgeable res = (Purgeable) restService.getResourceByName(buildResourceName(resource)); res.purge(uuid, context); return RestUtil.noContent(response); } /** * @param request * @param response * @return * @throws ResponseException */ @SuppressWarnings("rawtypes") @RequestMapping(value = "/{resource}", method = RequestMethod.GET) @ResponseBody public SimpleObject get(@PathVariable("resource") String resource, HttpServletRequest request, HttpServletResponse response) throws ResponseException { baseUriSetup.setup(request); Object res = restService.getResourceByName(buildResourceName(resource)); Converter conv = res instanceof Converter ? (Converter) res : null; RequestContext context = RestUtil.getRequestContext(request, response, Representation.REF); @SuppressWarnings("unchecked") SearchHandler searchHandler = restService.getSearchHandler(buildResourceName(resource), request.getParameterMap()); if (searchHandler != null) { return searchHandler.search(context).toSimpleObject(conv); } Enumeration parameters = request.getParameterNames(); while (parameters.hasMoreElements()) { if (!RestConstants.SPECIAL_REQUEST_PARAMETERS.contains(parameters.nextElement())) { if (res instanceof Searchable) { return ((Searchable) res).search(context); } else { throw new ResourceDoesNotSupportOperationException(res.getClass().getSimpleName() + " is not searchable"); } } } if (res instanceof Listable) { return ((Listable) res).getAll(context); } else { throw new ResourceDoesNotSupportOperationException(res.getClass().getSimpleName() + " is not listable"); } } }