1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.peaseplate.internal.designator;
21
22 import java.lang.reflect.InvocationTargetException;
23 import java.lang.reflect.Method;
24
25 import org.peaseplate.TemplateEngine;
26 import org.peaseplate.TemplateException;
27 import org.peaseplate.chunk.Chunk;
28 import org.peaseplate.internal.chunk.VoidChunk;
29 import org.peaseplate.internal.conversion.ConversionException;
30 import org.peaseplate.internal.lang.Parser;
31 import org.peaseplate.internal.model.CompileContext;
32 import org.peaseplate.internal.model.Directive;
33 import org.peaseplate.internal.parser.Token;
34 import org.peaseplate.lang.Designator;
35 import org.peaseplate.lang.TemplateDefinitionException;
36 import org.peaseplate.lang.TemplateParserException;
37
38 public class CompileDirectiveDesignator implements Designator {
39
40 public static final String NAME = "compile-directive";
41
42 public CompileDirectiveDesignator() {
43 super();
44 }
45
46
47
48
49 public String getKeyword() {
50 return NAME;
51 }
52
53
54
55
56 public boolean isEmpty() {
57 return false;
58 }
59
60
61
62
63 public boolean isBlockHead() {
64 return false;
65 }
66
67
68
69
70 public boolean isBlockTail() {
71 return false;
72 }
73
74
75
76
77 public boolean isExpandableBlock() {
78 return false;
79 }
80
81
82
83
84 public boolean isBlockExpansion() {
85 return false;
86 }
87
88
89
90
91 public boolean isVisible() {
92 return false;
93 }
94
95
96
97
98 public Chunk compile(TemplateEngine engine, CompileContext context, Token token) throws TemplateException {
99 Parser parser = new Parser(
100 engine, context,
101 token.getLine(), token.getColumn(), token.getSource(),
102 token.getOffset(), token.getLength()
103 );
104
105 String directive = parser.readIdentifier();
106 String value = parser.parseAssignedKey();
107 Method method = findDirective(directive);
108
109 if (method == null)
110 throw new TemplateParserException(
111 context.getLocator(), token.getLine(), token.getColumn(),
112 "Cannot find compile directive \"" + directive + "\""
113 );
114
115 Class<?>[] parameterTypes = method.getParameterTypes();
116
117 if (parameterTypes.length != 1)
118 throw new TemplateDefinitionException(
119 "The compile directive " + method + " must have exactly one parameter, which is not the case"
120 );
121
122 try {
123 method.invoke(context, new Object[]{
124 engine.getConversionService().convert(value, parameterTypes[0])
125 });
126 }
127 catch (ConversionException e) {
128 throw new TemplateParserException(
129 context.getLocator(), token.getLine(), token.getColumn(),
130 "Cannot set compile directive \"" + directive + "\". " +
131 "Cannot convert \"" + value + "\" to " + parameterTypes[0], e
132 );
133 }
134 catch (IllegalArgumentException e) {
135 throw new TemplateParserException(
136 context.getLocator(), token.getLine(), token.getColumn(),
137 "Cannot set compile directive \"" + directive + "\"", e
138 );
139 }
140 catch (IllegalAccessException e) {
141 throw new TemplateParserException(
142 context.getLocator(), token.getLine(), token.getColumn(),
143 "Cannot set compile directive \"" + directive + "\". Cannot access " + method, e
144 );
145 }
146 catch (InvocationTargetException e) {
147 throw new TemplateParserException(
148 context.getLocator(), token.getLine(), token.getColumn(),
149 "Cannot set compile directive \"" + directive + "\". Cannot invoke " + method, e
150 );
151 }
152
153 return new VoidChunk(context.getLocator(), token.getLine(), token.getColumn());
154 }
155
156 private Method findDirective(String directive) {
157 Method[] methods = CompileContext.class.getMethods();
158
159 for (Method method : methods) {
160 Directive annotation = method.getAnnotation(Directive.class);
161
162 if (annotation != null) {
163 if (directive.equals(annotation.value()))
164 return method;
165 }
166 }
167
168 return null;
169 }
170
171
172 }