/*******************************************************************************
 * This file is part of Pebble.
 * <p>
 * Copyright (c) 2014 by Mitchell Bösecke
 * <p>
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 ******************************************************************************/
package com.mitchellbosecke.pebble;

import com.mitchellbosecke.pebble.error.PebbleException;
import com.mitchellbosecke.pebble.extension.AbstractExtension;
import com.mitchellbosecke.pebble.extension.Filter;
import com.mitchellbosecke.pebble.loader.StringLoader;
import com.mitchellbosecke.pebble.template.EvaluationContext;
import com.mitchellbosecke.pebble.template.PebbleTemplate;
import org.junit.Test;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;

public class ExtendingPebbleTest extends AbstractTest {

    private final class CustomExtension extends AbstractExtension {

        @Override
        public Map<String, Filter> getFilters() {

            Map<String, Filter> filters = new HashMap<>();

            filters.put("noArgumentsButCanAccessContext", new Filter() {

                @Override
                public List<String> getArgumentNames() {
                    return null;
                }

                @Override
                public String apply(Object input, Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {
                    if (context != null && self != null) {
                        return "success";
                    } else {
                        return "failure";
                    }
                }

            });
            return filters;
        }
    }

    /**
     * Issue #51
     */
    @Test
    public void testFilterWithoutArgumentsCanAccessEvaluationContext() throws PebbleException, IOException {
        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false)
                .extension(new CustomExtension()).build();

        PebbleTemplate template = pebble.getTemplate("{{ 'test' | noArgumentsButCanAccessContext }}");

        Writer writer = new StringWriter();
        template.evaluate(writer);
        assertEquals("success", writer.toString());
    }
}

@@ -407,16 +407,80 @@
 ebble;%0A%0A
+import com.mitchellbosecke.pebble.attributes.AttributeResolver;%0A
 import c
@@ -819,16 +819,17 @@
 mplate;%0A
+%0A
 import o
@@ -916,32 +916,60 @@
 java.io.Writer;%0A
+import java.util.ArrayList;%0A
 import java.util
@@ -1022,16 +1022,43 @@
 til.Map;
+%0Aimport java.util.Optional;
 %0A%0Aimport
@@ -1162,43 +1162,1385 @@
     
-private final class CustomExtension
+/**%0A     * Issue #51%0A     */%0A    @Test%0A    public void testFilterWithoutArgumentsCanAccessEvaluationContext() throws PebbleException, IOException %7B%0A        PebbleEngine pebble = new PebbleEngine.Builder()%0A                .loader(new StringLoader())%0A                .strictVariables(false)%0A                .extension(new CustomExtensionWithFilter())%0A                .build();%0A%0A        PebbleTemplate template = pebble.getTemplate(%22%7B%7B 'test' %7C noArgumentsButCanAccessContext %7D%7D%22);%0A%0A        Writer writer = new StringWriter();%0A        template.evaluate(writer);%0A        assertEquals(%22success%22, writer.toString());%0A    %7D%0A%0A    @Test%0A    public void testCustomAttributeResolverEvaluateFirst() throws PebbleException, IOException %7B%0A        PebbleEngine pebble = new PebbleEngine.Builder()%0A                .loader(new StringLoader())%0A                .strictVariables(false)%0A                .extension(new CustomExtensionWithAttributeResolver())%0A                .build();%0A%0A        PebbleTemplate template = pebble.getTemplate(%22hello %7B%7B person.name %7D%7D%22);%0A        Map%3CString, Object%3E context = new HashMap%3C%3E();%0A        context.put(%22person%22, new SimplePerson());%0A%0A        Writer writer = new StringWriter();%0A        template.evaluate(writer, context);%0A        assertEquals(%22hello customAttributeResolver%22, writer.toString());%0A    %7D%0A%0A    private static final class CustomExtensionWithFilter
  ext
@@ -2564,17 +2564,16 @@
 nsion %7B%0A
-%0A
         
@@ -3352,331 +3352,451 @@
     
-/**%0A     * Issue #51%0A     */%0A    @Test%0A    public void testFilterWithoutArgumentsCanAccessEvaluationContext() throws PebbleException, IOException %7B%0A        PebbleEngine pebble = new PebbleEngine.Builder().loader(new StringLoader()).strictVariables(false)%0A                .extension(new CustomExtension()).build(
+private static final class CustomExtensionWithAttributeResolver extends AbstractExtension %7B%0A        @Override%0A        public List%3CAttributeResolver%3E getAttributeResolver() %7B%0A%0A            List%3CAttributeResolver%3E attributeResolvers = new ArrayList%3C%3E();%0A            attributeResolvers.add((instance, attribute, argumentValues, isStrictVariables, filename, lineNumber) -%3E%0A                    Optional.of(() -%3E %22customAttributeResolver%22)
 );%0A
-%0A
         
 Pebb
@@ -3795,233 +3795,136 @@
     
-PebbleTemplate template = pebble.getTemplate(%22%7B%7B 'test' %7C noArgumentsButCanAccessContext %7D%7D%22);%0A%0A        Writer writer = new StringWriter();%0A        template.evaluate(writer);%0A        assertEquals(%22success%22, writer.toString())
+    return attributeResolvers;%0A        %7D%0A    %7D%0A%0A    private static class SimplePerson %7B%0A        public final String name = %22Bob%22
 ;%0A  

Add test