/**
* Copyright (C) 2012 KRM Associates, Inc. healtheme@krminc.com
*
* 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.
*/
package com.krminc.phr.api.service;
import com.krminc.phr.api.converter.UserConverter;
import com.krminc.phr.api.converter.UsersConverter;
import com.krminc.phr.api.service.util.ServiceUtils;
import com.krminc.phr.core.UserConfig;
import com.krminc.phr.dao.PersistenceService;
import com.krminc.phr.domain.User;
import com.sun.jersey.api.core.ResourceContext;
import java.util.Collection;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.POST;
import javax.ws.rs.Consumes;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Users API RESTful resource class and mapping.
*
* @author Daniel Shaw (dshaw.com)
*/
public class UsersResource {
final Logger logger = LoggerFactory.getLogger(UsersResource.class);
@Context
protected UriInfo uriInfo;
@Context
protected ResourceContext resourceContext;
public UsersResource() {
}
/**
* Get method for retrieving a collection of User instance in XML format.
*
* @return an instance of UsersConverter
*/
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public UsersConverter get(
@QueryParam("start") @DefaultValue("0") int start,
@QueryParam("max") @DefaultValue("10") int max,
@QueryParam("orderBy") @DefaultValue("name") String orderBy,
@QueryParam("desc") @DefaultValue("0") int desc,
@QueryParam("u") @DefaultValue("") String username,
@QueryParam("e") @DefaultValue("") String name,
@QueryParam("r") @DefaultValue("a") String roles,
@QueryParam("area") @DefaultValue("") String area
) {
PersistenceService persistenceSvc = PersistenceService.getInstance();
try {
persistenceSvc.beginTx();
return new UsersConverter(
getEntities(start, max, orderBy, desc, username, name, roles, area),
uriInfo.getAbsolutePath(),
Api.DEFAULT_EXPAND_LEVEL);
} finally {
persistenceSvc.close();
}
}
/**
* Post method for creating an instance of User using XML as the input format.
*
* @param data an UserConverter entity that is deserialized from an XML stream
* @return an instance of UserConverter
*/
@POST
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response post(UserConverter data) {
PersistenceService persistenceSvc = PersistenceService.getInstance();
try {
persistenceSvc.beginTx();
EntityManager em = persistenceSvc.getEntityManager();
User entity = data.resolveEntity(em);
createEntity(data.resolveEntity(em));
persistenceSvc.commitTx();
return Response.created(uriInfo.getAbsolutePath().resolve(entity.getUserId() + "/")).build();
} finally {
persistenceSvc.close();
}
}
/**
* Returns a dynamic instance of UserResource used for entity navigation.
*
* @return an instance of UserResource
*/
@Path("{userId}/")
public UserResource getUserResource(@PathParam("userId") Long id) {
UserResource resource = resourceContext.getResource(UserResource.class);
resource.setId(id);
return resource;
}
/**
* Returns a dynamic instance of UserResource used for entity navigation.
*
* @return an instance of UserResource
*/
@Path("/username/{username}/")
public UserResource getUserResourceByUsername(@PathParam("username") String username) {
UserResource resource = resourceContext.getResource(UserResource.class);
resource.setUsername(username);
return resource;
}
private String comma(int stringLength) {
return stringLength == 0 ? "" : ",";
}
private String connector(int filterLength) {
return filterLength == 0 ? " WHERE" : " AND";
}
@Path("count/")
@GET
@Produces({ MediaType.APPLICATION_JSON })
public JSONObject getCount(
@QueryParam("u") @DefaultValue("") String username,
@QueryParam("e") @DefaultValue("") String name,
@QueryParam("r") @DefaultValue("a") String roles,
@QueryParam("area") @DefaultValue("") String area
) {
StringBuilder query = new StringBuilder("SELECT COUNT(DISTINCT u.user_id) FROM user_users u JOIN user_roles r ON u.username = r.username");
StringBuilder filter = new StringBuilder();
Long result = 0L;
Boolean hasFilterClause = false;
if (!roles.isEmpty() && !roles.equalsIgnoreCase("a")){
StringBuilder queryRoles = new StringBuilder();
for (String role : roles.split(",")) {
// user manager (AKA system manager)
if (role.equalsIgnoreCase("um") || role.equalsIgnoreCase("u")) {
queryRoles.append( comma(queryRoles.length())+"'"+UserConfig.ROLE_PATIENTADMIN+"'" );
// admin
} else if (role.equalsIgnoreCase("ad")) {
queryRoles.append( comma(queryRoles.length())+"'"+UserConfig.ROLE_ADMIN+"'" );
//patient
} else if (role.equalsIgnoreCase("p")) {
queryRoles.append( comma(queryRoles.length())+"'"+UserConfig.ROLE_PATIENT+"'" );
//care coordinator aka care taker
} else if (role.equalsIgnoreCase("cc")) {
queryRoles.append( comma(queryRoles.length())+"'"+UserConfig.ROLE_CARETAKER+"'" );
}
}
if (queryRoles.length() != 0) {
filter.append( connector(filter.length())+" r.role IN ("+queryRoles+")" );
}
}
if ( !area.equals("admin") ) {
//do not show admin users outside of admin area
filter.append( connector(filter.length())+" r.role <> '" +UserConfig.ROLE_ADMIN+"'" );
//do not show caretaker users outside of admin area
filter.append( connector(filter.length())+" r.role <> '" +UserConfig.ROLE_CARETAKER+"'" );
}
logger.debug("filter {} {}", filter, filter.length());
if (filter.length() != 0) {
query.append(filter);
hasFilterClause = true;
}
if (!username.isEmpty()){
if (ServiceUtils.hasValidCharacters(username)) {
if (!hasFilterClause){
query.append(" WHERE");
hasFilterClause = true;
} else {
query.append(" AND");
}
username = "%" + username + "%";
query.append(" u.username LIKE '" +username+"'");
//hasUsernameFilter = true;
} else {
throw new WebApplicationException(Response.Status.PRECONDITION_FAILED);
}
}
if (!name.isEmpty()){
if (ServiceUtils.hasValidCharacters(name)) {
if (!hasFilterClause){
query.append(" WHERE");
hasFilterClause = true;
} else {
query.append(" AND");
}
name = "%" + name + "%";
query.append(" (u.first_name LIKE '" +name+"'");
query.append(" OR");
query.append(" u.last_name LIKE '" +name+"')");
//hasNameFilter = true;
} else {
throw new WebApplicationException(Response.Status.PRECONDITION_FAILED);
}
}
PersistenceService persistenceSvc = PersistenceService.getInstance();
try {
persistenceSvc.beginTx();
EntityManager em = persistenceSvc.getEntityManager();
List resultD = (List)em.createNativeQuery(query.toString()).getSingleResult();
result = (Long)resultD.get(0);
} finally {
persistenceSvc.close();
}
JSONObject jsonResult = new JSONObject();
try {
jsonResult.put("count", result);
}
catch (JSONException ex) {
throw new WebApplicationException(Response.Status.PRECONDITION_FAILED);
}
return jsonResult;
}
/**
* Returns all the entities associated with this resource.
*
* @return a collection of User instances
*/
protected Collection<User> getEntities(
int start, int max, String orderBy, int desc,
String username, String name, String roles, String area) {
StringBuilder query = new StringBuilder("SELECT DISTINCT u.* FROM user_users u JOIN user_roles r ON u.username = r.username");
StringBuilder filter = new StringBuilder();
// orderBy :
// username
// name
// desc:
// 0 -- ascending (default)
// >0 -- descending
if(start<0) start=0;
Boolean hasMax = true;
if( max < 1 ){
hasMax = false;
start = 0;
}
Boolean hasFilterClause = false;
//Boolean hasUsernameFilter = false;
//Boolean hasNameFilter = false;
if (!roles.isEmpty() && !roles.equalsIgnoreCase("a")){
StringBuilder queryRoles = new StringBuilder();
for (String role : roles.split(",")) {
// user manager (AKA system manager)
if (role.equalsIgnoreCase("um") || role.equalsIgnoreCase("u")) {
queryRoles.append( comma(queryRoles.length())+"'"+UserConfig.ROLE_PATIENTADMIN+"'" );
// admin
} else if (role.equalsIgnoreCase("ad")) {
queryRoles.append( comma(queryRoles.length())+"'"+UserConfig.ROLE_ADMIN+"'" );
//patient
} else if (role.equalsIgnoreCase("p")) {
queryRoles.append( comma(queryRoles.length())+"'"+UserConfig.ROLE_PATIENT+"'" );
//care coordinator aka care taker
} else if (role.equalsIgnoreCase("cc")) {
queryRoles.append( comma(queryRoles.length())+"'"+UserConfig.ROLE_CARETAKER+"'" );
}
}
if (queryRoles.length() != 0) {
filter.append( connector(filter.length())+" r.role IN ("+queryRoles+")" );
}
}
if ( !area.equals("admin") ) {
//do not show admin users outside of admin area
filter.append( connector(filter.length())+" r.role <> '" +UserConfig.ROLE_ADMIN+"'" );
//do not show caretaker users outside of admin area
filter.append( connector(filter.length())+" r.role <> '" +UserConfig.ROLE_CARETAKER+"'" );
}
logger.debug("filter {} {}", filter, filter.length());
if (filter.length() != 0) {
query.append(filter);
hasFilterClause = true;
}
if (!username.isEmpty()){
if (ServiceUtils.hasValidCharacters(username)) {
if (!hasFilterClause){
query.append(" WHERE");
hasFilterClause = true;
} else {
query.append(" AND");
}
username = "%" + username + "%";
query.append(" u.username LIKE '" +username+"'");
//hasUsernameFilter = true;
} else {
throw new WebApplicationException(Response.Status.PRECONDITION_FAILED);
}
}
if (!name.isEmpty()){
if (ServiceUtils.hasValidCharacters(name)) {
if (!hasFilterClause){
query.append(" WHERE");
hasFilterClause = true;
} else {
query.append(" AND");
}
name = "%" + name + "%";
query.append(" (u.first_name LIKE '" +name+"'");
query.append(" OR");
query.append(" u.last_name LIKE '" +name+"')");
//hasNameFilter = true;
} else {
throw new WebApplicationException(Response.Status.PRECONDITION_FAILED);
}
}
Boolean wasOrdered = false;
if(orderBy.equalsIgnoreCase("username")){
query.append(" ORDER BY u.username");
wasOrdered = true;
} else if(orderBy.equalsIgnoreCase("name")){
query.append(" ORDER BY u.last_name, u.first_name, u.middle_name");
wasOrdered = true;
}
if (wasOrdered) {
if (desc>0) {
query.append(" DESC");
} else {
query.append(" ASC");
}
}
EntityManager em = PersistenceService.getInstance().getEntityManager();
//logger.error("QUERY: {}", query.toString());
Query filterQuery = em.createNativeQuery(query.toString(), User.class);
//filterQuery.setParameter("role", new UserRole(role));
//filterQuery.setParameter("role",role);
if (hasMax) filterQuery.setMaxResults(max);
//if (hasUsernameFilter) filterQuery.setParameter("username", username);
//if (hasNameFilter) filterQuery.setParameter("name", name.toUpperCase());
List<User> users = (List<User>)filterQuery.setFirstResult(start).getResultList();
//logger.debug("OUTPUT: {}", users);
return users;
// logger.debug("User count: {}", users.size());
// for (User user : users) {
// if (user.isAdmin()) {
// logger.debug("Admin user needs to be removed: {}", user);
// users.remove(user);
// }
// }
// logger.debug("User count: {}", users.size());
// return users;
}
/**
* Persist the given entity.
*
* @param entity the entity to persist
*/
protected void createEntity(User entity) {
entity.setUserId(null);
EntityManager em = PersistenceService.getInstance().getEntityManager();
em.persist(entity);
}
}