All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jongsoft.highchart.render.ImageRenderer Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * The MIT License
 *
 * Copyright 2016 Jong Soft.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.jongsoft.highchart.render;

import com.jongsoft.Renderer;
import com.jongsoft.highchart.AbstractHighchart;
import com.jongsoft.highchart.HeatmapChart;
import com.jongsoft.highchart.Highchart;
import com.jongsoft.highchart.PolarHighchart;
import com.jongsoft.highchart.monitoring.Monitoring;
import com.jongsoft.highchart.phantomjs.DriverPoolFactory;
import com.jongsoft.highchart.phantomjs.PhantomCommandBuilder;
import com.jongsoft.highchart.phantomjs.TimedPhantomJsDriver;
import com.jongsoft.highchart.serializer.JsonUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebDriverException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import static com.jongsoft.highchart.monitoring.Monitoring.Level.TRACE;

public class ImageRenderer implements Renderer> {

    private static final Logger LOG = LoggerFactory.getLogger(ImageRenderer.class);

    private AbstractHighchart globalOptions;
    private AbstractHighchart chartOptions;
    private OutputStream outStream;

    @Override
    @Monitoring(level = TRACE)
    public void render() {
        TimedPhantomJsDriver phantomJSDriver;
        
        if (globalOptions == null) {
            LOG.trace("No global options provided, instantiate default settings.");
            globalOptions = new Highchart();
        }

        if (outStream == null) {
            throw new RenderException("Cannot render highcharts when no outputstream is set");
        }
        
        if (chartOptions == null) {
            throw new RenderException("Cannot render when no highcharts graph is provided");
        }

        try {
            LOG.trace("Attempting to obtain a phantom js driver for rendering.");
            phantomJSDriver = DriverPoolFactory.getDriverPool(false).borrowObject();
        } catch (Exception e) {
            throw new RenderException("Unable to borrow phantom js driver from driver pool", e);
        }

        globalOptions.getChart().setRenderTo("svg-chart");
        try {
            LOG.trace("Executing a phantom js script for the render.");
            PhantomCommandBuilder phantomCommand = new PhantomCommandBuilder()
                    .libraryPath(DriverPoolFactory.getExpansionDir());

            LOG.trace("Injecting jQuey and Highchart.js");
            phantomCommand.injectJs("highchart.js");
            
            // Append any additional libraries based upon the type of Highchart instance being rendered
            if (chartOptions instanceof HeatmapChart) {
                LOG.trace("Injecting Highcharts Map.js");
                phantomCommand.injectJs("highchart-map.js");
            }
            if (chartOptions instanceof PolarHighchart) {
                phantomCommand.injectJs("highcharts-more.js");
            }

            // Set the global options for Highcharts
            chartOptions.getChart().setRenderTo("svg-chart");
            phantomCommand.appendScript("page.evaluate(function() {")
                    .appendScript("  Highcharts.setOptions(").appendScript(globalOptions.toJson()).appendScript(");")
                    .appendScript("});");
            
            // Append the provided chart by the client
            phantomCommand.appendScript("page.evaluate(function() {")
                    .appendScript("   document.write('
');") .appendScript(" new Highcharts.Chart(").appendScript(chartOptions.toJson()).appendScript(");") .appendScript("});") .build(); Object response = phantomJSDriver.executePhantomJS(phantomCommand.build()); if (response instanceof Map) { Map realResponse = (Map) response; if (realResponse.containsKey("exitCode")) { long exitCode = (long) realResponse.get("exitCode"); List exceptions = (List) realResponse.get("exception"); if (exitCode == 0 && exceptions.isEmpty()) { outStream.write(phantomJSDriver.getScreenshotAs(OutputType.BYTES)); outStream.flush(); } else { LOG.trace("Failed to execute command " + phantomCommand.build()); throw new RenderException(String.format("Failed to process script exit code %s exceptions %s ", exitCode, JsonUtils.serialize(exceptions))); } } else { throw new RenderException("Failed to process script, exception: " + JsonUtils.serialize(response)); } } } catch (IOException | WebDriverException e) { LOG.error("Unable to save image to provided output stream", e); throw new RenderException("Unable to save image to output stream"); } finally { DriverPoolFactory.getDriverPool(false).returnObject(phantomJSDriver); } } @Override public Renderer> setRenderObject(AbstractHighchart chartOptions) { this.chartOptions = chartOptions; return this; } @Override public Renderer> setGlobalOptions(AbstractHighchart chartOptions) { this.globalOptions = chartOptions; return this; } @Override public Renderer> setOutputStream(OutputStream outputStream) { this.outStream = outputStream; return this; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy