Repository: incubator-freemarker Updated Branches: refs/heads/3 4c6e08a1c -> 2af16e4f2
In XML processing, the @@ names are now also converted to camel case (like node.@@nested_markup to node.@@nestedMarkup). Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/a04ab89c Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/a04ab89c Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/a04ab89c Branch: refs/heads/3 Commit: a04ab89c6830c43d531f09c7fe9fae42b0cdf915 Parents: 4c6e08a Author: ddekany <ddek...@apache.org> Authored: Sun Jul 16 01:26:09 2017 +0200 Committer: ddekany <ddek...@apache.org> Committed: Sun Jul 16 01:32:55 2017 +0200 ---------------------------------------------------------------------- FM3-CHANGE-LOG.txt | 8 ++-- .../core/FM2ASTToFM3SourceConverter.java | 48 +++++++++++++++++-- .../freemarker/ext/dom/AtAtKeyAccessor.java | 35 ++++++++++++++ .../converter/FM2ToFM3ConverterTest.java | 14 +++++- .../java/org/apache/freemarker/dom/AtAtKey.java | 14 +++--- .../apache/freemarker/dom/DOMSiblingTest.java | 12 ++--- .../java/org/apache/freemarker/dom/DOMTest.java | 50 ++++++++++---------- 7 files changed, 136 insertions(+), 45 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a04ab89c/FM3-CHANGE-LOG.txt ---------------------------------------------------------------------- diff --git a/FM3-CHANGE-LOG.txt b/FM3-CHANGE-LOG.txt index 52b00c9..7cbd223 100644 --- a/FM3-CHANGE-LOG.txt +++ b/FM3-CHANGE-LOG.txt @@ -18,13 +18,15 @@ */ Because the Manual won't be updated for a good while, we will lead -the FreeMarer 3 changelog here: +the FreeMarker 3 changelog here: - Switched to camel case as the only supported naming convention. This is as if in FM2 you set the "namingConvention" configuration setting to "camelCase", however the "namingConvention" setting was removed, as no other convention will be supported (for the default dialect at least). Also, configuration setting names and values must use camel case - too (FM2 was forgiving there). This means `#elseif` becomes to ``#elseIf`, ``?upper_case`, `?upperCase`, and - if you configure FreeMarker with Properties, then `template_loader` becomes to `templateLoader`. + too (FM2 was forgiving there). Also, in XML processing, the @@ names were also converted to camel case. This means + `#elseif` becomes to ``#elseIf`, ``?upper_case`, `?upperCase`, and if you configure FreeMarker with Properties, + then `template_loader` becomes to `templateLoader`, and if you use the XML features, then `node.@@nested_markup` + becomes to `node.@@nestedMarkup`. Note that the template converter tool takes care of this conversion. - Increased version number to 3.0.0 (nightly aka. SNAPSHOT) - Removed legacy extensions: rhyno, jython, xml (not to be confused with dom), jdom, ant. http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a04ab89c/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java ---------------------------------------------------------------------- diff --git a/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java b/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java index e4a3e12..03eb9c5 100644 --- a/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java +++ b/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java @@ -46,6 +46,7 @@ import com.google.common.collect.ImmutableSet; import freemarker.cache.StringTemplateLoader; import freemarker.cache.TemplateLoader; +import freemarker.ext.dom.AtAtKeyAccessor; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.utility.StringUtil; @@ -1524,10 +1525,36 @@ public class FM2ASTToFM3SourceConverter { Expression lho = getParam(node, 0, ParameterRole.LEFT_HAND_OPERAND, Expression.class); String rho = getParam(node, 1, ParameterRole.RIGHT_HAND_OPERAND, String.class); printNode(lho); + printSeparatorAndWSAndExpComments(getEndPositionExclusive(lho), "."); + + rho = mapStringHashKey(rho); print(rho.startsWith("*") ? rho : FTLUtil.escapeIdentifier(rho)); } + private String mapStringHashKey(String key) { + if (key.startsWith("@@")) { + String mappedKey = DOM_KEY_MAPPING.get(key); + if (mappedKey != null) { + key = mappedKey; + } + } + return key; + } + + private static final Map<String, String> DOM_KEY_MAPPING; + static { + Map<String, String> domKeyMapping = new HashMap<>(); + for (String atAtKey : AtAtKeyAccessor.getAtAtKeys()) { + String atAtKeyCC = ConverterUtils.snakeCaseToCamelCase(atAtKey); + if (!atAtKeyCC.equals(atAtKey)) { + domKeyMapping.put(atAtKey, atAtKeyCC); + } + } + + DOM_KEY_MAPPING = Collections.unmodifiableMap(domKeyMapping); + } + private void printExpDynamicKeyName(DynamicKeyName node) throws ConverterException { assertParamCount(node, 2); @@ -1536,7 +1563,12 @@ public class FM2ASTToFM3SourceConverter { Expression keyExp = getParam(node, 1, ParameterRole.ENCLOSED_OPERAND, Expression.class); printParameterSeparatorSource(collExp, keyExp); - printExp(keyExp); + if (keyExp instanceof StringLiteral && keyExp.isLiteral()) { + StringLiteral keyStringLiteral = (StringLiteral) keyExp; + printExpStringLiteral(keyStringLiteral, mapStringHashKey((keyStringLiteral).getAsString())); + } else { + printExp(keyExp); + } printWithParamsTrailingSkippedTokens("]", node, 1); } @@ -1725,6 +1757,10 @@ public class FM2ASTToFM3SourceConverter { private int stringLiteralNestingLevel; private void printExpStringLiteral(StringLiteral node) throws ConverterException { + printExpStringLiteral(node, node.isLiteral() ? node.getAsString() : null); + } + + private void printExpStringLiteral(StringLiteral node, String value) throws ConverterException { boolean escapeAmp, escapeLT, escapeGT; if (stringLiteralNestingLevel == 0) { // We check if the source code has avoided '&', '<', and '>'. If it did, we will escape them in the output. @@ -1775,12 +1811,18 @@ public class FM2ASTToFM3SourceConverter { int parameterCount = node.getParameterCount(); if (parameterCount == 0) { + _NullArgumentException.check("value", value); if (!rawString) { - print(FTLUtil.escapeStringLiteralPart(node.getAsString(), quote, escapeAmp, escapeLT, escapeGT)); + print(FTLUtil.escapeStringLiteralPart(value, quote, escapeAmp, escapeLT, escapeGT)); } else { - print(node.getAsString()); + print(value); } } else { + if (value != null) { + throw new IllegalArgumentException("\"value\" argument must be null when the string contains " + + "interpolations."); + } + // Not really a literal; contains interpolations for (int paramIdx = 0; paramIdx < parameterCount; paramIdx++) { Object param = getParam(node, paramIdx, ParameterRole.VALUE_PART, Object.class); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a04ab89c/freemarker-converter/src/main/java/freemarker/ext/dom/AtAtKeyAccessor.java ---------------------------------------------------------------------- diff --git a/freemarker-converter/src/main/java/freemarker/ext/dom/AtAtKeyAccessor.java b/freemarker-converter/src/main/java/freemarker/ext/dom/AtAtKeyAccessor.java new file mode 100644 index 0000000..460b407 --- /dev/null +++ b/freemarker-converter/src/main/java/freemarker/ext/dom/AtAtKeyAccessor.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package freemarker.ext.dom; + +import java.util.HashSet; +import java.util.Set; + +public class AtAtKeyAccessor { + + public static Set<String> getAtAtKeys() { + Set<String> keys = new HashSet<>(); + for (AtAtKey atAtKey : AtAtKey.values()) { + keys.add(atAtKey.getKey()); + } + return keys; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a04ab89c/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java ---------------------------------------------------------------------- diff --git a/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java b/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java index b4bb719..aaa523c 100644 --- a/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java +++ b/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java @@ -480,7 +480,19 @@ public class FM2ToFM3ConverterTest extends ConverterTest { @Test public void testSquareBracketTagSyntax() throws IOException, ConverterException { - assertConvertedSame("[#if true <#-- c -->[#-- c --]]${v}[/#if]", true); + assertConverted("[#if true <#-- c -->[#-- c --]]${v}[#else][/#if]", + "[#if true <#-- c -->[#-- c --]]${v}[#else/][/#if]", true); + assertConverted("[#ftl][#if true <#-- c -->[#-- c --]]${v}[#else][/#if]", + "[#ftl][#if true <#-- c -->[#-- c --]]${v}[#else/][/#if]"); + } + + @Test + public void testXmlProcessing() throws IOException, ConverterException { + assertConverted("${node.@@nestedMarkup}", "${node.@@nested_markup}"); + assertConverted("${node['@@nestedMarkup']}", "${node['@@nested_markup']}"); + + assertConvertedSame("${node.@@markup}"); + assertConvertedSame("${node['@@markup']}"); } @Test http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a04ab89c/freemarker-dom/src/main/java/org/apache/freemarker/dom/AtAtKey.java ---------------------------------------------------------------------- diff --git a/freemarker-dom/src/main/java/org/apache/freemarker/dom/AtAtKey.java b/freemarker-dom/src/main/java/org/apache/freemarker/dom/AtAtKey.java index ca6ac6b..1139b18 100644 --- a/freemarker-dom/src/main/java/org/apache/freemarker/dom/AtAtKey.java +++ b/freemarker-dom/src/main/java/org/apache/freemarker/dom/AtAtKey.java @@ -24,17 +24,17 @@ package org.apache.freemarker.dom; enum AtAtKey { MARKUP("@@markup"), - NESTED_MARKUP("@@nested_markup"), - ATTRIBUTES_MARKUP("@@attributes_markup"), + NESTED_MARKUP("@@nestedMarkup"), + ATTRIBUTES_MARKUP("@@attributesMarkup"), TEXT("@@text"), - START_TAG("@@start_tag"), - END_TAG("@@end_tag"), + START_TAG("@@startTag"), + END_TAG("@@endTag"), QNAME("@@qname"), NAMESPACE("@@namespace"), - LOCAL_NAME("@@local_name"), + LOCAL_NAME("@@localName"), ATTRIBUTES("@@"), - PREVIOUS_SIBLING_ELEMENT("@@previous_sibling_element"), - NEXT_SIBLING_ELEMENT("@@next_sibling_element"); + PREVIOUS_SIBLING_ELEMENT("@@previousSiblingElement"), + NEXT_SIBLING_ELEMENT("@@nextSiblingElement"); private final String key; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a04ab89c/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSiblingTest.java ---------------------------------------------------------------------- diff --git a/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSiblingTest.java b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSiblingTest.java index af874fa..f69f0f2 100644 --- a/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSiblingTest.java +++ b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMSiblingTest.java @@ -64,32 +64,32 @@ public class DOMSiblingTest extends TemplateTest { @Test public void testSignificantPreviousSibling() throws IOException, TemplateException { - assertOutput("${doc.person.name.@@previous_sibling_element}", "male"); + assertOutput("${doc.person.name.@@previousSiblingElement}", "male"); } @Test public void testSignificantNextSibling() throws IOException, TemplateException { - assertOutput("${doc.person.name.@@next_sibling_element}", "12th August"); + assertOutput("${doc.person.name.@@nextSiblingElement}", "12th August"); } @Test public void testNullSignificantPreviousSibling() throws IOException, TemplateException { - assertOutput("${doc.person.phone.@@next_sibling_element?size}", "0"); + assertOutput("${doc.person.phone.@@nextSiblingElement?size}", "0"); } @Test public void testSkippingCommentNode() throws IOException, TemplateException { - assertOutput("${doc.person.profession.@@previous_sibling_element}", "Chennai, India"); + assertOutput("${doc.person.profession.@@previousSiblingElement}", "Chennai, India"); } @Test public void testSkippingEmptyCDataNode() throws IOException, TemplateException { - assertOutput("${doc.person.hobby.@@previous_sibling_element}", "Software Engineer"); + assertOutput("${doc.person.hobby.@@previousSiblingElement}", "Software Engineer"); } @Test public void testValidCDataNode() throws IOException, TemplateException { - assertOutput("${doc.person.phone.@@previous_sibling_element?size}", "0"); + assertOutput("${doc.person.phone.@@previousSiblingElement?size}", "0"); } } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a04ab89c/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMTest.java ---------------------------------------------------------------------- diff --git a/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMTest.java b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMTest.java index 36f7226..84187c7 100644 --- a/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMTest.java +++ b/freemarker-dom/src/test/java/org/apache/freemarker/dom/DOMTest.java @@ -78,8 +78,8 @@ public class DOMTest extends TemplateTest { assertOutput(ftlHeader + "${doc?children[0]?children[2]['@*'][0].@@qname}", "a1"); assertOutput(ftlHeader + "${doc?children[0]?children[2]['@*'][1].@@qname}", "n2:a2"); // Unfortunately these include the xmlns attributes, but that would be non-BC to fix now: - assertThat(getOutput(ftlHeader + "${doc?children[0].@@start_tag}"), startsWith("<root")); - assertThat(getOutput(ftlHeader + "${doc?children[0]?children[1].@@start_tag}"), startsWith("<n2:b")); + assertThat(getOutput(ftlHeader + "${doc?children[0].@@startTag}"), startsWith("<root")); + assertThat(getOutput(ftlHeader + "${doc?children[0]?children[1].@@startTag}"), startsWith("<n2:b")); } @Test @@ -115,45 +115,45 @@ public class DOMTest extends TemplateTest { public void testInvalidAtAtKeyErrors() throws Exception { addDocToDataModel("<r><multipleMatches /><multipleMatches /></r>"); assertErrorContains("${doc.r.@@invalid_key}", "Unsupported @@ key", "@invalid_key"); - assertErrorContains("${doc.@@start_tag}", "@@start_tag", "not supported", "document"); + assertErrorContains("${doc.@@startTag}", "@@startTag", "not supported", "document"); assertErrorContains("${doc.@@}", "\"@@\"", "not supported", "document"); assertErrorContains("${doc.r.noMatch.@@invalid_key}", "Unsupported @@ key", "@invalid_key"); assertErrorContains("${doc.r.multipleMatches.@@invalid_key}", "Unsupported @@ key", "@invalid_key"); - assertErrorContains("${doc.r.noMatch.@@attributes_markup}", "single XML node", "@@attributes_markup"); - assertErrorContains("${doc.r.multipleMatches.@@attributes_markup}", "single XML node", "@@attributes_markup"); + assertErrorContains("${doc.r.noMatch.@@attributesMarkup}", "single XML node", "@@attributesMarkup"); + assertErrorContains("${doc.r.multipleMatches.@@attributesMarkup}", "single XML node", "@@attributesMarkup"); } @Test public void testAtAtSiblingElement() throws Exception { addDocToDataModel("<r><a/><b/></r>"); - assertOutput("${doc.r.@@previous_sibling_element?size}", "0"); - assertOutput("${doc.r.@@next_sibling_element?size}", "0"); - assertOutput("${doc.r.a.@@previous_sibling_element?size}", "0"); - assertOutput("${doc.r.a.@@next_sibling_element.@@qname}", "b"); - assertOutput("${doc.r.b.@@previous_sibling_element.@@qname}", "a"); - assertOutput("${doc.r.b.@@next_sibling_element?size}", "0"); + assertOutput("${doc.r.@@previousSiblingElement?size}", "0"); + assertOutput("${doc.r.@@nextSiblingElement?size}", "0"); + assertOutput("${doc.r.a.@@previousSiblingElement?size}", "0"); + assertOutput("${doc.r.a.@@nextSiblingElement.@@qname}", "b"); + assertOutput("${doc.r.b.@@previousSiblingElement.@@qname}", "a"); + assertOutput("${doc.r.b.@@nextSiblingElement?size}", "0"); addDocToDataModel("<r>\r\n\t <a/>\r\n\t <b/>\r\n\t </r>"); - assertOutput("${doc.r.@@previous_sibling_element?size}", "0"); - assertOutput("${doc.r.@@next_sibling_element?size}", "0"); - assertOutput("${doc.r.a.@@previous_sibling_element?size}", "0"); - assertOutput("${doc.r.a.@@next_sibling_element.@@qname}", "b"); - assertOutput("${doc.r.b.@@previous_sibling_element.@@qname}", "a"); - assertOutput("${doc.r.b.@@next_sibling_element?size}", "0"); + assertOutput("${doc.r.@@previousSiblingElement?size}", "0"); + assertOutput("${doc.r.@@nextSiblingElement?size}", "0"); + assertOutput("${doc.r.a.@@previousSiblingElement?size}", "0"); + assertOutput("${doc.r.a.@@nextSiblingElement.@@qname}", "b"); + assertOutput("${doc.r.b.@@previousSiblingElement.@@qname}", "a"); + assertOutput("${doc.r.b.@@nextSiblingElement?size}", "0"); addDocToDataModel("<r>t<a/>t<b/>t</r>"); - assertOutput("${doc.r.a.@@previous_sibling_element?size}", "0"); - assertOutput("${doc.r.a.@@next_sibling_element?size}", "0"); - assertOutput("${doc.r.b.@@previous_sibling_element?size}", "0"); - assertOutput("${doc.r.b.@@next_sibling_element?size}", "0"); + assertOutput("${doc.r.a.@@previousSiblingElement?size}", "0"); + assertOutput("${doc.r.a.@@nextSiblingElement?size}", "0"); + assertOutput("${doc.r.b.@@previousSiblingElement?size}", "0"); + assertOutput("${doc.r.b.@@nextSiblingElement?size}", "0"); addDocToDataModelNoSimplification("<r><a/> <!-- --><?pi?> <b/></r>"); - assertOutput("${doc.r.a.@@next_sibling_element.@@qname}", "b"); - assertOutput("${doc.r.b.@@previous_sibling_element.@@qname}", "a"); + assertOutput("${doc.r.a.@@nextSiblingElement.@@qname}", "b"); + assertOutput("${doc.r.b.@@previousSiblingElement.@@qname}", "a"); addDocToDataModelNoSimplification("<r><a/> <!-- -->t<!-- --> <b/></r>"); - assertOutput("${doc.r.a.@@next_sibling_element?size}", "0"); - assertOutput("${doc.r.b.@@previous_sibling_element?size}", "0"); + assertOutput("${doc.r.a.@@nextSiblingElement?size}", "0"); + assertOutput("${doc.r.b.@@previousSiblingElement?size}", "0"); } }