pt.webdetails.cdf.dd.model.inst.writer.cdfrunjs.dashboard.CdfRunJsDashboardWriter.java Source code

Java tutorial

Introduction

Here is the source code for pt.webdetails.cdf.dd.model.inst.writer.cdfrunjs.dashboard.CdfRunJsDashboardWriter.java

Source

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

package pt.webdetails.cdf.dd.model.inst.writer.cdfrunjs.dashboard;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.regex.Matcher;

import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import pt.webdetails.cdf.dd.CdeConstants;
import pt.webdetails.cdf.dd.CdeEngine;
import pt.webdetails.cdf.dd.model.core.*;
import pt.webdetails.cdf.dd.model.core.writer.*;
import pt.webdetails.cdf.dd.model.core.writer.js.*;
import pt.webdetails.cdf.dd.model.inst.*;

import pt.webdetails.cdf.dd.render.DependenciesManager;
import pt.webdetails.cdf.dd.render.DependenciesManager.StdPackages;
import pt.webdetails.cdf.dd.render.RenderLayout;
import pt.webdetails.cdf.dd.render.Renderer;
import pt.webdetails.cdf.dd.structure.DashboardWcdfDescriptor;
import pt.webdetails.cdf.dd.util.CdeEnvironment;
import pt.webdetails.cdf.dd.util.Utils;
import pt.webdetails.cpf.Util;
import pt.webdetails.cpf.packager.StringFilter;

/**
 * @author dcleao
 */
public abstract class CdfRunJsDashboardWriter extends JsWriterAbstract implements IThingWriter {
    private static final Log logger = LogFactory.getLog(CdfRunJsDashboardWriter.class);

    private static final String EPILOGUE = wrapJsScriptTags("Dashboards.init();");

    // ------------

    public void write(Object output, IThingWriteContext context, Thing t) throws ThingWriteException {
        this.write((CdfRunJsDashboardWriteResult.Builder) output, (CdfRunJsDashboardWriteContext) context,
                (Dashboard) t);
    }

    public abstract String getType();

    public void write(CdfRunJsDashboardWriteResult.Builder builder, CdfRunJsDashboardWriteContext ctx,
            Dashboard dash) throws ThingWriteException {
        assert dash == ctx.getDashboard();

        DashboardWcdfDescriptor wcdf = dash.getWcdf();

        // ------------

        String template;
        try {
            template = this.readTemplate(wcdf);
        } catch (IOException ex) {
            throw new ThingWriteException("Could not read style template file.", ex);
        }

        template = ctx.replaceTokens(template);

        // ------------

        String footer;
        try {
            footer = Util.toString(
                    CdeEnvironment.getPluginSystemReader().getFileInputStream(CdeConstants.RESOURCE_FOOTER));
        } catch (IOException ex) {
            throw new ThingWriteException("Could not read footer file.", ex);
        }

        // ------------

        String layout = ctx.replaceTokensAndAlias(this.writeLayout(ctx, dash));
        String components = ctx.replaceTokensAndAlias(this.writeComponents(ctx, dash));
        String content = writeContent(layout, components);
        String header = ctx.replaceTokens(writeHeaders(content, ctx));

        // Leave the DASHBOARD_HEADER_TAG to replace additional stuff on render.
        template = template
                .replaceAll(CdeConstants.DASHBOARD_HEADER_TAG,
                        Matcher.quoteReplacement(header) + CdeConstants.DASHBOARD_HEADER_TAG)
                .replaceAll(CdeConstants.DASHBOARD_FOOTER_TAG, Matcher.quoteReplacement(footer))
                .replaceAll(CdeConstants.DASHBOARD_CONTENT_TAG, Matcher.quoteReplacement(content));

        // Export
        builder.setTemplate(template).setHeader(header).setLayout(layout).setComponents(components)
                .setContent(content).setFooter(footer).setLoadedDate(ctx.getDashboard().getSourceDate());
    }

    protected String readTemplate(DashboardWcdfDescriptor wcdf) throws IOException {
        return readStyleTemplateOrDefault(wcdf.getStyle());
    }

    // -----------------

    protected String writeLayout(CdfRunJsDashboardWriteContext context, Dashboard dash) {
        // TODO: HACK: uses pass-through XPath node...
        if (dash.getLayoutCount() == 1) {
            JXPathContext docXP = dash.getLayout("TODO").getLayoutXPContext();
            try {
                return getLayoutRenderer(docXP, context).render(context.getOptions().getAliasPrefix());
            } catch (Exception ex) {
                logger.error("Error rendering layout", ex);
            }
        }

        return "";
    }

    protected Renderer getLayoutRenderer(JXPathContext docXP, CdfRunJsDashboardWriteContext context) {
        return new RenderLayout(docXP, context);
    }

    // -----------------

    protected String writeComponents(CdfRunJsDashboardWriteContext context, Dashboard dash)
            throws ThingWriteException {
        DashboardWcdfDescriptor wcdf = dash.getWcdf();

        StringBuilder out = new StringBuilder();
        StringBuilder widgetsOut = new StringBuilder();

        // Output WCDF
        out.append("wcdfSettings = ");
        out.append(wcdf.toJSON().toString(2));
        out.append(';');
        out.append(NEWLINE);
        out.append(NEWLINE);

        boolean isFirstComp = true;

        StringBuilder addCompIds = new StringBuilder();
        boolean isFirstAddComp = true;

        IThingWriterFactory factory = context.getFactory();

        Iterable<Component> comps = dash.getRegulars();
        for (Component comp : comps) {
            if (StringUtils.isNotEmpty(comp.getName())) {
                IThingWriter writer;
                try {
                    writer = factory.getWriter(comp);
                } catch (UnsupportedThingException ex) {
                    throw new ThingWriteException(ex);
                }

                boolean isWidget = comp instanceof WidgetComponent;

                StringBuilder out2 = isWidget ? widgetsOut : out;
                if (!isFirstComp) {
                    out2.append(NEWLINE);
                }

                // NOTE: Widgets don't really exist at runtime, 
                // only their (leaf-)content does.
                if (comp instanceof VisualComponent && !(comp instanceof WidgetComponent)) {
                    if (isFirstAddComp) {
                        isFirstAddComp = false;
                    } else {
                        addCompIds.append(", ");
                    }

                    addCompIds.append(context.getId(comp));
                }

                writer.write(out2, context, comp);

                isFirstComp = false;
            }
        }

        if (!isFirstAddComp) {
            out.append(NEWLINE);
            out.append("Dashboards.addComponents([");
            out.append(addCompIds);
            out.append("]);");
            out.append(NEWLINE);
        }

        out.append(widgetsOut);

        return out.toString();
    }

