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

org.highfaces.component.chart.ChartRenderer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014 Bauer-Live Softwaredevelopment.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.highfaces.component.chart;

import org.highfaces.component.api.ChartModel;
import org.highfaces.component.api.ChartSeries;
import org.highfaces.component.api.DataPoint;
import org.highfaces.component.api.impl.DefaultChartSeries;
import org.highfaces.component.chartaxis.ChartAxis;
import org.highfaces.component.chartlegend.ChartLegend;
import org.highfaces.component.chartresetzoombutton.ChartResetZoomButton;
import org.highfaces.component.chartresetzoombutton.ChartResetZoomButtonPosition;
import org.highfaces.component.chartserie.ChartSerie;
import org.highfaces.component.charttooltip.ChartTooltip;
import org.highfaces.util.JSONFunction;
import org.highfaces.util.StreamResponseWriter;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import javax.el.MethodExpression;
import javax.faces.application.ResourceDependencies;
import javax.faces.application.ResourceDependency;
import javax.faces.component.UIComponent;
import javax.faces.component.UIOutput;
import javax.faces.component.behavior.ClientBehavior;
import javax.faces.component.behavior.ClientBehaviorContext;
import javax.faces.context.FacesContext;
import javax.faces.context.PartialResponseWriter;
import javax.faces.context.ResponseWriter;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.event.ComponentSystemEventListener;
import javax.faces.event.ListenerFor;
import javax.faces.event.PostAddToViewEvent;
import javax.faces.render.FacesRenderer;
import javax.faces.render.Renderer;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author markus.bauer
 */
@ResourceDependencies({
    @ResourceDependency(name = "jsf.js", target = "head", library = "javax.faces")
    ,
    @ResourceDependency(library = "highfaces", name = "highfaces.css")
    ,
    @ResourceDependency(library = "highfaces", name = "highfaces.js")})
@FacesRenderer(componentFamily = "org.highfaces.component", rendererType = "org.highfaces.component.ChartRenderer")
@ListenerFor(systemEventClass = PostAddToViewEvent.class)
public class ChartRenderer extends Renderer implements ComponentSystemEventListener {

    protected boolean need3d = false;

    public boolean isUpdate(FacesContext context) {
	Map externalParameters = context.getExternalContext().getRequestParameterMap();
	if (context.getPartialViewContext() != null && context.getPartialViewContext().isAjaxRequest()
		&& externalParameters.containsKey("javax.faces.behavior.event")) {

	    String eventName = externalParameters.get("javax.faces.behavior.event");
	    return "update".equals(eventName);
	}
	return false;
    }

    @Override
    public void decode(FacesContext context, UIComponent component) {
	super.decode(context, component);
	Map externalParameters = context.getExternalContext().getRequestParameterMap();
	Chart cv = (Chart) component;

	// Behavior
	if (externalParameters.containsKey("javax.faces.behavior.event")) {

	    String eventName = externalParameters.get("javax.faces.behavior.event");
	    String sourceId = externalParameters.get("javax.faces.source");

	    if ((sourceId != null) && (sourceId.equals(cv.getClientId()))) {
		if ("select".equals(eventName)) {

		    cv.select(externalParameters.get(cv.getClientId() + "_selectedSeries"), externalParameters.get(cv.getClientId() + "_selectedPoint"));
		} else if ("update".equals(eventName)) {
		    MethodExpression me = cv.getUpdateMethod();
		    if (me != null) {
			ActionEvent ae = new ActionEvent(component);
			me.invoke(context.getELContext(), new Object[]{ae});
			if (isUpdate(context)) {
			    try {
				//context.getPartialViewContext().getRenderIds().add(component.getClientId());
				//context.getPartialViewContext().getRenderIds().add(component.getId());

				PartialResponseWriter writer = context.getPartialViewContext().getPartialResponseWriter();

				writer.startDocument();
				JSONObject high = new JSONObject();
				JSONArray series = new JSONArray();
				if (cv.getValue() != null) {
				    encodeSimpleSeries(context, cv, series);
				}
				for (UIComponent comp : cv.getChildren()) {
				    if (comp instanceof ChartSerie) {
					ChartSerie serie = (ChartSerie) comp;
					JSONObject jSerie = encodeSerie(context, cv, serie, (Collection) serie.getValue(), false);

					series.put(jSerie);

				    }
				}
				high.put("series", series);
				Map ext = new HashMap();
				ext.put("id", sourceId);
				writer.startExtension(ext);
				writer.write(high.toString());
				writer.endExtension();
				writer.endDocument();
				context.responseComplete();
			    } catch (Exception ex) {

				Logger.getLogger(ChartRenderer.class.getName()).log(Level.SEVERE, null, ex);
			    }

			}
		    } else {
			LOG.warning("Should update " + sourceId + " but no updateMethod was found");
		    }
		}

		List behaviorsForEvent = cv.getClientBehaviors().get(eventName);

		if (cv.getClientBehaviors().size() > 0) {
		    String behaviorSource = externalParameters.get("javax.faces.source");
		    String clientId = cv.getClientId(context);
		    if (behaviorSource != null && behaviorSource.equals(clientId)) {
			for (ClientBehavior behavior : behaviorsForEvent) {
			    behavior.decode(context, cv);
			}
		    }
		}
	    } //else LOG.info("sourceId="+sourceId+" vs. "+cv.getClientId());
	}

	//Change selected values
	String currvis = externalParameters.get(cv.getClientId() + "_selectedSeries");
	if (currvis != null) {
	    cv.setSelectedSeries(currvis);
	}
	currvis = externalParameters.get(cv.getClientId() + "_selectedPoint");
	if (currvis != null) {
	    cv.setSelectedPoint(currvis);
	}
    }

