From 5a2e5607eec69c637b456f4befe3a521bc59e2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Dywicki?= Date: Fri, 23 Aug 2024 19:45:03 +0200 Subject: [PATCH] feat(plc4j)!: Improve stability of code through stricter compiler checks of generated contents. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: Removed `staticParse(io, ... args)` methods. Signed-off-by: Ɓukasz Dywicki --- .../java/complex-type-template.java.ftlh | 26 --- .../apache/plc4x/java/cbus/CBusDriver.java | 6 +- .../transport/CANOpenFrameDataHandler.java | 2 +- .../transport/CANOpenFrameDataAdapter.java | 2 +- .../apache/plc4x/java/eip/base/EIPDriver.java | 3 +- .../plc4x/java/eip/logix/LogixDriver.java | 3 +- .../java/firmata/readwrite/FirmataDriver.java | 4 +- .../java/modbus/ascii/ModbusAsciiDriver.java | 11 +- .../java/modbus/rtu/ModbusRtuDriver.java | 6 +- .../java/modbus/tcp/ModbusTcpDriver.java | 5 +- .../plc4x/java/opcua/OpcuaPlcDriver.java | 3 +- .../protocol/chunk/PayloadConverter.java | 4 +- .../java/openprotocol/OpenProtocolDriver.java | 3 +- .../plc4x/java/profinet/ProfinetDriver.java | 1 - .../S7HSingleProtocolStackConfigurer.java | 13 +- .../GeneratedDriverByteToMessageCodec.java | 6 +- .../CustomProtocolStackConfigurer.java | 2 +- .../GeneratedProtocolMessageCodec.java | 6 +- .../SingleProtocolStackConfigurer.java | 13 +- .../java/spi/generation/MessageInput.java | 2 +- .../java/spi/generation/MessageOutput.java | 2 +- .../plc4x/java/transport/can/FrameData.java | 2 +- .../socketcan/SocketCANTransport.java | 4 +- .../transport/virtualcan/VirtualCANFrame.java | 2 +- .../virtualcan/VirtualCANTransport.java | 4 +- .../server/bacnet/BacnetServerModule.java | 1 - .../server/cbus/CBusServerModule.java | 10 +- .../simulator/server/s7/S7ServerModule.java | 2 +- .../handlers/IncomingPlcMessageHandler.java | 4 +- .../plc4x/test/migration/MessageResolver.java | 156 ++++++++++-------- .../MessageValidatorAndMigrator.java | 39 +++-- .../ParserSerializerTestsuiteRunner.java | 6 +- 32 files changed, 159 insertions(+), 194 deletions(-) diff --git a/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh b/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh index 6a200a452dd..8c4ae7c20ad 100644 --- a/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh +++ b/code-generation/language-java/src/main/resources/templates/java/complex-type-template.java.ftlh @@ -580,32 +580,6 @@ public<#if type.isDiscriminatedParentTypeDefinition()> abstract class ${ty return lengthInBits; } -<#-- The parse and serialize methods here are just proxies for forwardning the requests to static counterparts --> - <#if !type.isDiscriminatedChildTypeDefinition()> - public static ${type.name} staticParse(ReadBuffer readBuffer, Object... args) throws ParseException { - PositionAware positionAware = readBuffer; - <#if parserArguments?has_content> - if((args == null) || (args.length != ${parserArguments?size})) { - throw new PlcRuntimeException("Wrong number of arguments, expected ${parserArguments?size}, but got " + args.length); - } - <#list parserArguments as parserArgument> - <#assign languageName=helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)> - ${languageName} ${parserArgument.name}; - if(args[${parserArgument?index}] instanceof ${languageName}) { - ${parserArgument.name} = (${languageName}) args[${parserArgument?index}]; - <#if parserArgument.type.isSimpleTypeReference() || parserArgument.type.isEnumTypeReference()> - } else if (args[${parserArgument?index}] instanceof String) { - ${parserArgument.name} = ${languageName}.valueOf((String) args[${parserArgument?index}]); - - } else { - throw new PlcRuntimeException("Argument ${parserArgument?index} expected to be of type ${languageName} or a string which is parseable but was " + args[${parserArgument?index}].getClass().getName()); - } - - - return staticParse(readBuffer<#if parserArguments?has_content>, <#list parserArguments as parserArgument>${parserArgument.name}<#sep>, ); - } - - <#-- Here come the actual parse and serialize methods that actually do the parsing and serlaizing --> <#assign hasParserArguments=parserArguments?has_content/> <#assign parserArgumentList><#if hasParserArguments><#list parserArguments as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)} ${parserArgument.name}<#sep>, diff --git a/plc4j/drivers/c-bus/src/main/java/org/apache/plc4x/java/cbus/CBusDriver.java b/plc4j/drivers/c-bus/src/main/java/org/apache/plc4x/java/cbus/CBusDriver.java index a8239c04a95..300ffa9450f 100644 --- a/plc4j/drivers/c-bus/src/main/java/org/apache/plc4x/java/cbus/CBusDriver.java +++ b/plc4j/drivers/c-bus/src/main/java/org/apache/plc4x/java/cbus/CBusDriver.java @@ -19,6 +19,9 @@ package org.apache.plc4x.java.cbus; import io.netty.buffer.ByteBuf; +import org.apache.plc4x.java.cbus.readwrite.CBusMessage; +import org.apache.plc4x.java.cbus.readwrite.CBusOptions; +import org.apache.plc4x.java.cbus.readwrite.RequestContext; import org.apache.plc4x.java.spi.configuration.PlcConnectionConfiguration; import org.apache.plc4x.java.spi.configuration.PlcTransportConfiguration; import org.apache.plc4x.java.api.value.PlcValueHandler; @@ -92,7 +95,8 @@ protected PlcValueHandler getValueHandler() { @Override protected ProtocolStackConfigurer getStackConfigurer() { - return SingleProtocolStackConfigurer.builder(CBusCommand.class, CBusCommand::staticParse) + return SingleProtocolStackConfigurer.builder(CBusCommand.class, io -> + CBusCommand.staticParse(io, new CBusOptions(false, false, false, false, false, false, false, false, false))) .withProtocol(CBusProtocolLogic.class) .withDriverContext(CBusDriverContext.class) .withPacketSizeEstimator(ByteLengthEstimator.class) diff --git a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/transport/CANOpenFrameDataHandler.java b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/transport/CANOpenFrameDataHandler.java index afe400ae24a..ec52a771c4f 100644 --- a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/transport/CANOpenFrameDataHandler.java +++ b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/transport/CANOpenFrameDataHandler.java @@ -48,7 +48,7 @@ public CANOpenFrameDataHandler(Supplier> builder) { public CANOpenFrame fromCAN(FrameData frame) { CANOpenService service = StaticHelper.serviceId((short) frame.getNodeId()); int nodeId = Math.abs(service.getMin() - frame.getNodeId()); - return new CANOpenFrame((short) nodeId, service, frame.read(CANOpenPayload::staticParse, service)); + return new CANOpenFrame((short) nodeId, service, frame.read(io -> CANOpenPayload.staticParse(io, service))); } @Override diff --git a/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/transport/CANOpenFrameDataAdapter.java b/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/transport/CANOpenFrameDataAdapter.java index a2b44ec5d07..62f3c41bfc6 100644 --- a/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/transport/CANOpenFrameDataAdapter.java +++ b/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/transport/CANOpenFrameDataAdapter.java @@ -43,7 +43,7 @@ public int getNodeId() { } @Override - public T read(MessageInput input, Object... args) { + public T read(MessageInput input) { return (T) frame.getPayload(); } diff --git a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/base/EIPDriver.java b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/base/EIPDriver.java index e4d0e434e71..2f85009e8f0 100644 --- a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/base/EIPDriver.java +++ b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/base/EIPDriver.java @@ -120,10 +120,9 @@ protected boolean canWrite() { @Override protected ProtocolStackConfigurer getStackConfigurer() { - return SingleProtocolStackConfigurer.builder(EipPacket.class, EipPacket::staticParse) + return SingleProtocolStackConfigurer.builder(EipPacket.class, io -> EipPacket.staticParse(io, true)) .withProtocol(EipProtocolLogic.class) .withPacketSizeEstimator(ByteLengthEstimator.class) - .withParserArgs(true) .withCorruptPacketRemover(CorruptPackageCleaner.class) .byteOrder(this.configuration.getByteOrder()) .build(); diff --git a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/logix/LogixDriver.java b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/logix/LogixDriver.java index 6b5229e6f3c..b8bb251d2a9 100644 --- a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/logix/LogixDriver.java +++ b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/logix/LogixDriver.java @@ -99,10 +99,9 @@ protected boolean canWrite() { @Override protected ProtocolStackConfigurer getStackConfigurer() { - return SingleProtocolStackConfigurer.builder(EipPacket.class, EipPacket::staticParse) + return SingleProtocolStackConfigurer.builder(EipPacket.class, io -> EipPacket.staticParse(io, true)) .withProtocol(EipProtocolLogic.class) .withPacketSizeEstimator(ByteLengthEstimator.class) - .withParserArgs(true) .withCorruptPacketRemover(CorruptPackageCleaner.class) .littleEndian() .build(); diff --git a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/FirmataDriver.java b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/FirmataDriver.java index ee2547f8e15..de494150400 100644 --- a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/FirmataDriver.java +++ b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/FirmataDriver.java @@ -96,13 +96,11 @@ protected boolean awaitDisconnectComplete() { @Override protected ProtocolStackConfigurer getStackConfigurer() { - return SingleProtocolStackConfigurer.builder(FirmataMessage.class, FirmataMessage::staticParse) + return SingleProtocolStackConfigurer.builder(FirmataMessage.class, io -> FirmataMessage.staticParse(io, true)) .withProtocol(FirmataProtocolLogic.class) .withDriverContext(FirmataDriverContext.class) .withPacketSizeEstimator(ByteLengthEstimator.class) .withCorruptPacketRemover(CorruptPackageCleaner.class) - // Every incoming message is to be treated as a response. - .withParserArgs(true) .build(); } diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/ModbusAsciiDriver.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/ModbusAsciiDriver.java index 071b6373e82..d1a1ddde0b6 100644 --- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/ModbusAsciiDriver.java +++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/ascii/ModbusAsciiDriver.java @@ -133,13 +133,10 @@ protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() { @Override protected ProtocolStackConfigurer getStackConfigurer() { - return SingleProtocolStackConfigurer.builder(ModbusAsciiADU.class, - new ModbusAsciiInput(), new ModbusAsciiOutput()) + return SingleProtocolStackConfigurer.builder(ModbusAsciiADU.class, new ModbusAsciiInput(), new ModbusAsciiOutput()) .withProtocol(ModbusAsciiProtocolLogic.class) .withPacketSizeEstimator(ModbusAsciiDriver.ByteLengthEstimator.class) .withCorruptPacketRemover(ModbusAsciiDriver.CorruptPackageCleaner.class) - // Every incoming message is to be treated as a response. - .withParserArgs(DriverType.MODBUS_ASCII, true) .build(); } @@ -160,7 +157,7 @@ public int applyAsInt(ByteBuf byteBuf) { // Try to parse the buffer content. try { ModbusAsciiInput input = new ModbusAsciiInput(); - ModbusAsciiADU modbusADU = input.parse(reader, DriverType.MODBUS_ASCII, true); + ModbusAsciiADU modbusADU = input.parse(reader); // Make sure we only read one message. return (modbusADU.getLengthInBytes() * 2) + 3; @@ -198,7 +195,7 @@ public ModbusTag prepareTag(String tagAddress){ public static class ModbusAsciiInput implements MessageInput { @Override - public ModbusAsciiADU parse(ReadBuffer io, Object... args) throws ParseException { + public ModbusAsciiADU parse(ReadBuffer io) throws ParseException { // A Modbus ASCII message starts with an ASCII character ":" and is ended by two characters CRLF // (Carriage-Return + Line-Feed) // The actual payload is that each byte of the message is encoded by a string representation of it's @@ -228,7 +225,7 @@ public ModbusAsciiADU parse(ReadBuffer io, Object... args) throws ParseException public static class ModbusAsciiOutput implements MessageOutput { @Override - public WriteBufferByteBased serialize(ModbusAsciiADU value, Object... args) throws SerializationException { + public WriteBufferByteBased serialize(ModbusAsciiADU value) throws SerializationException { // First serialize the packet the normal way. WriteBufferByteBased writeBufferByteBased = new WriteBufferByteBased(value.getLengthInBytes()); value.serialize(writeBufferByteBased); diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/ModbusRtuDriver.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/ModbusRtuDriver.java index 0d96a3704bc..a3763b6be32 100644 --- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/ModbusRtuDriver.java +++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/rtu/ModbusRtuDriver.java @@ -32,6 +32,7 @@ import org.apache.plc4x.java.spi.connection.GeneratedDriverBase; import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer; import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer; +import org.apache.plc4x.java.spi.generation.MessageInput; import org.apache.plc4x.java.spi.generation.ParseException; import org.apache.plc4x.java.spi.generation.ReadBufferByteBased; import org.apache.plc4x.java.spi.optimizer.BaseOptimizer; @@ -129,12 +130,9 @@ protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() { @Override protected ProtocolStackConfigurer getStackConfigurer() { - return SingleProtocolStackConfigurer.builder(ModbusRtuADU.class, - (io, args) -> (ModbusRtuADU) ModbusRtuADU.staticParse(io, args)) + return SingleProtocolStackConfigurer.builder(ModbusRtuADU.class, io -> (ModbusRtuADU) ModbusRtuADU.staticParse(io, DriverType.MODBUS_RTU, true)) .withProtocol(ModbusRtuProtocolLogic.class) .withPacketSizeEstimator(ModbusRtuDriver.ByteLengthEstimator.class) - // Every incoming message is to be treated as a response. - .withParserArgs(DriverType.MODBUS_RTU, true) .build(); } diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/ModbusTcpDriver.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/ModbusTcpDriver.java index 9a5cb59f485..2d4c8fca602 100644 --- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/ModbusTcpDriver.java +++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/tcp/ModbusTcpDriver.java @@ -134,12 +134,9 @@ protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() { @Override protected ProtocolStackConfigurer getStackConfigurer() { - return SingleProtocolStackConfigurer.builder(ModbusTcpADU.class, - (io, args) -> (ModbusTcpADU) ModbusTcpADU.staticParse(io, args)) + return SingleProtocolStackConfigurer.builder(ModbusTcpADU.class, (io) -> (ModbusTcpADU) ModbusTcpADU.staticParse(io, DriverType.MODBUS_TCP, true)) .withProtocol(ModbusTcpProtocolLogic.class) .withPacketSizeEstimator(ByteLengthEstimator.class) - // Every incoming message is to be treated as a response. - .withParserArgs(DriverType.MODBUS_TCP, true) .build(); } diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java index 7901f294137..6d083cfb693 100644 --- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java +++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java @@ -107,10 +107,9 @@ protected boolean awaitDiscoverComplete() { @Override protected ProtocolStackConfigurer getStackConfigurer() { - return SingleProtocolStackConfigurer.builder(OpcuaAPU.class, OpcuaAPU::staticParse) + return SingleProtocolStackConfigurer.builder(OpcuaAPU.class, io -> OpcuaAPU.staticParse(io, true)) .withProtocol(OpcuaProtocolLogic.class) .withPacketSizeEstimator(ByteLengthEstimator.class) - .withParserArgs(true) .withDriverContext(OpcuaDriverContext.class) .littleEndian() .build(); diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/chunk/PayloadConverter.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/chunk/PayloadConverter.java index c84d8589218..2ae7f375caa 100644 --- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/chunk/PayloadConverter.java +++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/chunk/PayloadConverter.java @@ -81,9 +81,9 @@ public static Payload fromStream(byte[] payload, boolean extensible) throws Pars return Payload.staticParse(buffer, extensible, (long) (extensible ? -1 : payload.length - 8)); } - public static MessagePDU fromStream(ByteBuffer chunkBuffer, boolean response, boolean encrypted) throws ParseException { + public static MessagePDU fromStream(ByteBuffer chunkBuffer, boolean response) throws ParseException { ReadBufferByteBased buffer = new ReadBufferByteBased(chunkBuffer.array(), ByteOrder.LITTLE_ENDIAN); - return MessagePDU.staticParse(buffer, response, encrypted); + return MessagePDU.staticParse(buffer, response); } public static MessagePDU pduFromStream(byte[] message, boolean response) throws ParseException { diff --git a/plc4j/drivers/open-protocol/src/main/java/org/apache/plc4x/java/openprotocol/OpenProtocolDriver.java b/plc4j/drivers/open-protocol/src/main/java/org/apache/plc4x/java/openprotocol/OpenProtocolDriver.java index 7c96d262c3e..6bdf9d68434 100644 --- a/plc4j/drivers/open-protocol/src/main/java/org/apache/plc4x/java/openprotocol/OpenProtocolDriver.java +++ b/plc4j/drivers/open-protocol/src/main/java/org/apache/plc4x/java/openprotocol/OpenProtocolDriver.java @@ -112,8 +112,7 @@ protected org.apache.plc4x.java.api.value.PlcValueHandler getValueHandler() { @Override protected ProtocolStackConfigurer getStackConfigurer() { - return SingleProtocolStackConfigurer.builder(OpenProtocolMessage.class, - OpenProtocolMessage::staticParse) + return SingleProtocolStackConfigurer.builder(OpenProtocolMessage.class, io -> OpenProtocolMessage.staticParse(io, 1)) .withProtocol(OpenProtocolProtocolLogic.class) .withPacketSizeEstimator(ByteLengthEstimator.class) .build(); diff --git a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/ProfinetDriver.java b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/ProfinetDriver.java index d38a046d27b..60de10c6d04 100644 --- a/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/ProfinetDriver.java +++ b/plc4j/drivers/profinet/src/main/java/org/apache/plc4x/java/profinet/ProfinetDriver.java @@ -151,7 +151,6 @@ protected ProtocolStackConfigurer getStackConfigurer() { .withProtocol(ProfinetProtocolLogic.class) .withDriverContext(ProfinetDriverContext.class) // Every incoming message is to be treated as a response. - .withParserArgs(true) .build(); } diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7HSingleProtocolStackConfigurer.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7HSingleProtocolStackConfigurer.java index 61adcbcc244..afb71d3741c 100644 --- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7HSingleProtocolStackConfigurer.java +++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7HSingleProtocolStackConfigurer.java @@ -60,7 +60,6 @@ public class S7HSingleProtocolStackConfigurer private final Class> packetSizeEstimatorClass; private final Class> corruptPacketRemoverClass; private final MessageToMessageCodec encryptionHandler; - private final Object[] parserArgs; private Plc4xProtocolBase protocol = null; @@ -77,7 +76,6 @@ public static S7HSingleProtocolStackBuilder builder(C */ S7HSingleProtocolStackConfigurer(Class basePacketClass, ByteOrder byteOrder, - Object[] parserArgs, Class> protocol, Class driverContextClass, MessageInput messageInput, @@ -87,7 +85,6 @@ public static S7HSingleProtocolStackBuilder builder(C MessageToMessageCodec encryptionHandler) { this.basePacketClass = basePacketClass; this.byteOrder = byteOrder; - this.parserArgs = parserArgs; this.protocolClass = protocol; this.driverContextClass = driverContextClass; this.messageInput = messageInput; @@ -98,7 +95,7 @@ public static S7HSingleProtocolStackBuilder builder(C } private ChannelHandler getMessageCodec(PlcConnectionConfiguration configuration) { - return new GeneratedProtocolMessageCodec<>(basePacketClass, messageInput, messageOutput, byteOrder, parserArgs, + return new GeneratedProtocolMessageCodec<>(basePacketClass, messageInput, messageOutput, byteOrder, packetSizeEstimatorClass != null ? configure(configuration, createInstance(packetSizeEstimatorClass)) : null, corruptPacketRemoverClass != null ? configure(configuration, createInstance(corruptPacketRemoverClass)) : null); } @@ -154,7 +151,6 @@ public static final class S7HSingleProtocolStackBuilder messageOutput; private Class driverContextClass; private ByteOrder byteOrder = ByteOrder.BIG_ENDIAN; - private Object[] parserArgs; private Class> protocol; private Class> packetSizeEstimator; private Class> corruptPacketRemover; @@ -186,11 +182,6 @@ public S7HSingleProtocolStackBuilder littleEndian() { return this; } - public S7HSingleProtocolStackBuilder withParserArgs(Object... parserArgs) { - this.parserArgs = parserArgs; - return this; - } - public S7HSingleProtocolStackBuilder withProtocol(Class> protocol) { this.protocol = protocol; return this; @@ -213,7 +204,7 @@ public S7HSingleProtocolStackBuilder withEncryptionHandler(Me public S7HSingleProtocolStackConfigurer build() { assert this.protocol != null; - return new S7HSingleProtocolStackConfigurer<>(basePacketClass, byteOrder, parserArgs, protocol, + return new S7HSingleProtocolStackConfigurer<>(basePacketClass, byteOrder, protocol, driverContextClass, messageInput, messageOutput, packetSizeEstimator, corruptPacketRemover, encryptionHandler); } diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java index a8ed314a121..d3dac42b5a2 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java @@ -33,17 +33,15 @@ public abstract class GeneratedDriverByteToMessageCodec exten private static final Logger LOGGER = LoggerFactory.getLogger(GeneratedDriverByteToMessageCodec.class); private final ByteOrder byteOrder; - private final Object[] parserArgs; private final MessageInput messageInput; private final MessageOutput messageOutput; protected GeneratedDriverByteToMessageCodec(MessageInput messageInput, MessageOutput messageOutput, - Class outboundMessageType, ByteOrder byteOrder, Object[] parserArgs) { + Class outboundMessageType, ByteOrder byteOrder) { super(outboundMessageType); this.messageInput = messageInput; this.messageOutput = messageOutput; this.byteOrder = byteOrder; - this.parserArgs = parserArgs; } @Override @@ -84,7 +82,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List o ReadBuffer readBuffer = new ReadBufferByteBased(bytes, byteOrder); // Parse the packet. - T packet = messageInput.parse(readBuffer, parserArgs); + T packet = messageInput.parse(readBuffer); // Pass the packet to the pipeline. out.add(packet); diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/CustomProtocolStackConfigurer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/CustomProtocolStackConfigurer.java index 2fc9c59fb8f..c61c25e7df1 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/CustomProtocolStackConfigurer.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/CustomProtocolStackConfigurer.java @@ -84,7 +84,7 @@ public static CustomProtocolStackBuilder builder(Clas } private ChannelHandler getMessageCodec(PlcConnectionConfiguration configuration) { - return new GeneratedProtocolMessageCodec<>(basePacketClass, protocolIO.apply(configuration), byteOrder, parserArgs, + return new GeneratedProtocolMessageCodec<>(basePacketClass, protocolIO.apply(configuration), byteOrder, packetSizeEstimator == null ? null : packetSizeEstimator.apply(configuration), corruptPacketRemover == null ? null : corruptPacketRemover.apply(configuration)); } diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedProtocolMessageCodec.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedProtocolMessageCodec.java index 41d8a4dd1c8..f7521f5bd3f 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedProtocolMessageCodec.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedProtocolMessageCodec.java @@ -34,10 +34,9 @@ public GeneratedProtocolMessageCodec( Class basePacketClass, MessageInput messageInput, ByteOrder byteOrder, - Object[] parserArgs, ToIntFunction packetSizeEstimator, Consumer corruptPackageRemover) { - super(messageInput, null, basePacketClass, byteOrder, parserArgs); + super(messageInput, null, basePacketClass, byteOrder); this.packetSizeEstimator = packetSizeEstimator; this.corruptPackageRemover = corruptPackageRemover; } @@ -47,10 +46,9 @@ public GeneratedProtocolMessageCodec( MessageInput messageInput, MessageOutput messageOutput, ByteOrder byteOrder, - Object[] parserArgs, ToIntFunction packetSizeEstimator, Consumer corruptPackageRemover) { - super(messageInput, messageOutput, basePacketClass, byteOrder, parserArgs); + super(messageInput, messageOutput, basePacketClass, byteOrder); this.packetSizeEstimator = packetSizeEstimator; this.corruptPackageRemover = corruptPackageRemover; } diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java index 8252eec9f36..5ea017c591b 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java @@ -57,7 +57,6 @@ public class SingleProtocolStackConfigurer im private final Class> packetSizeEstimatorClass; private final Class> corruptPacketRemoverClass; private final MessageToMessageCodec encryptionHandler; - private final Object[] parserArgs; public static SingleProtocolStackBuilder builder(Class basePacketClass, MessageInput messageInput) { return new SingleProtocolStackBuilder<>(basePacketClass, messageInput, null); @@ -72,7 +71,6 @@ public static SingleProtocolStackBuilder builder(Clas */ SingleProtocolStackConfigurer(Class basePacketClass, ByteOrder byteOrder, - Object[] parserArgs, Class> protocol, Class driverContextClass, MessageInput messageInput, @@ -82,7 +80,6 @@ public static SingleProtocolStackBuilder builder(Clas MessageToMessageCodec encryptionHandler) { this.basePacketClass = basePacketClass; this.byteOrder = byteOrder; - this.parserArgs = parserArgs; this.protocolClass = protocol; this.driverContextClass = driverContextClass; this.messageInput = messageInput; @@ -93,7 +90,7 @@ public static SingleProtocolStackBuilder builder(Clas } private ChannelHandler getMessageCodec(PlcConnectionConfiguration configuration) { - return new GeneratedProtocolMessageCodec<>(basePacketClass, messageInput, messageOutput, byteOrder, parserArgs, + return new GeneratedProtocolMessageCodec<>(basePacketClass, messageInput, messageOutput, byteOrder, packetSizeEstimatorClass != null ? configure(configuration, createInstance(packetSizeEstimatorClass)) : null, corruptPacketRemoverClass != null ? configure(configuration, createInstance(corruptPacketRemoverClass)) : null); } @@ -144,7 +141,6 @@ public static final class SingleProtocolStackBuilder messageOutput; private Class driverContextClass; private ByteOrder byteOrder = ByteOrder.BIG_ENDIAN; - private Object[] parserArgs; private Class> protocol; private Class> packetSizeEstimator; private Class> corruptPacketRemover; @@ -176,11 +172,6 @@ public SingleProtocolStackBuilder littleEndian() { return this; } - public SingleProtocolStackBuilder withParserArgs(Object... parserArgs) { - this.parserArgs = parserArgs; - return this; - } - public SingleProtocolStackBuilder withProtocol(Class> protocol) { this.protocol = protocol; return this; @@ -203,7 +194,7 @@ public SingleProtocolStackBuilder withEncryptionHandler(Messa public SingleProtocolStackConfigurer build() { assert this.protocol != null; - return new SingleProtocolStackConfigurer<>(basePacketClass, byteOrder, parserArgs, protocol, + return new SingleProtocolStackConfigurer<>(basePacketClass, byteOrder, protocol, driverContextClass, messageInput, messageOutput, packetSizeEstimator, corruptPacketRemover, encryptionHandler); } diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageInput.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageInput.java index 2d1ee1f9fd0..e6005a1a877 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageInput.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageInput.java @@ -21,6 +21,6 @@ @FunctionalInterface public interface MessageInput { - PARSER_TYPE parse(ReadBuffer io, Object... args) throws ParseException; + PARSER_TYPE parse(ReadBuffer io) throws ParseException; } diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageOutput.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageOutput.java index a0147f5b5b1..e28d465eefe 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageOutput.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/MessageOutput.java @@ -20,6 +20,6 @@ public interface MessageOutput { - WriteBufferByteBased serialize(SERIALIZER_TYPE value, Object... args) throws SerializationException; + WriteBufferByteBased serialize(SERIALIZER_TYPE value) throws SerializationException; } diff --git a/plc4j/transports/can/src/main/java/org/apache/plc4x/java/transport/can/FrameData.java b/plc4j/transports/can/src/main/java/org/apache/plc4x/java/transport/can/FrameData.java index 05ec7c9b6ad..55795a0a7aa 100644 --- a/plc4j/transports/can/src/main/java/org/apache/plc4x/java/transport/can/FrameData.java +++ b/plc4j/transports/can/src/main/java/org/apache/plc4x/java/transport/can/FrameData.java @@ -25,7 +25,7 @@ public interface FrameData { int getNodeId(); - T read(MessageInput input, Object ... args); + T read(MessageInput input); int getDataLength(); byte[] getData(); diff --git a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANTransport.java b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANTransport.java index 57129e6434c..382bcfad2ad 100644 --- a/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANTransport.java +++ b/plc4j/transports/socketcan/src/main/java/org/apache/plc4x/java/transport/socketcan/SocketCANTransport.java @@ -102,9 +102,9 @@ public byte[] getData() { } @Override - public T read(MessageInput input, Object... args) { + public T read(MessageInput input) { try { - return input.parse(new ReadBufferByteBased(frame.getData(), ByteOrder.LITTLE_ENDIAN), args); + return input.parse(new ReadBufferByteBased(frame.getData(), ByteOrder.LITTLE_ENDIAN)); } catch (ParseException e) { throw new PlcRuntimeException(e); } diff --git a/plc4j/transports/virtualcan/src/main/java/org/apache/plc4x/java/transport/virtualcan/VirtualCANFrame.java b/plc4j/transports/virtualcan/src/main/java/org/apache/plc4x/java/transport/virtualcan/VirtualCANFrame.java index 1a5f13730be..f1992fba205 100644 --- a/plc4j/transports/virtualcan/src/main/java/org/apache/plc4x/java/transport/virtualcan/VirtualCANFrame.java +++ b/plc4j/transports/virtualcan/src/main/java/org/apache/plc4x/java/transport/virtualcan/VirtualCANFrame.java @@ -37,7 +37,7 @@ public class VirtualCANFrame implements Message { public final static MessageInput PARSER = new MessageInput() { @Override - public VirtualCANFrame parse(ReadBuffer io, Object... args) throws ParseException { + public VirtualCANFrame parse(ReadBuffer io) throws ParseException { WithOption withOption = WithOption.WithByteOrder(ByteOrder.LITTLE_ENDIAN); short length = io.readUnsignedShort("length", 8, withOption); diff --git a/plc4j/transports/virtualcan/src/main/java/org/apache/plc4x/java/transport/virtualcan/VirtualCANTransport.java b/plc4j/transports/virtualcan/src/main/java/org/apache/plc4x/java/transport/virtualcan/VirtualCANTransport.java index 343c48e7d43..18322c98a2d 100644 --- a/plc4j/transports/virtualcan/src/main/java/org/apache/plc4x/java/transport/virtualcan/VirtualCANTransport.java +++ b/plc4j/transports/virtualcan/src/main/java/org/apache/plc4x/java/transport/virtualcan/VirtualCANTransport.java @@ -95,9 +95,9 @@ public int getNodeId() { } @Override - public T read(MessageInput input, Object... args) { + public T read(MessageInput input) { try { - return input.parse(new ReadBufferByteBased(getData(), ByteOrder.LITTLE_ENDIAN), args); + return input.parse(new ReadBufferByteBased(getData(), ByteOrder.LITTLE_ENDIAN)); } catch (ParseException e) { throw new PlcRuntimeException(e); } diff --git a/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/bacnet/BacnetServerModule.java b/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/bacnet/BacnetServerModule.java index 6a9b08a1705..6459a0c82b7 100644 --- a/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/bacnet/BacnetServerModule.java +++ b/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/bacnet/BacnetServerModule.java @@ -103,7 +103,6 @@ protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List out) }) .addLast(new GeneratedProtocolMessageCodec<>(BVLC.class, BVLC::staticParse, ByteOrder.BIG_ENDIAN, - null, new BacNetIpDriver.ByteLengthEstimator(), new BacNetIpDriver.CorruptPackageCleaner())) .addLast(new BacnetServerAdapter(context)); diff --git a/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/cbus/CBusServerModule.java b/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/cbus/CBusServerModule.java index 0c2f177c555..1e6f8f02e25 100644 --- a/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/cbus/CBusServerModule.java +++ b/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/cbus/CBusServerModule.java @@ -33,6 +33,9 @@ import org.apache.plc4x.java.cbus.readwrite.RequestContext; import org.apache.plc4x.java.spi.connection.GeneratedProtocolMessageCodec; import org.apache.plc4x.java.spi.generation.ByteOrder; +import org.apache.plc4x.java.spi.generation.MessageInput; +import org.apache.plc4x.java.spi.generation.ParseException; +import org.apache.plc4x.java.spi.generation.ReadBuffer; import org.apache.plc4x.simulator.PlcSimulatorConfig; import org.apache.plc4x.simulator.exceptions.SimulatorException; import org.apache.plc4x.simulator.model.Context; @@ -41,6 +44,10 @@ public class CBusServerModule implements ServerModule { + public static final MessageInput MESSAGE_INPUT = io -> + CBusMessage.staticParse(io, false, new RequestContext(false), + new CBusOptions(false, false, false, false, false, false, false, false, false)); + private EventLoopGroup loopGroup; private EventLoopGroup workerGroup; private Context context; @@ -79,8 +86,7 @@ public void start() throws SimulatorException { public void initChannel(SocketChannel channel) { ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(new GeneratedProtocolMessageCodec<>(CBusMessage.class, - CBusMessage::staticParse, ByteOrder.BIG_ENDIAN, - new Object[]{false, new RequestContext(false), new CBusOptions(false, false, false, false, false, false, false, false, false)}, + MESSAGE_INPUT, ByteOrder.BIG_ENDIAN, new CBusDriver.ByteLengthEstimator(), new CBusDriver.CorruptPackageCleaner())); pipeline.addLast(new CBusServerAdapter(context)); diff --git a/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java b/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java index e14b5ffdb4a..ea659edcb0e 100644 --- a/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java +++ b/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java @@ -79,7 +79,7 @@ public void start() throws SimulatorException { public void initChannel(SocketChannel channel) { ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(new GeneratedProtocolMessageCodec<>(TPKTPacket.class, - TPKTPacket::staticParse, ByteOrder.BIG_ENDIAN, null, + TPKTPacket::staticParse, ByteOrder.BIG_ENDIAN, new S7Driver.ByteLengthEstimator(), new S7Driver.CorruptPackageCleaner())); pipeline.addLast(new S7Step7ServerAdapter(context)); diff --git a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/internal/handlers/IncomingPlcMessageHandler.java b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/internal/handlers/IncomingPlcMessageHandler.java index d52042c8cfa..84be246bac5 100644 --- a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/internal/handlers/IncomingPlcMessageHandler.java +++ b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/internal/handlers/IncomingPlcMessageHandler.java @@ -54,9 +54,9 @@ public void executeIncomingPlcMessage(Plc4xEmbeddedChannel embeddedChannel, Byte public byte[] getBytesFromXml(Element referenceXml, ByteOrder byteOrder) throws DriverTestsuiteException { // TODO: Find some smart way to find out how big the buffer should be. final WriteBufferByteBased writeBuffer = new WriteBufferByteBased(1024 * 100, byteOrder); - MessageInput messageInput = MessageResolver.getMessageInput(driverTestsuiteConfiguration.getOptions(), referenceXml.getName()); + MessageInput messageInput = MessageResolver.getMessageInput(driverTestsuiteConfiguration.getOptions(), referenceXml.getName(), parserArguments); // Get Message and Validate - Message message = MessageValidatorAndMigrator.validateInboundMessageAndGet(messageInput, referenceXml, parserArguments); + Message message = MessageValidatorAndMigrator.validateInboundMessageAndGet(messageInput, referenceXml); // Get Bytes try { diff --git a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/migration/MessageResolver.java b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/migration/MessageResolver.java index 90f5ea80201..4b2bdfc5198 100644 --- a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/migration/MessageResolver.java +++ b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/migration/MessageResolver.java @@ -42,71 +42,44 @@ public class MessageResolver { * * @param options Test framework options * @param name name of the message + * @param parserArguments the parser arguments to create an instance of the message * @return the found MessageIO * @throws DriverTestsuiteException if a MessageIO couldn't be found. */ @SuppressWarnings("rawtypes") - public static MessageInput getMessageInput(Map options, String name) throws DriverTestsuiteException { + public static MessageInput getMessageInput(Map options, String name, List parserArguments) throws DriverTestsuiteException { try { - return MessageResolver.getMessageIOType(options, name).getMessageInput(); + return MessageResolver.getMessageIOType(options, name, parserArguments); } catch (ClassNotFoundException e) { throw new DriverTestsuiteException(e); } } - public static MessageInput getMessageIOStaticLinked(Map options, String typeName) throws ParserSerializerTestsuiteException { + public static MessageInput getMessageIOStaticLinked(Map options, String typeName, List parserArguments) throws ParserSerializerTestsuiteException { try { - TypeMessageInput typeMessageInput = getMessageIOType(options, typeName); - final List> parameterTypes = new LinkedList<>(); - for (Method method : typeMessageInput.type.getMethods()) { - int parameterCount = method.getParameterCount(); - boolean isNonGenericParse = parameterCount > 1 && method.getParameterTypes()[parameterCount - 1] != Object[].class; - if (method.getName().equals("staticParse") && Modifier.isStatic(method.getModifiers()) && isNonGenericParse) { - // Get a list of additional parameter types for the parser. - parameterTypes.addAll(Arrays.asList(method.getParameterTypes()).subList(1, parameterCount)); - break; - } - } - return (io, args) -> { - Object[] argValues = new Object[args.length]; - for (int i = 0; i < args.length; i++) { - String parameterValue = (String) args[i]; - Class parameterType = parameterTypes.get(i); - if (parameterType == Boolean.class) { - argValues[i] = Boolean.parseBoolean(parameterValue); - } else if (parameterType == Byte.class) { - argValues[i] = Byte.parseByte(parameterValue); - } else if (parameterType == Short.class) { - argValues[i] = Short.parseShort(parameterValue); - } else if (parameterType == Integer.class) { - argValues[i] = Integer.parseInt(parameterValue); - } else if (parameterType == Long.class) { - argValues[i] = Long.parseLong(parameterValue); - } else if (parameterType == Float.class) { - argValues[i] = Float.parseFloat(parameterValue); - } else if (parameterType == Double.class) { - argValues[i] = Double.parseDouble(parameterValue); - } else if (parameterType == String.class) { - argValues[i] = parameterValue; - } else if (Enum.class.isAssignableFrom(parameterType)) { - argValues[i] = Enum.valueOf((Class) parameterType, parameterValue); - } else { - throw new ParseException("Currently unsupported parameter type"); - } - } - return typeMessageInput.getMessageInput().parse(io, argValues); - }; + MessageInput typeMessageInput = getMessageIOType(options, typeName, parserArguments); +// final List> parameterTypes = new LinkedList<>(); +// for (Method method : typeMessageInput.type.getMethods()) { +// int parameterCount = method.getParameterCount(); +// boolean isNonGenericParse = parameterCount > 1 && method.getParameterTypes()[parameterCount - 1] != Object[].class; +// if (method.getName().equals("staticParse") && Modifier.isStatic(method.getModifiers()) && isNonGenericParse) { +// // Get a list of additional parameter types for the parser. +// parameterTypes.addAll(Arrays.asList(method.getParameterTypes()).subList(1, parameterCount)); +// break; +// } +// } + return typeMessageInput; } catch (DriverTestsuiteException | ClassNotFoundException e) { throw new ParserSerializerTestsuiteException("Unable to instantiate IO component", e); } } @SuppressWarnings("unchecked") - private static TypeMessageInput getMessageIOType(Map options, String typeName) throws DriverTestsuiteException, ClassNotFoundException { + private static MessageInput getMessageIOType(Map options, String typeName, List parserArguments) throws DriverTestsuiteException, ClassNotFoundException { String extraMessage = ""; if (options.containsKey("package")) { try { - return lookup(options.get("package"), typeName); + return lookup(options.get("package"), typeName, parserArguments); } catch (NoSuchMethodException e) { extraMessage = "custom package '" + options.get("package") + "' and "; } @@ -116,13 +89,13 @@ private static TypeMessageInput getMessageIOType(Map options, St String outputFlavor = options.get("outputFlavor"); String classPackage = String.format("org.apache.plc4x.java.%s.%s", protocolName, StringUtils.replace(outputFlavor, "-", "")); try { - return lookup(classPackage, typeName); + return lookup(classPackage, typeName, parserArguments); } catch (NoSuchMethodException e) { throw new DriverTestsuiteException("Could not find " + typeName + " in " + extraMessage + "standard package '" + classPackage + "'"); } } - private static TypeMessageInput lookup(String driverPackage, String typeName) throws ClassNotFoundException, NoSuchMethodException { + private static MessageInput lookup(String driverPackage, String typeName, List parserArguments) throws ClassNotFoundException, NoSuchMethodException { try { Package.getPackage(driverPackage); } catch (RuntimeException e) { @@ -131,35 +104,82 @@ private static TypeMessageInput lookup(String driverPackage, String typeName) th String ioRootClassName = driverPackage.replace("-", "") + "." + typeName; // make sure both type and it's IO are present Class messageType = (Class) Class.forName(ioRootClassName); - Method staticParse = messageType.getMethod("staticParse", ReadBuffer.class, Object[].class); - return new TypeMessageInput( - messageType, - (io, args) -> { - try { - return staticParse.invoke(null, io, args); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); + Method parseMethod = null; + for (Method method : messageType.getMethods()) { + if (Modifier.isStatic(method.getModifiers()) && "staticParse".equals(method.getName()) && Message.class.isAssignableFrom(method.getReturnType())) { + // because we still have var-arg and non var-arg methods we have to be careful + // below is additional verification of staticParse method which refuses var-arg variant + if (method.getParameterCount() == 1) { + parseMethod = method; + break; + } else if (method.getParameterCount() >= 2 && method.getParameterTypes()[1] != Object[].class) { + // TODO above if statement can be removed later on - when we get rid of var-args + parseMethod = method; + break; } } - ); + } + if (parseMethod == null) { + throw new DriverTestsuiteException("Could not find static parse method for " + typeName); + } + return new DeferredMessageInput(parseMethod, parserArguments); } - static class TypeMessageInput { - private final Class type; - private final MessageInput messageInput; + public static class DeferredMessageInput implements MessageInput { - TypeMessageInput(Class type, MessageInput messageInput) { - this.type = type; - this.messageInput = messageInput; - } + private final Method method; + private final List args; - Class getType() { - return type; + public DeferredMessageInput(Method method, List args) { + this.method = method; + this.args = args; } + @Override + public Message parse(ReadBuffer io) throws ParseException { + Object[] argValues = new Object[args.size() + 1]; + int index = 0; + argValues[index++] = io; + Class[] parameterTypes = method.getParameterTypes(); + + if (parameterTypes.length - 1 != args.size()) { + String type = method.getDeclaringClass().getName(); + int totalArgs = parameterTypes.length - 1; + int given = args.size(); + throw new ParseException("Invalid parameters detected. Type " + type + " expected " + totalArgs + ", not " + given); + } + + for (int i = 0; i < args.size(); i++) { + String parameterValue = args.get(i); + Class parameterType = parameterTypes[index]; + if (parameterType == Boolean.class) { + argValues[index++] = Boolean.parseBoolean(parameterValue); + } else if (parameterType == Byte.class) { + argValues[index++] = Byte.parseByte(parameterValue); + } else if (parameterType == Short.class) { + argValues[index++] = Short.parseShort(parameterValue); + } else if (parameterType == Integer.class) { + argValues[index++] = Integer.parseInt(parameterValue); + } else if (parameterType == Long.class) { + argValues[index++] = Long.parseLong(parameterValue); + } else if (parameterType == Float.class) { + argValues[index++] = Float.parseFloat(parameterValue); + } else if (parameterType == Double.class) { + argValues[index++] = Double.parseDouble(parameterValue); + } else if (parameterType == String.class) { + argValues[index++] = parameterValue; + } else if (Enum.class.isAssignableFrom(parameterType)) { + argValues[index++] = Enum.valueOf((Class) parameterType, parameterValue); + } else { + throw new ParseException("Currently unsupported parameter type"); + } + } + + try { + return (Message) method.invoke(null, argValues); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new ParseException("Could not parse payload", e); + } - MessageInput getMessageInput() { - return messageInput; } } - } diff --git a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/migration/MessageValidatorAndMigrator.java b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/migration/MessageValidatorAndMigrator.java index df28e89a22e..fd73fde28c9 100644 --- a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/migration/MessageValidatorAndMigrator.java +++ b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/migration/MessageValidatorAndMigrator.java @@ -18,6 +18,7 @@ */ package org.apache.plc4x.test.migration; +import java.util.Collections; import java.util.Map; import org.apache.commons.lang3.RegExUtils; @@ -65,30 +66,30 @@ public class MessageValidatorAndMigrator { */ @SuppressWarnings({"rawtypes"}) public static void validateOutboundMessageAndMigrate(String testCaseName, Map options, Element referenceXml, List parserArguments, byte[] data, ByteOrder byteOrder, boolean autoMigrate, URI siteURI) throws DriverTestsuiteException { - MessageInput messageInput = MessageResolver.getMessageInput(options, referenceXml.getName()); - validateOutboundMessageAndMigrate(testCaseName, messageInput, referenceXml, parserArguments, data, byteOrder, autoMigrate, siteURI); + MessageInput messageInput = MessageResolver.getMessageInput(options, referenceXml.getName(), parserArguments); + validateOutboundMessageAndMigrate(testCaseName, messageInput, referenceXml, data, byteOrder, autoMigrate, siteURI); } /** - * Validates a outbound message and migrates it to the expectation if the parameter {@code autoMigrate} is set to true + * Validates a outbound message and migrates it to the expectation if the parameter + * {@code autoMigrate} is set to true * - * @param testCaseName name of the testcase - * @param messageInput the pre-constructed MessageInput - * @param referenceXml the xml we expect the outbound message to be - * @param parserArguments the parser arguments to create an instance of the message - * @param data the bytes of the message - * @param byteOrder the byte-order being used - * @param autoMigrate indicates if we want to migrate to a new version - * @param siteURI the file which we want to auto migrate + * @param testCaseName name of the testcase + * @param messageInput the pre-constructed MessageInput + * @param referenceXml the xml we expect the outbound message to be + * @param data the bytes of the message + * @param byteOrder the byte-order being used + * @param autoMigrate indicates if we want to migrate to a new version + * @param siteURI the file which we want to auto migrate * @return true if migration happened * @throws DriverTestsuiteException if something goes wrong */ @SuppressWarnings({"rawtypes", "unchecked"}) - public static boolean validateOutboundMessageAndMigrate(String testCaseName, MessageInput messageInput, Element referenceXml, List parserArguments, byte[] data, ByteOrder byteOrder, boolean autoMigrate, URI siteURI) throws DriverTestsuiteException { + public static boolean validateOutboundMessageAndMigrate(String testCaseName, MessageInput messageInput, Element referenceXml, byte[] data, ByteOrder byteOrder, boolean autoMigrate, URI siteURI) throws DriverTestsuiteException { final ReadBufferByteBased readBuffer = new ReadBufferByteBased(data, byteOrder); try { - final Message parsedOutput = (Message) messageInput.parse(readBuffer, parserArguments.toArray()); + final Message parsedOutput = (Message) messageInput.parse(readBuffer); final String referenceXmlString = referenceXml.asXML(); try { // First try to use the native xml writer @@ -189,13 +190,12 @@ public static boolean validateOutboundMessageAndMigrate(String testCaseName, Mes * and 'outputFlavor' (flavor of the output e.g read-write) which are used to construct * class lookup root package. * @param referenceXml the xml we expect the outbound message - * @param parserArguments the parser arguments to create an instance of the message * @return the message if all went well */ @SuppressWarnings("rawtypes") - public static Message validateInboundMessageAndGet(Map options, Element referenceXml, List parserArguments) { - MessageInput messageIO = MessageResolver.getMessageInput(options, referenceXml.getName()); - return validateInboundMessageAndGet(messageIO, referenceXml, parserArguments); + public static Message validateInboundMessageAndGet(Map options, Element referenceXml) { + MessageInput messageIO = MessageResolver.getMessageInput(options, referenceXml.getName(), Collections.emptyList()); + return validateInboundMessageAndGet(messageIO, referenceXml); } /** @@ -203,14 +203,13 @@ public static Message validateInboundMessageAndGet(Map options, * * @param messageInput the pre-constructed MessageInput * @param referenceXml the xml we expect the outbound messag - * @param parserArguments the parser arguments to create an instance of the message * @return the message if all went well */ @SuppressWarnings({"rawtypes", "unchecked"}) - public static Message validateInboundMessageAndGet(MessageInput messageInput, Element referenceXml, List parserArguments) { + public static Message validateInboundMessageAndGet(MessageInput messageInput, Element referenceXml) { final String referenceXmlString = referenceXml.asXML(); try { - return (Message) messageInput.parse(new ReadBufferXmlBased(new ByteArrayInputStream(referenceXmlString.getBytes(StandardCharsets.UTF_8))), parserArguments.toArray(new String[0])); + return (Message) messageInput.parse(new ReadBufferXmlBased(new ByteArrayInputStream(referenceXmlString.getBytes(StandardCharsets.UTF_8)))); } catch (RuntimeException | ParseException e) { throw new DriverTestsuiteException(String.format("Error parsing message from:\n%s", referenceXmlString), e); } diff --git a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/parserserializer/ParserSerializerTestsuiteRunner.java b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/parserserializer/ParserSerializerTestsuiteRunner.java index 38ff095fc94..d14e5476ee8 100644 --- a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/parserserializer/ParserSerializerTestsuiteRunner.java +++ b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/parserserializer/ParserSerializerTestsuiteRunner.java @@ -148,7 +148,8 @@ private void run(ParserSerializerTestsuite testSuite, Testcase testcase) throws try { MessageInput messageInput = MessageResolver.getMessageIOStaticLinked( testSuite.getOptions(), - testcase.getRootType() + testcase.getRootType(), + testcase.getParserArguments() ); //////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -156,7 +157,7 @@ private void run(ParserSerializerTestsuite testSuite, Testcase testcase) throws //////////////////////////////////////////////////////////////////////////////////////////////////////////// LOGGER.trace("Parsing message"); - Message parsedOutput = (Message) messageInput.parse(readBuffer, testcase.getParserArguments().toArray()); + Message parsedOutput = (Message) messageInput.parse(readBuffer); LOGGER.trace("Validating and migrating"); //////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -179,7 +180,6 @@ else if (testcase.getXml().elements().size() > 1) { testcase.getName(), messageInput, testcase.getXml().elements().get(0), - testcase.getParserArguments(), testcaseRaw, testSuite.getByteOrder(), autoMigrate,