Java tutorial
/** * Copyright [2008] [Bayon Technologies, Inc] * 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 com.bayontechnologies.bi.pentaho.plugin.openflashchart; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.pentaho.commons.connection.IPentahoResultSet; import org.pentaho.core.repository.IContentItem; import org.pentaho.core.repository.IContentLocation; import org.pentaho.core.repository.IContentRepository; import org.pentaho.core.session.IPentahoSession; import org.pentaho.core.solution.IActionResource; import org.pentaho.core.system.PentahoSystem; import org.pentaho.messages.util.LocaleHelper; import org.pentaho.plugin.jfreechart.ChartComponent; import org.pentaho.repository.content.ContentRepository; import org.pentaho.util.UUIDUtil; /** * To integrate the open-flash-chart, we write this component. * This component has the following parameters: * ?chart_template-----optional, * ?chart_template_string-----optional,Contains the open flash chart template for this chart, along with the required tokens for replacing values in the chart with values from the dataset * ?chart_dataset (required), * ?chart_width, * ?chart_height, * ?ofc_url.It is the URL of the open flash chart .swf file. Defaults to the pentaho base URL (style deployment) / images / open-flash-chart.swf. * For instance, http://localhost:8080/pentaho-style/images/open-flash-chart.swf. * * @author tom qin * */ public class OpenFlashChartComponent extends ChartComponent { public static final String LOCATION_DIR_PATH = "OpenFlashChart"; private static final long serialVersionUID = 825147871232129168L; private static final Log log = LogFactory.getLog(OpenFlashChartComponent.class); private static final String CHART_DATA_PROP = "chart_dataset"; private static final String CHART_WIDTH = "chart_width"; private static final String CHART_HEIGHT = "chart_height"; private static final String OFC_URL = "ofc_url"; private static final String CHART_TEMPLATE_STRING = "chart_template_string"; private static final String CHART_TEMPLATE = "chart_template"; protected int width = 500; protected int height = 300; protected String template = null; protected IPentahoResultSet data = null; Map<String, ArrayList<String>> map = null; protected static String flashFragment; static { flashFragment = "<object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000'" + "codebase='http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0'" + "width='{chart-width}' height='{chart-height}' id='graph-2' align='middle'>" + "<param name='allowScriptAccess' value='sameDomain' />" + "<param name='movie' value='{ofc-url}?width={chart-width}&height={chart-height}&data={data}' />" + "<param name='quality' value='high' /><param name='bgcolor' value='#FFFFFF' /> " + "<embed src='{ofc-url}?width={chart-width}&height={chart-height}&data={data}' quality='high' bgcolor='#FFFFFF'" + "width='{chart-width}' height='{chart-height}' name='open-flash-chart' align='middle' allowScriptAccess='sameDomain'" + "type='application/x-shockwave-flash' pluginspage='http://www.macromedia.com/go/getflashplayer' /> </object>"; } public OpenFlashChartComponent() { } public OpenFlashChartComponent(String template, int width, int height, IPentahoResultSet data) { this.template = template; this.width = width; this.height = height; this.data = data; } protected boolean validateAction() { // See if we have the chart data if (!isDefinedInput(CHART_DATA_PROP)) { inputMissingError(CHART_DATA_PROP); return false; } //See if we have the chart definition if (!isDefinedInput(CHART_TEMPLATE_STRING)) { if (!isDefinedResource(CHART_TEMPLATE)) { inputMissingError(CHART_TEMPLATE); return false; } } return true; } protected boolean executeAction() { //get the input datas IPentahoResultSet data = (IPentahoResultSet) getInputValue(CHART_DATA_PROP); String chartTemplateString = getInputStringValue(CHART_TEMPLATE_STRING); Integer chartWidth = null; IPentahoSession userSession = this.getSession(); String input1 = getInputStringValue(CHART_WIDTH); if (null == input1) { chartWidth = new Integer(this.width); } else { chartWidth = Integer.valueOf(input1); } Integer chartHeight = null; String input2 = getInputStringValue(CHART_HEIGHT); if (null == input2) { chartHeight = new Integer(this.height); } else { chartHeight = Integer.valueOf(input2); } IActionResource fileResource = null; String ofcURL = getInputStringValue(OFC_URL); if (ofcURL == null || "".equals(ofcURL)) { ofcURL = "/pentaho-style/images/open-flash-chart.swf"; } if (chartTemplateString == null || chartTemplateString.equals("")) { fileResource = this.getResource(CHART_TEMPLATE); try { chartTemplateString = PentahoSystem.getSolutionRepository(userSession) .getResourceAsString(fileResource); } catch (IOException e) { error(e.getLocalizedMessage()); return false; } } //parse the chart Template String and get the parsed tokens map = parseString(chartTemplateString); chartTemplateString = replaceChartDefParams(chartTemplateString, data); //replace the custom variables ArrayList<String> customs = map.get("customs"); Set inputNames = this.getInputNames(); for (Iterator iterator = inputNames.iterator(); iterator.hasNext();) { String name = (String) iterator.next(); if (customs.contains(name)) { Object value = this.getInputValue(name); chartTemplateString = replaceLongStr(chartTemplateString, "{" + name + "}", "" + value); } } log.debug("chartTemplateString after replacing:" + chartTemplateString); String solutionName = this.getSolutionName(); //uuid String uuid = "openFlashChart-" + UUIDUtil.getUUIDAsString(); IContentRepository repository = ContentRepository.getInstance(userSession); IContentLocation cl = null; cl = repository.getContentLocationByPath(LOCATION_DIR_PATH); if (cl == null) cl = repository.newContentLocation(LOCATION_DIR_PATH, solutionName, solutionName, this.getId(), true); //Fix me, to create a new contentitem every time is not a good choice. //Maybe we can remove the older and create a new one. But I can't find the solution right now. :( IContentItem citem = cl.newContentItem(uuid, uuid, this.getActionTitle(), "txt", "text/plain", "", IContentItem.WRITEMODE_OVERWRITE); try { //get the outputstream and write the content into the repository. OutputStream os = citem.getOutputStream(this.getActionName()); os.write(chartTemplateString.getBytes(LocaleHelper.getSystemEncoding())); os.close(); } catch (IOException e) { error(e.getLocalizedMessage()); return false; } //replace the parameters in the flashFragment String flashContent = replace(flashFragment, citem.getId(), chartWidth, chartHeight, ofcURL); log.debug("html_fragment=" + flashContent); Set outputNames = this.getOutputNames(); if (outputNames.contains("html_fragment")) { this.setOutputValue("html_fragment", flashContent); } if (outputNames.contains("content_url")) { this.setOutputValue("content_url", this.getTmpContentURL(citem.getId())); } return true; } /** * 1.? {colN} will be replaced with a comma separated list of values of the column in N in the dataset. * For instance,x_values={col1}could be replaced with the values in the FIRST column of the data set * x_values=2039,193,8930,3839,1023 * ?2. {minN} will be replaced with the minimum value in the column N in the dataset. * 3. ?{maxN} will be replaced with the maximum value in the column N in the dataset. * 4. ?{headN} will be replaced with the header value for the column N in the dataset. * @param chartTemplateString * @return the clear chart definition string. */ public String replaceChartDefParams(String chartTemplateString, IPentahoResultSet data) { ArrayList<String> columns = map.get("colN"); ArrayList<String> maxs = map.get("maxN"); ArrayList<String> mins = map.get("minN"); if (columns.size() == 0) { return chartTemplateString; } String[] colValues = new String[columns.size()]; for (int i = 0; i < colValues.length; i++) { colValues[i] = ""; } Object[] maxValues = new Object[maxs.size()]; Object[] minValues = new Object[mins.size()]; int rowCount = data.getRowCount(); Object max = null; Object min = null; for (int j = 0; j < rowCount; j++) { for (int i = 0; i < columns.size(); i++) { String column = columns.get(i); // k is from 1 to N int k = Integer.valueOf(column.substring(column.indexOf("col") + "col".length())); //get the value of colN Object obj = data.getValueAt(j, k - 1); if (null == obj) { continue; } colValues[i] = colValues[i] + obj; if (j < rowCount - 1) { colValues[i] = colValues[i] + ","; } } //maxN can have more than one //minN can have more than one for (int i = 0; i < maxs.size(); i++) { String maxN = maxs.get(i); int k = Integer.valueOf(maxN.substring(maxN.indexOf("max") + "max".length())); Object obj = data.getValueAt(j, k - 1); if (null == obj) { continue; } if (j == 0) { // max = obj; // min = obj; if (maxValues.length > 0) { maxValues[i] = obj; } if (minValues.length > 0) { minValues[i] = obj; } continue; } if (obj instanceof Comparable) { // if(((Comparable)obj).compareTo(max)>0) // { // max = obj; // } // else if(((Comparable)obj).compareTo(min)<0) // { // min = obj; // } if (maxValues.length > 0 && ((Comparable) obj).compareTo(maxValues[i]) > 0) { maxValues[i] = obj; } else if (minValues.length > 0 && ((Comparable) obj).compareTo(minValues[i]) < 0) { minValues[i] = obj; } } } } for (int i = 0; i < colValues.length; i++) { String values = colValues[i]; chartTemplateString = replaceLongStr(chartTemplateString, "{" + columns.get(i) + "}", values); } //replace the maxN and minN for (int i = 0; i < maxs.size(); i++) { chartTemplateString = replaceLongStr(chartTemplateString, "{" + maxs.get(i) + "}", "" + maxValues[i]); } for (int i = 0; i < mins.size(); i++) { chartTemplateString = replaceLongStr(chartTemplateString, "{" + mins.get(i) + "}", "" + minValues[i]); } //replace headers Object[][] objs = data.getMetaData().getColumnHeaders(); if (null == objs) { return chartTemplateString; } Object headers[] = objs[0]; ArrayList<String> heads = map.get("headN"); ArrayList<String> colHeaders = new ArrayList<String>(heads.size()); for (int i = 0; i < heads.size(); i++) { String head = heads.get(i); // k is from 1 to N int k = Integer.valueOf(head.substring(head.indexOf("head") + "head".length())); chartTemplateString = replaceLongStr(chartTemplateString, "{" + head + "}", "" + headers[k - 1]); } return chartTemplateString; } /** * Flash Template String Replacement. It is the latest replacement. * @param flashFragment2 the flash template * @param id the id of the content item * @param chartWidth * @param chartHeight * @param ofcURL * @return the working flash codes */ public String replace(String flashFragment2, String id, Integer chartWidth, Integer chartHeight, String ofcURL) { StringBuffer buff = new StringBuffer(flashFragment2); //replace the {chart-width} String token = "{chart-width}"; int index; replaceByToken(buff, "" + chartWidth, token); //replace the {chart-height} token = "{chart-height}"; replaceByToken(buff, "" + chartHeight, token); //replace the {ofc-url} token = "{ofc-url}"; replaceByToken(buff, ofcURL, token); //replace the {data} token = "{data}"; index = buff.lastIndexOf(token); buff.replace(index, index + token.length(), getTmpContentURL(id)); //replace the {data} again index = buff.lastIndexOf(token); if (index != -1) { buff.replace(index, index + token.length(), getTmpContentURL(id)); } log.debug(" flash codes after replacing:" + buff.toString()); return buff.toString(); } private String getTmpContentURL(String id) { return PentahoSystem.getApplicationContext().getBaseUrl() + "GetContent?id=" + id; } private StringBuffer replaceByToken(StringBuffer buff, String value, String token) { int index = buff.indexOf(token); buff.replace(index, index + token.length(), value); if (buff.indexOf(token) != -1) { //loop replaceByToken again until there is no token at all. return replaceByToken(buff, value, token); } return buff; } public void done() { //clear something } public boolean init() { // nothing to do here really return true; } public static Map<String, ArrayList<String>> parseString(final String template) { Map<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>(); ArrayList<String> columns = new ArrayList<String>(); ArrayList<String> headers = new ArrayList<String>(); ArrayList<String> maxs = new ArrayList<String>(); ArrayList<String> mins = new ArrayList<String>(); ArrayList<String> customs = new ArrayList<String>(); String token1 = "{"; String token2 = "}"; String tmpTemplate = template; int index = tmpTemplate.indexOf(token1); int index2 = tmpTemplate.indexOf(token2); while (index != -1) { String tmpStr = tmpTemplate.substring(index + 1, index2); //check the illegal token if (tmpStr.indexOf(":") != -1 || tmpStr.indexOf(";") != -1) { tmpTemplate = tmpTemplate.substring(0, index - 1 >= 0 ? index - 1 : 0) + tmpTemplate.substring(index2 + 1); index = tmpTemplate.indexOf(token1); index2 = tmpTemplate.indexOf(token2); continue; } if (tmpStr.indexOf("col") != -1) { if (!columns.contains(tmpStr)) columns.add(tmpStr); } else if (tmpStr.indexOf("head") != -1) { if (!headers.contains(tmpStr)) headers.add(tmpStr); } else if (tmpStr.indexOf("max") != -1) { if (!maxs.contains(tmpStr)) maxs.add(tmpStr); } else if (tmpStr.indexOf("min") != -1) { if (!mins.contains(tmpStr)) mins.add(tmpStr); } else //any other my custom variable { if (!customs.contains(tmpStr)) customs.add(tmpStr); } tmpTemplate = tmpTemplate.substring(0, index - 1 >= 0 ? index - 1 : 0) + tmpTemplate.substring(index2 + 1); index = tmpTemplate.indexOf(token1); index2 = tmpTemplate.indexOf(token2); } map.put("colN", columns); map.put("headN", headers); map.put("maxN", maxs); map.put("minN", mins); map.put("customs", customs); return map; } public static String replaceLongStr(String str, String fromStr, String toStr) { StringBuffer result = new StringBuffer(); if (str != null && !str.equals("")) { while (str.indexOf(fromStr) != -1) { result.append(str.substring(0, str.indexOf(fromStr))); result.append(toStr); str = str.substring(str.indexOf(fromStr) + fromStr.length()); System.out.println(str); } result.append(str); } return result.toString(); } // public static void main(String[] args) { // OpenFlashChartComponent test = new OpenFlashChartComponent(); // String a = "<![CDATA[&is_thousand_separator_disabled=false&&title=Actuals By Region,{font-size:18px; color: #d01f3c}& &x_axis_steps=1& &y_ticks=5,10,5& &line=3,#87421F& &y_min=0& &y_max=20& &pie=60,#505050,{font-size: 12px; color: #404040;}& &values={col1}& &pie_labels={head1}{head1}& &colours=#d01f3c,#356aa0,#C79810& &links=& &tool_tip=%23val%23&]]></default-value>"; // String token1 = "{"; // String token2 = "}"; // int index = a.indexOf(token1); // int index2 = a.indexOf(token2); // String tmpStr = a.substring(index+1,index2); //// System.out.println(tmpStr); //// System.out.println(a.substring(0,index-1>=0?index-1:0)+a.substring(index2+1)); // System.out.println(parseString(a)); // String t = "col1"; // System.out.println(t.substring(t.indexOf("col")+"col".length())); // System.out.println(replaceLongStr(a,"{head1}","Header1")); //// System.out.println(test.replaceByToken(new StringBuffer(a),"{head1}","Header1")); // // // } }