org.bimserver.charting.Charts.Chart.java Source code

Java tutorial

Introduction

Here is the source code for org.bimserver.charting.Charts.Chart.java

Source

package org.bimserver.charting.Charts;

/******************************************************************************
 * Copyright (C) 2009-2015  BIMserver.org
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *****************************************************************************/

import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map.Entry;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.bimserver.charting.Containers.ChartOption;
import org.bimserver.charting.Containers.ChartRow;
import org.bimserver.charting.Containers.ChartRows;
import org.bimserver.charting.Dimensions.ModelDimension;

public class Chart {

    // Removed.
    //public int ID = 0;
    public String Title = "Untitled";
    public String Description = null;
    public String Category = null;
    // Removed.
    //public String Thumbnail = "";
    public ArrayList<ChartOption> Options = new ArrayList<>();
    public org.bimserver.charting.Models.Model Model = null;
    // Convenience shortcut, skipping a need to keep such a variable on the ChartOption object. Controls SVG export. 100% versus actual value in header.
    public boolean FitToSize = false;

    /**
     * @param title
     * @param description
     * @param category
     * @param options
     * @param model
     * @param fitToSize
     */
    public Chart(String title, String description, String category, ArrayList<ChartOption> options,
            org.bimserver.charting.Models.Model model, boolean fitToSize) {
        super();
        Title = title;
        Description = description;
        Category = category;
        Options = options;
        Model = model;
        FitToSize = fitToSize;
    }

    /**
     * @param title
     * @param description
     * @param category
     * @param options
     * @param model
     */
    public Chart(String title, String description, String category, ArrayList<ChartOption> options,
            org.bimserver.charting.Models.Model model) {
        this(title, description, category, options, model, false);
    }

    /**
     * @param title
     * @param description
     * @param category
     * @param model
     */
    public Chart(String title, String description, String category, org.bimserver.charting.Models.Model model) {
        this(title, description, category, new ArrayList<ChartOption>(), model);
    }

    public boolean hasOption(String optionTitle) {
        for (ChartOption option : Options)
            if (option.Title.equals(optionTitle))
                return true;
        return false;
    }

    public Object getOptionValue(String optionTitle) {
        for (ChartOption option : Options)
            if (option.Title.equals(optionTitle))
                return option.getValue();
        return null;
    }

    public ChartOption getOption(String optionTitle) {
        for (ChartOption option : Options)
            if (option.Title.equals(optionTitle))
                return option;
        return null;
    }

    public boolean setOption(String optionTitle, Object value) {
        if (hasOption(optionTitle)) {
            ChartOption option = getOption(optionTitle);
            option.setValue(value);
            return true;
        }
        return false;
    }

    // SVG Tiny profile removes/ignores scripting and styling. It is meant for mobile devices.
    /*
    <svg version="1.1" baseProfile="tiny" id="chart-id" width="100%" height="100%" viewBox="0 0 480 360" xmlns="http://www.w3.org/2000/svg">
    <title id="chart-title">Title</title>
    <g id="body-content" font-family="sans-serif" font-size="18">
     <g stroke="black" stroke-width="5">
       <line x1="0" y1="0" x2="150" y2="0"/>
       <line x1="0" y1="0" x2="0" y2="150"/>
     </g>
     <g fill="blue">
       <rect width="15" height="15"/>
       <rect x="150" width="15" height="15"/>
       <rect y="150" width="15" height="15"/>
     </g>
     <g fill="yellow">
       <rect x="0" y="0" width="10" height="10"/>
       <rect x="150" y="0" width="10" height="10"/>
       <rect x="0" y="150" width="10" height="10"/>
     </g>
    </g>
    <g font-family="sans-serif" font-size="32">
     <text id="title" x="10" y="340" stroke="none" fill="black">Title Text</text>
    </g>
    <rect id="frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000"/>
    </svg>
     */
    /**
     * Writes out an SVG file given raw format of data. This method is not meant to be overriden.
     *
     * @param data
     * @return
     */
    public StringBuilder writeSVG(ArrayList<LinkedHashMap<String, Object>> data) {
        StringBuilder builder = new StringBuilder();
        // Create a chart identification string based around the chart's title.
        String chartId = Title.toLowerCase().replace(' ', '-');
        // If there is a diameter option, treat as both width and height. Otherwise, specifically look for them.
        if (hasOption("Diameter")) {
            // Look for "Diameter" in options (in pixels).
            int diameter = (hasOption("Diameter")) ? ((Number) getOptionValue("Diameter")).intValue() : 1000;
            // Write the SVG header.
            String svgWidth = (FitToSize) ? "100%" : String.format("%d", diameter);
            String svgHeight = (FitToSize) ? "100%" : String.format("%d", diameter);
            // Write the SVG header.
            builder.append(String.format(
                    "<svg version=\"1.1\" baseProfile=\"%s\" id=\"%s\" width=\"%s\" height=\"%s\" viewBox=\"0 0 %d %d\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">",
                    "tiny", chartId, svgWidth, svgHeight, diameter, diameter));
        } else {
            // Look for "Width" in options (in pixels).
            int width = (hasOption("Width")) ? ((Number) getOptionValue("Width")).intValue() : 1000;
            // Look for "Height" in options (in pixels).
            int height = (hasOption("Height")) ? ((Number) getOptionValue("Height")).intValue() : 500;
            // Write the SVG header.
            String svgWidth = (FitToSize) ? "100%" : String.format("%d", width);
            String svgHeight = (FitToSize) ? "100%" : String.format("%d", height);
            //
            builder.append(String.format(
                    "<svg version=\"1.1\" baseProfile=\"%s\" id=\"%s\" width=\"%s\" height=\"%s\" viewBox=\"0 0 %d %d\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">",
                    "tiny", chartId, svgWidth, svgHeight, width, height));
        }
        builder.append("\n");
        // Write title (undrawn).
        builder.append(String.format("   <title id=\"chart-title\">%s</title>", Title));
        builder.append("\n");
        // Defer to model functionality to write SVG.
        writeSVGBody(builder, data);
        // Close the SVG.
        builder.append("</svg>");
        // Return builder.
        return builder;
    }