    /* renderes jQuery-Script inclusion conditionally. After the jQuery Script, it includes HighCharts script */
    public void renderScript(FacesContext context) {
	UIComponent headFacet = context.getViewRoot().getFacet("javax_faces_location_HEAD");
	if (headFacet == null) {
	    return;
	}
	boolean needjQuery = true;
	for (UIComponent c : headFacet.getChildren()) {
	    if (c.getAttributes().containsKey("name")) {
		if (c.getAttributes().get("name").toString().contains("jquery") && c.getAttributes().get("name").toString().contains(".js")) {
		    needjQuery = false;
		}
	    }
	}
	if (needjQuery) {
	    UIOutput jquery = (UIOutput) context.getApplication().createComponent(context, "javax.faces.Output", "javax.faces.resource.Script");
	    jquery.getAttributes().put("library", "highfaces");
	    jquery.getAttributes().put("name", "jquery/jquery.js");
	    jquery.getAttributes().put("target", "head");
	    jquery.setId("highfaces-resource-jquery");
	    jquery.setRendererType("javax.faces.resource.Script");
	    context.getViewRoot().addComponentResource(context, jquery, "head");
	}
	boolean needHighCharts = true;
	for (UIComponent c : headFacet.getChildren()) {
	    if (c.getAttributes().get("name").toString().endsWith("highcharts.js")) {
		needHighCharts = false;
	    }
	}
	if (needHighCharts) {
	    UIOutput high = (UIOutput) context.getApplication().createComponent(context, "javax.faces.Output", "javax.faces.resource.Script");
	    high.getAttributes().put("library", "highfaces");
	    high.getAttributes().put("name", "highcharts/highcharts.js");
	    high.getAttributes().put("target", "head");
	    high.setId("highfaces-resource-highcharts");
	    high.setRendererType("javax.faces.resource.Script");
	    context.getViewRoot().addComponentResource(context, high, "head");

	    if (need3d) {
		high = (UIOutput) context.getApplication().createComponent(context, "javax.faces.Output", "javax.faces.resource.Script");
		high.getAttributes().put("library", "highfaces");
		high.getAttributes().put("name", "highcharts/highcharts-3d.js");
		high.getAttributes().put("target", "head");
		high.setId("highfaces-resource-highcharts-3d");
		high.setRendererType("javax.faces.resource.Script");
		context.getViewRoot().addComponentResource(context, high, "head");
	    }

	}
    }

    @Override
    public void processEvent(final ComponentSystemEvent event) throws AbortProcessingException {
	if (event instanceof PostAddToViewEvent) {
	    final FacesContext context = FacesContext.getCurrentInstance();
	    renderScript(context);
	}
    }

    @Override
    public boolean getRendersChildren() {
	return true;
    }

    @Override
    public void encodeChildren(FacesContext context, UIComponent component)
	    throws IOException {
	if (context == null || component == null) {
	    throw new NullPointerException();
	}
	for (UIComponent comp : component.getChildren()) {

	}
	LOG.info("Rendering children");
    }

    @Override
    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
	super.encodeBegin(context, component);
	Chart cv = (Chart) component;
	String clientId = cv.getClientId(context);

	String style = cv.getStyle();
	ResponseWriter responseWriter = context.getResponseWriter();
	if (isUpdate(context)) {

	    return;
	}

