package com.belladati.demo.view; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; import org.apache.commons.codec.binary.Base64; import com.belladati.sdk.view.ImageView; import com.belladati.sdk.view.TableView.Table; import com.belladati.sdk.view.View; import com.belladati.sdk.view.ViewType; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; /** * View object representing a single chart or KPI view. * * @author Chris Hennigfeld */ public class ViewDisplay { private static final Logger logger = Logger.getLogger(ViewDisplay.class.getName()); private final String id; private final String urlId; private final String title; private final ViewType type; private final Future<?> future; private String script; public ViewDisplay(View view, Future<?> future) { this.id = view.getType().name().toLowerCase() + "-" + view.getId(); this.urlId = view.getId(); this.title = view.getName(); this.type = view.getType(); this.future = future; } /** * Tells this view display to invoke the future passed in the constructor. * This may block the current thread until the future is resolved. */ public void processFuture() { // get JSON data from the future // then set up a script injecting the JSON into the page if (future == null) { return; } switch (type) { case CHART: try { script = "chartJson['" + id + "'] = " + postProcess((JsonNode) future.get()); } catch (JsonProcessingException e) { logger.log(Level.WARNING, "Error getting data", e); } catch (InterruptedException e) { logger.log(Level.WARNING, "Error getting data", e); } catch (ExecutionException e) { logger.log(Level.WARNING, "Error getting data", e); } break; case KPI: try { script = "kpiJson['" + id + "'] = " + postProcess((JsonNode) future.get()); } catch (JsonProcessingException e) { logger.log(Level.WARNING, "Error getting data", e); } catch (InterruptedException e) { logger.log(Level.WARNING, "Error getting data", e); } catch (ExecutionException e) { logger.log(Level.WARNING, "Error getting data", e); } break; case TABLE: try { script = "tableJson['" + id + "'] = " + postProcess((Table) future.get()); } catch (InterruptedException e) { logger.log(Level.WARNING, "Error getting data", e); } catch (ExecutionException e) { logger.log(Level.WARNING, "Error getting data", e); } break; case IMAGE: try { script = "image['" + id + "'] = '" + postProcess((ImageView.Image) future.get()) + "'"; } catch (InterruptedException e) { logger.log(Level.WARNING, "Error getting data", e); } catch (ExecutionException e) { logger.log(Level.WARNING, "Error getting data", e); } break; case TEXT: try { script = "textJson['" + id + "'] = " + postProcess((JsonNode) future.get()); } catch (JsonProcessingException e) { logger.log(Level.WARNING, "Error getting data", e); } catch (InterruptedException e) { logger.log(Level.WARNING, "Error getting data", e); } catch (ExecutionException e) { logger.log(Level.WARNING, "Error getting data", e); } break; default: // do nothing } } private String postProcess(JsonNode node) throws JsonProcessingException { return new ObjectMapper().writeValueAsString(node); } private String postProcess(ImageView.Image image) { String imageString = null; ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { ImageIO.write(image.getImage(), "png", bos); byte[] imageBytes = bos.toByteArray(); Base64 encoder = new Base64(); imageString = new String(encoder.encode(imageBytes)); bos.close(); } catch (IOException e) { e.printStackTrace(); } return imageString; } private String postProcess(final Table table) throws InterruptedException { final int rowCount = table.getRowCount(); final int columnCount = table.getColumnCount(); final ObjectNode tableNode = new ObjectMapper().createObjectNode(); ExecutorService service = Executors.newCachedThreadPool(); service.submit(new Runnable() { @Override public void run() { tableNode.put("left", table.loadLeftHeader(0, rowCount).get("content")); } }); service.submit(new Runnable() { @Override public void run() { tableNode.put("top", table.loadTopHeader(0, columnCount).get("content")); } }); service.submit(new Runnable() { @Override public void run() { tableNode.put("data", table.loadData(0, rowCount, 0, columnCount).get("content")); } }); service.shutdown(); service.awaitTermination(10, TimeUnit.SECONDS); return tableNode.toString(); } /** * ID to use for the view DOM element. */ public String getId() { return id; } /** * Title shown for the view. */ public String getTitle() { return title; } /** * A script to invoke for the view in the context of the main page. */ public String getScript() { return script; } /** * CSS class to set on the iFrame. */ public String getCssClass() { return type.name().toLowerCase(); } public String getUrlId() { return urlId; } public ViewType getType() { return type; } }