/*
* @(#)RegulationDispatchAction.java
*
* Copyright 2011 Instituto Superior Tecnico
* Founding Authors: Anil Kassamali
*
* https://fenix-ashes.ist.utl.pt/
*
* This file is part of the Dispatch Registry Module.
*
* The Dispatch Registry Module is free software: you can
* redistribute it and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation, either version
* 3 of the License, or (at your option) any later version.
*
* The Dispatch Registry Module 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Dispatch Registry Module. If not, see .
*
*/
package module.regulation.dispatch.presentationTier;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import module.organization.domain.Person;
import module.regulation.dispatch.domain.IRegulationDispatchEntry;
import module.regulation.dispatch.domain.RegulationDispatchProcessFile;
import module.regulation.dispatch.domain.RegulationDispatchQueue;
import module.regulation.dispatch.domain.RegulationDispatchWorkflowMetaProcess;
import module.regulation.dispatch.utils.NaturalOrderComparator;
import module.workflow.domain.WorkflowUserGroupQueue;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.lang.StringUtils;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.joda.time.LocalDate;
import pt.ist.bennu.core.applicationTier.Authenticate.UserView;
import pt.ist.bennu.core.domain.User;
import pt.ist.bennu.core.domain.VirtualHost;
import pt.ist.bennu.core.domain.contents.ActionNode;
import pt.ist.bennu.core.domain.contents.Node;
import pt.ist.bennu.core.domain.groups.UserGroup;
import pt.ist.bennu.core.presentationTier.Context;
import pt.ist.bennu.core.presentationTier.LayoutContext;
import pt.ist.bennu.core.presentationTier.actions.ContextBaseAction;
import pt.ist.fenixWebFramework.servlets.filters.contentRewrite.GenericChecksumRewriter;
import pt.ist.fenixWebFramework.servlets.functionalities.CreateNodeAction;
import pt.ist.fenixWebFramework.struts.annotations.Mapping;
@Mapping(path = "/regulationDispatch")
/**
*
* @author Anil Kassamali
*
*/
public class RegulationDispatchAction extends ContextBaseAction {
@Override
public ActionForward execute(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request,
final HttpServletResponse response) throws Exception {
WorkflowUserGroupQueue regulationProcessesQueue = readQueue(request);
request.setAttribute("queue", regulationProcessesQueue);
return super.execute(mapping, form, request, response);
}
@CreateNodeAction(bundle = "REGULATION_DISPATCH_RESOURCES", key = "link.node.configuration.regulation.dispatch.interface",
groupKey = "title.node.configuration.module.regulation.dispatch")
public ActionForward prepareCreateNewPage(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) {
final VirtualHost virtualHost = getDomainObject(request, "virtualHostToManageId");
final Node node = getDomainObject(request, "parentOfNodesToManageId");
ActionNode.createActionNode(virtualHost, node, "/regulationDispatch", "prepare", "resources.RegulationDispatchResources",
"label.sideBar.regulation.dispatch.manage", UserGroup.getInstance());
return forwardToMuneConfiguration(request, virtualHost, node);
}
public ActionForward prepare(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request,
final HttpServletResponse response) {
User user = UserView.getCurrentUser();
List queues = RegulationDispatchQueue.getRegulationDispatchQueuesForUser(user);
request.setAttribute("queues", queues);
return forward(request, "/regulationDispatch/chooseQueue.jsp");
}
public ActionForward viewQueue(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request,
final HttpServletResponse response) {
if (readQueue(request) == null) {
return prepare(mapping, form, request, response);
}
return forward(request, "/regulationDispatch/viewQueue.jsp");
}
public static final NaturalOrderComparator NATURAL_ORDER_COMPARATOR = new NaturalOrderComparator();
public static final Comparator SORT_BY_REFERENCE_COMPARATOR =
new Comparator() {
@Override
public int compare(IRegulationDispatchEntry left, IRegulationDispatchEntry right) {
return NATURAL_ORDER_COMPARATOR.compare(left.getReference(), right.getReference());
}
};
public static class RegulationDispatchEntryFieldComparator implements Comparator {
private Comparator beanComparator;
public RegulationDispatchEntryFieldComparator(final String property) {
beanComparator = new BeanComparator(property);
}
@Override
public int compare(IRegulationDispatchEntry left, IRegulationDispatchEntry right) {
int value = beanComparator.compare(left, right);
if (value == 0) {
return SORT_BY_REFERENCE_COMPARATOR.compare(left, right);
}
return value;
}
}
private static final java.util.Map DISPATCH_TABLE_COLUMNS_MAP = new java.util.HashMap();
static {
DISPATCH_TABLE_COLUMNS_MAP.put("0", SORT_BY_REFERENCE_COMPARATOR);
DISPATCH_TABLE_COLUMNS_MAP.put("1", new RegulationDispatchEntryFieldComparator("emissionDate"));
DISPATCH_TABLE_COLUMNS_MAP.put("2", new RegulationDispatchEntryFieldComparator("dispatchDescription"));
DISPATCH_TABLE_COLUMNS_MAP.put("3", new RegulationDispatchEntryFieldComparator("emissor.name"));
DISPATCH_TABLE_COLUMNS_MAP.put("4", new RegulationDispatchEntryFieldComparator("regulationReference"));
DISPATCH_TABLE_COLUMNS_MAP.put("asc", 1);
DISPATCH_TABLE_COLUMNS_MAP.put("desc", -1);
}
private Comparator[] getPropertiesToCompare(HttpServletRequest request, Integer iSortingCols) {
java.util.List properties = new java.util.ArrayList();
java.util.Map mapToUse = DISPATCH_TABLE_COLUMNS_MAP;
for (int i = 0; i < iSortingCols; i++) {
String iSortingColIdx = request.getParameter("iSortCol_" + i);
properties.add((Comparator) mapToUse.get(iSortingColIdx));
}
return properties.toArray(new Comparator[] {});
}
private Integer[] getOrdering(HttpServletRequest request, Integer iSortingCols) {
java.util.List order = new java.util.ArrayList();
java.util.Map mapToUse = DISPATCH_TABLE_COLUMNS_MAP;
for (int i = 0; i < iSortingCols; i++) {
String iSortingColDir = request.getParameter("iSortDir_" + i);
order.add((Integer) mapToUse.get(iSortingColDir));
}
return order.toArray(new Integer[] {});
}
private java.util.List limitAndOrderSearchedEntries(java.util.List searchedEntries,
final Comparator[] propertiesToCompare, final Integer[] orderToUse, Integer iDisplayStart, Integer iDisplayLength) {
Collections.sort(searchedEntries, new Comparator() {
@Override
public int compare(IRegulationDispatchEntry oLeft, IRegulationDispatchEntry oRight) {
for (int i = 0; i < propertiesToCompare.length; i++) {
try {
Comparator comparator = propertiesToCompare[i];
if (comparator.compare(oLeft, oRight) != 0) {
return orderToUse[i] * comparator.compare(oLeft, oRight);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return 0;
}
});
return searchedEntries.subList(iDisplayStart, Math.min(iDisplayStart + iDisplayLength, searchedEntries.size()));
}
private String generateLinkForView(HttpServletRequest request, IRegulationDispatchEntry entry) {
RegulationDispatchQueue queue = readQueue(request);
String contextPath = request.getContextPath();
String realLink =
contextPath
+ String.format("/regulationDispatch.do?dispatchId=%s&method=viewDispatch&queueId=%s",
entry.getExternalId(), queue.getExternalId());
realLink +=
String.format("&%s=%s", GenericChecksumRewriter.CHECKSUM_ATTRIBUTE_NAME,
GenericChecksumRewriter.calculateChecksum(realLink));
return realLink;
}
private String generateLinkForEdition(HttpServletRequest request, IRegulationDispatchEntry entry) {
RegulationDispatchQueue queue = readQueue(request);
String contextPath = request.getContextPath();
String realLink =
contextPath
+ String.format("/createRegulationDispatch.do?dispatchId=%s&method=prepareEdit&queueId=%s",
entry.getExternalId(), queue.getExternalId());
realLink +=
String.format("&%s=%s", GenericChecksumRewriter.CHECKSUM_ATTRIBUTE_NAME,
GenericChecksumRewriter.calculateChecksum(realLink));
return realLink;
}
private String generateLinkForRemoval(HttpServletRequest request, IRegulationDispatchEntry entry) {
RegulationDispatchQueue queue = readQueue(request);
String contextPath = request.getContextPath();
String realLink =
contextPath
+ String.format(
"/createRegulationDispatch.do?dispatchId=%s&method=prepareRemoveDispatch&queueId=%s",
entry.getExternalId(), queue.getExternalId());
realLink +=
String.format("&%s=%s", GenericChecksumRewriter.CHECKSUM_ATTRIBUTE_NAME,
GenericChecksumRewriter.calculateChecksum(realLink));
return realLink;
}
private String generateLinkForMainDocument(HttpServletRequest request, IRegulationDispatchEntry entry) {
RegulationDispatchQueue queue = readQueue(request);
String contextPath = request.getContextPath();
String realLink =
contextPath
+ String.format("/regulationDispatch.do?dispatchId=%s&method=downloadMainDocument&queueId=%s",
entry.getExternalId(), queue.getExternalId());
realLink +=
String.format("&%s=%s", GenericChecksumRewriter.CHECKSUM_ATTRIBUTE_NAME,
GenericChecksumRewriter.calculateChecksum(realLink));
return realLink;
}
private String serializeAjaxFilterResponse(String sEcho, Integer iTotalRecords, Integer iTotalDisplayRecords,
java.util.List limitedEntries, HttpServletRequest request) {
StringBuilder stringBuilder = new StringBuilder("{");
stringBuilder.append("\"sEcho\": ").append(sEcho).append(", \n");
stringBuilder.append("\"iTotalRecords\": ").append(iTotalRecords).append(", \n");
stringBuilder.append("\"iTotalDisplayRecords\": ").append(iTotalDisplayRecords).append(", \n");
stringBuilder.append("\"aaData\": ").append("[ \n");
for (IRegulationDispatchEntry entry : limitedEntries) {
RegulationDispatchWorkflowMetaProcess meta = ((RegulationDispatchWorkflowMetaProcess) entry);
boolean ableToAccessQueue = meta.isCurrentUserAbleToAccessAnyQueues();
String reference = entry.getReference();
LocalDate emissionDate = entry.getEmissionDate();
String dispatchDescription = entry.getDispatchDescription();
Person emissor = entry.getEmissor();
String regulationReference = entry.getRegulationReference() != null ? entry.getRegulationReference() : "";
Boolean hasMainDocument = entry.getMainDocument() != null;
stringBuilder.append("[ \"").append(reference).append("\", ");
stringBuilder.append("\"").append(escapeQuotes(emissionDate.toString("dd/MM/yyyy"))).append("\", ");
stringBuilder.append("\"").append(escapeQuotes(dispatchDescription)).append("\", ");
stringBuilder.append("\"").append(escapeQuotes(emissor.getName())).append("\", ");
stringBuilder.append("\"").append(escapeQuotes(regulationReference)).append("\", ");
stringBuilder.append("\"").append(ableToAccessQueue ? generateLinkForView(request, entry) : "permission_not_granted")
.append(",");
stringBuilder.append(ableToAccessQueue ? generateLinkForEdition(request, entry) : "permission_not_granted").append(
",");
stringBuilder.append(
ableToAccessQueue && entry.isActive() ? generateLinkForRemoval(request, entry) : "permission_not_granted")
.append(",");
stringBuilder
.append(ableToAccessQueue && hasMainDocument ? generateLinkForMainDocument(request, entry) : "permission_not_granted")
.append("\",");
stringBuilder.append("\"").append(entry.isActive()).append("\" ], ");
}
stringBuilder.delete(stringBuilder.length() - 2, stringBuilder.length());
stringBuilder.append(" ]\n }");
return stringBuilder.toString();
}
private Object escapeQuotes(String value) {
return value.replaceAll("\\\"", "\\\\\"");
}
public ActionForward processesForAjaxDataTable(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) throws IOException {
String sEcho = request.getParameter("sEcho");
Integer iSortingCols = Integer.valueOf(request.getParameter("iSortingCols"));
String sSearch = request.getParameter("sSearch");
Integer iDisplayStart = Integer.valueOf(request.getParameter("iDisplayStart"));
Integer iDisplayLength = Integer.valueOf(request.getParameter("iDisplayLength"));
Comparator[] propertiesToCompare = getPropertiesToCompare(request, iSortingCols);
Integer[] orderToUse = getOrdering(request, iSortingCols);
if (propertiesToCompare.length == 0) {
propertiesToCompare = new Comparator[] { new BeanComparator("reference") };
orderToUse = new Integer[] { -1 };
}
List entries = null;
RegulationDispatchQueue queue = readQueue(request);
if (StringUtils.isEmpty(sSearch)) {
entries = queue.getActiveEntries();
} else {
entries = queue.findEntriesBy(sSearch);
}
Integer numberOfRecordsMatched = entries.size();
java.util.List limitedEntries =
limitAndOrderSearchedEntries(entries, propertiesToCompare, orderToUse, iDisplayStart, iDisplayLength);
String jsonResponseString = null;
jsonResponseString =
serializeAjaxFilterResponse(sEcho, queue.getActiveEntries().size(), numberOfRecordsMatched, limitedEntries,
request);
final byte[] jsonResponsePayload = jsonResponseString.getBytes("iso-8859-15");
response.setContentType("application/json; charset=iso-8859-15");
response.setContentLength(jsonResponsePayload.length);
response.getOutputStream().write(jsonResponsePayload);
response.getOutputStream().flush();
response.getOutputStream().close();
return null;
}
public ActionForward viewDispatch(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request,
final HttpServletResponse response) {
IRegulationDispatchEntry dispatch = readDispatchEntry(request);
request.setAttribute("dispatch", dispatch);
return forward(request, "/regulationDispatch/viewDispatch.jsp");
}
public ActionForward downloadMainDocument(final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, final HttpServletResponse response) throws IOException {
IRegulationDispatchEntry dispatch = readDispatchEntry(request);
RegulationDispatchProcessFile mainDocument = dispatch.getMainDocument();
if (mainDocument == null) {
throw new RuntimeException("this should not be here");
}
return download(response, mainDocument.getFilename(), mainDocument.getStream(), mainDocument.getContentType());
}
public ActionForward downloadFile(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request,
final HttpServletResponse response) throws IOException {
RegulationDispatchProcessFile file = readFile(request);
if (file == null) {
throw new RuntimeException("this should not be here");
}
return download(response, file.getFilename(), file.getStream(), file.getContentType());
}
private IRegulationDispatchEntry readDispatchEntry(final HttpServletRequest request) {
return (IRegulationDispatchEntry) getDomainObject(request, "dispatchId");
}
private RegulationDispatchProcessFile readFile(final HttpServletRequest request) {
return (RegulationDispatchProcessFile) getDomainObject(request, "fileId");
}
private RegulationDispatchQueue readQueue(final HttpServletRequest request) {
return getDomainObject(request, "queueId");
}
protected RegulationDispatchWorkflowMetaProcess getProcess(final HttpServletRequest request) {
return getDomainObject(request, "processId");
}
@Override
public Context createContext(String contextPathString, HttpServletRequest request) {
LayoutContext context = (LayoutContext) super.createContext(contextPathString, request);
context.addHead("/regulationDispatch/layoutHead.jsp");
return context;
}
}