	responseWriter.startElement("div", null);
	responseWriter.writeAttribute("class", "hc-chartframe", "class");
	responseWriter.writeAttribute("id", clientId, "id");
	if (style != null) {
	    responseWriter.writeAttribute("style", style, "style");
	}
	responseWriter.startElement("input", null);
	responseWriter.writeAttribute("type", "hidden", null);
	responseWriter.writeAttribute("id", clientId + "_selectedSeries", null);
	responseWriter.writeAttribute("name", clientId + "_selectedSeries", null);
	responseWriter.writeAttribute("value", cv.getSelectedSeries(), null);
	responseWriter.endElement("input");
	responseWriter.startElement("input", null);
	responseWriter.writeAttribute("type", "hidden", null);
	responseWriter.writeAttribute("id", clientId + "_selectedPoint", null);
	responseWriter.writeAttribute("name", clientId + "_selectedPoint", null);
	responseWriter.writeAttribute("value", cv.getSelectedPoint(), null);
	responseWriter.endElement("input");
    }

    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
	super.encodeEnd(context, component);
	Chart chart = (Chart) component;
	String clientId = chart.getClientId(context);

	if (isUpdate(context)) {
	    try {
		JSONObject high = new JSONObject();
		JSONArray series = new JSONArray();
		if (chart.getValue() != null) {
		    encodeSimpleSeries(context, chart, series);
		}
		for (UIComponent comp : chart.getChildren()) {
		    if (comp instanceof ChartSerie) {
			ChartSerie serie = (ChartSerie) comp;
			JSONObject jSerie = encodeSerie(context, chart, serie, (Collection) serie.getValue(), true);

			series.put(jSerie);

		    }
		}
		high.put("series", series);
		PartialResponseWriter prw = context.getPartialViewContext().getPartialResponseWriter();
		prw.startExtension(new HashMap());
		prw.write(high.toString());
		prw.endExtension();
	    } catch (Exception e) {
		LOG.log(Level.SEVERE, e.getMessage(), e);
	    }
	    return;
	}

	encodeChart(context, chart);
	ResponseWriter responseWriter = context.getResponseWriter();

	responseWriter.endElement("div");

    }

    private void encodeChart(FacesContext context, Chart cv) throws IOException {
	try {
	    ResponseWriter responseWriter = context.getResponseWriter();
	    responseWriter.startElement("div", null);
	    String div_id = cv.getClientId(context).replace(':', '_') + "_chart";
	    String style = "height:";
	    style += cv.getHeight();
	    if (cv.getWidth() != null) {
		style += ";width:" + cv.getWidth();
	    }
	    responseWriter.writeAttribute("style", style, null);
	    responseWriter.writeAttribute("id", div_id, null);
	    responseWriter.endElement("div");
	    responseWriter.startElement("script", null);
	    responseWriter.writeAttribute("type", "text/javascript", null);

	    responseWriter.write("$(function () {");
	    // 1.0.5: Set the timezone to JSF Locale
	    responseWriter.write("Highcharts.setOptions({");
	    responseWriter.write("global:{");
	    Boolean useUTC = false;
	    try {
		if ("true".equals(context.getExternalContext().getInitParameter("highfaces.useUTC"))) {
		    useUTC = true;
		}
	    } catch (Exception e) {
		LOG.log(Level.WARNING, "Expected true or false for init param highfaces.useUTC", e);
	    }
	    if (!useUTC) {
		responseWriter.write("useUTC: false");
	    }
	    responseWriter.write("}");
	    responseWriter.write("});");
	    responseWriter.write("var options = ");

	    JSONObject high = new JSONObject();
	    JSONObject chart = new JSONObject();
	    JSONObject plotOptions = new JSONObject();
	    chart.put("type", cv.getType());

	    JSONObject options3d = null;
	    if (cv.getAlpha3d() != null) {
		options3d = new JSONObject();
		options3d.put("enabled", true);
		options3d.put("alpha", cv.getAlpha3d());
	    }
	    if (cv.getBeta3d() != null) {
		if (options3d == null) {
		    options3d = new JSONObject();
		    options3d.put("enabled", true);
		}
		options3d.put("beta", cv.getBeta3d());
	    }
	    if (cv.getDepth3d() != null) {
		if (options3d == null) {
		    options3d = new JSONObject();
		    options3d.put("enabled", true);
		}
		options3d.put("depth", cv.getDepth3d());
	    }
	    if (cv.getViewDistance3d() != null) {
		if (options3d == null) {
		    options3d = new JSONObject();
		    options3d.put("enabled", true);
		}
		options3d.put("viewDistance", cv.getViewDistance3d());
	    }
	    if (options3d != null) {
		chart.put("options3d", options3d);
		need3d = true;
	    }
	    // 1.2: Live Update Extension
	    if (cv.getUpdateInterval() > 0) {
		JSONObject events = new JSONObject();
		String setUpLiveUpdate = "function () {";
		setUpLiveUpdate += "setInterval(function() {hfLiveUpdate($('#" + div_id + "').parent());}, " + cv.getUpdateInterval() * 1000 + ");";
		setUpLiveUpdate += "}";
		events.put("load", new JSONFunction(setUpLiveUpdate));
		chart.put("events", events);
		chart.put("capacity", cv.getUpdateCapacity());
	    }
	    high.put("chart", chart);
	    // colors
	    JSONObject credits = new JSONObject();
	    if (cv.getCredits() != null) {
		if ("".equals(cv.getCredits()) || "false".equals(cv.getCredits())) {
		    credits.put("enabled", false);
		} else {
		    credits.put("text", cv.getCredits());
		    credits.put("href", "");
		}
	    } else {
		credits.put("text", "highfaces.org");
		credits.put("href", "http://www.highfaces.org");
	    }

	    high.put("credits", credits);
	    if (cv.getZoomType() != null) {
		if (!cv.getZoomType().equals("")) {
		    chart.put("zoomType", cv.getZoomType());

		    JSONObject resetZoomButtonObject = new JSONObject();
		    for (UIComponent component : cv.getChildren()) {
			if (component instanceof ChartResetZoomButton) {
			    ChartResetZoomButton resetZoomButton = (ChartResetZoomButton) component;
			    resetZoomButtonObject.put("relativeTo", resetZoomButton.getRelativeTo());

			    for (UIComponent resetZoomButtonComponent : resetZoomButton.getChildren()) {
				if (resetZoomButtonComponent instanceof ChartResetZoomButtonPosition) {
				    ChartResetZoomButtonPosition position = (ChartResetZoomButtonPosition) resetZoomButtonComponent;
				    JSONObject positionObject = new JSONObject();

				    if (position.getAlign() != null && !position.getAlign().equals("")) {
					positionObject.put("align", position.getAlign());
				    }

				    if (position.getVerticalAlign() != null && !position.getVerticalAlign().equals("")) {
					positionObject.put("verticalAlign", position.getVerticalAlign());
				    }

				    if (position.getX() != null && !position.getX().equals("")) {
					positionObject.put("x", position.getX());
				    }

				    if (position.getY() != null && !position.getY().equals("")) {
					positionObject.put("y", position.getY());
				    }

				    resetZoomButtonObject.put("position", positionObject);
				    chart.put("resetZoomButton", resetZoomButtonObject);
				    break;
				}
			    }

			}
		    }
		}
	    }
	    if (cv.getColors() != null) {
		JSONArray col = new JSONArray();
		String[] arr = cv.getColors().split(",");
		for (String arr1 : arr) {
		    col.put(arr1);
		}
		high.put("colors", col);
	    }

	    JSONObject plotOptionsSeries = new JSONObject();

	    // stacking
	    if (cv.getStacking() != null) {
		plotOptionsSeries.put("stacking", cv.getStacking());
	    }

	    if (cv.getOnmouseover() != null && !cv.getOnmouseover().isEmpty()) {
		JSONObject events = new JSONObject();
		events.put("mouseOver", new JSONFunction(cv.getOnmouseover()));
		plotOptionsSeries.put("events", events);
	    }

	    if (cv.getOnmouseoverpoint() != null && !cv.getOnmouseoverpoint().isEmpty()) {
		JSONObject point = new JSONObject();
		JSONObject events = new JSONObject();
		plotOptionsSeries.put("point", point);
		point.put("events", events);
		events.put("mouseOver", new JSONFunction(cv.getOnmouseoverpoint()));
	    }
	    if (plotOptionsSeries.length() > 0) {
		plotOptions.put("series", plotOptionsSeries);
	    }

	    // Title Object
	    JSONObject title = new JSONObject();
	    title.put("text", cv.getTitle());
	    high.put("title", title);
	    // Subtitle Object
	    if (cv.getSubTitle() != null) {
		JSONObject stitle = new JSONObject();
		stitle.put("text", cv.getSubTitle());
		high.put("subtitle", stitle);
	    }

	    // Axis Objects
	    encodeAxes(context, cv, high);
	    JSONArray yaxes = high.optJSONArray("yAxis");
	    if (yaxes == null) {
		yaxes = new JSONArray();
	    }
	    // Optional Child Objects
	    for (UIComponent component : cv.getChildren()) {
		if (component instanceof ChartLegend) {
		    ChartLegend legend = (ChartLegend) component;
		    JSONObject l = new JSONObject();
		    if (legend.getStyle() != null) {
			String[] separated = legend.getStyle().toString().split(";");
			for (String s : separated) {
			    String[] sep2 = s.split(":");
			    l.put(sep2[0], sep2[1]);
			}
		    }
		    if (!legend.getEnabled()) {
			l.put("enabled", false);
		    }
		    if (legend.getLayout() != null) {
			l.put("layout", legend.getLayout());
		    }
		    if (legend.getBackgroundColor() != null) {
			l.put("backgroundColor", legend.getBackgroundColor());
		    }
		    if (legend.getPosition() != null) {
			String pos = legend.getPosition().toString();
			if (pos.startsWith("n")) {
			    l.put("verticalAlign", "top");
			} else if (pos.startsWith("s")) {
			    l.put("verticalAlign", "bottom");
			} else {
			    l.put("verticalAlign", "middle");
			}
			if (pos.endsWith("e")) {
			    l.put("align", "right");
			} else if (pos.endsWith("w")) {
			    l.put("align", "left");
			} else {
			    l.put("align", "center");
			}
		    }
		    if (legend.getTitle() != null) {
			JSONObject tt = new JSONObject();
			tt.put("text", legend.getTitle());
			l.put("title", tt);
		    }
		    high.put("legend", l);
		} else if (component instanceof ChartTooltip) {
		    ChartTooltip tooltip = (ChartTooltip) component;
		    JSONObject l = new JSONObject();
		    if (tooltip.getStyle() != null) {
			JSONObject st = new JSONObject();
			String[] separated = tooltip.getStyle().toString().split(";");
			for (String s : separated) {
			    String[] sep2 = s.split(":");
			    st.put(sep2[0], sep2[1]);
			}
			l.put("style", st);
		    }

		    if (tooltip.getBackgroundColor() != null) {
			l.put("backgroundColor", tooltip.getBackgroundColor());
		    }
		    if (tooltip.getShared() != null) {
			l.put("shared", tooltip.getShared());
		    }
		    if (tooltip.getFacet("header") != null) {
			UIComponent c = tooltip.getFacet("header");
			ResponseWriter saved = FacesContext.getCurrentInstance().getResponseWriter();
			StringWriter sw = new StringWriter();
			StreamResponseWriter srw = new StreamResponseWriter(sw);

			FacesContext.getCurrentInstance().setResponseWriter(srw);
			c.encodeAll(context);
			l.put("headerFormat", sw.toString());
			l.put("useHTML", true);
			FacesContext.getCurrentInstance().setResponseWriter(saved);
		    }
		    if (tooltip.getFacet("body") != null) {
			UIComponent c = tooltip.getFacet("body");
			ResponseWriter saved = FacesContext.getCurrentInstance().getResponseWriter();
			StringWriter sw = new StringWriter();
			StreamResponseWriter srw = new StreamResponseWriter(sw);

			FacesContext.getCurrentInstance().setResponseWriter(srw);
			c.encodeAll(context);
			l.put("pointFormat", sw.toString());
			l.put("useHTML", true);
			FacesContext.getCurrentInstance().setResponseWriter(saved);
		    }
		    if (tooltip.getFacet("footer") != null) {
			UIComponent c = tooltip.getFacet("footer");
			ResponseWriter saved = FacesContext.getCurrentInstance().getResponseWriter();
			StringWriter sw = new StringWriter();
			StreamResponseWriter srw = new StreamResponseWriter(sw);

			FacesContext.getCurrentInstance().setResponseWriter(srw);
			c.encodeAll(context);
			l.put("footerFormat", sw.toString());

			FacesContext.getCurrentInstance().setResponseWriter(saved);
			l.put("useHTML", true);
		    }
		    high.put("tooltip", l);
		}
	    }
	    // Encoding Series
	    JSONArray series = new JSONArray();
	    if (cv.getValue() != null) {
		encodeSimpleSeries(context, cv, series);
	    }
	    if (cv.getModel() != null) {
		if (cv.getModel() instanceof ChartModel) {
		    ChartModel model = (ChartModel) cv.getModel();
		    for (ChartSeries serie : model.getSeries()) {
			JSONObject jSerie = encodeSerie(context, cv, serie, (List) serie.getValue(), true);
			if (serie.getYaxis() != null) {
			    for (int i = 0; i < yaxes.length(); i++) {
				if (yaxes.getJSONObject(i).optString("id", "").equals(serie.getYaxis())) {
				    jSerie.put("yAxis", i);
				}
			    }
			}
			series.put(jSerie);
			// pie charts treatment
			if ("pie".equals(serie.getType()) || "pie".equals(cv.getType())) {
			    JSONObject pie = new JSONObject();
			    pie.put("allowPointSelect", true);
			    pie.put("cursor", "pointer");

			    plotOptions.put("pie", pie);
			}
		    }
		}
	    }
	    for (UIComponent comp : cv.getChildren()) {
		if (comp instanceof ChartSerie) {
		    ChartSerie serie = (ChartSerie) comp;
		    JSONObject jSerie = encodeSerie(context, cv, serie, (Collection) serie.getValue(), true);
		    if (serie.getYaxis() != null) {
			for (int i = 0; i < yaxes.length(); i++) {
			    if (yaxes.getJSONObject(i).optString("id", "").equals(serie.getYaxis())) {
				jSerie.put("yAxis", i);
			    }
			}
		    }
		    series.put(jSerie);
		    // pie charts treatment
		    if ("pie".equals(serie.getType()) || "pie".equals(cv.getType())) {
			JSONObject pie = new JSONObject();
			pie.put("allowPointSelect", true);
			pie.put("cursor", "pointer");

			plotOptions.put("pie", pie);
		    }
		}
	    }

	    high.put("series", series);
	    if (plotOptions.length() != 0) {
		high.put("plotOptions", plotOptions);
	    }

	    responseWriter.write(high.toString());
	    responseWriter.write(";");
	    if (cv.getExtender() != null) {
		responseWriter.write("options.extender = " + cv.getExtender() + ";");
		responseWriter.write("options.extender();");
	    }
	    responseWriter.write("$('#" + div_id + "').highcharts(options);");
	    responseWriter.write("});");

	    responseWriter.endElement("script");
	} catch (JSONException ex) {
	    Logger.getLogger(ChartRenderer.class.getName()).log(Level.SEVERE, null, ex);
	}
    }

    private void encodeSimpleSeries(FacesContext context, Chart cv, JSONArray target) throws IOException, JSONException {
	if (cv.getValue() instanceof Map) {
	    for (Object o : ((Map) cv.getValue()).entrySet()) {
		Map.Entry e = (Map.Entry) o;
		DefaultChartSeries serie = new DefaultChartSeries();
		serie.setName(e.getKey().toString());
		target.put(encodeSerie(context, cv, serie, (Collection) e.getValue(), true));
	    }
	} else if (cv.getValue() instanceof Collection) {
	    Collection coll = (Collection) cv.getValue();
	    target.put(encodeSerie(context, cv, null, coll, true));
	}
    }

    private JSONObject encodeSerie(FacesContext context, Chart cv, ChartSeries serie, Collection coll, boolean addEvents) throws IOException, JSONException {
	JSONObject result = new JSONObject();
	if (serie != null && serie.getName() != null) {
	    result.put("name", serie.getName());
	}
	if (serie != null && serie.getType() != null) {
	    result.put("type", serie.getType());

	}
	if (serie != null && serie.getColorByPoint()) {
	    result.put("colorByPoint", true);

	}
	JSONArray data = new JSONArray();
	Iterator it = coll.iterator();
	Integer index = 0;
	// Do we need Pie Charts treatment ?
	// find out if this series contains datetime stuff
	boolean needNames = (serie != null && ("pie".equals(serie.getType()) || ("pie".equals(cv.getType()) && serie.getType() == null)));
	if (!needNames && "datetime".equals(getAxisType(cv, serie))) {
	    needNames = true;

	}

	while (it.hasNext()) {
	    Object o = it.next();
	    // assigning the value to the var
	    if (serie != null && serie.getVar() != null) {
		Map requestMap = context.getExternalContext().getRequestMap();
		requestMap.put(serie.getVar(), o);
	    } else if (cv.getVar() != null) {
		Map requestMap = context.getExternalContext().getRequestMap();
		requestMap.put(cv.getVar(), o);

	    }
	    if (cv.getRowIndexVar() != null) {
		Map requestMap = context.getExternalContext().getRequestMap();
		requestMap.put(cv.getRowIndexVar(), index);
	    }

	    if (needNames) {
		Object value = null;
		Object name = null;
		if (serie != null && serie.getVar() != null && serie.getPoint() != null) {
		    if (serie.getValueExpression("point") != null) {
			value = (new JSONFunction(serie.getPoint().toString()));
		    } else {
			value = (new JSONFunction(context.getApplication().getELResolver().getValue(context.getELContext(), serie.getVar(), serie.getPoint()).toString()));
		    }
		} else if (cv.getVar() != null && cv.getPoint() != null) {
		    if (cv.getValueExpression("point") != null) {
			value = (new JSONFunction(cv.getPoint().toString()));
		    } else {
			value = (new JSONFunction(context.getApplication().getELResolver().getValue(context.getELContext(), cv.getVar(), cv.getPoint()).toString()));
		    }
		} else {
		    value = (new JSONFunction(o.toString()));
		}
		if (o instanceof DataPoint) {
		    value = ((DataPoint) o).getValue();
		    name = ((DataPoint) o).getName();
		    JSONArray a = new JSONArray();
		    if (name instanceof Date) {
			a.put(((Date) name).getTime());
		    } else {
			a.put(name);
		    }
		    a.put(value);
		    data.put(a);
		} else if (serie != null && serie.getTickLabel() != null) {
		    name = serie.getTickLabel();
		    JSONArray a = new JSONArray();
		    if (name instanceof Date) {
			a.put(((Date) name).getTime());
		    } else {
			a.put(name);
		    }
		    a.put(value);
		    data.put(a);
		} else if ((serie == null || serie.getVar() == null) && cv.getTickLabel() != null) {
		    name = cv.getTickLabel();
		    JSONArray a = new JSONArray();
		    if (name instanceof Date) {
			a.put(((Date) name).getTime());
		    } else {
			a.put(name);
		    }
		    a.put(value);
		    data.put(a);
		} else {
		    /*
                     System.out.println("Serie: " + serie);
                     if (serie != null) {
                     System.out.println("serie.getVar()=" + serie.getVar());
                     }
                     System.out.println("cv.getTickLabel()=" + cv.getTickLabel());
		     */
		    data.put(value);
		}

	    } else {
		Object object;
		Object value;
		if (o instanceof DataPoint) {
		    value = ((DataPoint) o).getValue();
		} else if (serie != null && serie.getVar() != null && serie.getPoint() != null) {
		    if (serie.getValueExpression("point") != null) {
			value = serie.getPoint();
		    } else {
			value = context.getApplication().getELResolver().getValue(context.getELContext(), serie.getVar(), serie.getPoint());
		    }
		} else if (cv.getVar() != null && cv.getPoint() != null) {
		    if (cv.getValueExpression("point") != null) {
			value = cv.getPoint();
		    } else {
			value = context.getApplication().getELResolver().getValue(context.getELContext(), cv.getVar(), cv.getPoint());
		    }
		} else {
		    value = o;
		}
		if (isJsonable(value)) {
		    object = new JSONFunction(value.toString());
		} else {
		    object = new JSONObject(value);
		}
		data.put(object);
	    }
	    index++;
	}
	if (serie != null && serie.getVar() != null) {
	    Map requestMap = context.getExternalContext().getRequestMap();
	    requestMap.remove(serie.getVar());
	}
	if (cv.getVar() != null) {
	    Map requestMap = context.getExternalContext().getRequestMap();
	    requestMap.remove(cv.getVar());
	}
	if (cv.getRowIndexVar() != null) {
	    Map requestMap = context.getExternalContext().getRequestMap();
	    requestMap.remove(cv.getRowIndexVar());
	}
	result.put("data", data);
	if (serie != null && serie.getDataLabel() != null) {
	    JSONObject dataLabels = new JSONObject();
	    dataLabels.put("enabled", true);
	    dataLabels.put("format", serie.getDataLabel());
	    result.put("dataLabels", dataLabels);
	}
	if (serie != null && (cv.getSelectedPoint() != null || cv.getSelectedSeries() != null)) {
	    JSONObject point = new JSONObject();
	    JSONObject events = new JSONObject();
	    String escaped = cv.getClientId().replaceAll(":", "\\\\\\\\:");

	    ClientBehaviorContext clientBehaviorContext = ClientBehaviorContext.createClientBehaviorContext(context, cv, "select", cv.getClientId(context), null);
	    StringBuilder builder = new StringBuilder();
	    if (cv.getClientBehaviors() != null && cv.getClientBehaviors().get("select") != null) {
		for (ClientBehavior behavior : cv.getClientBehaviors().get("select")) {
		    builder.append(behavior.getScript(clientBehaviorContext));
		    builder.append(';');
		}
	    }

	    String onclick = builder.toString();
	    events.put("click", new JSONFunction("function () {$('#" + escaped + "_selectedSeries').val('" + serie.getName() + "');$('#" + escaped + "_selectedPoint').val(" + (("pie".equals(serie.getType()) || ("pie".equals(cv.getType()) && serie.getType() == null)) ? "this.name" : "this.category") + ");" + onclick + "}"));
	    if (addEvents) {
		point.put("events", events);
	    }
	    result.put("point", point);
	}
	return result;
    }
    private static final Logger LOG = Logger.getLogger(ChartRenderer.class.getName());

    private JSONArray encodeTickLabel(FacesContext context, Chart cv) throws IOException {
	JSONArray arr = null;
	if (cv.getValue() instanceof Map) {
	    Iterator it = ((Map) cv.getValue()).entrySet().iterator();
	    if (it.hasNext()) {
		Map.Entry entry = (Map.Entry) it.next();
		if (entry.getValue() instanceof Collection) {
		    arr = encodeTickLabel(context, cv, (Collection) entry.getValue());
		}
	    }
	} else if (cv.getValue() instanceof Collection) {
	    arr = encodeTickLabel(context, cv, (Collection) cv.getValue());
	}
	return arr;
    }

    private JSONArray encodeTickLabel(FacesContext context, Chart cv, Collection collection) throws IOException {
	JSONArray arr = new JSONArray();
	Iterator it = collection.iterator();
	boolean isFirst = true;
	Map requestMap = context.getExternalContext().getRequestMap();
	Integer index = 0;
	while (it.hasNext()) {
	    Object o = it.next();
	    if (cv.getRowIndexVar() != null) {
		requestMap.put(cv.getRowIndexVar(), index);
	    }

	    isFirst = false;

	    requestMap.put(cv.getVar(), o);
	    if (o instanceof DataPoint) {
		Object ob = ((DataPoint) o).getName();
		if (ob instanceof Date) {
		    arr.put(((Date) ob).getTime());
		} else {
		    arr.put(ob.toString());
		}
	    } else {
		Object ob = cv.getTickLabel();
		if (ob instanceof Date) {
		    arr.put(((Date) ob).getTime());
		} else {
		    arr.put(ob.toString());
		}
	    }
	    index++;
	}
	requestMap.remove(cv.getVar());
	if (cv.getRowIndexVar() != null) {
	    requestMap.remove(cv.getRowIndexVar());
	}
	return arr;
    }

    private JSONArray encodeTickLabel(FacesContext context, Chart chart, ChartSerie cv) {
	JSONArray arr = null;
	if (cv.getValue() instanceof Map) {
	    Iterator it = ((Map) cv.getValue()).entrySet().iterator();
	    if (it.hasNext()) {
		Map.Entry entry = (Map.Entry) it.next();
		if (entry.getValue() instanceof Collection) {
		    arr = encodeTickLabel(context, chart, cv, (Collection) entry.getValue());
		}
	    }
	} else if (cv.getValue() instanceof Collection) {
	    arr = encodeTickLabel(context, chart, cv, (Collection) cv.getValue());
	}
	return arr;
    }

    private JSONArray encodeTickLabel(FacesContext context, Chart chart, ChartSeries cv, Collection collection) {
	JSONArray arr = new JSONArray();
	Iterator it = collection.iterator();

	Map requestMap = context.getExternalContext().getRequestMap();
	Integer index = 0;
	while (it.hasNext()) {
	    Object o = it.next();
	    if (chart.getRowIndexVar() != null) {
		requestMap.put(chart.getRowIndexVar(), index);
	    }
	    if (cv.getVar() != null) {
		requestMap.put(cv.getVar(), o);
	    }
	    if (o instanceof DataPoint) {
		Object ob = ((DataPoint) o).getName();
		if (ob instanceof Date) {
		    arr.put(((Date) ob).getTime());
		} else {
		    arr.put(ob.toString());
		}
	    } else {
		Object ob = cv.getTickLabel();
		if (ob instanceof Date) {
		    arr.put(((Date) ob).getTime());
		} else {
		    arr.put(ob.toString());
		}
	    }
	    index++;
	}
	if (cv.getVar() != null) {
	    requestMap.remove(cv.getVar());
	}
	if (chart.getRowIndexVar() != null) {
	    requestMap.remove(chart.getRowIndexVar());
	}
	return arr;
    }

    private void encodeAxes(FacesContext context, Chart cv, JSONObject high) throws JSONException, IOException {
	// First of all let's see if we have some declared ChartAxis components
	JSONArray xaxes = new JSONArray();
	JSONArray yaxes = new JSONArray();
	for (UIComponent component : cv.getChildren()) {
	    if (component instanceof ChartAxis) {
		ChartAxis axis = (ChartAxis) component;
		JSONObject j = new JSONObject();
		if (axis.getId() != null) {
		    j.put("id", axis.getId());
		}
		if (axis.getType() != null) {
		    j.put("type", axis.getType());
		}
		if (axis.getMin() != null) {
		    j.put("min", axis.getMin());
		}
		if (axis.getMax() != null) {
		    j.put("max", axis.getMax());
		}
		if (axis.getGridLineColor() != null) {
		    j.put("gridLineColor", axis.getGridLineColor());
		}
		if (axis.getGridLineWidth() != null) {
		    j.put("gridLineWidth", axis.getGridLineWidth());
		}
		if (axis.getStyle() != null || axis.getFormat() != null || axis.getTickAngle() != null) {
		    JSONObject labels = new JSONObject();
		    if (axis.getFormat() != null) {
			labels.put("format", axis.getFormat());
		    }
		    if (axis.getStyle() != null) {
			String[] separated = axis.getStyle().toString().split(";");
			JSONObject st = new JSONObject();
			for (String s : separated) {
			    String[] sep2 = s.split(":");
			    st.put(sep2[0], sep2[1]);
			}
			labels.put("style", st);
		    }
		    if (axis.getTickAngle() != null) {
			labels.put("rotation", new JSONFunction(axis.getTickAngle().toString()));
		    }
		    j.put("labels", labels);

		}
		if (axis.getTitle() != null) {
		    JSONObject axistitle = new JSONObject();
		    axistitle.put("text", axis.getTitle());
		    j.put("title", axistitle);
		}

		if ("e".equals(axis.getPosition()) || "n".equals(axis.getPosition())) {
		    j.put("opposite", true);
		}
		if ("n".equals(axis.getPosition()) || "s".equals(axis.getPosition())) {
		    xaxes.put(j);
		} else {
		    yaxes.put(j);
		}
	    }
	}
	// now let's see if we have some in the ChartModel
	if (cv.getModel() != null && cv.getModel() instanceof ChartModel) {
	    ChartModel model = (ChartModel) cv.getModel();

	}
	// Then let's analyze if something is defined in the chart itself
	if (cv.getValueExpression("tickLabel") != null && cv.getValue() != null) {
	    if (xaxes.length() == 0) {
		JSONObject xAxis = new JSONObject();

		xAxis.put("categories", encodeTickLabel(context, cv));
		if (cv.getXaxisLabel() != null) {
		    JSONObject j = new JSONObject();
		    j.put("text", cv.getXaxisLabel());
		    xAxis.put("title", j);
		}
		xaxes.put(xAxis);

	    }
	}

	// finally check the chart series for some tickLabel attributes
	if (xaxes.length() == 0) {
	    if (cv.getModel() != null && cv.getModel() instanceof ChartModel) {
		ChartModel model = (ChartModel) cv.getModel();
		for (ChartSeries serie : model.getSeries()) {
		    if (serie.getValueExpression("tickLabel") != null && serie.getValue() != null) {
			if (xaxes.length() == 0) {
			    JSONObject xAxis = new JSONObject();

			    xAxis.put("categories", encodeTickLabel(context, cv, serie, (Collection) serie.getValue()));
			    if (cv.getXaxisLabel() != null) {
				JSONObject j = new JSONObject();
				j.put("text", cv.getXaxisLabel());
				xAxis.put("title", j);
			    }
			    xaxes.put(xAxis);
			}
		    }
		}
	    }
	    if (xaxes.length() == 0) {
		for (UIComponent comp : cv.getChildren()) {
		    if (comp instanceof ChartSerie) {
			ChartSerie serie = (ChartSerie) comp;

			if (serie.getValueExpression("tickLabel") != null && serie.getValue() != null) {
			    if (xaxes.length() == 0) {
				JSONObject xAxis = new JSONObject();

				xAxis.put("categories", encodeTickLabel(context, cv, serie));
				if (cv.getXaxisLabel() != null) {
				    JSONObject j = new JSONObject();
				    j.put("text", cv.getXaxisLabel());
				    xAxis.put("title", j);
				}
				xaxes.put(xAxis);
			    }
			}
		    }
		}
	    }
	}

	// if nothing is found. let's do some default axes
	if (xaxes.length() == 0 && cv.getXaxisLabel() != null) {
	    JSONObject xAxis = new JSONObject();

	    JSONObject j = new JSONObject();
	    j.put("text", cv.getXaxisLabel());
	    xAxis.put("title", j);

	    xaxes.put(xAxis);
	}
	if (yaxes.length() == 0 && cv.getYaxisLabel() != null) {
	    JSONObject yAxis = new JSONObject();

	    JSONObject j = new JSONObject();
	    j.put("text", cv.getYaxisLabel());
	    yAxis.put("title", j);

	    yaxes.put(yAxis);
	}
	if (xaxes.length() == 0 && cv.getModel() != null) {
	    ChartModel model = (ChartModel) cv.getModel();
	    if (model.getSeries() != null) {
		ChartSeries serie = model.getSeries().get(0);
		JSONObject xAxis = new JSONObject();

		xAxis.put("categories", encodeTickLabel(context, cv, serie, (Collection) serie.getValue()));
		if (cv.getXaxisLabel() != null) {
		    JSONObject j = new JSONObject();
		    j.put("text", cv.getXaxisLabel());
		    xAxis.put("title", j);
		}
		xaxes.put(xAxis);
	    }
	}
	/* if (xaxes.length() == 1) {
         high.put("xAxis", xaxes.getJSONObject(0));
         } else */ if (xaxes.length() > 0) {
	    high.put("xAxis", xaxes);
	}
	/* if (yaxes.length() == 1) {
         high.put("yAxis", yaxes.getJSONObject(0));
         } else*/ if (yaxes.length() > 0) {
	    high.put("yAxis", yaxes);
	}
    }

    private String getAxisType(Chart cv, ChartSeries serie) {
	String result = "category";
	for (UIComponent c : cv.getChildren()) {
	    if (c instanceof ChartAxis) {
		ChartAxis axis = (ChartAxis) c;
		if ("s".equals(axis.getPosition()) || "n".equals(axis.getPosition())) {
		    if ("datetime".equals(axis.getType())) {
			return "datetime";
		    }
		}
	    }
	}

	return result;
    }

    private boolean isJsonable(Object object) {
	if (object instanceof CharSequence) {
	    return true;
	} else if (object instanceof Number) {
	    return true;
	}
	return false;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy