cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ntimof...@apache.org
Subject cayenne git commit: Template parser minor refactoring - use injectable Context factory to create parsing contexts - make Context less mutable - warn if unknown directive is used - minor test changes
Date Thu, 21 Sep 2017 09:17:59 GMT
Repository: cayenne
Updated Branches:
  refs/heads/master a60b09b15 -> 9f410575b


Template parser minor refactoring
 - use injectable Context factory to create parsing contexts
 - make Context less mutable
 - warn if unknown directive is used
 - minor test changes


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/9f410575
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/9f410575
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/9f410575

Branch: refs/heads/master
Commit: 9f410575bfe6fccb53cc9de6224b979c580dd4da
Parents: a60b09b
Author: Nikita Timofeev <stariy95@gmail.com>
Authored: Thu Sep 21 12:17:53 2017 +0300
Committer: Nikita Timofeev <stariy95@gmail.com>
Committed: Thu Sep 21 12:17:53 2017 +0300

----------------------------------------------------------------------
 .../configuration/server/ServerModule.java      |   3 +
 .../template/CayenneSQLTemplateProcessor.java   |  13 ++-
 .../org/apache/cayenne/template/Context.java    |  82 ++++++--------
 .../template/DefaultTemplateContextFactory.java |  64 +++++++++++
 .../template/TemplateContextFactory.java        |  35 ++++++
 .../cayenne/template/parser/ASTDirective.java   |   5 +
 .../template/parser/SQLTemplateParser.jjt       |   1 -
 .../CayenneSQLTemplateProcessorTest.java        |  39 ++++---
 .../template/parser/SQLTemplateParserTest.java  | 108 +++++++++++--------
 .../VelocitySQLTemplateProcessorTest.java       |   7 ++
 10 files changed, 239 insertions(+), 118 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/9f410575/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
index 1b8c76b..bc2e879 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
@@ -115,6 +115,8 @@ import org.apache.cayenne.access.types.ValueObjectType;
 import org.apache.cayenne.resource.ClassLoaderResourceLocator;
 import org.apache.cayenne.resource.ResourceLocator;
 import org.apache.cayenne.template.CayenneSQLTemplateProcessor;
+import org.apache.cayenne.template.DefaultTemplateContextFactory;
+import org.apache.cayenne.template.TemplateContextFactory;
 import org.apache.cayenne.tx.DefaultTransactionFactory;
 import org.apache.cayenne.tx.DefaultTransactionManager;
 import org.apache.cayenne.tx.TransactionFactory;
