package org.aperteworkflow.portlets;
import com.vaadin.terminal.gwt.server.ApplicationPortlet2;
import org.apache.commons.lang.StringEscapeUtils;
import org.aperteworkflow.bpm.graph.GraphElement;
import org.aperteworkflow.bpm.graph.StateNode;
import org.aperteworkflow.bpm.graph.TransitionArc;
import org.aperteworkflow.bpm.graph.TransitionArcPoint;
import pl.net.bluesoft.rnd.processtool.ProcessToolContext;
import pl.net.bluesoft.rnd.processtool.ProcessToolContextCallback;
import pl.net.bluesoft.rnd.processtool.bpm.ProcessToolBpmSession;
import pl.net.bluesoft.rnd.util.i18n.I18NSourceFactory;
import pl.net.bluesoft.rnd.util.i18n.impl.DefaultI18NSource;
import pl.net.bluesoft.rnd.processtool.model.ProcessInstance;
import pl.net.bluesoft.rnd.processtool.model.UserData;
import pl.net.bluesoft.rnd.processtool.plugins.ProcessToolRegistry;
import pl.net.bluesoft.rnd.util.i18n.I18NSource;
import javax.imageio.ImageIO;
import javax.portlet.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
/**
* @author tlipski@bluesoft.net.pl
*/
public class ProcessInstanceManagerApplicationPortlet extends ApplicationPortlet2 {
private static final Logger logger = Logger.getLogger(ProcessInstanceManagerApplicationPortlet.class.getName());
@Override
protected void handleRequest(final PortletRequest request, final PortletResponse response) throws PortletException, IOException {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
try {
ProcessToolRegistry registry = (ProcessToolRegistry) getPortletConfig()
.getPortletContext().getAttribute(ProcessToolRegistry.class.getName());
registry.withProcessToolContext(new ProcessToolContextCallback() {
@Override
public void withContext(ProcessToolContext ctx) {
ProcessToolContext.Util.setThreadProcessToolContext(ctx);
try {
try {
I18NSource.ThreadUtil.setThreadI18nSource(I18NSourceFactory.createI18NSource(request.getLocale()));
if (request instanceof ResourceRequest) {
ResourceRequest rr = (ResourceRequest) request;
ResourceResponse resp = (ResourceResponse) response;
if (rr.getParameter("instanceId") != null) { //special handling
logger.info("Image request");
ProcessToolBpmSession session = ctx.getProcessToolSessionFactory()
.createSession(new UserData("admin", "admin@aperteworkflow.org", "Admin admin"),
new ArrayList<String>());
byte[] bytes = session.getProcessMapImage(
session.getProcessData(rr.getParameter("instanceId"), ctx));
if (bytes != null) {
resp.setContentType("image/png");
resp.getPortletOutputStream().write(bytes);
}
return;
} else if (rr.getParameter("svg") != null) { //to use svg inside of a window
logger.info("SVG request");
ProcessToolBpmSession session = ctx.getProcessToolSessionFactory()
.createSession(new UserData("admin", "admin@aperteworkflow.org", "Admin admin"),
new ArrayList<String>());
ProcessInstance pi = session.getProcessData(rr.getParameter("svg"), ctx);
List<GraphElement> processHistory = session.getProcessHistory(pi);
// final StringBuffer svg = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
final StringBuffer svg = new StringBuffer("<html><body style=\"margin:0; padding:0\">\n\n");
final byte[] png = session.getProcessMapImage(pi);
if (png != null) {
BufferedImage read;
try {
read = ImageIO.read(new ByteArrayInputStream(png));
ResourceURL resourceURL = resp.createResourceURL();
resourceURL.setParameter("instanceId", pi.getInternalId());
String url = resourceURL.toString();
url = StringEscapeUtils.escapeXml(url);
svg.append(String.format("<svg xmlns=\"http://www.w3.org/2000/svg\"\n" + " viewBox='0 0 %d %d' " +
" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
read.getWidth(),
read.getHeight()));
svg.append(String.format("<image x=\"0\" y=\"0\" width=\"%d\" height=\"%d\"\n" +
"xlink:href=\"%s\" />",
read.getWidth(),
read.getHeight(),
url));
} catch (IOException e) {
throw new RuntimeException(e);
}
String strokeStyle = "stroke:#1B59E0;stroke-width:5;opacity: 1;";
for (GraphElement el : processHistory) {
if (el instanceof StateNode) {
StateNode sn = (StateNode) el;
String fill = sn.isUnfinished() ? "fill:#1B59E0;fill-opacity:0.3" : "fill-opacity:0.0";
svg.append(String.format("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\"\n" +
" rx=\"5\" ry=\"5\"\n" +
" style=\"" + strokeStyle + fill + "\"/>\n",
sn.getX(),
sn.getY(),
sn.getHeight(),
sn.getWidth()));
} else if (el instanceof TransitionArc) {
TransitionArc ta = (TransitionArc) el;
TransitionArcPoint prevPoint = null;
for (TransitionArcPoint p : ta.getPath()) {
if (prevPoint != null) {
svg.append(String.format("<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\"\n" +
" style=\"" + strokeStyle + "\"/>\n",
prevPoint.getX(),
prevPoint.getY(),
p.getX(),
p.getY()
));
}
prevPoint = p;
}
}
}
svg.append("</svg></body></html>");
resp.setContentType("text/html");
resp.getPortletOutputStream().write(svg.toString().getBytes());
}
}
}
ProcessInstanceManagerApplicationPortlet.super.handleRequest(request, response);
} finally {
I18NSource.ThreadUtil.removeThreadI18nSource();
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
ProcessToolContext.Util.removeThreadProcessToolContext();
}
}
});
} finally {
Thread.currentThread().setContextClassLoader(contextClassLoader);
}
}
}