/*
* Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
package components.components;
import javax.faces.context.FacesContext;
import javax.faces.component.UIOutput;
import javax.faces.el.ValueBinding;
import javax.faces.component.UIComponent;
import javax.faces.context.ResponseWriter;
import javax.faces.component.UIViewRoot;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import components.model.ChartItem;
/**
* <p>{@link ChartComponent} is a JavaServer Faces component that renders
* a given set of data as a bar or pie chart.</p>
*/
public class ChartComponent extends UIOutput {
/**
* <p>The standard component type for this component.</p>
*/
public static final String COMPONENT_TYPE = "Chart";
/**
* <p>The standard component family for this component.</p>
*/
public static final String COMPONENT_FAMILY = "Chart";
/**
* <p>Name of the servlet that renders the image.</p>
*/
public static final String CHART_SERVLET_NAME = "ChartServlet";
// ------------------------------------------------------ Instance Variables
private String width = null;
private String height = null;
private String orientation = null;
private String type = null;
private String title = null;
private String xlabel = null;
private String ylabel = null;
// --------------------------------------------------------------Constructors
public ChartComponent() {
super();
setRendererType(null);
}
// -------------------------------------------------------------- Properties
/**
* <p>Return the width of the chart
*/
public String getWidth() {
if (null != this.width) {
return this.width;
}
ValueBinding _vb = getValueBinding("width");
if (_vb != null) {
return (java.lang.String) _vb.getValue(getFacesContext());
} else {
return null;
}
}
/**
* <p>Set the width of the chart
*
* @param width The new width of the chart
*/
public void setWidth(String width) {
this.width = width;
}
/**
* <p>Return the height of the chart
*/
public String getHeight() {
if (null != this.height) {
return this.height;
}
ValueBinding _vb = getValueBinding("height");
if (_vb != null) {
return (java.lang.String) _vb.getValue(getFacesContext());
} else {
return null;
}
}
/**
* <p>Set the height of the chart
*
* @param height The new height of the chart
*/
public void setHeight(String height) {
this.height = height;
}
/**
* <p>Return the orientation of the chart
*/
public String getOrientation() {
if (null != this.orientation) {
return this.orientation;
}
ValueBinding _vb = getValueBinding("orientation");
if (_vb != null) {
return (java.lang.String) _vb.getValue(getFacesContext());
} else {
return null;
}
}
/**
* <p>Set the orientation of the chart
*
* @param orientation The new orientation of the chart
*/
public void setOrientation(String orientation) {
this.orientation = orientation;
}
/**
* <p>Return the type of the chart
*/
public String getType() {
if (null != this.type) {
return this.type;
}
ValueBinding _vb = getValueBinding("type");
if (_vb != null) {
return (java.lang.String) _vb.getValue(getFacesContext());
} else {
return null;
}
}
/**
* <p>Set the type of the chart
*
* @param type The new type of the chart
*/
public void setType(String type) {
this.type = type;
}
/**
* <p>Return the title of the chart
*/
public String getTitle() {
if (null != this.title) {
return this.title;
}
ValueBinding _vb = getValueBinding("title");
if (_vb != null) {
return (java.lang.String) _vb.getValue(getFacesContext());
} else {
return null;
}
}
/**
* <p>Set the title of the chart
*
* @param title The new title of the chart
*/
public void setTitle(String title) {
this.title = title;
}
/**
* <p>Return the x axis label of the chart
*/
public String getXlabel() {
if (null != this.xlabel) {
return this.xlabel;
}
ValueBinding _vb = getValueBinding("xlabel");
if (_vb != null) {
return (java.lang.String) _vb.getValue(getFacesContext());
} else {
return null;
}
}
/**
* <p>Set the x axis label of the chart
*
* @param xlabel The new x axis label of the chart
*/
public void setXlabel(String xlabel) {
this.xlabel = xlabel;
}
/**
* <p>Return the y axis label of the chart
*/
public String getYlabel() {
if (null != this.ylabel) {
return this.ylabel;
}
ValueBinding _vb = getValueBinding("ylabel");
if (_vb != null) {
return (java.lang.String) _vb.getValue(getFacesContext());
} else {
return null;
}
}
/**
* <p>Set the y axis label of the chart
*
* @param ylabel The new y axis label of the chart
*/
public void setYlabel(String ylabel) {
this.ylabel = ylabel;
}
/**
* <p>Return the component family for this component.
*/
public String getFamily() {
return (COMPONENT_FAMILY);
}
// ----------------------------------------------------- StateHolder Methods
/**
* <p>Return the state to be saved for this component.
*
* @param context <code>FacesContext</code> for the current request
*/
public Object saveState(FacesContext context) {
Object values[] = new Object[8];
values[0] = super.saveState(context);
values[1] = width;
values[2] = height;
values[3] = orientation;
values[4] = type;
values[5] = title;
values[6] = xlabel;
values[7] = ylabel;
return (values);
}
/**
* <p>Restore the state for this component.
*
* @param context <code>FacesContext</code> for the current request
* @param state State to be restored
*
* @throws IOException if an input/output error occurs
*/
public void restoreState(FacesContext context, Object state) {
Object values[] = (Object[]) state;
super.restoreState(context, values[0]);
width = (String) values[1];
height = (String) values[2];
orientation = (String) values[3];
type = (String) values[4];
title = (String) values[5];
xlabel = (String) values[6];
ylabel = (String) values[7];
}
public void encodeEnd(FacesContext context) throws IOException {
placeChartDataInScope(context);
// render an image that would initiate a request to a URL pointing
// back into the webapp passing in whatever parameters are needed to
// create the dynamic image.
ResponseWriter writer = context.getResponseWriter();
writer.startElement("img", this);
writeIdAttributeIfNecessary(context, writer, this);
writer.writeAttribute("src", src(context, this), "value");
writer.endElement("img");
}
// ----------------------------------------------------- Private Methods
protected void writeIdAttributeIfNecessary(FacesContext context,
ResponseWriter writer,
UIComponent component) {
String id;
if ((id = component.getId()) != null &&
!id.startsWith(UIViewRoot.UNIQUE_ID_PREFIX)) {
try {
writer.writeAttribute("id", component.getClientId(context),
"id");
} catch (IOException e) {
/* if (log.isDebugEnabled()) {
log.debug("Can't write ID attribute" + e.getMessage());
} */
}
}
}
private String src(FacesContext context, UIComponent component) {
String contextPath = context.getExternalContext().getRequestContextPath();
StringBuffer result = new StringBuffer(contextPath);
result.append("/");
result.append(CHART_SERVLET_NAME);
// append parameters to be passed to be servlet
// ChartServlet will use clientId as the attribute name to get the chart
// data from session.
result.append("?chartId=");
result.append(getClientId(context));
result.append("&");
result.append("height=");
if ( getHeight() != null ) {
result.append(getHeight());
}
result.append("&");
result.append("width=");
if ( getWidth() != null ) {
result.append(getWidth());
}
result.append("&");
result.append("orientation=");
if ( getOrientation() != null ) {
result.append(getOrientation());
}
result.append("&");
result.append("type=");
if ( type != null ) {
result.append(type);
}
result.append("&");
result.append("title=");
if ( title != null ) {
result.append(title);
}
result.append("&");
result.append("xlabel=");
if ( xlabel != null ) {
result.append(xlabel);
}
result.append("&");
result.append("ylabel=");
if ( ylabel != null ) {
result.append(ylabel);
}
return (result.toString());
}
/** Place the appropriate data for chart in session scope, so that
* it will be there when the separate request for the image is
* processed by the chart servlet. This servlet is responsible for
* writing out the chart as an image into the respone stream.
*/
protected void placeChartDataInScope(FacesContext context) {
int i = 0;
ChartItem[] chartItems = null;
// if there is a value attribute set on the bean, data for the chart is
// retrieved from the bean. If not, we build an array of ChartItem
// using the children of this component.
chartItems = (ChartItem[]) getValue();
if (chartItems == null || chartItems.length == 0 ) {
chartItems = new ChartItem[getChildCount()];
Iterator kids = this.getChildren().iterator();
while ( kids.hasNext()) {
UIComponent kid = (UIComponent) kids.next();
if (kid instanceof ChartItemComponent) {
ChartItemComponent ci = (ChartItemComponent) kid;
ChartItem item = (ChartItem) ci.getValue();
if (item == null) {
int itemVal =
(new Integer((String)ci.getItemValue())).intValue();
item = new ChartItem(ci.getItemLabel(),itemVal,
ci.getItemColor());
}
chartItems[i] = item;
++i;
}
}
}
// store the chart data against the clientId in session.
Map sessionMap =
getFacesContext().getExternalContext().getSessionMap();
sessionMap.put(getClientId(context), chartItems);
}
}