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;