Search in sources :

Example 1 with TemplateMethodModelEx

use of freemarker.template.TemplateMethodModelEx in project freemarker by apache.

the class GetOptionalTemplateMethod method exec.

public Object exec(List args) throws TemplateModelException {
    final int argCnt = args.size();
    if (argCnt < 1 || argCnt > 2) {
        throw _MessageUtil.newArgCntError(methodName, argCnt, 1, 2);
    }
    final Environment env = Environment.getCurrentEnvironment();
    if (env == null) {
        throw new IllegalStateException("No freemarer.core.Environment is associated to the current thread.");
    }
    final String absTemplateName;
    {
        TemplateModel arg = (TemplateModel) args.get(0);
        if (!(arg instanceof TemplateScalarModel)) {
            throw _MessageUtil.newMethodArgMustBeStringException(methodName, 0, arg);
        }
        String templateName = EvalUtil.modelToString((TemplateScalarModel) arg, null, env);
        try {
            absTemplateName = env.toFullTemplateName(env.getCurrentTemplate().getName(), templateName);
        } catch (MalformedTemplateNameException e) {
            throw new _TemplateModelException(e, "Failed to convert template path to full path; see cause exception.");
        }
    }
    final TemplateHashModelEx options;
    if (argCnt > 1) {
        TemplateModel arg = (TemplateModel) args.get(1);
        if (!(arg instanceof TemplateHashModelEx)) {
            throw _MessageUtil.newMethodArgMustBeExtendedHashException(methodName, 1, arg);
        }
        options = (TemplateHashModelEx) arg;
    } else {
        options = null;
    }
    String encoding = null;
    boolean parse = true;
    if (options != null) {
        final KeyValuePairIterator kvpi = TemplateModelUtils.getKeyValuePairIterator(options);
        while (kvpi.hasNext()) {
            final KeyValuePair kvp = kvpi.next();
            final String optName;
            {
                TemplateModel optNameTM = kvp.getKey();
                if (!(optNameTM instanceof TemplateScalarModel)) {
                    throw _MessageUtil.newMethodArgInvalidValueException(methodName, 1, "All keys in the options hash must be strings, but found ", new _DelayedAOrAn(new _DelayedFTLTypeDescription(optNameTM)));
                }
                optName = ((TemplateScalarModel) optNameTM).getAsString();
            }
            final TemplateModel optValue = kvp.getValue();
            if (OPTION_ENCODING.equals(optName)) {
                encoding = getStringOption(OPTION_ENCODING, optValue);
            } else if (OPTION_PARSE.equals(optName)) {
                parse = getBooleanOption(OPTION_PARSE, optValue);
            } else {
                throw _MessageUtil.newMethodArgInvalidValueException(methodName, 1, "Unsupported option ", new _DelayedJQuote(optName), "; valid names are: ", new _DelayedJQuote(OPTION_ENCODING), ", ", new _DelayedJQuote(OPTION_PARSE), ".");
            }
        }
    }
    final Template template;
    try {
        template = env.getTemplateForInclusion(absTemplateName, encoding, parse, true);
    } catch (IOException e) {
        throw new _TemplateModelException(e, "I/O error when trying to load optional template ", new _DelayedJQuote(absTemplateName), "; see cause exception");
    }
    SimpleHash result = new SimpleHash(env.getObjectWrapper());
    result.put(RESULT_EXISTS, template != null);
    // conveniently provided like in <@optTemp.include!myDefaultMacro />.
    if (template != null) {
        result.put(RESULT_INCLUDE, new TemplateDirectiveModel() {

            public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
                if (!params.isEmpty()) {
                    throw new TemplateException("This directive supports no parameters.", env);
                }
                if (loopVars.length != 0) {
                    throw new TemplateException("This directive supports no loop variables.", env);
                }
                if (body != null) {
                    throw new TemplateException("This directive supports no nested content.", env);
                }
                env.include(template);
            }
        });
        result.put(RESULT_IMPORT, new TemplateMethodModelEx() {

            public Object exec(List args) throws TemplateModelException {
                if (!args.isEmpty()) {
                    throw new TemplateModelException("This method supports no parameters.");
                }
                try {
                    return env.importLib(template, null);
                } catch (IOException e) {
                    throw new _TemplateModelException(e, "Failed to import loaded template; see cause exception");
                } catch (TemplateException e) {
                    throw new _TemplateModelException(e, "Failed to import loaded template; see cause exception");
                }
            }
        });
    }
    return result;
}
Also used : TemplateModelException(freemarker.template.TemplateModelException) TemplateModel(freemarker.template.TemplateModel) MalformedTemplateNameException(freemarker.template.MalformedTemplateNameException) Template(freemarker.template.Template) TemplateMethodModelEx(freemarker.template.TemplateMethodModelEx) List(java.util.List) KeyValuePairIterator(freemarker.template.TemplateHashModelEx2.KeyValuePairIterator) KeyValuePair(freemarker.template.TemplateHashModelEx2.KeyValuePair) TemplateException(freemarker.template.TemplateException) IOException(java.io.IOException) TemplateDirectiveBody(freemarker.template.TemplateDirectiveBody) TemplateHashModelEx(freemarker.template.TemplateHashModelEx) SimpleHash(freemarker.template.SimpleHash) TemplateScalarModel(freemarker.template.TemplateScalarModel) Map(java.util.Map) TemplateDirectiveModel(freemarker.template.TemplateDirectiveModel)