    // -----------------

    protected String writeHeaders(String contents, CdfRunJsDashboardWriteContext context) {
        CdfRunJsDashboardWriteOptions options = context.getOptions();

        DashboardWcdfDescriptor wcdf = context.getDashboard().getWcdf();

        final String title = "<title>" + wcdf.getTitle() + "</title>";

        // Get CDF headers
        String cdfDeps;
        try {
            cdfDeps = CdeEngine.getEnv().getCdfIncludes(contents, this.getType(), options.isDebug(),
                    options.isAbsolute(), options.getAbsRoot(), options.getScheme());
        } catch (Exception ex) {
            logger.error("Failed to get cdf includes");
            cdfDeps = "";
        }

        // Get CDE headers
        final String baseUrl = (options.isAbsolute()
                ? (!StringUtils.isEmpty(options.getAbsRoot()) ? options.getSchemedRoot() + "/"
                        : CdeEngine.getInstance().getEnvironment().getUrlProvider().getWebappContextRoot())
                : "");
        //    +
        //          ;

        StringFilter cssFilter = new StringFilter() {
            public String filter(String input) {
                return String.format("\t\t<link href=\"%s%s\" rel=\"stylesheet\" type=\"text/css\" />\n",

                        baseUrl,
                        baseUrl.endsWith("/") && input.startsWith("/") ? input.replaceFirst("/", "") : input);

            }

            public String filter(String input, String baseUrl) {
                return String.format("\t\t<link href=\"%s%s\" rel=\"stylesheet\" type=\"text/css\" />\n",

                        baseUrl,
                        baseUrl.endsWith("/") && input.startsWith("/") ? input.replaceFirst("/", "") : input);

            }
        };

        StringFilter jsFilter = new StringFilter() {
            public String filter(String input) {
                return String.format(
                        "\t\t<script language=\"javascript\" type=\"text/javascript\" src=\"%s%s\"></script>\n",

                        baseUrl,
                        baseUrl.endsWith("/") && input.startsWith("/") ? input.replaceFirst("/", "") : input);

            }

            public String filter(String input, String baseUrl) {
                return String.format(
                        "\t\t<script language=\"javascript\" type=\"text/javascript\" src=\"%s%s\"></script>\n",

                        baseUrl,
                        baseUrl.endsWith("/") && input.startsWith("/") ? input.replaceFirst("/", "") : input);

            }
        };

        DependenciesManager depMgr = DependenciesManager.getInstance();
        boolean isPackaged = !options.isDebug();
        String scriptDeps = depMgr.getPackage(StdPackages.COMPONENT_DEF_SCRIPTS).getDependencies(jsFilter,
                isPackaged);
        String styleDeps = depMgr.getPackage(StdPackages.COMPONENT_STYLES).getDependencies(cssFilter, isPackaged);
        String rawDeps = depMgr.getPackage(StdPackages.COMPONENT_SNIPPETS).getRawDependencies(false);

        return title + cdfDeps + rawDeps + scriptDeps + styleDeps;
    }

    // -----------------

    protected static String readStyleTemplateOrDefault(String styleName) throws IOException {
        if (StringUtils.isNotEmpty(styleName)) {
            try {
                return readStyleTemplate(styleName);
            } catch (IOException ex) {
            }
        }

        // Couldn't open template file, attempt to use default
        return readStyleTemplate(CdeConstants.DEFAULT_STYLE);
    }

    protected static String readStyleTemplate(String styleName) throws IOException {
        return readTemplateFile(
                CdeEnvironment.getPluginResourceLocationManager().getStyleResourceLocation(styleName));
    }

    protected static String readTemplateFile(String templateFile) throws IOException {
        try {
            if (CdeEnvironment.getPluginRepositoryReader().fileExists(templateFile)) {
                // template is in solution repository
                return Util.toString(CdeEnvironment.getPluginRepositoryReader().getFileInputStream(templateFile));

            } else if (CdeEnvironment.getPluginSystemReader().fileExists(templateFile)) {
                // template is in system
                return Util.toString(CdeEnvironment.getPluginSystemReader().getFileInputStream(templateFile));
            } else if (Utils.getAppropriateReadAccess(templateFile).fileExists(templateFile)) {
                return Util.toString(Utils.getAppropriateReadAccess(templateFile).getFileInputStream(templateFile));
            } else {
                // last chance : template is in user-defined folder
                return Util.toString(CdeEnvironment.getUserContentAccess().getFileInputStream(templateFile));
            }
        } catch (IOException ex) {
            logger.error(MessageFormat.format("Couldn't open template file '{0}'.", templateFile), ex);
            throw ex;
        }
    }

    private String writeContent(String layout, String components) {
        StringBuilder out = new StringBuilder();

        out.append(layout);

        wrapJsScriptTags(out, components);

        out.append(EPILOGUE);

        return out.toString();
    }

}