/*
* The contents of this file are subject to the OpenMRS Public 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://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* Copyright (C) OpenMRS, LLC. All Rights Reserved.
*/
package org.openmrs.module.webservices.rest.resource;
import java.lang.reflect.ParameterizedType;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.OpenmrsObject;
import org.openmrs.api.context.Context;
import org.openmrs.module.openhmis.commons.api.PagingInfo;
import org.openmrs.module.openhmis.commons.api.entity.IObjectDataService;
import org.openmrs.module.openhmis.commons.api.exception.PrivilegeException;
import org.openmrs.module.webservices.rest.web.RequestContext;
import org.openmrs.module.webservices.rest.web.representation.DefaultRepresentation;
import org.openmrs.module.webservices.rest.web.representation.Representation;
import org.openmrs.module.webservices.rest.web.resource.api.PageableResult;
import org.openmrs.module.webservices.rest.web.resource.impl.DelegatingCrudResource;
import org.openmrs.module.webservices.rest.web.resource.impl.DelegatingResourceDescription;
/**
* REST resource for {@link org.openmrs.OpenmrsObject} entities.
* @param <E> The model class
*/
public abstract class BaseRestObjectResource<E extends OpenmrsObject> extends DelegatingCrudResource<E>
implements IObjectDataServiceResource<E, IObjectDataService<E>> {
private static final Log LOG = LogFactory.getLog(BaseRestObjectResource.class);
private Class<E> entityClass = null;
@Override
public abstract E newDelegate();
@Override
public abstract Class<? extends IObjectDataService<E>> getServiceClass();
@Override
public DelegatingResourceDescription getRepresentationDescription(Representation rep) {
DelegatingResourceDescription description = new DelegatingResourceDescription();
description.addProperty("uuid");
return description;
}
@Override
public DelegatingResourceDescription getCreatableProperties() {
DelegatingResourceDescription description = getRepresentationDescription(new DefaultRepresentation());
description.removeProperty("uuid");
return description;
}
@Override
public E save(E delegate) {
Class<? extends IObjectDataService<E>> clazz = getServiceClass();
if (clazz == null) {
throw new IllegalStateException("This resource has not be defined to allow saving. "
+ "To save, implement the resource getServiceClass method.");
}
IObjectDataService<E> service = Context.getService(clazz);
service.save(delegate);
return delegate;
}
@Override
public E getByUniqueId(String uniqueId) {
Class<? extends IObjectDataService<E>> clazz = getServiceClass();
if (clazz == null) {
throw new IllegalStateException("This resource has not be defined to allow searching. "
+ "To search, implement the resource getServiceClass method.");
}
E result = null;
// Ensure that a service is found for this resource. This is a fix for changes to the RESTWS module as of v2.12.
IObjectDataService<E> service = getService();
if (service != null) {
try {
result = service.getByUuid(uniqueId);
} catch (PrivilegeException p) {
LOG.error("Exception occured when trying to get entity with ID <" + uniqueId
+ "> as privilege is missing", p);
throw new PrivilegeException("Can't get entity with ID <" + uniqueId + "> as privilege is missing");
}
}
return result;
}
@Override
public void delete(E delegate, String reason, RequestContext context) {
purge(delegate, context);
}
@Override
public void purge(E delegate, RequestContext context) {
Class<? extends IObjectDataService<E>> clazz = getServiceClass();
if (clazz == null) {
throw new IllegalStateException("This resource has not be defined to allow purging. "
+ "To purge, implement the resource getServiceClass method.");
}
IObjectDataService<E> service = Context.getService(clazz);
service.purge(delegate);
}
@Override
protected PageableResult doGetAll(RequestContext context) {
Class<? extends IObjectDataService<E>> clazz = getServiceClass();
if (clazz == null) {
throw new IllegalStateException("This resource has not be defined to allow searching. "
+ "To search, implement the resource getServiceClass method.");
}
IObjectDataService<E> service = Context.getService(clazz);
PagingInfo pagingInfo = PagingUtil.getPagingInfoFromContext(context);
return new AlreadyPagedWithLength<E>(context, service.getAll(pagingInfo), pagingInfo.hasMoreResults(),
pagingInfo.getTotalRecordCount());
}
protected IObjectDataService<E> getService() {
// Ensure that the service class is not null. This is a fix for changes to the RESTWS module as of v2.12.
Class<? extends IObjectDataService<E>> cls = getServiceClass();
if (cls == null) {
return null;
} else {
return Context.getService(cls);
}
}
/**
* Gets a usable instance of the actual class of the generic type E defined by the implementing sub-class.
* @return The class object for the entity.
*/
@SuppressWarnings("unchecked")
public Class<E> getEntityClass() {
if (entityClass == null) {
ParameterizedType parameterizedType = (ParameterizedType)getClass().getGenericSuperclass();
entityClass = (Class)parameterizedType.getActualTypeArguments()[0];
}
return entityClass;
}
}