    /**
     * Functionality to call functionality to write out non-header components of the SVG file, representing the chart. 
     *
     * @param builder
     * @param data
     * @return
     */
    public StringBuilder writeSVGBody(StringBuilder builder, ArrayList<LinkedHashMap<String, Object>> data) {
        // Obtain data, filtered by dimension.
        ChartRows filteredData = Model.filterData(data);
        // Write axes and/or backgrounds.
        writeSVGChartSpecificPayload(builder, filteredData);
        // Send it back.
        return builder;
    }

    /**
     * Functionality to calculate and write out axes and/or backgrounds.
     *
     * @param builder
     * @param filteredData
     * @return
     */
    public StringBuilder writeSVGChartSpecificPayload(StringBuilder builder, ChartRows filteredData) {
        // Pass-through. Calculate necessary metrics and backgrounds.
        // Pass-through. Write necessary metrics and backgrounds.
        // Pass-through.
        return builder;
    }

    public boolean setDimensionLookupKey(String dimensionKey, String dataKey) {
        return Model.setDimensionLookupKey(dimensionKey, dataKey);
    }

    public boolean setDimensionLookupKeys(String dimensionKey, Collection<String> dataKeys) {
        return Model.setDimensionLookupKeys(dimensionKey, dataKeys);
    }

    public StringBuilder getRawTextDataSet(ArrayList<LinkedHashMap<String, Object>> data) {
        // Obtain data, filtered by dimension.
        ChartRows filteredData = Model.filterData(data);
        //
        StringBuilder builder = new StringBuilder();
        // Handle headers.
        ArrayList<String> headers = new ArrayList<>();
        for (ModelDimension dimension : Model.Dimensions) {
            String key = dimension.StoreAsKey;
            int count = dimension.getLength();
            for (int i = 0; i < count; i++) {
                // Make a numbered column.
                String thisKey = (count > 1) ? String.format("%s%s", key, (i + 1)) : key;
                if (thisKey.contains(","))
                    headers.add(String.format("\"%s\"", thisKey));
                else
                    headers.add(thisKey);
            }
        }
        builder.append(StringUtils.join(headers, ", "));
        builder.append("\n");
        // Handle data.
        for (ChartRow row : filteredData) {
            ArrayList<Object> values = new ArrayList<>();
            for (Entry<ModelDimension, ArrayList<Object>> value : row.entrySet()) {
                for (Object thisValue : value.getValue()) {
                    if (thisValue instanceof String) {
                        String thisValueString = (String) thisValue;
                        if (thisValueString.contains(","))
                            values.add(String.format("\"%s\"", thisValueString));
                        else
                            values.add(thisValueString);
                    } else
                        values.add(thisValue);
                }
            }
            //
            builder.append(StringUtils.join(values, ", "));
            builder.append("\n");
        }
        // Send it back.
        return builder;
    }

    public void saveToSVGInUserDirectory(ArrayList<LinkedHashMap<String, Object>> rawData) {
        String home = System.getProperty("user.home");
        String directoryPath = ((System.getProperty("os.name").startsWith("Windows")))
                ? FilenameUtils.concat(home, "Desktop")
                : home;
        saveToSVG(rawData, directoryPath);
    }

    public void saveToSVGInUserDirectory(ArrayList<LinkedHashMap<String, Object>> rawData, String filename) {
        String home = System.getProperty("user.home");
        String directoryPath = ((System.getProperty("os.name").startsWith("Windows")))
                ? FilenameUtils.concat(home, "Desktop")
                : home;
        saveToSVG(rawData, directoryPath, filename);
    }

    public void saveToSVG(ArrayList<LinkedHashMap<String, Object>> rawData, String directoryPath) {
        saveToSVG(rawData, directoryPath, String.format("%s.svg", Title));
    }

    public void saveToSVG(ArrayList<LinkedHashMap<String, Object>> rawData, String directoryPath, String filename) {
        StringBuilder builder = this.writeSVG(rawData);
        String data = builder.toString();
        PrintWriter writer;
        String file = FilenameUtils.concat(directoryPath, filename);
        try {
            writer = new PrintWriter(file, "UTF-8");
            writer.println(data);
            writer.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}