Example 2 with TemplateMethodModelEx

use of freemarker.template.TemplateMethodModelEx in project freemarker by apache.

the class MethodCall method _eval.

@Override
TemplateModel _eval(Environment env) throws TemplateException {
    TemplateModel targetModel = target.eval(env);
    if (targetModel instanceof TemplateMethodModel) {
        TemplateMethodModel targetMethod = (TemplateMethodModel) targetModel;
        List argumentStrings = targetMethod instanceof TemplateMethodModelEx ? arguments.getModelList(env) : arguments.getValueList(env);
        Object result = targetMethod.exec(argumentStrings);
        return env.getObjectWrapper().wrap(result);
    } else if (targetModel instanceof Macro) {
        Macro func = (Macro) targetModel;
        env.setLastReturnValue(null);
        if (!func.isFunction()) {
            throw new _MiscTemplateException(env, "A macro cannot be called in an expression. (Functions can be.)");
        }
        Writer prevOut = env.getOut();
        try {
            env.setOut(NullWriter.INSTANCE);
            env.invoke(func, null, arguments.items, null, this);
        } catch (IOException e) {
            // Should not occur
            throw new TemplateException("Unexpected exception during function execution", e, env);
        } finally {
            env.setOut(prevOut);
        }
        return env.getLastReturnValue();
    } else {
        throw new NonMethodException(target, targetModel, env);
    }
}
Also used : TemplateException(freemarker.template.TemplateException) TemplateMethodModelEx(freemarker.template.TemplateMethodModelEx) List(java.util.List) ArrayList(java.util.ArrayList) TemplateModel(freemarker.template.TemplateModel) IOException(java.io.IOException) TemplateMethodModel(freemarker.template.TemplateMethodModel) Writer(java.io.Writer) NullWriter(freemarker.template.utility.NullWriter)

Example 3 with TemplateMethodModelEx

use of freemarker.template.TemplateMethodModelEx in project freemarker by apache.

the class Java8BeansWrapperBridgeMethodsTest method test.

private void test(Class<?> pClass) throws TemplateModelException {
    BeansWrapper ow = new BeansWrapperBuilder(Configuration.VERSION_2_3_26).build();
    TemplateHashModel wrapped;
    try {
        wrapped = (TemplateHashModel) ow.wrap(pClass.newInstance());
    } catch (Exception e) {
        throw new IllegalStateException(e);
    }
    TemplateMethodModelEx m1 = (TemplateMethodModelEx) wrapped.get("m1");
    assertEquals(BridgeMethodsBean.M1_RETURN_VALUE, "" + m1.exec(Collections.emptyList()));
    TemplateMethodModelEx m2 = (TemplateMethodModelEx) wrapped.get("m2");
    assertNull(m2.exec(Collections.emptyList()));
}
Also used : TemplateHashModel(freemarker.template.TemplateHashModel) TemplateMethodModelEx(freemarker.template.TemplateMethodModelEx) TemplateModelException(freemarker.template.TemplateModelException)

