/*
* FinTP - Financial Transactions Processing Application
* Copyright (C) 2013 Business Information Systems (Allevo) S.R.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* or contact Allevo at : 031281 Bucuresti, 23C Calea Vitan, Romania,
* phone +40212554577, office@allevo.ro <mailto:office@allevo.ro>, www.allevo.ro.
*/
package ro.allevo.fintpws.resources;
import java.math.BigDecimal;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.Query;
import javax.persistence.RollbackException;
import javax.persistence.TypedQuery;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Response.Status;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
//import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.security.access.AccessDeniedException;
import ro.allevo.fintpws.exceptions.ApplicationJsonException;
//import ro.allevo.fintpws.model.QMovePrivMapEntity;
import ro.allevo.fintpws.model.QueueEntity;
import ro.allevo.fintpws.model.QueueTypeEntity;
import ro.allevo.fintpws.model.ServiceMapEntity;
import ro.allevo.fintpws.security.RolesUtils;
import ro.allevo.fintpws.util.JsonResponseWrapper;
import ro.allevo.fintpws.util.ResourcesUtils;
/**
* Resource class implementing /queues/{name} path methods.
*
* @author horia
* @version $Revision: 1.0 $
*/
public class QueueResource {
/**
* Field logger.
*/
private static Logger logger = LogManager.getLogger(QueueResource.class
.getName());
/**
* Field ERROR_MESSAGE_GET_QUEUE. (value is ""Error returning queue : "")
*/
static final String ERROR_MESSAGE_GET_QUEUE = "Error returning queue : ";
/**
* Field ERROR_MESSAGE_PUT_QUEUE. (value is ""Error updating queue : "")
*/
static final String ERROR_MESSAGE_PUT_QUEUE = "Error updating queue : ";
/**
* Field ERROR_MESSAGE_DELETE_QUEUE. (value is ""Error deleting queue : "")
*/
static final String ERROR_MESSAGE_DELETE_QUEUE = "Error deleting queue : ";
/**
* Field ERROR_MESSAGE_Q_NOT_FOUND. (value is ""Queue with name [%s] not
* found"")
*/
static final String ERROR_MESSAGE_Q_NOT_FOUND = "Queue with name [%s] not found";
/**
* Field ERROR_REASON_JSON. (value is ""json"")
*/
static final String ERROR_REASON_JSON = "json";
/**
* Field ERROR_REASON_NUMBER_FORMAT. (value is ""number format"")
*/
static final String ERROR_REASON_NUMBER_FORMAT = "number format";
/**
* Field ERROR_REASON_CONFLICT. (value is ""conflict"")
*/
static final String ERROR_REASON_CONFLICT = "conflict";
/**
* Field ERROR_REASON_ROLLBACK. (value is ""rollback"")
*/
static final String ERROR_REASON_ROLLBACK = "rollback";
// actual uri info provided by parent resource
/**
* Field uriInfo.
*/
private UriInfo uriInfo;
/**
* Field entityManagerConfig.
*/
private EntityManager entityManagerConfig;
/**
* Field entityManagerData.
*/
private EntityManager entityManagerData;
/**
* the JPA entity
*/
private QueueEntity queueEntity;
/**
* queue name
*/
private String queueName;
/**
* Creates a new instance of QueueResource
*
* @param uriInfo
* UriInfo actual uri passed by parent resource
*
* @param queueName
* String Queue name
* @param entityManagerConfig
* EntityManager
* @param entityManagerData
* EntityManager
*/
public QueueResource(UriInfo uriInfo, EntityManager entityManagerConfig,
EntityManager entityManagerData, String queueName) {
this.uriInfo = uriInfo;
this.entityManagerConfig = entityManagerConfig;
this.entityManagerData = entityManagerData;
this.queueName = queueName;
this.queueEntity = null;
queueEntity = QueueResource.findByName(entityManagerConfig, queueName);
}
/**
* Method findByName. Looks for a QueueEntity based on it's name.
*
* @param entityManager
* EntityManager
* @param name
* String
* @return QueueEntity
*/
public static QueueEntity findByName(EntityManager entityManager,
String name) {
// entityManager.find is much faster than a query, but name is char (
// not varchar ) and can't be used as ID
// queueEntity = entityManager.find(QueueEntity.class, queueName);
// TODO : change datatype to varchar and mark name as @ID in the entity
// Also, not using getSingleResult because unchecked exception
// NoResultException can actually be recovered from
TypedQuery<QueueEntity> query = entityManager.createNamedQuery(
"QueueEntity.findByName", QueueEntity.class);
List<QueueEntity> results = query.setParameter("name", name)
.getResultList();
if (!results.isEmpty()) {
return results.get(0);
}
return null;
}
/**
* GET method : returns an application/json formatted queue
*
* @return JSONObject the queue
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public JSONObject getQueue() {
if(!RolesUtils.hasUserOrAdministratorRole()){
throw new ApplicationJsonException(new AccessDeniedException("forbidden"), "forbidden",
Status.FORBIDDEN.getStatusCode());
}
if (null == queueEntity) {
logger.error(String.format(ERROR_MESSAGE_Q_NOT_FOUND, queueName));
throw new EntityNotFoundException(String.format(
ERROR_MESSAGE_Q_NOT_FOUND, queueName));
}
try {
return QueueResource.asJson(queueEntity, uriInfo.getPath());
} catch (JSONException je) {
logger.error(ERROR_MESSAGE_GET_QUEUE + ERROR_REASON_JSON, je);
throw new ApplicationJsonException(je, ERROR_MESSAGE_GET_QUEUE
+ ERROR_REASON_JSON,
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
}
/**
* Sub-resource locator for /alerts resource
*
* @return alerts
*/
/*
* @Path("alerts") public AlertsResource getAlerts() { if (null ==
* this.queueEntity) { logger.error(String.format(ERROR_MESSAGE_Q_NOT_FOUND,
* this.queueName)); throw new EntityNotFoundException(String.format(
* ERROR_MESSAGE_Q_NOT_FOUND, this.queueName)); } return new
* AlertsResource(uriInfo, entityManagerConfig, null, queueEntity); }
*/
/**
* Method getMessages.
*
* @return MessagesResource
*/
@Path("messages")
public MessagesResource getMessages() {
if (null == this.queueEntity) {
logger.error(String.format(ERROR_MESSAGE_Q_NOT_FOUND,
this.queueName));
throw new EntityNotFoundException(String.format(
ERROR_MESSAGE_Q_NOT_FOUND, this.queueName));
}
return new MessagesResource(uriInfo, entityManagerData,
entityManagerConfig, queueEntity);
}
/**
* Method getMessageTypes.
*
* @return MessageTypesResource
*/
@Path("messagetypes")
public MessageTypesResource getMessageTypes() {
if (null == this.queueEntity) {
logger.error(String.format(ERROR_MESSAGE_Q_NOT_FOUND,
this.queueName));
throw new EntityNotFoundException(String.format(
ERROR_MESSAGE_Q_NOT_FOUND, this.queueName));
}
return new MessageTypesResource(uriInfo, entityManagerData,
entityManagerConfig, queueEntity);
}
/**
* Method getServiceMaps.
*
* @return ServiceMapsResource
*/
/*
* @Path("servicemaps") public ServiceMapsResource getServiceMaps(){ if
* (null == this.queueEntity) {
* logger.error(String.format(ERROR_MESSAGE_Q_NOT_FOUND, this.queueName));
* throw new EntityNotFoundException(String.format(
* ERROR_MESSAGE_Q_NOT_FOUND, this.queueName)); } return new
* ServiceMapsResource(uriInfo, entityManagerConfig, queueEntity); }
*/
/**
* PUT method : updates the queue
*
* @param jsonEntity
* JSONObject the queue holding new values
* @return Response
*/
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public Response updateQueue(JSONObject jsonEntity) {
if(!RolesUtils.hasAdministratorRole()){
throw new ApplicationJsonException(new AccessDeniedException("forbidden"), "forbidden",
Status.FORBIDDEN.getStatusCode());
}
if (null == queueEntity) {
logger.error(String.format(ERROR_MESSAGE_Q_NOT_FOUND, queueName));
throw new EntityNotFoundException(String.format(
ERROR_MESSAGE_Q_NOT_FOUND, queueName));
}
try {
// fill data
if (jsonEntity.has("name")) {
queueEntity.setName(jsonEntity.getString("name"));
}
if (jsonEntity.has("holdstatus")) {
queueEntity.setHoldstatus(new BigDecimal(jsonEntity
.getInt("holdstatus")));
}
if (jsonEntity.has("type")) {
try {
QueueTypeEntity queueType = QueueTypeResource
.findByTypeName(entityManagerConfig,
jsonEntity.getString("type"));
queueEntity.setQueueTypeEntity(queueType);
} catch (NullPointerException e) {
// TODO: change reason
logger.error(ERROR_MESSAGE_PUT_QUEUE + ERROR_REASON_JSON, e);
throw new ApplicationJsonException(e,
ERROR_MESSAGE_PUT_QUEUE + ERROR_REASON_JSON,
Response.Status.BAD_REQUEST.getStatusCode());
}
}
if (jsonEntity.has("connector")) {
try {
ServiceMapEntity serviceMap = ServiceMapResource
.findByFriendlyName(entityManagerConfig,
jsonEntity.getString("connector"));
queueEntity.setServiceMapEntity(serviceMap);
} catch (NullPointerException e) {
// TODO: change reason
logger.error(ERROR_MESSAGE_PUT_QUEUE + ERROR_REASON_JSON, e);
throw new ApplicationJsonException(e,
ERROR_MESSAGE_PUT_QUEUE + ERROR_REASON_JSON,
Response.Status.BAD_REQUEST.getStatusCode());
}
}
if (jsonEntity.has("description")) {
queueEntity.setDescription(jsonEntity.getString("description"));
}
if (jsonEntity.has("batchno")) {
queueEntity.setBatchno(new BigDecimal(jsonEntity
.getInt("batchno")));
}
if (jsonEntity.has("priority")) {
queueEntity.setPriority(new BigDecimal(jsonEntity
.getInt("priority")));
}
entityManagerConfig.getTransaction().begin();
entityManagerConfig.merge(queueEntity);
entityManagerConfig.getTransaction().commit();
/*
* if (jsonEntity.has("moveto")) {
* entityManagerConfig.getTransaction().begin(); boolean find =
* false; JSONArray moveto = jsonEntity.getJSONArray("moveto"); for
* (int i = 0; i < moveto.length(); i++) { JSONObject row =
* moveto.getJSONObject(i); if (row.has("destqueueid")){ find =
* false; for (QMovePrivMapEntity moveTo : queueEntity
* .getqMovePrivMapEntity()) { if
* (moveTo.getDestqueueid().intValue() == row
* .getInt("destqueueid")) { find = true; } } if (!find) {
* QMovePrivMapEntity qMovePrivMapEntity = new QMovePrivMapEntity();
* qMovePrivMapEntity.setDestqueueid(new BigDecimal(
* row.getInt("destqueueid")));
* qMovePrivMapEntity.setSourcequeueid(queueEntity .getGuid());
* entityManagerConfig.persist(qMovePrivMapEntity); } } }
*/
/*
* for (QMovePrivMapEntity moveTo : queueEntity
* .getqMovePrivMapEntity()){ find = false; for (int i = 0; i <
* moveto.length(); i++) { JSONObject row = moveto.getJSONObject(i);
* if (moveTo.getDestqueueid().intValue() == row
* .getInt("destqueueid")) { find = true; } } if (!find) {
* entityManagerConfig.remove(moveTo); } }
*
* entityManagerConfig.getTransaction().commit(); }
*/
} catch (JSONException je) {
logger.error(ERROR_MESSAGE_PUT_QUEUE + ERROR_REASON_JSON, je);
throw new ApplicationJsonException(je, ERROR_MESSAGE_PUT_QUEUE
+ ERROR_REASON_JSON,
Response.Status.BAD_REQUEST.getStatusCode());
} catch (NumberFormatException nfe) {
logger.error(ERROR_MESSAGE_PUT_QUEUE + ERROR_REASON_NUMBER_FORMAT,
nfe);
throw new ApplicationJsonException(nfe, ERROR_MESSAGE_PUT_QUEUE
+ ERROR_REASON_NUMBER_FORMAT,
Response.Status.BAD_REQUEST.getStatusCode());
} catch (RollbackException re) {
ApplicationJsonException.handleSQLException(re,
ERROR_MESSAGE_PUT_QUEUE, logger);
// log and rethrow the original error
logger.error(ERROR_MESSAGE_PUT_QUEUE + ERROR_REASON_ROLLBACK, re);
throw re;
} finally {
// Tomcat does not support container managed transactions
if (null != entityManagerConfig) {
entityManagerConfig.close();
}
}
return JsonResponseWrapper.getResponse(Response.Status.OK,
"queue updated");
}
/**
* DELETE method : deletes the queue
*
* @return Response
*/
@DELETE
public Response deleteQueue() {
if(!RolesUtils.hasAdministratorRole()){
throw new ApplicationJsonException(new AccessDeniedException("forbidden"), "forbidden",
Status.FORBIDDEN.getStatusCode());
}
if (null == queueEntity) {
logger.error(String.format(ERROR_MESSAGE_Q_NOT_FOUND, queueName));
throw new EntityNotFoundException(String.format(
ERROR_MESSAGE_Q_NOT_FOUND, queueName));
}
try {
entityManagerConfig.getTransaction().begin();
entityManagerConfig.remove(queueEntity);
entityManagerConfig.getTransaction().commit();
} catch(RollbackException re){
ApplicationJsonException.handleSQLException(re,
ERROR_MESSAGE_DELETE_QUEUE, logger);
}finally {
if (null != entityManagerConfig) {
entityManagerConfig.close();
}
}
return JsonResponseWrapper.getResponse(Response.Status.OK,
"queue deleted");
}
/**
* Returns the resource formatted as json
*
* @param queueEntity
* QueueEntity
* @param path
* String
* @return JSONObject
* @throws JSONException
*/
public static JSONObject asJson(QueueEntity queueEntity, String path)
throws JSONException {
JSONObject queueAsJson = ApiResource.getMetaResource(path,
QueueResource.class);
// fill data
queueAsJson.put("name", queueEntity.getName())
.put("description", queueEntity.getDescription())
.put("holdstatus", queueEntity.getHoldstatus())
.put("batchno", queueEntity.getBatchno())
.put("type", queueEntity.getQueueTypeEntity().getTypename())
.put("priority", queueEntity.getPriority());
if (queueEntity.getServiceMapEntity() != null) {
queueAsJson.put("connector", queueEntity.getServiceMapEntity()
.getFriendlyname());
}
/*
* if (!hasAll) { JSONArray moveToArray = new JSONArray(); for
* (QMovePrivMapEntity queueMove : queueEntity .getqMovePrivMapEntity())
* { moveToArray.put(new JSONObject().put("destqueueid",
* queueMove.getDestqueueid())); } queueAsJson.put("moveto",
* moveToArray); }
*/
ResourcesUtils.createLink(queueAsJson, path + "/messages", "messages");
return queueAsJson;
}
/**
* Method toString.
*
* @return String
*/
public String toString() {
return queueEntity.getName();
}
}