You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2019/07/30 12:42:01 UTC

[plc4x] branch develop updated: - Added support for calling static methods - Added support for simple typed arrayFields

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new 2b768c2  - Added support for calling static methods - Added support for simple typed arrayFields
2b768c2 is described below

commit 2b768c204d738d15ef6654c2674a0915ca9a3fc7
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Jul 30 14:41:55 2019 +0200

    - Added support for calling static methods
    - Added support for simple typed arrayFields
---
 .../freemarker/FreemarkerLanguageOutput.java       |  3 +-
 .../language/java/JavaLanguageTemplateHelper.java  | 30 ++++++++++-
 .../main/resources/templates/java/io-template.ftlh | 60 +++++++++++++++++++---
 3 files changed, 84 insertions(+), 9 deletions(-)

diff --git a/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java b/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java
index d349e45..6b69f20 100644
--- a/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java
+++ b/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java
@@ -56,6 +56,8 @@ public abstract class FreemarkerLanguageOutput implements LanguageOutput {
 
             // Iterate over the types and have content generated for each one
             for (Map.Entry<String, ComplexTypeDefinition> typeEntry : types.entrySet()) {
+                LOGGER.info("Generating type " + typeEntry.getKey());
+
                 // Prepare a new generation context
                 Map<String, Object> typeContext = new HashMap<>();
                 typeContext.put("packageName", packageName);
@@ -96,7 +98,6 @@ public abstract class FreemarkerLanguageOutput implements LanguageOutput {
                     }
                     outputFileWriter.flush();
                 }
-                LOGGER.info("Generating type " + typeEntry.getKey());
             }
         } catch (TemplateNotFoundException | TemplateException | MalformedTemplateNameException | ParseException e) {
             throw new GenerationException("Error resolving template", e);
diff --git a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index 35531bc..25ec787 100644
--- a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -483,8 +483,30 @@ public class JavaLanguageTemplateHelper implements FreemarkerLanguageTemplateHel
 
     private String toVariableSerializationExpression(Term term) {
         VariableLiteral vl = (VariableLiteral) term;
+        if("STATIC_CALL".equals(vl.getName())) {
+            StringBuilder sb = new StringBuilder();
+            if(!(vl.getArgs().get(0) instanceof StringLiteral)) {
+                throw new RuntimeException("Expecting the first argument of a 'STATIC_CALL' to be a StringLiteral");
+            }
+            String methodName = ((StringLiteral) vl.getArgs().get(0)).getValue();
+            methodName = methodName.substring(1, methodName.length() - 1);
+            sb.append(methodName).append("(");
+            for(int i = 1; i < vl.getArgs().size(); i++) {
+                Term arg = vl.getArgs().get(i);
+                if(i > 1) {
+                    sb.append(", ");
+                }
+                if(arg instanceof VariableLiteral) {
+                    sb.append(toVariableSerializationExpression(arg));
+                } else if(arg instanceof StringLiteral) {
+                    sb.append(((StringLiteral) arg).getValue());
+                }
+            }
+            sb.append(")");
+            return sb.toString();
+        }
         // All uppercase names are not fields, but utility methods.
-        if(vl.getName().equals(vl.getName().toUpperCase())) {
+        else if(vl.getName().equals(vl.getName().toUpperCase())) {
             StringBuilder sb = new StringBuilder(vl.getName());
             if(vl.getArgs() != null) {
                 sb.append("(");
@@ -493,7 +515,11 @@ public class JavaLanguageTemplateHelper implements FreemarkerLanguageTemplateHel
                     if(!firstArg) {
                         sb.append(", ");
                     }
-                    sb.append(toVariableSerializationExpression(arg));
+                    if(arg instanceof VariableLiteral) {
+                        sb.append(toVariableSerializationExpression(arg));
+                    } else if(arg instanceof StringLiteral) {
+                        sb.append(((StringLiteral) arg).getValue());
+                    }
                     firstArg = false;
                 }
                 sb.append(")");
diff --git a/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh b/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh
index f4b0880..32ef907 100644
--- a/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh
+++ b/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh
@@ -44,10 +44,9 @@ import org.apache.plc4x.java.utils.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
 
 public class ${typeName}IO implements MessageIO<${typeName}<#if helper.isDiscriminatedType(type)>IO.${typeName}Builder</#if>, ${typeName}> {
 
@@ -97,7 +96,14 @@ public class ${typeName}IO implements MessageIO<${typeName}<#if helper.isDiscrim
             </#if>
             ${field.name}List.add(<#if helper.isSimpleType(field.type)>io.${helper.getReadBufferReadMethodCall(field.type)}<#else>${field.type.name?uncap_first}IO.parse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getArgumentType(field.type, parserArgument?index)}) (${helper.toDeserializationExpression(parserArgument)})<#sep>, </#sep></#list></#if>)</#if>);
         }
-        ${helper.getLanguageTypeNameForField(field)}[] ${field.name} = ${field.name}List.toArray(new ${helper.getLanguageTypeNameForField(field)}[0]);
+        <#if helper.isSimpleType(field.type)>
+        ${helper.getLanguageTypeNameForField(field)}[] ${field.name} = new ${helper.getLanguageTypeNameForField(field)}[${field.name}List.size()];
+        for(int i = 0; i < ${field.name}List.size(); i++) {
+            ${field.name}[i] = (${helper.getLanguageTypeNameForField(field)}) ${field.name}List.get(i);
+        }
+        <#else>
+        ${helper.getLanguageTypeNameForField(field)}[] ${field.name} = ${field.name}List.toArray(new ${helper.getNonPrimitiveLanguageTypeNameForField(field)}[0]);
+        </#if>
         </#if>
         <#break>
     <#case "const">
@@ -200,7 +206,7 @@ public class ${typeName}IO implements MessageIO<${typeName}<#if helper.isDiscrim
     <#case "implicit">
 
         // Implicit Field (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
-        io.${helper.getWriteBufferReadMethodCall(field.type, "(" + helper.toSerializationExpression(field.serializationExpression) + ")")};
+        io.${helper.getWriteBufferReadMethodCall(field.type, "(" + helper.toSerializationExpression(field.serializationExpression) + ")")?no_esc};
         <#break>
     <#case "optional">
 
@@ -240,6 +246,48 @@ public class ${typeName}IO implements MessageIO<${typeName}<#if helper.isDiscrim
 </#list>
     }
 
+    private static Map<String, Method> staticMethods;
+
+    /**
+     * Notice, this method doesn't support using multiple static methods with the same name
+     * but with different argument types. In this case it will use the first used method and
+     * probably fail for all others.
+     *
+     * @param fullyQualifiedMethodName Fully qualified Class name with method name (Example "a.b.c.Foo.bar")
+     * @param args arguments passed to the static method.
+     * @return
+     */
+    private static Object STATIC_CALL(String fullyQualifiedMethodName, Object... args) {
+        if(staticMethods == null) {
+            staticMethods = new HashMap<>();
+        }
+        // Get the method handle and cache it for later usage.
+        if(!staticMethods.containsKey(fullyQualifiedMethodName)) {
+            // Get the types of the arguments.
+            Class<?>[] argTypes = new Class[args.length];
+            for(int i = 0; i < args.length; i++) {
+                argTypes[i] = args[i].getClass();
+            }
+            // Get the method handle.
+            String className = fullyQualifiedMethodName.substring(0, fullyQualifiedMethodName.lastIndexOf("."));
+            String methodName = fullyQualifiedMethodName.substring(className.length());
+            try {
+                Class clazz = Class.forName(className);
+                Method method = clazz.getMethod(methodName, argTypes);
+                staticMethods.put(fullyQualifiedMethodName, method);
+            } catch (ClassNotFoundException | NoSuchMethodException e) {
+                throw new RuntimeException("Error finding static method", e);
+            }
+        }
+        Method method = staticMethods.get(fullyQualifiedMethodName);
+        try {
+            // Invoke the static method.
+            return method.invoke(null, args);
+        } catch (InvocationTargetException | IllegalAccessException e) {
+            throw new RuntimeException("Error invoking static method", e);
+        }
+    }
+
     private static int COUNT(Object obj) {
         if(obj.getClass().isArray()) {
             Object[] arr = (Object[]) obj;