Example 4 with TemplateMethodModelEx

use of freemarker.template.TemplateMethodModelEx in project freemarker by apache.

the class Java8BeansWrapperTest method testDefaultMethodRecognized.

@Test
public void testDefaultMethodRecognized() throws TemplateModelException {
    BeansWrapperBuilder owb = new BeansWrapperBuilder(Configuration.VERSION_2_3_0);
    owb.setTreatDefaultMethodsAsBeanMembers(true);
    BeansWrapper ow = owb.build();
    TemplateHashModel wrappedBean = (TemplateHashModel) ow.wrap(new Java8DefaultMethodsBean());
    {
        TemplateScalarModel prop = (TemplateScalarModel) wrappedBean.get(Java8DefaultMethodsBean.NORMAL_PROP);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.NORMAL_PROP_VALUE, prop.getAsString());
    }
    {
        // This is overridden in the subclass, so it's visible even without default method support:
        TemplateScalarModel prop = (TemplateScalarModel) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_PROP_2);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.PROP_2_OVERRIDE_VALUE, prop.getAsString());
    }
    {
        TemplateScalarModel prop = (TemplateScalarModel) wrappedBean.get(Java8DefaultMethodsBeanBase.DEFAULT_METHOD_PROP);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBeanBase.DEFAULT_METHOD_PROP_VALUE, prop.getAsString());
    }
    {
        TemplateSequenceModel prop = (TemplateSequenceModel) wrappedBean.get(Java8DefaultMethodsBeanBase.DEFAULT_METHOD_INDEXED_PROP);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBeanBase.DEFAULT_METHOD_INDEXED_PROP_VALUE, ((TemplateScalarModel) prop.get(0)).getAsString());
    }
    {
        // We see default method indexed read method, but it's invalidated by normal getter in the subclass
        TemplateNumberModel prop = (TemplateNumberModel) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_NOT_AN_INDEXED_PROP);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.NOT_AN_INDEXED_PROP_VALUE, prop.getAsNumber());
    }
    {
        // The default method read method invalidates the indexed read method in the subclass
        TemplateScalarModel prop = (TemplateScalarModel) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_NOT_AN_INDEXED_PROP_2);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.DEFAULT_METHOD_NOT_AN_INDEXED_PROP_2_VALUE, prop.getAsString());
    }
    {
        // The default method read method invalidates the indexed read method in the subclass
        TemplateSequenceModel prop = (TemplateSequenceModel) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_NOT_AN_INDEXED_PROP_3);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.DEFAULT_METHOD_NOT_AN_INDEXED_PROP_3_VALUE_0, ((TemplateScalarModel) prop.get(0)).getAsString());
    }
    {
        // We see the default method indexed reader, which overrides the plain array reader in the subclass.
        TemplateSequenceModel prop = (TemplateSequenceModel) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_INDEXED_PROP_2);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.DEFAULT_METHOD_INDEXED_PROP_2_VALUE_0, ((TemplateScalarModel) prop.get(0)).getAsString());
    }
    {
        // We do see the default method non-indexed reader, but the subclass has a matching indexed reader, so that
        // takes over.
        TemplateSequenceModel prop = (TemplateSequenceModel) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_INDEXED_PROP_3);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.INDEXED_PROP_3_VALUE, ((TemplateScalarModel) prop.get(0)).getAsString());
    }
    {
        // Only present in the subclass.
        TemplateSequenceModel prop = (TemplateSequenceModel) wrappedBean.get(Java8DefaultMethodsBean.INDEXED_PROP_4);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.INDEXED_PROP_4_VALUE, ((TemplateScalarModel) prop.get(0)).getAsString());
    }
    {
        TemplateMethodModelEx action = (TemplateMethodModelEx) wrappedBean.get(Java8DefaultMethodsBean.NORMAL_ACTION);
        assertNotNull(action);
        assertEquals(Java8DefaultMethodsBean.NORMAL_ACTION_RETURN_VALUE, ((TemplateScalarModel) action.exec(Collections.emptyList())).getAsString());
    }
    {
        TemplateMethodModelEx action = (TemplateMethodModelEx) wrappedBean.get(Java8DefaultMethodsBean.NORMAL_ACTION);
        assertNotNull(action);
        assertEquals(Java8DefaultMethodsBean.NORMAL_ACTION_RETURN_VALUE, ((TemplateScalarModel) action.exec(Collections.emptyList())).getAsString());
    }
    {
        TemplateMethodModelEx action = (TemplateMethodModelEx) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_ACTION);
        assertNotNull(action);
        assertEquals(Java8DefaultMethodsBean.DEFAULT_METHOD_ACTION_RETURN_VALUE, ((TemplateScalarModel) action.exec(Collections.emptyList())).getAsString());
    }
    {
        TemplateMethodModelEx action = (TemplateMethodModelEx) wrappedBean.get(Java8DefaultMethodsBean.OVERRIDDEN_DEFAULT_METHOD_ACTION);
        assertNotNull(action);
        assertEquals(Java8DefaultMethodsBean.OVERRIDDEN_DEFAULT_METHOD_ACTION_RETURN_VALUE, ((TemplateScalarModel) action.exec(Collections.emptyList())).getAsString());
    }
}
Also used : TemplateSequenceModel(freemarker.template.TemplateSequenceModel) TemplateHashModel(freemarker.template.TemplateHashModel) TemplateMethodModelEx(freemarker.template.TemplateMethodModelEx) TemplateNumberModel(freemarker.template.TemplateNumberModel) TemplateScalarModel(freemarker.template.TemplateScalarModel) Test(org.junit.Test)

