All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.jknack.handlebars.helper.DefaultHelperRegistry Maven / Gradle / Ivy

/**
 * Copyright (c) 2012-2015 Edgar Espina
 *
 * This file is part of Handlebars.java.
 *
 * 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.
 */
/**
 * This copy of Woodstox XML processor is licensed under the
 * Apache (Software) License, version 2.0 ("the License").
 * See the License for details about distribution rights, and the
 * specific rights regarding derivate works.
 *
 * You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/
 *
 * A copy is also included in the downloadable source code package
 * containing Woodstox, in file "ASL2.0", under the same directory
 * as this file.
 */
package com.github.jknack.handlebars.helper;

import static org.apache.commons.lang3.Validate.isTrue;
import static org.apache.commons.lang3.Validate.notEmpty;
import static org.apache.commons.lang3.Validate.notNull;

import java.io.File;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

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

import com.github.jknack.handlebars.Decorator;
import com.github.jknack.handlebars.Handlebars;
import com.github.jknack.handlebars.Helper;
import com.github.jknack.handlebars.HelperRegistry;
import com.github.jknack.handlebars.internal.Files;
import com.github.jknack.handlebars.js.HandlebarsJs;

/**
 * Default implementation of {@link HelperRegistry}.
 *
 * @author edgar
 * @since 1.2.0
 */
public class DefaultHelperRegistry implements HelperRegistry {

  /** The logging system. */
  private final Logger logger = LoggerFactory.getLogger(HelperRegistry.class);

  /**
   * The helper registry.
   */
  private final Map> helpers = new HashMap>();

  /** Decorators. */
  private final Map decorators = new HashMap<>();

  /**
   * A Handlebars.js implementation.
   */
  private HandlebarsJs handlebarsJs = HandlebarsJs.create(this);

  {
    // make sure default helpers are registered
    registerBuiltinsHelpers(this);
  }

  @SuppressWarnings("unchecked")
  @Override
  public  Helper helper(final String name) {
    notEmpty(name, "A helper's name is required.");
    return (Helper) helpers.get(name);
  }

  @Override
  public  HelperRegistry registerHelper(final String name, final Helper helper) {
    notEmpty(name, "A helper's name is required.");
    notNull(helper, "A helper is required.");

    Helper oldHelper = helpers.put(name, helper);
    if (oldHelper != null) {
      logger.warn("Helper '{}' has been replaced by '{}'", name, helper);
    }
    return this;
  }

  @Override
  public  HelperRegistry registerHelperMissing(final Helper helper) {
    return registerHelper(Handlebars.HELPER_MISSING, helper);
  }

  @SuppressWarnings("rawtypes")
  @Override
  public HelperRegistry registerHelpers(final Object helperSource) {
    notNull(helperSource, "The helper source is required.");
    isTrue(!(helperSource instanceof String), "java.lang.String isn't a helper source.");
    try {
      if (helperSource instanceof File) {
        // adjust to File version
        return registerHelpers((File) helperSource);
      } else if (helperSource instanceof URI) {
        // adjust to URI version
        return registerHelpers((URI) helperSource);
      } else if (helperSource instanceof Class) {
        // adjust to Class version
        return registerHelpers((Class) helperSource);
      }
    } catch (RuntimeException ex) {
      throw ex;
    } catch (Exception ex) {
      throw new IllegalArgumentException("Can't register helpres", ex);
    }
    registerDynamicHelper(helperSource, helperSource.getClass());
    return this;
  }

  @SuppressWarnings({"rawtypes", "unchecked" })
  @Override
  public HelperRegistry registerHelpers(final Class helperSource) {
    notNull(helperSource, "The helper source is required.");
    if (Enum.class.isAssignableFrom(helperSource)) {
      Enum[] helpers = ((Class) helperSource).getEnumConstants();
      for (Enum helper : helpers) {
        isTrue(helper instanceof Helper, "'%s' isn't a helper.", helper.name());
        registerHelper(helper.name(), (Helper) helper);
      }
    } else {
      registerDynamicHelper(null, helperSource);
    }
    return this;
  }