@@ -416,6 +418,7 @@ public class ServerModule implements Module {
         binder.bind(RowReaderFactory.class).to(DefaultRowReaderFactory.class);
 
         binder.bind(SQLTemplateProcessor.class).to(CayenneSQLTemplateProcessor.class);
+        binder.bind(TemplateContextFactory.class).to(DefaultTemplateContextFactory.class);
 
         binder.bind(HandlerFactory.class).to(DefaultHandlerFactory.class);
         binder.bind(DataChannelMetaData.class).to(NoopDataChannelMetaData.class);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/9f410575/cayenne-server/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java
b/cayenne-server/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java
index 2d80523..fa57bd9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/CayenneSQLTemplateProcessor.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.access.jdbc.SQLStatement;
 import org.apache.cayenne.access.jdbc.SQLTemplateProcessor;
+import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.template.parser.Node;
 import org.apache.cayenne.template.parser.ParseException;
 import org.apache.cayenne.template.parser.SQLTemplateParser;
@@ -44,22 +45,26 @@ public class CayenneSQLTemplateProcessor implements SQLTemplateProcessor
{
 
     TemplateParserPool parserPool = new TemplateParserPool();
 
+    private TemplateContextFactory contextFactory;
+
+    public CayenneSQLTemplateProcessor(@Inject TemplateContextFactory contextFactory) {
+        this.contextFactory = contextFactory;
+    }
+
     @Override
     public SQLStatement processTemplate(String template, Map<String, ?> parameters)
{
-        Context context = new Context();
-        context.addParameters(parameters);
+        Context context = contextFactory.createContext(parameters);
         return process(template, context);
     }
 
     @Override
     public SQLStatement processTemplate(String template, List<Object> positionalParameters)
{
-        Context context = new Context(true);
         Map<String, Object> parameters = new HashMap<>();
         int i=0;
         for(Object param : positionalParameters) {
             parameters.put(String.valueOf(i++), param);
         }
-        context.addParameters(parameters);
+        Context context = contextFactory.createContext(parameters, true);
         return process(template, context);
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/9f410575/cayenne-server/src/main/java/org/apache/cayenne/template/Context.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/Context.java b/cayenne-server/src/main/java/org/apache/cayenne/template/Context.java
index c15371c..31d3c1f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/Context.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/Context.java
@@ -27,51 +27,30 @@ import java.util.Map;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.access.jdbc.ColumnDescriptor;
 import org.apache.cayenne.access.translator.ParameterBinding;
-import org.apache.cayenne.template.directive.Bind;
-import org.apache.cayenne.template.directive.BindEqual;
-import org.apache.cayenne.template.directive.BindNotEqual;
-import org.apache.cayenne.template.directive.BindObjectEqual;
-import org.apache.cayenne.template.directive.BindObjectNotEqual;
 import org.apache.cayenne.template.directive.Directive;
-import org.apache.cayenne.template.directive.Result;
 
 /**
  * @since 4.1
  */
 public class Context {
 
-    Map<String, Directive> directives = new HashMap<>();
+    private final StringBuilder builder;
+    private final Map<String, ?> objects;
+    private final Map<String, String> parameterAliases;
+    private final Map<String, Directive> directives;
 
-    Map<String, Object> objects = new HashMap<>();
+    private List<ParameterBinding> parameterBindings;
+    private List<ColumnDescriptor> columnDescriptors;
+    private int counter;
 
-    Map<String, String> parameterAliases;
-
-    List<ParameterBinding> parameterBindings = new ArrayList<>();
-
-    List<ColumnDescriptor> columnDescriptors = new ArrayList<>();
-
-    StringBuilder builder = new StringBuilder();
-
-    boolean positionalMode;
-
-    int counter;
-
-    public Context() {
-        addDirective(             "result", Result.INSTANCE);
-        addDirective(               "bind", Bind.INSTANCE);
-        addDirective(          "bindEqual", BindEqual.INSTANCE);
-        addDirective(       "bindNotEqual", BindNotEqual.INSTANCE);
-        addDirective(    "bindObjectEqual", BindObjectEqual.INSTANCE);
-        addDirective( "bindObjectNotEqual", BindObjectNotEqual.INSTANCE);
-
-        addParameter("helper", new SQLTemplateRenderingUtils());
-    }
-
-    public Context(boolean positionalMode) {
-        this();
-        this.positionalMode = positionalMode;
+    public Context(Map<String, Directive> directives, Map<String, ?> parameters,
boolean positionalMode) {
+        this.directives = directives;
+        this.objects = parameters;
+        this.builder = new StringBuilder();
         if(positionalMode) {
             parameterAliases = new HashMap<>();
+        } else {
+            parameterAliases = null;
         }
     }
 
@@ -84,8 +63,9 @@ public class Context {
     }
 
     public String buildTemplate() {
-        if(positionalMode) {
-            if(counter <= objects.size() - 2) {
+        if(parameterAliases != null) {
+            // there is always helper object, thus -1
+            if(counter < objects.size() - 1) {
                 throw new CayenneRuntimeException("Too many parameters to bind template:
" + (objects.size() - 1));
             }
         }
@@ -102,7 +82,7 @@ public class Context {
             return object;
         }
 
-        if(positionalMode) {
+        if(parameterAliases != null) {
             String alias = parameterAliases.get(name);
             if(alias == null) {
                 if(counter > objects.size() - 2) {
@@ -118,31 +98,31 @@ public class Context {
         return null;
     }
 
-    public void addParameter(String name, Object value) {
-        objects.put(name, value);
-    }
-
-    public void addParameters(Map<String, ?> parameters) {
-        objects.putAll(parameters);
-    }
-
-    public void addDirective(String name, Directive directive) {
-        directives.put(name, directive);
-    }
-
     public void addParameterBinding(ParameterBinding binding) {
+        if(parameterBindings == null) {
+            parameterBindings = new ArrayList<>();
+        }
         parameterBindings.add(binding);
     }
 
     public void addColumnDescriptor(ColumnDescriptor descriptor) {
+        if(columnDescriptors == null) {
+            columnDescriptors = new ArrayList<>();
+        }
         columnDescriptors.add(descriptor);
     }
 
     public ColumnDescriptor[] getColumnDescriptors() {
-        return columnDescriptors.toArray(new ColumnDescriptor[0]);
+        if(columnDescriptors == null) {
+            return new ColumnDescriptor[0];
+        }
+        return columnDescriptors.toArray(new ColumnDescriptor[columnDescriptors.size()]);
     }
 
     public ParameterBinding[] getParameterBindings() {
-        return parameterBindings.toArray(new ParameterBinding[0]);
+        if(parameterBindings == null) {
+            return new ParameterBinding[0];
+        }
+        return parameterBindings.toArray(new ParameterBinding[parameterBindings.size()]);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/9f410575/cayenne-server/src/main/java/org/apache/cayenne/template/DefaultTemplateContextFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/DefaultTemplateContextFactory.java
b/cayenne-server/src/main/java/org/apache/cayenne/template/DefaultTemplateContextFactory.java
new file mode 100644
index 0000000..6aac206
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/DefaultTemplateContextFactory.java
@@ -0,0 +1,64 @@
+/*****************************************************************
+ *   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 org.apache.cayenne.template;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cayenne.template.directive.Bind;
+import org.apache.cayenne.template.directive.BindEqual;
+import org.apache.cayenne.template.directive.BindNotEqual;
+import org.apache.cayenne.template.directive.BindObjectEqual;
+import org.apache.cayenne.template.directive.BindObjectNotEqual;
+import org.apache.cayenne.template.directive.Directive;
+import org.apache.cayenne.template.directive.Result;
+
+/**
+ * @since 4.1
+ */
+public class DefaultTemplateContextFactory implements TemplateContextFactory {
+
+    private final SQLTemplateRenderingUtils helper;
+
+    // directive map is static for now, can be easily injected
+    private final Map<String, Directive> directives;
+
+    public DefaultTemplateContextFactory() {
+        Map<String, Directive> directiveHashMap = new HashMap<>();
+        directiveHashMap.put("bind", Bind.INSTANCE);
+        directiveHashMap.put("bindEqual", BindEqual.INSTANCE);
+        directiveHashMap.put("bindNotEqual", BindNotEqual.INSTANCE);
+        directiveHashMap.put("bindObjectEqual", BindObjectEqual.INSTANCE);
+        directiveHashMap.put("bindObjectNotEqual", BindObjectNotEqual.INSTANCE);
+        directiveHashMap.put("result", Result.INSTANCE);
+
+        directives = Collections.unmodifiableMap(directiveHashMap);
+        helper = new SQLTemplateRenderingUtils();
+    }
+
+    @Override
+    public Context createContext(Map<String, ?> parameters, boolean positionalMode)
{
+        Map<String, Object> realParameters = new HashMap<>(parameters.size()
+ 1);
+        realParameters.putAll(parameters);
+        realParameters.put("helper", helper);
+        return new Context(directives, realParameters, positionalMode);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/9f410575/cayenne-server/src/main/java/org/apache/cayenne/template/TemplateContextFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/TemplateContextFactory.java
b/cayenne-server/src/main/java/org/apache/cayenne/template/TemplateContextFactory.java
new file mode 100644
index 0000000..0fe09fc
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/TemplateContextFactory.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 org.apache.cayenne.template;
+
+import java.util.Map;
+
+/**
+ * @since 4.1
+ */
+public interface TemplateContextFactory {
+
+    Context createContext(Map<String, ?> parameters, boolean positionalMode);
+
+    default Context createContext(Map<String, ?> parameters) {
+        return createContext(parameters, false);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/9f410575/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java
b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java
index cd3b656..34bb39e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/template/parser/ASTDirective.java
@@ -21,12 +21,16 @@ package org.apache.cayenne.template.parser;
 
 import org.apache.cayenne.template.Context;
 import org.apache.cayenne.template.directive.Directive;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * @since 4.1
  */
 public class ASTDirective extends IdentifierNode {
 
+    private static final Logger logger = LoggerFactory.getLogger(ASTDirective.class);
+
     public ASTDirective(int id) {
         super(id);
     }
@@ -35,6 +39,7 @@ public class ASTDirective extends IdentifierNode {
     public void evaluate(Context context) {
         Directive directive = context.getDirective(getIdentifier());
         if(directive == null) {
+            logger.warn("Unknown directive #{}", getIdentifier());
             return;
         }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/9f410575/cayenne-server/src/main/jjtree/org/apache/cayenne/template/parser/SQLTemplateParser.jjt
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/jjtree/org/apache/cayenne/template/parser/SQLTemplateParser.jjt
b/cayenne-server/src/main/jjtree/org/apache/cayenne/template/parser/SQLTemplateParser.jjt
index b4114bc..5788e06 100644
--- a/cayenne-server/src/main/jjtree/org/apache/cayenne/template/parser/SQLTemplateParser.jjt
+++ b/cayenne-server/src/main/jjtree/org/apache/cayenne/template/parser/SQLTemplateParser.jjt
@@ -26,7 +26,6 @@ This template will be resolved correctly
 
 Comparision to Velocity:
 - no escape syntax, i.e. ${a}, directives and vars must be space separated
-- no arrays syntax
 - no #set directive
 - no loops
 - no complex expressions (neither logical nor math)

http://git-wip-us.apache.org/repos/asf/cayenne/blob/9f410575/cayenne-server/src/test/java/org/apache/cayenne/template/CayenneSQLTemplateProcessorTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/template/CayenneSQLTemplateProcessorTest.java
b/cayenne-server/src/test/java/org/apache/cayenne/template/CayenneSQLTemplateProcessorTest.java
index de148e0..9e17849 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/template/CayenneSQLTemplateProcessorTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/template/CayenneSQLTemplateProcessorTest.java
@@ -44,14 +44,14 @@ public class CayenneSQLTemplateProcessorTest {
 
     @Before
     public void before() {
-        processor = new CayenneSQLTemplateProcessor();
+        processor = new CayenneSQLTemplateProcessor(new DefaultTemplateContextFactory());
     }
 
     @Test
     public void testProcessTemplateUnchanged1() throws Exception {
         String sqlTemplate = "SELECT * FROM ME";
 
-        SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String,
Object> emptyMap());
+        SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
 
         assertEquals(sqlTemplate, compiled.getSql());
         assertEquals(0, compiled.getBindings().length);
@@ -61,7 +61,7 @@ public class CayenneSQLTemplateProcessorTest {
     public void testProcessTemplateUnchanged2() throws Exception {
         String sqlTemplate = "SELECT a.b as XYZ FROM $SYSTEM_TABLE";
 
-        SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String,
Object> emptyMap());
+        SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
 
         assertEquals(sqlTemplate, compiled.getSql());
         assertEquals(0, compiled.getBindings().length);
@@ -71,7 +71,7 @@ public class CayenneSQLTemplateProcessorTest {
     public void testProcessTemplateSimpleDynamicContent() throws Exception {
         String sqlTemplate = "SELECT * FROM ME WHERE $a";
 
-        Map<String, Object> map = Collections.<String, Object> singletonMap("a",
"VALUE_OF_A");
+        Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
         SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
 
         assertEquals("SELECT * FROM ME WHERE VALUE_OF_A", compiled.getSql());
@@ -84,7 +84,7 @@ public class CayenneSQLTemplateProcessorTest {
     public void testProcessTemplateBind() throws Exception {
         String sqlTemplate = "SELECT * FROM ME WHERE "
                 + "COLUMN1 = #bind($a 'VARCHAR') AND COLUMN2 = #bind($b 'INTEGER')";
-        Map<String, Object> map = Collections.<String, Object> singletonMap("a",
"VALUE_OF_A");
+        Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
         SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
 
         assertEquals("SELECT * FROM ME WHERE COLUMN1 = ? AND COLUMN2 = ?", compiled.getSql());
@@ -96,7 +96,7 @@ public class CayenneSQLTemplateProcessorTest {
     @Test
     public void testProcessTemplateBindGuessVarchar() throws Exception {
         String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
-        Map<String, Object> map = Collections.<String, Object> singletonMap("a",
"VALUE_OF_A");
+        Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
 
         SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
 
@@ -107,7 +107,7 @@ public class CayenneSQLTemplateProcessorTest {
     @Test
     public void testProcessTemplateBindGuessInteger() throws Exception {
         String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
-        Map<String, Object> map = Collections.<String, Object> singletonMap("a",
4);
+        Map<String, Object> map = Collections.singletonMap("a", 4);
 
         SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
 
@@ -119,12 +119,12 @@ public class CayenneSQLTemplateProcessorTest {
     public void testProcessTemplateBindEqual() throws Exception {
         String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindEqual($a 'VARCHAR')";
 
-        SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String,
Object> emptyMap());
+        SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
 
         assertEquals("SELECT * FROM ME WHERE COLUMN IS NULL", compiled.getSql());
         assertEquals(0, compiled.getBindings().length);
 
-        Map<String, Object> map = Collections.<String, Object> singletonMap("a",
"VALUE_OF_A");
+        Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
 
         compiled = processor.processTemplate(sqlTemplate, map);
 
@@ -137,12 +137,12 @@ public class CayenneSQLTemplateProcessorTest {
     public void testProcessTemplateBindNotEqual() throws Exception {
         String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindNotEqual($a 'VARCHAR')";
 
-        SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.<String,
Object> emptyMap());
+        SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
 
         assertEquals("SELECT * FROM ME WHERE COLUMN IS NOT NULL", compiled.getSql());
         assertEquals(0, compiled.getBindings().length);
 
-        Map<String, Object> map = Collections.<String, Object> singletonMap("a",
"VALUE_OF_A");
+        Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
 
         compiled = processor.processTemplate(sqlTemplate, map);
 
@@ -158,7 +158,7 @@ public class CayenneSQLTemplateProcessorTest {
         DataObject dataObject = new CayenneDataObject();
         dataObject.setObjectId(new ObjectId("T", "ID_COLUMN", 5));
 
-        Map<String, Object> map = Collections.<String, Object> singletonMap("a",
dataObject);
+        Map<String, Object> map = Collections.singletonMap("a", dataObject);
 
         SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
 
@@ -180,7 +180,7 @@ public class CayenneSQLTemplateProcessorTest {
         DataObject dataObject = new CayenneDataObject();
         dataObject.setObjectId(id);
 
-        Map<String, Object> map = Collections.<String, Object> singletonMap("a",
dataObject);
+        Map<String, Object> map = Collections.singletonMap("a", dataObject);
 
         SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
 
@@ -194,7 +194,7 @@ public class CayenneSQLTemplateProcessorTest {
     public void testProcessTemplateConditions() throws Exception {
         String sqlTemplate = "SELECT * FROM ME #if($a) WHERE COLUMN1 > #bind($a)#end";
 
-        Map<String, Object> map = Collections.<String, Object> singletonMap("a",
"VALUE_OF_A");
+        Map<String, Object> map = Collections.singletonMap("a", "VALUE_OF_A");
 
         SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
 
@@ -202,7 +202,7 @@ public class CayenneSQLTemplateProcessorTest {
         assertEquals(1, compiled.getBindings().length);
         assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
 
-        compiled = processor.processTemplate(sqlTemplate, Collections.<String, Object>
emptyMap());
+        compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
 
         assertEquals("SELECT * FROM ME ", compiled.getSql());
         assertEquals(0, compiled.getBindings().length);
@@ -212,7 +212,7 @@ public class CayenneSQLTemplateProcessorTest {
     public void testProcessTemplateBindCollection() throws Exception {
         String sqlTemplate = "SELECT * FROM ME WHERE COLUMN IN (#bind($list 'VARCHAR'))";
 
-        Map<String, Object> map = Collections.<String, Object> singletonMap("list",
Arrays.asList("a", "b", "c"));
+        Map<String, Object> map = Collections.singletonMap("list", Arrays.asList("a",
"b", "c"));
         SQLStatement compiled = processor.processTemplate(sqlTemplate, map);
 
         assertEquals("SELECT * FROM ME WHERE COLUMN IN (?,?,?)", compiled.getSql());
@@ -222,6 +222,13 @@ public class CayenneSQLTemplateProcessorTest {
         assertBindingValue("c", compiled.getBindings()[2]);
     }
 
+    @Test
+    public void testUnknownDirective() throws Exception {
+        String sqlTemplate = "SELECT #from(1) FROM a";
+        SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
+        assertEquals("SELECT  FROM a", compiled.getSql());
+    }
+
     private void assertBindingValue(Object expectedValue, Object binding) {
         assertTrue("Not a binding!", binding instanceof ParameterBinding);
         assertEquals(expectedValue, ((ParameterBinding) binding).getValue());

http://git-wip-us.apache.org/repos/asf/cayenne/blob/9f410575/cayenne-server/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java
b/cayenne-server/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java
index 22d91a0..36735ad 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/template/parser/SQLTemplateParserTest.java
@@ -20,8 +20,15 @@
 package org.apache.cayenne.template.parser;
 
 import java.io.ByteArrayInputStream;
+import java.time.LocalDateTime;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.apache.cayenne.template.Context;
+import org.apache.cayenne.template.DefaultTemplateContextFactory;
+import org.apache.cayenne.template.TemplateContextFactory;
+import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 
@@ -32,9 +39,16 @@ import static org.junit.Assert.*;
  */
 public class SQLTemplateParserTest {
 
+    private TemplateContextFactory contextFactory;
+
+    @Before
+    public void setUp() {
+        contextFactory = new DefaultTemplateContextFactory();
+    }
+
     @Test
     public void testUnchangedParse() throws Exception {
-        Context context = new Context();
+        Context context = contextFactory.createContext(Collections.emptyMap());
         String template = "SELECT * FROM a";
 
         String sql = parseString(template, context);
@@ -43,8 +57,7 @@ public class SQLTemplateParserTest {
 
     @Test
     public void testParameterParse() throws Exception {
-        Context context = new Context();
-        context.addParameter("a", true);
+        Context context = contextFactory.createContext(Collections.singletonMap("a", true));
         String template = "SELECT $a FROM a";
 
         String sql = parseString(template, context);
@@ -53,15 +66,13 @@ public class SQLTemplateParserTest {
 
     @Test
     public void testIfElseParse() throws Exception {
-        Context context = new Context();
-        context.addParameter("a", true);
+        Context context = contextFactory.createContext(Collections.singletonMap("a", true));
         String template = "SELECT #if($a) * #else 1 #end FROM a";
 
         String sql = parseString(template, context);
         assertEquals("SELECT  *  FROM a", sql);
 
-        context = new Context();
-        context.addParameter("a", false);
+        context = contextFactory.createContext(Collections.singletonMap("a", false));
         template = "SELECT #if($a) * #else 1 #end FROM a";
 
         sql = parseString(template, context);
@@ -70,9 +81,11 @@ public class SQLTemplateParserTest {
 
     @Test
     public void testBindParse() throws Exception {
-        Context context = new Context();
-        context.addParameter("a", "var");
-        context.addParameter("b", "bbb");
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("a", "var");
+        parameters.put("b", "bbb");
+
+        Context context = contextFactory.createContext(parameters);
         String template = "SELECT #if($a) #bind($a, 'INT' ,2) #else #bind($b, 'CHAR' ,2)
#end FROM a";
 
         String sql = parseString(template, context);
@@ -84,22 +97,24 @@ public class SQLTemplateParserTest {
 
     @Test
     public void testComplexParse() throws Exception {
+        class Helper {
+            public String cayenneExp(Object obj, String exp) {
+                return "aaaa";
+            }
+        }
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("a", "var");
+        parameters.put("myHelper", new Helper());
+
         String template = "SELECT * \n" +
                 "FROM ME\n" +
                 "#if($a) \n" +
                 "WHERE \n" +
-                "COLUMN1 #bind($helper.cayenneExp($a, 'db:ID_COLUMN1'), 'INT')\n" +
+                "COLUMN1 #bind($myHelper.cayenneExp($a, 'db:ID_COLUMN1'), 'INT')\n" +
                 "     \tAND \n" +
-                "COLUMN2 #bind($helper.cayenneExp($a, 'db:ID_COLUMN2'), 'VARCHAR')\n" +
+                "COLUMN2 #bind($myHelper.cayenneExp($a, 'db:ID_COLUMN2'), 'VARCHAR')\n" +
                 "#end\n";
-        Context context = new Context();
-        class Helper {
-            public String cayenneExp(Object obj, String exp) {
-                return "aaaa";
-            }
-        }
-        context.addParameter("a", "var");
-        context.addParameter("helper", new Helper());
+        Context context = contextFactory.createContext(parameters);
 
         String sql = parseString(template, context);
         assertEquals("SELECT * \n" +
@@ -120,14 +135,15 @@ public class SQLTemplateParserTest {
                 "#result('t0.ID' 'java.lang.Integer' 'ec0_1' 'ec0_1' 4) " +
                 "FROM BIGDECIMAL_ENTITY t0 WHERE {fn ABS( t0.BIGDECIMAL_FIELD)} < #bind($id0
'DECIMAL')";
 
-        Context context = new Context();
-        context.addParameter("$id0", 123);
+        Context context = contextFactory.createContext(Collections.singletonMap("id0", 123));
         String sql = parseString(tpl, context);
 
         assertEquals("SELECT " +
                 "t0.BIGDECIMAL_FIELD AS ec0_0, " +
                 "t0.ID AS ec0_1 " +
                 "FROM BIGDECIMAL_ENTITY t0 WHERE {fn ABS( t0.BIGDECIMAL_FIELD)} < ?",
sql);
+        assertEquals(1, context.getParameterBindings().length);
+        assertEquals(2, context.getColumnDescriptors().length);
     }
 
     @Test
@@ -141,14 +157,20 @@ public class SQLTemplateParserTest {
                 "FROM ARTIST t0 " +
                 "LEFT OUTER JOIN PAINTING t1 ON (t0.ARTIST_ID = t1.ARTIST_ID) " +
                 "GROUP BY t0.ARTIST_NAME, t0.DATE_OF_BIRTH, t0.ARTIST_ID ORDER BY t0.ARTIST_NAME";
-        parseString(tpl, new Context());
+        Context context = contextFactory.createContext(Collections.emptyMap());
+        String sql = parseString(tpl, context);
+        assertEquals(5, context.getColumnDescriptors().length);
+        assertEquals("SELECT COUNT(*) AS sc0, t0.ARTIST_NAME AS ec1_0, " +
+                "t0.DATE_OF_BIRTH AS ec1_1, t0.ARTIST_ID AS ec1_2, SUM(t1.ESTIMATED_PRICE)
AS sc2 " +
+                "FROM ARTIST t0 " +
+                "LEFT OUTER JOIN PAINTING t1 ON (t0.ARTIST_ID = t1.ARTIST_ID) " +
+                "GROUP BY t0.ARTIST_NAME, t0.DATE_OF_BIRTH, t0.ARTIST_ID ORDER BY t0.ARTIST_NAME",
sql);
     }
 
     @Test
     public void testHelperObject() throws Exception {
         String tpl = "($helper.cayenneExp($a, 'field'))";
-        Context context = new Context();
-        context.addParameter("a", new TestBean(5));
+        Context context = contextFactory.createContext(Collections.singletonMap("a", new
TestBean(5)));
 
         String sql = parseString(tpl, context);
         assertEquals("(5)", sql);
@@ -157,8 +179,7 @@ public class SQLTemplateParserTest {
     @Test
     public void testMethodCallArray() throws Exception {
         String tpl = "$a.arrayMethod(['1' '2' '3'])";
-        Context context = new Context();
-        context.addParameter("a", new TestBean(5));
+        Context context = contextFactory.createContext(Collections.singletonMap("a", new
TestBean(5)));
 
         String sql = parseString(tpl, context);
         assertEquals("array_3", sql);
@@ -167,8 +188,7 @@ public class SQLTemplateParserTest {
     @Test
     public void testMethodCallInt() throws Exception {
         String tpl = "$a.intMethod(42)";
-        Context context = new Context();
-        context.addParameter("a", new TestBean(5));
+        Context context = contextFactory.createContext(Collections.singletonMap("a", new
TestBean(5)));
 
         String sql = parseString(tpl, context);
         assertEquals("int_42", sql);
@@ -177,8 +197,7 @@ public class SQLTemplateParserTest {
     @Test
     public void testMethodCallString() throws Exception {
         String tpl = "$a.stringMethod(\"abc\")";
-        Context context = new Context();
-        context.addParameter("a", new TestBean(5));
+        Context context = contextFactory.createContext(Collections.singletonMap("a", new
TestBean(5)));
 
         String sql = parseString(tpl, context);
         assertEquals("string_abc", sql);
@@ -187,8 +206,7 @@ public class SQLTemplateParserTest {
     @Test
     public void testMethodCallFloat() throws Exception {
         String tpl = "$a.floatMethod(3.14)";
-        Context context = new Context();
-        context.addParameter("a", new TestBean(5));
+        Context context = contextFactory.createContext(Collections.singletonMap("a", new
TestBean(5)));
 
         String sql = parseString(tpl, context);
         assertEquals("float_3.14", sql);
@@ -198,8 +216,7 @@ public class SQLTemplateParserTest {
     @Ignore("Method overload not properly supported, this test can return m2_true")
     public void testMethodCallSelectByArgType1() throws Exception {
         String tpl = "$a.method(123)";
-        Context context = new Context();
-        context.addParameter("a", new TestBean(5));
+        Context context = contextFactory.createContext(Collections.singletonMap("a", new
TestBean(5)));
 
         String sql = parseString(tpl, context);
         assertEquals("m1_123", sql);
@@ -208,8 +225,7 @@ public class SQLTemplateParserTest {
     @Test
     public void testMethodCallSelectByArgType2() throws Exception {
         String tpl = "$a.method(true)";
-        Context context = new Context();
-        context.addParameter("a", new TestBean(5));
+        Context context = contextFactory.createContext(Collections.singletonMap("a", new
TestBean(5)));
 
         String sql = parseString(tpl, context);
         assertEquals("m2_true", sql);
@@ -218,8 +234,7 @@ public class SQLTemplateParserTest {
     @Test
     public void testPropertyAccess() throws Exception {
         String tpl = "$a.field()";
-        Context context = new Context();
-        context.addParameter("a", new TestBean(5));
+        Context context = contextFactory.createContext(Collections.singletonMap("a", new
TestBean(5)));
 
         String sql = parseString(tpl, context);
         assertEquals("5", sql);
@@ -228,20 +243,20 @@ public class SQLTemplateParserTest {
     @Test
     public void testNestedBrackets() throws Exception {
         String tpl = "(#bind('A' 'b'))";
-        String sql = parseString(tpl, new Context());
+        String sql = parseString(tpl, contextFactory.createContext(Collections.emptyMap()));
         assertEquals("(?)", sql);
     }
 
     @Test
     public void testQuotes() throws Exception {
         String template = "\"$a\"";
-        Context context = new Context();
-        context.addParameter("a", "val");
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("a", "val");
+        Context context = contextFactory.createContext(parameters);
         String sql = parseString(template, context);
         assertEquals("\"val\"", sql);
 
-        context = new Context();
-        context.addParameter("a", "val");
+        context = contextFactory.createContext(parameters);
         template = "'$a'";
         sql = parseString(template, context);
         assertEquals("'val'", sql);
@@ -250,8 +265,9 @@ public class SQLTemplateParserTest {
     @Test
     public void testComma() throws Exception {
         String template = "$a,$a";
-        Context context = new Context();
-        context.addParameter("a", "val");
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("a", "val");
+        Context context = contextFactory.createContext(parameters);
         String sql = parseString(template, context);
         assertEquals("val,val", sql);
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/9f410575/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessorTest.java
----------------------------------------------------------------------
diff --git a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessorTest.java
b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessorTest.java
index 504179b..2b8a5e5 100644
--- a/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessorTest.java
+++ b/cayenne-velocity/src/test/java/org/apache/cayenne/velocity/VelocitySQLTemplateProcessorTest.java
@@ -222,6 +222,13 @@ public class VelocitySQLTemplateProcessorTest {
 		assertBindingValue("c", compiled.getBindings()[2]);
 	}
 
+	@Test
+	public void testUnknownDirective() throws Exception {
+		String sqlTemplate = "SELECT #from(1) FROM a";
+		SQLStatement compiled = processor.processTemplate(sqlTemplate, Collections.emptyMap());
+        assertEquals("SELECT #from(1) FROM a", compiled.getSql());
+	}
+
 	private void assertBindingValue(Object expectedValue, Object binding) {
 		assertTrue("Not a binding!", binding instanceof ParameterBinding);
 		assertEquals(expectedValue, ((ParameterBinding) binding).getValue());


Mime
View raw message