Java tutorial
/** * Copyright (c) 2012-2013 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 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 helper registry. */ private final Map<String, Helper<?>> helpers = new HashMap<String, Helper<?>>(); /** * A Handlebars.js implementation. */ private HandlebarsJs handlebarsJs = HandlebarsJs.create(this); { // make sure default helpers are registered registerBuiltinsHelpers(this); } @SuppressWarnings("unchecked") @Override public <C> Helper<C> helper(final String name) { notEmpty(name, "A helper's name is required."); return (Helper<C>) helpers.get(name); } @Override public <H> HelperRegistry registerHelper(final String name, final Helper<H> helper) { notEmpty(name, "A helper's name is required."); notNull(helper, "A helper is required."); Helper<?> oldHelper = helpers.put(name, helper); if (oldHelper != null) { Handlebars.warn("Helper '%s' has been replaced by '%s'", name, helper); } return this; } @Override public <H> HelperRegistry registerHelperMissing(final Helper<H> 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<Enum>) 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<Entry<String, Helper<?>>> helpers() { return this.helpers.entrySet(); } /** * <p> * Register all the helper methods for the given helper source. * </p> * * @param source The helper source. * @param clazz The helper source class. */ private void registerDynamicHelper(final Object source, final Class<?> clazz) { int size = helpers.size(); int replaced = 0; if (clazz != Object.class) { Set<String> overloaded = new HashSet<String>(); // 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) { if (helpers.containsKey(helperName)) { replaced++; } isTrue(overloaded.add(helperName), "name conflict found: " + helperName); registerHelper(helperName, new MethodHelper(method, source)); } } } } isTrue((size + replaced) != helpers.size(), "No helper method was found in: " + clazz.getName()); } /** * 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); } }