com.viddu.handlebars.HandlebarsNashorn.java Source code

Java tutorial

Introduction

Here is the source code for com.viddu.handlebars.HandlebarsNashorn.java

Source

/*
 * Copyright [Sep 22, 2014] [Viddu Devigere]
 *
 * 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.viddu.handlebars;

import java.io.InputStream;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Map;
import java.util.Scanner;
import java.util.function.BiFunction;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import jdk.nashorn.api.scripting.ScriptObjectMirror;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

public class HandlebarsNashorn implements Handlebars {
    private final ScriptEngine engine;
    private final ObjectMapper objectMapper, mapper;
    private final Object handlebars;
    private final Object JSON;

    private final Logger logger = LoggerFactory.getLogger(HandlebarsNashorn.class);

    HandlebarsNashorn(Reader handlebarsLib) throws HandlebarsException {
        ScriptEngineManager engineManager = new ScriptEngineManager();
        this.engine = engineManager.getEngineByName("nashorn");
        try {
            engine.eval(handlebarsLib);
            handlebars = engine.eval("Handlebars");
            JSON = engine.eval("JSON");

            engine.eval("var ScriptUtils = Java.type('jdk.nashorn.api.scripting.ScriptUtils')\n"
                    + "var wrapper = function(name, biFunctionInstance){\n"
                    + "    Handlebars.registerHelper(name, function(context, options){\n"
                    + "        var wrappedContext = ScriptUtils.wrap(context);\n"
                    + "        var wrappedOptions = ScriptUtils.wrap(options);\n"
                    + "        return biFunctionInstance.apply(wrappedContext, wrappedOptions); \n" + "    }); \n"
                    + "}");
        } catch (ScriptException e) {
            logger.debug("Error in script:{}", e);
            throw new HandlebarsException(e);
        }
        this.objectMapper = new ObjectMapper();
        this.objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
        this.mapper = new ObjectMapper();
    }

    @Override
    public String render(String templateString, String contextJson) throws HandlebarsException {
        logger.debug("Context JSON={}", contextJson);
        logger.debug("templateString={}", templateString);
        Invocable render = (Invocable) engine;
        try {
            Object context = render.invokeMethod(JSON, "parse", contextJson);
            ScriptObjectMirror obj = (ScriptObjectMirror) render.invokeMethod(handlebars, "compile",
                    templateString);
            return (String) obj.call(null, context);
        } catch (NoSuchMethodException | ScriptException e) {
            throw new HandlebarsException(e);
        }
    }

    @Override
    public String render(String templateString, Map<String, Object> context) throws HandlebarsException {
        String contextJson = null;
        try {
            contextJson = mapper.writeValueAsString(context);
        } catch (JsonProcessingException e) {
            throw new HandlebarsException(e);
        }
        return render(templateString, contextJson);
    }

    @Override
    public String render(String templateString, Collection<?> context) throws HandlebarsException {
        String contextJson = null;
        try {
            contextJson = mapper.writeValueAsString(context);
        } catch (JsonProcessingException e) {
            throw new HandlebarsException(e);
        }
        return render(templateString, contextJson);
    }

    @Override
    public String render(String templateString, Object context) throws HandlebarsException {
        String contextJson = null;
        try {
            contextJson = objectMapper.writeValueAsString(context);
        } catch (JsonProcessingException e) {
            throw new HandlebarsException(e);
        }
        return render(templateString, contextJson);
    }

    @Override
    public String render(InputStream templateStream, String contextJson) throws HandlebarsException {
        Scanner scanner = new Scanner(templateStream, StandardCharsets.UTF_8.name());
        String template = scanner.useDelimiter("\\A").next();
        scanner.close();
        return render(template, contextJson);
    }

    @Override
    public String render(InputStream templateStream, Map<String, Object> context) throws HandlebarsException {
        Scanner scanner = new Scanner(templateStream, StandardCharsets.UTF_8.name());
        String template = scanner.useDelimiter("\\A").next();
        scanner.close();
        return render(template, context);
    }

    @Override
    public String render(InputStream templateStream, Collection<?> context) throws HandlebarsException {
        Scanner scanner = new Scanner(templateStream, StandardCharsets.UTF_8.name());
        String template = scanner.useDelimiter("\\A").next();
        scanner.close();
        return render(template, context);
    }

    @Override
    public String render(InputStream templateStream, Object context) throws HandlebarsException {
        Scanner scanner = new Scanner(templateStream, StandardCharsets.UTF_8.name());
        String template = scanner.useDelimiter("\\A").next();
        scanner.close();
        return render(template, context);
    }

    @Override
    public <T, U> void registerHelper(String helperName,
            BiFunction<ScriptObjectMirror, ScriptObjectMirror, String> biFunction) throws HandlebarsException {
        Invocable invocable = (Invocable) engine;
        try {
            invocable.invokeFunction("wrapper", helperName, biFunction);
        } catch (NoSuchMethodException | ScriptException e) {
            throw new HandlebarsException(e);
        }
    }

}