  @Override
  public HelperRegistry registerHelpers(final URI location) throws Exception {
    return registerHelpers(location.getPath(), Files.read(location.toString()));
  }

  @Override
  public HelperRegistry registerHelpers(final File input) throws Exception {
    return registerHelpers(input.getAbsolutePath(), Files.read(input));
  }

  @Override
  public HelperRegistry registerHelpers(final String filename, final Reader source)
      throws Exception {
    return registerHelpers(filename, Files.read(source));
  }

  @Override
  public HelperRegistry registerHelpers(final String filename, final InputStream source)
      throws Exception {
    return registerHelpers(filename, Files.read(source));
  }

  @Override
  public HelperRegistry registerHelpers(final String filename, final String source)
      throws Exception {
    notNull(filename, "The filename is required.");
    notEmpty(source, "The source is required.");
    handlebarsJs.registerHelpers(filename, source);
    return this;
  }

  @Override
  public Set>> helpers() {
    return this.helpers.entrySet();
  }

  /**
   * 

* Register all the helper methods for the given helper source. *

* * @param source The helper source. * @param clazz The helper source class. */ private void registerDynamicHelper(final Object source, final Class clazz) { if (clazz != Object.class) { Set overloaded = new HashSet(); // Keep backing up the inheritance hierarchy. Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { boolean isPublic = Modifier.isPublic(method.getModifiers()); String helperName = method.getName(); if (isPublic && CharSequence.class.isAssignableFrom(method.getReturnType())) { boolean isStatic = Modifier.isStatic(method.getModifiers()); if (source != null || isStatic) { isTrue(overloaded.add(helperName), "name conflict found: " + helperName); registerHelper(helperName, new MethodHelper(method, source)); } } } } } /** * Register built-in helpers. * * @param registry The handlebars instance. */ private static void registerBuiltinsHelpers(final HelperRegistry registry) { registry.registerHelper(WithHelper.NAME, WithHelper.INSTANCE); registry.registerHelper(IfHelper.NAME, IfHelper.INSTANCE); registry.registerHelper(UnlessHelper.NAME, UnlessHelper.INSTANCE); registry.registerHelper(EachHelper.NAME, EachHelper.INSTANCE); registry.registerHelper(EmbeddedHelper.NAME, EmbeddedHelper.INSTANCE); registry.registerHelper(BlockHelper.NAME, BlockHelper.INSTANCE); registry.registerHelper(PartialHelper.NAME, PartialHelper.INSTANCE); registry.registerHelper(PrecompileHelper.NAME, PrecompileHelper.INSTANCE); registry.registerHelper("i18n", I18nHelper.i18n); registry.registerHelper("i18nJs", I18nHelper.i18nJs); registry.registerHelper(LookupHelper.NAME, LookupHelper.INSTANCE); registry.registerHelper(LogHelper.NAME, LogHelper.INSTANCE); // decorator registry.registerDecorator("inline", InlineDecorator.INSTANCE); } @Override public Decorator decorator(final String name) { notEmpty(name, "A decorator's name is required."); return decorators.get(name); } @Override public HelperRegistry registerDecorator(final String name, final Decorator decorator) { notEmpty(name, "A decorator's name is required."); notNull(decorator, "A decorator is required."); Decorator old = decorators.put(name, decorator); if (old != null) { logger.warn("Decorator '{}' has been replaced by '{}'", name, decorator); } return this; } /** * Set the handlebars Js. This operation will override previously registered * handlebars Js. * * @param handlebarsJs The handlebars Js. Required. * @return This DefaultHelperRegistry object. */ public DefaultHelperRegistry with(final HandlebarsJs handlebarsJs) { notNull(handlebarsJs, "The handlebarsJs is required."); this.handlebarsJs = handlebarsJs; return this; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy