View Javadoc

1   /*
2    * This file is part of Pease Plate Template Engine.
3    * 
4    * Pease Plate Template Engine is free software: you can redistribute
5    * it and/or modify it under the terms of the GNU Lesser General 
6    * Public License as published by the Free Software Foundation, 
7    * either version 3 of the License, or any later version.
8    * 
9    * Pease Plate Template Engine is distributed in the hope that it 
10   * will be useful, but WITHOUT ANY WARRANTY; without even the implied
11   * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12   * See the GNU Lesser General Public License for more details.
13   * 
14   * You should have received a copy of the GNU Lesser General Public 
15   * License along with Pease Plate Template Engine. If not, see 
16   * <http://www.gnu.org/licenses/>.
17   * 
18   * Copyright (c) 2008 Manfred HANTSCHEL
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  	 * @see org.peaseplate.lang.Designator#getKeyword()
48  	 */
49  	public String getKeyword() {
50  	    return NAME;
51      }
52  	
53  	/**
54  	 * @see org.peaseplate.lang.Designator#isEmpty()
55  	 */
56  	public boolean isEmpty() {
57  		return false;
58      }
59  
60  	/**
61  	 * @see org.peaseplate.lang.Designator#isBlockHead()
62  	 */
63  	public boolean isBlockHead() {
64  	    return false;
65      }
66  
67  	/**
68  	 * @see org.peaseplate.lang.Designator#isBlockTail()
69  	 */
70  	public boolean isBlockTail() {
71  	    return false;
72      }
73  
74  	/**
75  	 * @see org.peaseplate.lang.Designator#isExpandableBlock()
76  	 */
77  	public boolean isExpandableBlock() {
78  		return false;
79  	}
80  
81  	/**
82  	 * @see org.peaseplate.lang.Designator#isBlockExpansion()
83  	 */
84  	public boolean isBlockExpansion() {
85  		return false;
86  	}
87  
88  	/**
89  	 * @see org.peaseplate.lang.Designator#isVisible()
90  	 */
91  	public boolean isVisible() {
92  		return false;
93  	}
94  
95  	/**
96  	 * @see org.peaseplate.lang.Designator#compile(org.peaseplate.TemplateEngine, org.peaseplate.internal.model.CompileContext, org.peaseplate.internal.parser.Token)
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 }