Example 5 with TemplateMethodModelEx

use of freemarker.template.TemplateMethodModelEx in project freemarker by apache.

the class Java8BeansWrapperTest method testDefaultMethodNotRecognized.

@Test
public void testDefaultMethodNotRecognized() throws TemplateModelException {
    BeansWrapperBuilder owb = new BeansWrapperBuilder(Configuration.VERSION_2_3_0);
    // owb.setTreatDefaultMethodsAsBeanMembers(false);
    BeansWrapper ow = owb.build();
    TemplateHashModel wrappedBean = (TemplateHashModel) ow.wrap(new Java8DefaultMethodsBean());
    {
        TemplateScalarModel prop = (TemplateScalarModel) wrappedBean.get(Java8DefaultMethodsBean.NORMAL_PROP);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.NORMAL_PROP_VALUE, prop.getAsString());
    }
    {
        // This is overridden in the subclass, so it's visible even without default method support:
        TemplateScalarModel prop = (TemplateScalarModel) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_PROP_2);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.PROP_2_OVERRIDE_VALUE, prop.getAsString());
    }
    assertNull(wrappedBean.get(Java8DefaultMethodsBeanBase.DEFAULT_METHOD_PROP));
    assertNull(wrappedBean.get(Java8DefaultMethodsBeanBase.DEFAULT_METHOD_INDEXED_PROP));
    {
        // We don't see the default method indexed reader, but see the plain reader method in the subclass.
        TemplateNumberModel prop = (TemplateNumberModel) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_NOT_AN_INDEXED_PROP);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.NOT_AN_INDEXED_PROP_VALUE, prop.getAsNumber());
    }
    {
        // We don't see the default method non-indexed reader that would spoil the indexed reader in the subclass.
        TemplateSequenceModel prop = (TemplateSequenceModel) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_NOT_AN_INDEXED_PROP_2);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.NOT_AN_INDEXED_PROP_2_VALUE, ((TemplateScalarModel) prop.get(0)).getAsString());
    }
    {
        // We don't see the default method non-indexed reader that would spoil the indexed reader in the subclass.
        TemplateSequenceModel prop = (TemplateSequenceModel) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_NOT_AN_INDEXED_PROP_3);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.NOT_AN_INDEXED_PROP_3_VALUE, ((TemplateNumberModel) prop.get(0)).getAsNumber());
    }
    {
        // We don't see the default method indexed reader, but see the plain array reader in the subclass.
        TemplateSequenceModel prop = (TemplateSequenceModel) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_INDEXED_PROP_2);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.ARRAY_PROP_2_VALUE_0, ((TemplateScalarModel) prop.get(0)).getAsString());
    }
    {
        // Only present in the subclass.
        TemplateSequenceModel prop = (TemplateSequenceModel) wrappedBean.get(Java8DefaultMethodsBean.INDEXED_PROP_4);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.INDEXED_PROP_4_VALUE, ((TemplateScalarModel) prop.get(0)).getAsString());
    }
    {
        // We don't see the default method non-indexed reader
        TemplateSequenceModel prop = (TemplateSequenceModel) wrappedBean.get(Java8DefaultMethodsBean.DEFAULT_METHOD_INDEXED_PROP_3);
        assertNotNull(prop);
        assertEquals(Java8DefaultMethodsBean.INDEXED_PROP_3_VALUE, ((TemplateScalarModel) prop.get(0)).getAsString());
    }
    {
        TemplateMethodModelEx action = (TemplateMethodModelEx) wrappedBean.get(Java8DefaultMethodsBean.NORMAL_ACTION);
        assertNotNull(action);
        assertEquals(Java8DefaultMethodsBean.NORMAL_ACTION_RETURN_VALUE, ((TemplateScalarModel) action.exec(Collections.emptyList())).getAsString());
    }
    assertNull(wrappedBean.get(Java8DefaultMethodsBeanBase.DEFAULT_METHOD_ACTION));
    {
        TemplateMethodModelEx action = (TemplateMethodModelEx) wrappedBean.get(Java8DefaultMethodsBean.OVERRIDDEN_DEFAULT_METHOD_ACTION);
        assertNotNull(action);
        assertEquals(Java8DefaultMethodsBean.OVERRIDDEN_DEFAULT_METHOD_ACTION_RETURN_VALUE, ((TemplateScalarModel) action.exec(Collections.emptyList())).getAsString());
    }
}
Also used : TemplateSequenceModel(freemarker.template.TemplateSequenceModel) TemplateHashModel(freemarker.template.TemplateHashModel) TemplateMethodModelEx(freemarker.template.TemplateMethodModelEx) TemplateNumberModel(freemarker.template.TemplateNumberModel) TemplateScalarModel(freemarker.template.TemplateScalarModel) Test(org.junit.Test)

Aggregations

TemplateMethodModelEx (freemarker.template.TemplateMethodModelEx)11 TemplateHashModel (freemarker.template.TemplateHashModel)8 TemplateScalarModel (freemarker.template.TemplateScalarModel)7 TemplateModel (freemarker.template.TemplateModel)6 TemplateModelException (freemarker.template.TemplateModelException)6 Test (org.junit.Test)6 ArrayList (java.util.ArrayList)4 List (java.util.List)3 Map (java.util.Map)3 TemplateException (freemarker.template.TemplateException)2 TemplateNumberModel (freemarker.template.TemplateNumberModel)2 TemplateSequenceModel (freemarker.template.TemplateSequenceModel)2 IOException (java.io.IOException)2 TemplateHTMLOutputModel (freemarker.core.TemplateHTMLOutputModel)1 MalformedTemplateNameException (freemarker.template.MalformedTemplateNameException)1 SimpleHash (freemarker.template.SimpleHash)1 SimpleScalar (freemarker.template.SimpleScalar)1 Template (freemarker.template.Template)1 TemplateDirectiveBody (freemarker.template.TemplateDirectiveBody)1 TemplateDirectiveModel (freemarker.template.TemplateDirectiveModel)1