Continued work on TemplateLanguage configuration and new file extensions: Renamed...
[freemarker.git] / freemarker-core-test / src / test / java / org / apache / freemarker / core / templateresolver / TemplateConfigurationFactoryTest.java
1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.freemarker.core.templateresolver;
20
21 import static org.hamcrest.Matchers.*;
22 import static org.junit.Assert.*;
23
24 import java.io.IOException;
25 import java.io.Serializable;
26 import java.util.ArrayList;
27 import java.util.List;
28
29 import org.apache.freemarker.core.ProcessingConfiguration;
30 import org.apache.freemarker.core.TemplateConfiguration;
31 import org.junit.Test;
32
33 public class TemplateConfigurationFactoryTest {
34
35 @Test
36 public void testCondition1() throws IOException, TemplateConfigurationFactoryException {
37 TemplateConfiguration tc = newTemplateConfiguration(1);
38
39 TemplateConfigurationFactory tcf = new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.tx"), tc);
40
41 assertNotApplicable(tcf, "x.t");
42 assertApplicable(tcf, "x.tx", tc);
43 }
44
45 @Test
46 public void testCondition2() throws IOException, TemplateConfigurationFactoryException {
47 TemplateConfiguration tc = newTemplateConfiguration(1);
48
49 TemplateConfigurationFactory tcf = new ConditionalTemplateConfigurationFactory(
50 new FileNameGlobMatcher("*.tx"),
51 new ConditionalTemplateConfigurationFactory(
52 new FileNameGlobMatcher("x.*"), tc));
53
54 assertNotApplicable(tcf, "x.t");
55 assertNotApplicable(tcf, "y.tx");
56 assertApplicable(tcf, "x.tx", tc);
57 }
58
59 @Test
60 public void testMerging() throws IOException, TemplateConfigurationFactoryException {
61 TemplateConfiguration tc1 = newTemplateConfiguration(1);
62 TemplateConfiguration tc2 = newTemplateConfiguration(2);
63 TemplateConfiguration tc3 = newTemplateConfiguration(3);
64
65 TemplateConfigurationFactory tcf = new MergingTemplateConfigurationFactory(
66 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.tx"), tc1),
67 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*a*.*"), tc2),
68 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*b*.*"), tc3));
69
70 assertNotApplicable(tcf, "x.t");
71 assertApplicable(tcf, "x.tx", tc1);
72 assertApplicable(tcf, "a.t", tc2);
73 assertApplicable(tcf, "b.t", tc3);
74 assertApplicable(tcf, "a.tx", tc1, tc2);
75 assertApplicable(tcf, "b.tx", tc1, tc3);
76 assertApplicable(tcf, "ab.t", tc2, tc3);
77 assertApplicable(tcf, "ab.tx", tc1, tc2, tc3);
78
79 assertNotApplicable(new MergingTemplateConfigurationFactory(), "x.t");
80 }
81
82 @Test
83 public void testFirstMatch() throws IOException, TemplateConfigurationFactoryException {
84 TemplateConfiguration tc1 = newTemplateConfiguration(1);
85 TemplateConfiguration tc2 = newTemplateConfiguration(2);
86 TemplateConfiguration tc3 = newTemplateConfiguration(3);
87
88 FirstMatchTemplateConfigurationFactory tcf = new FirstMatchTemplateConfigurationFactory(
89 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.tx"), tc1),
90 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*a*.*"), tc2),
91 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*b*.*"), tc3));
92
93 try {
94 assertNotApplicable(tcf, "x.t");
95 } catch (TemplateConfigurationFactoryException e) {
96 assertThat(e.getMessage(), containsString("x.t"));
97 }
98 tcf.setNoMatchErrorDetails("Test details");
99 try {
100 assertNotApplicable(tcf, "x.t");
101 } catch (TemplateConfigurationFactoryException e) {
102 assertThat(e.getMessage(), containsString("Test details"));
103 }
104
105 tcf.setAllowNoMatch(true);
106
107 assertNotApplicable(tcf, "x.t");
108 assertApplicable(tcf, "x.tx", tc1);
109 assertApplicable(tcf, "a.t", tc2);
110 assertApplicable(tcf, "b.T", tc3);
111 assertApplicable(tcf, "a.tx", tc1);
112 assertApplicable(tcf, "b.tx", tc1);
113 assertApplicable(tcf, "ab.t", tc2);
114 assertApplicable(tcf, "ab.tx", tc1);
115
116 assertNotApplicable(new FirstMatchTemplateConfigurationFactory().allowNoMatch(true), "x.t");
117 }
118
119 @Test
120 public void testComplex() throws IOException, TemplateConfigurationFactoryException {
121 TemplateConfiguration tcA = newTemplateConfiguration(1);
122 TemplateConfiguration tcBSpec = newTemplateConfiguration(2);
123 TemplateConfiguration tcBCommon = newTemplateConfiguration(3);
124 TemplateConfiguration tcHH = newTemplateConfiguration(4);
125 TemplateConfiguration tcHtml = newTemplateConfiguration(5);
126 TemplateConfiguration tcXml = newTemplateConfiguration(6);
127 TemplateConfiguration tcNWS = newTemplateConfiguration(7);
128
129 TemplateConfigurationFactory tcf = new MergingTemplateConfigurationFactory(
130 new FirstMatchTemplateConfigurationFactory(
131 new ConditionalTemplateConfigurationFactory(new PathGlobMatcher("a/**"), tcA),
132 new ConditionalTemplateConfigurationFactory(new PathGlobMatcher("b/**"),
133 new MergingTemplateConfigurationFactory(
134 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*"), tcBCommon),
135 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.s.*"), tcBSpec))))
136 .allowNoMatch(true),
137 new FirstMatchTemplateConfigurationFactory(
138 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.hh"), tcHH),
139 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.*h"), tcHtml),
140 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.*x"), tcXml))
141 .allowNoMatch(true),
142 new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.nws.*"), tcNWS));
143
144 assertNotApplicable(tcf, "x.t");
145 assertApplicable(tcf, "b/x.t", tcBCommon);
146 assertApplicable(tcf, "b/x.s.t", tcBCommon, tcBSpec);
147 assertApplicable(tcf, "b/x.s.th", tcBCommon, tcBSpec, tcHtml);
148 assertApplicable(tcf, "b/x.s.nws.tx", tcBCommon, tcBSpec, tcXml, tcNWS);
149 assertApplicable(tcf, "a/x.s.nws.tx", tcA, tcXml, tcNWS);
150 assertApplicable(tcf, "a.hh", tcHH);
151 assertApplicable(tcf, "a.nws.hh", tcHH, tcNWS);
152 }
153
154 @SuppressWarnings("boxing")
155 private TemplateConfiguration newTemplateConfiguration(int id) {
156 TemplateConfiguration.Builder tcb = new TemplateConfiguration.Builder();
157 tcb.setCustomSetting("id", id);
158 tcb.setCustomSetting("contains" + id, true);
159 return tcb.build();
160 }
161
162 private void assertNotApplicable(TemplateConfigurationFactory tcf, String sourceName)
163 throws IOException, TemplateConfigurationFactoryException {
164 assertNull(tcf.get(sourceName, DummyTemplateLoadingSource.INSTANCE));
165 }
166
167 private void assertApplicable(TemplateConfigurationFactory tcf, String sourceName, TemplateConfiguration... expectedTCs)
168 throws IOException, TemplateConfigurationFactoryException {
169 TemplateConfiguration mergedTC = tcf.get(sourceName, DummyTemplateLoadingSource.INSTANCE);
170 List<Serializable> mergedTCAttNames = new ArrayList<>(mergedTC.getCustomSettings(false).keySet());
171
172 for (TemplateConfiguration expectedTC : expectedTCs) {
173 Integer tcId = (Integer) expectedTC.getCustomSetting("id");
174 if (tcId == null) {
175 fail("TemplateConfiguration-s must be created with newTemplateConfiguration(id) in this test");
176 }
177 if (!mergedTCAttNames.contains("contains" + tcId)) {
178 fail("TemplateConfiguration with ID " + tcId + " is missing from the asserted value");
179 }
180 }
181
182 for (Serializable attKey: mergedTCAttNames) {
183 if (!containsCustomAttr(attKey, expectedTCs)) {
184 fail("The asserted TemplateConfiguration contains an unexpected custom setting: " + attKey);
185 }
186 }
187
188 assertEquals(expectedTCs[expectedTCs.length - 1].getCustomSetting("id"), mergedTC.getCustomSetting("id"));
189 }
190
191 private boolean containsCustomAttr(Serializable attKey, TemplateConfiguration... expectedTCs) {
192 for (TemplateConfiguration expectedTC : expectedTCs) {
193 if (expectedTC.getCustomSetting(attKey, ProcessingConfiguration.MISSING_VALUE_MARKER)
194 != ProcessingConfiguration.MISSING_VALUE_MARKER) {
195 return true;
196 }
197 }
198 return false;
199 }
200
201 @SuppressWarnings("serial")
202 private static class DummyTemplateLoadingSource implements TemplateLoadingSource {
203 private static DummyTemplateLoadingSource INSTANCE = new DummyTemplateLoadingSource();
204 }
205
206 }