diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 02ee1f1..1a236d0 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerinax" name = "ibm.ibmmq" -version = "1.0.0" +version = "1.1.0" authors = ["Ballerina"] keywords = ["ibm.ibmmq", "client", "messaging", "network", "pubsub"] repository = "https://github.com/ballerina-platform/module-ballerinax-ibm.ibmmq" @@ -12,8 +12,8 @@ distribution = "2201.9.0" [[platform.java17.dependency]] groupId = "io.ballerina.stdlib" artifactId = "ibm.ibmmq-native" -version = "1.0.0" -path = "../native/build/libs/ibm.ibmmq-native-1.0.0.jar" +version = "1.1.0" +path = "../native/build/libs/ibm.ibmmq-native-1.1.0-SNAPSHOT.jar" [[platform.java17.dependency]] groupId = "org.json" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index cabef97..a198d03 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -90,7 +90,7 @@ modules = [ [[package]] org = "ballerinax" name = "ibm.ibmmq" -version = "1.0.0" +version = "1.1.0" dependencies = [ {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "jballerina.java"}, diff --git a/ballerina/build.gradle b/ballerina/build.gradle index 3a5094f..e197f43 100644 --- a/ballerina/build.gradle +++ b/ballerina/build.gradle @@ -180,6 +180,7 @@ publishing { updateTomlFiles.dependsOn copyStdlibs +build.dependsOn "generatePomFileForMavenPublication" build.dependsOn ":${packageName}-native:build" build.dependsOn startIBMMQServer build.finalizedBy stopIBMMQServer diff --git a/ballerina/tests/queue_producer_consumer_tests.bal b/ballerina/tests/queue_producer_consumer_tests.bal index 1a15fd4..09bce20 100644 --- a/ballerina/tests/queue_producer_consumer_tests.bal +++ b/ballerina/tests/queue_producer_consumer_tests.bal @@ -518,3 +518,178 @@ function produceAndConsumerMessageWithMultipleHeaderTypesWithJsonPayloadTest() r check queueManager.disconnect(); } +@test:Config { + groups: ["ibmmqQueue", "matchOptions"] +} +function produceConsumeWithMsgId() returns error? { + QueueManager queueManager = check new ( + name = "QM1", host = "localhost", channel = "DEV.APP.SVRCONN", + userID = "app", password = "password"); + Queue queue = check queueManager.accessQueue("DEV.QUEUE.2", MQOO_OUTPUT | MQOO_INPUT_AS_Q_DEF); + + byte[] providedMsgId = "msg-id-1".toBytes(); + string messageContent = "This is a sample message with a message-id."; + check queue->put({ + messageId: providedMsgId, + payload: messageContent.toBytes() + }); + + Message? message = check queue->get(matchOptions = { messageId: providedMsgId }); + test:assertTrue(message is Message, "Could not retrieve a message for a valid message identifier"); + + byte[]? payload = message?.payload; + test:assertEquals(string:fromBytes(check payload.ensureType()), messageContent); + + check queue->close(); + check queueManager.disconnect(); +} + +@test:Config { + groups: ["ibmmqQueue", "matchOptions"] +} +function produceConsumeWithInvalidMsgId() returns error? { + QueueManager queueManager = check new ( + name = "QM1", host = "localhost", channel = "DEV.APP.SVRCONN", + userID = "app", password = "password"); + Queue queue = check queueManager.accessQueue("DEV.QUEUE.2", MQOO_OUTPUT | MQOO_INPUT_AS_Q_DEF); + + string messageContent = "This is a sample message with a message-id."; + check queue->put({ + payload: messageContent.toBytes() + }); + + Message? message = check queue->get(matchOptions = { messageId: "test-msg-id-1".toBytes() }); + test:assertTrue(message is (), "Retrieved a message for an invalid message identifier"); + + check queue->close(); + check queueManager.disconnect(); +} + +@test:Config { + groups: ["ibmmqQueue", "matchOptions"] +} +function produceConsumeWithCorrId() returns error? { + QueueManager queueManager = check new ( + name = "QM1", host = "localhost", channel = "DEV.APP.SVRCONN", + userID = "app", password = "password"); + Queue queue = check queueManager.accessQueue("DEV.QUEUE.2", MQOO_OUTPUT | MQOO_INPUT_AS_Q_DEF); + + byte[] providedCorrId = "corr-id-1".toBytes(); + string messageContent = "This is a sample message with a correlation-id."; + check queue->put({ + correlationId: providedCorrId, + payload: messageContent.toBytes() + }); + + Message? message = check queue->get(matchOptions = { correlationId: providedCorrId }); + test:assertTrue(message is Message, "Could not retrieve a message for a valid correlation identifier"); + + byte[]? correlationId = message?.correlationId; + test:assertTrue(correlationId is byte[], "Could not find the correlation identifier for the message"); + + byte[]? payload = message?.payload; + test:assertEquals(string:fromBytes(check payload.ensureType()), messageContent); + + check queue->close(); + check queueManager.disconnect(); +} + +@test:Config { + groups: ["ibmmqQueue", "matchOptions"] +} +function produceConsumeWithInvalidCorrId() returns error? { + QueueManager queueManager = check new ( + name = "QM1", host = "localhost", channel = "DEV.APP.SVRCONN", + userID = "app", password = "password"); + Queue queue = check queueManager.accessQueue("DEV.QUEUE.2", MQOO_OUTPUT | MQOO_INPUT_AS_Q_DEF); + + string messageContent = "This is a sample message with a message-id."; + check queue->put({ + payload: messageContent.toBytes() + }); + + Message? message = check queue->get(matchOptions = { correlationId: "test-corr-id-1".toBytes() }); + test:assertTrue(message is (), "Retrieved a message for an invalid correlation identifier"); + + check queue->close(); + check queueManager.disconnect(); +} + +@test:Config { + groups: ["ibmmqQueue", "matchOptions"] +} +function produceConsumeWithMsgIdAndCorrId() returns error? { + QueueManager queueManager = check new ( + name = "QM1", host = "localhost", channel = "DEV.APP.SVRCONN", + userID = "app", password = "password"); + Queue queue = check queueManager.accessQueue("DEV.QUEUE.2", MQOO_OUTPUT | MQOO_INPUT_AS_Q_DEF); + + byte[] providedMsgId = "msg-id-1".toBytes(); + byte[] providedCorrId = "corr-id-1".toBytes(); + string messageContent = "This is a sample message with a message-id and a correlation-id."; + check queue->put({ + messageId: providedMsgId, + correlationId: providedCorrId, + payload: messageContent.toBytes() + }); + + Message? message = check queue->get(matchOptions = { messageId: providedMsgId, correlationId: providedCorrId }); + test:assertTrue(message is Message, "Could not retrieve a message for a valid message identifier and correlation identifier"); + + byte[]? payload = message?.payload; + test:assertEquals(string:fromBytes(check payload.ensureType()), messageContent); + + check queue->close(); + check queueManager.disconnect(); +} + +@test:Config { + groups: ["ibmmqQueue", "matchOptions"], + dependsOn: [produceConsumeWithMsgIdAndCorrId] +} +function produceConsumeWithInvalidMsgIdAndCorrId() returns error? { + QueueManager queueManager = check new ( + name = "QM1", host = "localhost", channel = "DEV.APP.SVRCONN", + userID = "app", password = "password"); + Queue queue = check queueManager.accessQueue("DEV.QUEUE.2", MQOO_OUTPUT | MQOO_INPUT_AS_Q_DEF); + + byte[] providedMsgId = "msg-id-1".toBytes(); + byte[] providedCorrId = "corr-id-1".toBytes(); + string messageContent = "This is a sample message with a message-id and a correlation-id."; + check queue->put({ + correlationId: providedCorrId, + payload: messageContent.toBytes() + }); + + Message? message = check queue->get(matchOptions = { messageId: providedMsgId, correlationId: providedCorrId }); + test:assertTrue(message is (), "Retrieved a message for an invalid message-id and a correct correlation identifier"); + + check queue->close(); + check queueManager.disconnect(); +} + +@test:Config { + groups: ["ibmmqQueue", "matchOptions"], + dependsOn: [produceConsumeWithInvalidMsgIdAndCorrId] +} +function produceConsumeWithMsgIdAndInvalidCorrId() returns error? { + QueueManager queueManager = check new ( + name = "QM1", host = "localhost", channel = "DEV.APP.SVRCONN", + userID = "app", password = "password"); + Queue queue = check queueManager.accessQueue("DEV.QUEUE.2", MQOO_OUTPUT | MQOO_INPUT_AS_Q_DEF); + + byte[] providedMsgId = "msg-id-1".toBytes(); + byte[] providedCorrId = "corr-id-1".toBytes(); + string messageContent = "This is a sample message with a message-id and a correlation-id."; + check queue->put({ + messageId: providedMsgId, + payload: messageContent.toBytes() + }); + + Message? message = check queue->get(matchOptions = { messageId: providedMsgId, correlationId: providedCorrId }); + test:assertTrue(message is (), "Retrieved a message for a correct message-id and an invalid correlation identifier"); + + check queue->close(); + check queueManager.disconnect(); +} + diff --git a/ballerina/types.bal b/ballerina/types.bal index 2e2fb10..c5f06b8 100644 --- a/ballerina/types.bal +++ b/ballerina/types.bal @@ -83,9 +83,20 @@ public type CertKey record {| # + options - Get message option # + waitInterval - The maximum time (in seconds) that a `get` call waits for a suitable message to # arrive. It is used in conjunction with `ibmmq.MQGMO_WAIT`. +# + matchOptions - Message selection criteria public type GetMessageOptions record {| int options = MQGMO_NO_WAIT; int waitInterval = 10; + MatchOptions matchOptions?; +|}; + +# Represents the selection criteria that determine which message is retrieved. +# +# + messageId - The message identifier of the message which needs to be retrieved +# + correlationId - The Correlation identifier of the message which needs to be retrieved +public type MatchOptions record {| + byte[] messageId?; + byte[] correlationId?; |}; # Represents an IBM MQ message property. diff --git a/changelog.md b/changelog.md index 1e5cf2e..9e61103 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Added + +- [Add Support for Retrieving Messages from IBM MQ by Matching Correlation ID and Message ID](https://github.com/ballerina-platform/ballerina-library/issues/6918) + +## [1.0.0] - 2024-07-08 + ### Changed - [Decouple IBM MQ java client jar from the IBM MQ connector](https://github.com/ballerina-platform/ballerina-library/issues/6287) diff --git a/docs/spec/spec.md b/docs/spec/spec.md index 172c308..22e5d29 100644 --- a/docs/spec/spec.md +++ b/docs/spec/spec.md @@ -408,7 +408,7 @@ public type Message record {| ## 4. Client Options -- GetMessageOptions record represents client options which can be used when retrieving messages from an IBM MQ destination. +- `GetMessageOptions` record represents client options which can be used when retrieving messages from an IBM MQ destination. ```ballerina public type GetMessageOptions record {| @@ -416,6 +416,19 @@ public type GetMessageOptions record {| int options = MQGMO_NO_WAIT; # The maximum time (in seconds) that a `get` call waits for a suitable message to arrive. It is used in conjunction with `ibmmq.MQGMO_WAIT`. int waitInterval = 10; + # Message selection criteria + MatchOptions matchOptions?; +|}; +``` + +- `MatchOptions` record represents the selection criteria that determine which message is retrieved. + +```ballerina +public type MatchOptions record {| + # The message identifier of the message which needs to be retrieved + byte[] messageId?; + # The Correlation identifier of the message which needs to be retrieved + byte[] correlationId?; |}; ``` diff --git a/gradle.properties b/gradle.properties index ef89c59..55ae950 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.caching=true group=io.ballerina.lib -version=1.0.1-SNAPSHOT +version=1.1.0-SNAPSHOT ballerinaLangVersion=2201.9.0 checkstylePluginVersion=10.12.1 diff --git a/native/src/main/java/io/ballerina/lib/ibm.ibmmq/CommonUtils.java b/native/src/main/java/io/ballerina/lib/ibm.ibmmq/CommonUtils.java index d3957f9..c49e6d8 100644 --- a/native/src/main/java/io/ballerina/lib/ibm.ibmmq/CommonUtils.java +++ b/native/src/main/java/io/ballerina/lib/ibm.ibmmq/CommonUtils.java @@ -22,7 +22,10 @@ import com.ibm.mq.MQGetMessageOptions; import com.ibm.mq.MQMessage; import com.ibm.mq.MQPropertyDescriptor; +import com.ibm.mq.constants.MQConstants; import com.ibm.mq.headers.MQHeaderList; +import io.ballerina.lib.ibm.ibmmq.config.GetMessageOptions; +import io.ballerina.lib.ibm.ibmmq.config.MatchOptions; import io.ballerina.lib.ibm.ibmmq.headers.MQRFH2Header; import io.ballerina.runtime.api.PredefinedTypes; import io.ballerina.runtime.api.Runtime; @@ -66,7 +69,6 @@ import static io.ballerina.lib.ibm.ibmmq.Constants.MESSAGE_PROPERTY; import static io.ballerina.lib.ibm.ibmmq.Constants.MESSAGE_PROPERTIES; import static io.ballerina.lib.ibm.ibmmq.Constants.MESSAGE_TYPE_FIELD; -import static io.ballerina.lib.ibm.ibmmq.Constants.OPTIONS; import static io.ballerina.lib.ibm.ibmmq.Constants.PD_CONTEXT; import static io.ballerina.lib.ibm.ibmmq.Constants.PD_COPY_OPTIONS; import static io.ballerina.lib.ibm.ibmmq.Constants.PD_OPTIONS; @@ -79,7 +81,6 @@ import static io.ballerina.lib.ibm.ibmmq.Constants.PUT_APPLICATION_TYPE_FIELD; import static io.ballerina.lib.ibm.ibmmq.Constants.REPLY_TO_QM_NAME_FIELD; import static io.ballerina.lib.ibm.ibmmq.Constants.REPLY_TO_QUEUE_NAME_FIELD; -import static io.ballerina.lib.ibm.ibmmq.Constants.WAIT_INTERVAL; import static io.ballerina.lib.ibm.ibmmq.ModuleUtils.getModule; import static io.ballerina.lib.ibm.ibmmq.headers.MQCIHHeader.createMQCIHHeaderFromBHeader; import static io.ballerina.lib.ibm.ibmmq.headers.MQIIHHeader.createMQIIHHeaderFromBHeader; @@ -293,13 +294,40 @@ private static BMap populateDescriptorFromMQPropertyDescriptor(MQPropertyDescrip return descriptor; } - public static MQGetMessageOptions getGetMessageOptions(BMap bOptions) { - int waitInterval = bOptions.getIntValue(WAIT_INTERVAL).intValue(); - int options = bOptions.getIntValue(OPTIONS).intValue(); - MQGetMessageOptions getMessageOptions = new MQGetMessageOptions(); - getMessageOptions.waitInterval = waitInterval * 1000; - getMessageOptions.options = options; - return getMessageOptions; + public static MQMessage getMqMessage(MatchOptions matchOptions) { + MQMessage message = new MQMessage(); + if (Objects.isNull(matchOptions)) { + return message; + } + + if (Objects.nonNull(matchOptions.messageId())) { + message.messageId = matchOptions.messageId(); + } + if (Objects.nonNull(matchOptions.correlationId())) { + message.correlationId = matchOptions.correlationId(); + } + return message; + } + + public static MQGetMessageOptions getMqGetMsgOptions(GetMessageOptions getMsgOptions) { + MQGetMessageOptions mqGetMsgOptions = new MQGetMessageOptions(); + mqGetMsgOptions.waitInterval = getMsgOptions.waitInterval(); + mqGetMsgOptions.options = getMsgOptions.options(); + + MatchOptions matchOptions = getMsgOptions.matchOptions(); + if (Objects.isNull(matchOptions)) { + return mqGetMsgOptions; + } + + int matchOpt = MQConstants.MQMO_NONE; + if (Objects.nonNull(matchOptions.messageId())) { + matchOpt |= MQConstants.MQMO_MATCH_MSG_ID; + } + if (Objects.nonNull(matchOptions.correlationId())) { + matchOpt |= MQConstants.MQMO_MATCH_CORREL_ID; + } + mqGetMsgOptions.matchOptions = matchOpt; + return mqGetMsgOptions; } private static Object getBHeaders(Runtime runtime, MQMessage mqMessage) { diff --git a/native/src/main/java/io/ballerina/lib/ibm.ibmmq/Constants.java b/native/src/main/java/io/ballerina/lib/ibm.ibmmq/Constants.java index 60d9551..91d3b3b 100644 --- a/native/src/main/java/io/ballerina/lib/ibm.ibmmq/Constants.java +++ b/native/src/main/java/io/ballerina/lib/ibm.ibmmq/Constants.java @@ -108,6 +108,7 @@ public interface Constants { BString PROPERTY_DESCRIPTOR = StringUtils.fromString("descriptor"); BString WAIT_INTERVAL = StringUtils.fromString("waitInterval"); BString OPTIONS = StringUtils.fromString("options"); + BString MATCH_OPTIONS = StringUtils.fromString("matchOptions"); BString FORMAT_FIELD = StringUtils.fromString("format"); BString MESSAGE_ID_FIELD = StringUtils.fromString("messageId"); BString CORRELATION_ID_FIELD = StringUtils.fromString("correlationId"); diff --git a/native/src/main/java/io/ballerina/lib/ibm.ibmmq/Queue.java b/native/src/main/java/io/ballerina/lib/ibm.ibmmq/Queue.java index a723fdc..5b314ed 100644 --- a/native/src/main/java/io/ballerina/lib/ibm.ibmmq/Queue.java +++ b/native/src/main/java/io/ballerina/lib/ibm.ibmmq/Queue.java @@ -23,6 +23,7 @@ import com.ibm.mq.MQMessage; import com.ibm.mq.MQQueue; import com.ibm.mq.constants.CMQC; +import io.ballerina.lib.ibm.ibmmq.config.GetMessageOptions; import io.ballerina.runtime.api.Environment; import io.ballerina.runtime.api.Future; import io.ballerina.runtime.api.values.BError; @@ -60,15 +61,16 @@ public static Object put(Environment environment, BObject queueObject, BMap options) { + public static Object get(Environment environment, BObject queueObject, BMap bGetMsgOptions) { MQQueue queue = (MQQueue) queueObject.getNativeData(Constants.NATIVE_QUEUE); - MQGetMessageOptions getMessageOptions = CommonUtils.getGetMessageOptions(options); + GetMessageOptions getMsgOptions = new GetMessageOptions(bGetMsgOptions); + MQMessage mqMessage = CommonUtils.getMqMessage(getMsgOptions.matchOptions()); + MQGetMessageOptions mqGetMsgOptions = CommonUtils.getMqGetMsgOptions(getMsgOptions); Future future = environment.markAsync(); QUEUE_EXECUTOR_SERVICE.execute(() -> { try { - MQMessage message = new MQMessage(); - queue.get(message, getMessageOptions); - future.complete(CommonUtils.getBMessageFromMQMessage(environment.getRuntime(), message)); + queue.get(mqMessage, mqGetMsgOptions); + future.complete(CommonUtils.getBMessageFromMQMessage(environment.getRuntime(), mqMessage)); } catch (MQException e) { if (e.reasonCode == CMQC.MQRC_NO_MSG_AVAILABLE) { future.complete(null); diff --git a/native/src/main/java/io/ballerina/lib/ibm.ibmmq/Topic.java b/native/src/main/java/io/ballerina/lib/ibm.ibmmq/Topic.java index fc6272b..1d5611d 100644 --- a/native/src/main/java/io/ballerina/lib/ibm.ibmmq/Topic.java +++ b/native/src/main/java/io/ballerina/lib/ibm.ibmmq/Topic.java @@ -23,6 +23,7 @@ import com.ibm.mq.MQMessage; import com.ibm.mq.MQTopic; import com.ibm.mq.constants.CMQC; +import io.ballerina.lib.ibm.ibmmq.config.GetMessageOptions; import io.ballerina.runtime.api.Environment; import io.ballerina.runtime.api.Future; import io.ballerina.runtime.api.values.BError; @@ -60,15 +61,16 @@ public static Object put(Environment environment, BObject topicObject, BMap mess return null; } - public static Object get(Environment environment, BObject topicObject, BMap options) { + public static Object get(Environment environment, BObject topicObject, BMap bGetMsgOptions) { MQTopic topic = (MQTopic) topicObject.getNativeData(Constants.NATIVE_TOPIC); - MQGetMessageOptions getMessageOptions = CommonUtils.getGetMessageOptions(options); + GetMessageOptions getMsgOptions = new GetMessageOptions(bGetMsgOptions); + MQMessage mqMessage = CommonUtils.getMqMessage(getMsgOptions.matchOptions()); + MQGetMessageOptions mqGetMsgOptions = CommonUtils.getMqGetMsgOptions(getMsgOptions); Future future = environment.markAsync(); topicExecutorService.execute(() -> { try { - MQMessage message = new MQMessage(); - topic.get(message, getMessageOptions); - future.complete(CommonUtils.getBMessageFromMQMessage(environment.getRuntime(), message)); + topic.get(mqMessage, mqGetMsgOptions); + future.complete(CommonUtils.getBMessageFromMQMessage(environment.getRuntime(), mqMessage)); } catch (MQException e) { if (e.reasonCode == CMQC.MQRC_NO_MSG_AVAILABLE) { future.complete(null); diff --git a/native/src/main/java/io/ballerina/lib/ibm.ibmmq/config/GetMessageOptions.java b/native/src/main/java/io/ballerina/lib/ibm.ibmmq/config/GetMessageOptions.java new file mode 100644 index 0000000..338c867 --- /dev/null +++ b/native/src/main/java/io/ballerina/lib/ibm.ibmmq/config/GetMessageOptions.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). + * + * WSO2 LLC. 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 io.ballerina.lib.ibm.ibmmq.config; + +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BString; + +import static io.ballerina.lib.ibm.ibmmq.Constants.MATCH_OPTIONS; +import static io.ballerina.lib.ibm.ibmmq.Constants.OPTIONS; +import static io.ballerina.lib.ibm.ibmmq.Constants.WAIT_INTERVAL; + +/** + * Represents the IBM MQ GET message options. + * + * @param options Get message option + * @param waitInterval The maximum time (in seconds) that a `get` call waits for a suitable message to arrive. + * It is used in conjunction with `MQGMO_WAIT`. + * @param matchOptions Message selection criteria + */ +public record GetMessageOptions(int options, int waitInterval, MatchOptions matchOptions) { + + public GetMessageOptions(BMap getMsgOptions) { + this( + getMsgOptions.getIntValue(OPTIONS).intValue(), + getMsgOptions.getIntValue(WAIT_INTERVAL).intValue() * 1000, + getMatchOptions(getMsgOptions) + ); + } + + @SuppressWarnings("unchecked") + private static MatchOptions getMatchOptions(BMap getMsgOptions) { + if (!getMsgOptions.containsKey(MATCH_OPTIONS)) { + return null; + } + return new MatchOptions((BMap) getMsgOptions.getMapValue(MATCH_OPTIONS)); + } +} diff --git a/native/src/main/java/io/ballerina/lib/ibm.ibmmq/config/MatchOptions.java b/native/src/main/java/io/ballerina/lib/ibm.ibmmq/config/MatchOptions.java new file mode 100644 index 0000000..1ead78e --- /dev/null +++ b/native/src/main/java/io/ballerina/lib/ibm.ibmmq/config/MatchOptions.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). + * + * WSO2 LLC. 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 io.ballerina.lib.ibm.ibmmq.config; + +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BString; + +import static io.ballerina.lib.ibm.ibmmq.Constants.CORRELATION_ID_FIELD; +import static io.ballerina.lib.ibm.ibmmq.Constants.MESSAGE_ID_FIELD; + +/** + * Represents the selection criteria that determine which message is retrieved. + * + * @param messageId The message identifier of the message which needs to be retrieved + * @param correlationId The Correlation identifier of the message which needs to be retrieved + */ +public record MatchOptions(byte[] messageId, byte[] correlationId) { + + public MatchOptions(BMap matchOptions) { + this( + getByteArrIfPresent(matchOptions, MESSAGE_ID_FIELD), + getByteArrIfPresent(matchOptions, CORRELATION_ID_FIELD) + ); + } + + private static byte[] getByteArrIfPresent(BMap matchOptions, BString key) { + if (!matchOptions.containsKey(key)) { + return null; + } + return matchOptions.getArrayValue(key).getByteArray(); + } +} diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index 0151992..ae4f7c8 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -24,10 +24,22 @@ + + + + + + + + + + + +