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

zbendhiba pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new e1215d172f5c CAMEL-23251- Google mail Add DataTypeTransformer for 
Gmail ModifyMess… (#22285)
e1215d172f5c is described below

commit e1215d172f5c69a3756cc70f763950ff260150ae
Author: Zineb BENDHIBA <[email protected]>
AuthorDate: Thu Mar 26 16:21:00 2026 +0100

    CAMEL-23251- Google mail Add DataTypeTransformer for Gmail ModifyMess… 
(#22285)
    
    * CAMEL-23251- Google mail Add DataTypeTransformer for Gmail 
ModifyMessageRequest to update labels
    Fixes #CAMEL-23251
    
    Co-authored-by: Guillaume Nodet <[email protected]>
---
 .../apache/camel/catalog/transformers.properties   |   1 +
 .../google-mail-update-message-labels.json         |  14 ++
 .../org/apache/camel/transformer.properties        |   2 +-
 .../transformer/google-mail-update-message-labels  |   2 +
 .../google-mail-update-message-labels.json         |  14 ++
 .../src/main/docs/google-mail-component.adoc       |  78 ++++++
 ...MailUpdateMessageLabelsDataTypeTransformer.java | 133 ++++++++++
 .../google/mail/MockGoogleMailClientFactory.java   |  83 +++++++
 ...UpdateMessageLabelsDataTypeTransformerTest.java | 273 +++++++++++++++++++++
 9 files changed, 599 insertions(+), 1 deletion(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers.properties
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers.properties
index d9a9a5e978be..c261164480cc 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers.properties
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers.properties
@@ -22,6 +22,7 @@ azure-storage-datalake-application-cloudevents
 azure-storage-queue-application-cloudevents
 google-calendar-stream-application-cloudevents
 google-mail-stream-application-cloudevents
+google-mail-update-message-labels
 google-pubsub-application-cloudevents
 google-sheets-application-x-struct
 google-sheets-stream-application-cloudevents
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/google-mail-update-message-labels.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/google-mail-update-message-labels.json
new file mode 100644
index 000000000000..6f56dd20d990
--- /dev/null
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/transformers/google-mail-update-message-labels.json
@@ -0,0 +1,14 @@
+{
+  "transformer": {
+    "kind": "transformer",
+    "name": "google-mail:update-message-labels",
+    "title": "Google Mail (Update Message Labels)",
+    "description": "Updates Gmail message labels by resolving label names from 
addLabels\/removeLabels exchange variables",
+    "deprecated": false,
+    "javaType": 
"org.apache.camel.component.google.mail.transform.GoogleMailUpdateMessageLabelsDataTypeTransformer",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-google-mail",
+    "version": "4.19.0-SNAPSHOT"
+  }
+}
+
diff --git 
a/components/camel-google/camel-google-mail/src/generated/resources/META-INF/services/org/apache/camel/transformer.properties
 
b/components/camel-google/camel-google-mail/src/generated/resources/META-INF/services/org/apache/camel/transformer.properties
index ff3378f9a0fe..20bd343808d0 100644
--- 
a/components/camel-google/camel-google-mail/src/generated/resources/META-INF/services/org/apache/camel/transformer.properties
+++ 
b/components/camel-google/camel-google-mail/src/generated/resources/META-INF/services/org/apache/camel/transformer.properties
@@ -1,5 +1,5 @@
 # Generated by camel build tools - do NOT edit this file!
-transformers=google-mail-stream:application-cloudevents
+transformers=google-mail-stream:application-cloudevents 
google-mail:update-message-labels
 groupId=org.apache.camel
 artifactId=camel-google-mail
 version=4.19.0-SNAPSHOT
diff --git 
a/components/camel-google/camel-google-mail/src/generated/resources/META-INF/services/org/apache/camel/transformer/google-mail-update-message-labels
 
b/components/camel-google/camel-google-mail/src/generated/resources/META-INF/services/org/apache/camel/transformer/google-mail-update-message-labels
new file mode 100644
index 000000000000..e439c96ed1ff
--- /dev/null
+++ 
b/components/camel-google/camel-google-mail/src/generated/resources/META-INF/services/org/apache/camel/transformer/google-mail-update-message-labels
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.google.mail.transform.GoogleMailUpdateMessageLabelsDataTypeTransformer
diff --git 
a/components/camel-google/camel-google-mail/src/generated/resources/META-INF/services/org/apache/camel/transformer/google-mail-update-message-labels.json
 
b/components/camel-google/camel-google-mail/src/generated/resources/META-INF/services/org/apache/camel/transformer/google-mail-update-message-labels.json
new file mode 100644
index 000000000000..6f56dd20d990
--- /dev/null
+++ 
b/components/camel-google/camel-google-mail/src/generated/resources/META-INF/services/org/apache/camel/transformer/google-mail-update-message-labels.json
@@ -0,0 +1,14 @@
+{
+  "transformer": {
+    "kind": "transformer",
+    "name": "google-mail:update-message-labels",
+    "title": "Google Mail (Update Message Labels)",
+    "description": "Updates Gmail message labels by resolving label names from 
addLabels\/removeLabels exchange variables",
+    "deprecated": false,
+    "javaType": 
"org.apache.camel.component.google.mail.transform.GoogleMailUpdateMessageLabelsDataTypeTransformer",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-google-mail",
+    "version": "4.19.0-SNAPSHOT"
+  }
+}
+
diff --git 
a/components/camel-google/camel-google-mail/src/main/docs/google-mail-component.adoc
 
b/components/camel-google/camel-google-mail/src/main/docs/google-mail-component.adoc
index bf1eb6788ae3..69381e4843e7 100644
--- 
a/components/camel-google/camel-google-mail/src/main/docs/google-mail-component.adoc
+++ 
b/components/camel-google/camel-google-mail/src/main/docs/google-mail-component.adoc
@@ -63,6 +63,84 @@ include::partial$component-endpoint-options.adoc[]
 include::partial$component-endpoint-headers.adoc[]
 // component options: END
 
+== Data Type Transformer: update-message-labels
+
+The `google-mail:update-message-labels` data type transformer builds a 
`ModifyMessageRequest` from exchange variables, resolving label names to Gmail 
label IDs automatically.
+
+This is useful for modifying Gmail message labels (categorizing, archiving, 
starring, moving, etc.) without manually calling the labels/list API.
+
+=== Exchange Variables
+
+[cols="1,1,3"]
+|===
+| Variable | Type | Description
+
+| `addLabels`
+| `String` (comma-separated) or `List<String>`
+| Label names to add to the message.
+
+| `removeLabels`
+| `String` (comma-separated) or `List<String>`
+| Label names to remove from the message.
+|===
+
+At least one of the two variables must be set.
+
+Both system labels (INBOX, UNREAD, STARRED, SPAM, TRASH, IMPORTANT, etc.) and 
custom user-defined labels are resolved via the Gmail labels/list API.
+
+=== Examples
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("google-mail-stream:0")
+    .setVariable("addLabels", constant("Work"))
+    .setVariable("removeLabels", constant("INBOX,UNREAD"))
+    .transformDataType(new DataType("google-mail:update-message-labels"))
+    .to("google-mail:messages/modify");
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+    from:
+      uri: "google-mail-stream:0"
+    steps:
+      - setVariable:
+          name: addLabels
+          constant: "Work"
+      - setVariable:
+          name: removeLabels
+          constant: "INBOX,UNREAD"
+      - transformDataType:
+          toType: "google-mail:update-message-labels"
+      - to:
+          uri: "google-mail:messages/modify"
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+    <from uri="google-mail-stream:0"/>
+    <setVariable name="addLabels">
+        <constant>Work</constant>
+    </setVariable>
+    <setVariable name="removeLabels">
+        <constant>INBOX,UNREAD</constant>
+    </setVariable>
+    <transformDataType toType="google-mail:update-message-labels"/>
+    <to uri="google-mail:messages/modify"/>
+</route>
+----
+====
+
 == More Information
 
 For more information on the endpoints and options see API documentation
diff --git 
a/components/camel-google/camel-google-mail/src/main/java/org/apache/camel/component/google/mail/transform/GoogleMailUpdateMessageLabelsDataTypeTransformer.java
 
b/components/camel-google/camel-google-mail/src/main/java/org/apache/camel/component/google/mail/transform/GoogleMailUpdateMessageLabelsDataTypeTransformer.java
new file mode 100644
index 000000000000..6dcf63b8cd70
--- /dev/null
+++ 
b/components/camel-google/camel-google-mail/src/main/java/org/apache/camel/component/google/mail/transform/GoogleMailUpdateMessageLabelsDataTypeTransformer.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.google.mail.transform;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.api.services.gmail.Gmail;
+import com.google.api.services.gmail.model.Label;
+import com.google.api.services.gmail.model.ListLabelsResponse;
+import com.google.api.services.gmail.model.ModifyMessageRequest;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.google.mail.GoogleMailComponent;
+import org.apache.camel.component.google.mail.internal.GoogleMailConstants;
+import org.apache.camel.spi.DataType;
+import org.apache.camel.spi.DataTypeTransformer;
+import org.apache.camel.spi.Transformer;
+
+/**
+ * Data type transformer that builds a {@link ModifyMessageRequest} that 
updates labels of a message from exchange
+ * variables {@code addLabels} and {@code removeLabels} .
+ *
+ */
+@DataTypeTransformer(name = "google-mail:update-message-labels",
+                     description = "Updates Gmail message labels by resolving 
label names from addLabels/removeLabels exchange variables")
+public class GoogleMailUpdateMessageLabelsDataTypeTransformer extends 
Transformer {
+
+    public static final String VARIABLE_ADD_LABELS = "addLabels";
+    public static final String VARIABLE_REMOVE_LABELS = "removeLabels";
+
+    private static final String DEFAULT_USER_ID = "me";
+    private static final String HEADER_USER_ID = 
GoogleMailConstants.PROPERTY_PREFIX + "userId";
+
+    @Override
+    public void transform(Message message, DataType fromType, DataType toType) 
throws Exception {
+        Exchange exchange = message.getExchange();
+
+        List<String> addLabelNames = getLabelsVariable(exchange, 
VARIABLE_ADD_LABELS);
+        List<String> removeLabelNames = getLabelsVariable(exchange, 
VARIABLE_REMOVE_LABELS);
+
+        if (addLabelNames.isEmpty() && removeLabelNames.isEmpty()) {
+            throw new CamelExecutionException(
+                    "At least one of 'addLabels' or 'removeLabels' exchange 
variables must be set", exchange);
+        }
+
+        String userId = message.getHeader(HEADER_USER_ID, DEFAULT_USER_ID, 
String.class);
+        Map<String, String> labelMap = fetchLabelMap(userId);
+
+        List<String> addLabelIds = resolveLabelIds(addLabelNames, labelMap, 
exchange);
+        List<String> removeLabelIds = resolveLabelIds(removeLabelNames, 
labelMap, exchange);
+
+        ModifyMessageRequest request = new ModifyMessageRequest();
+        if (!addLabelIds.isEmpty()) {
+            request.setAddLabelIds(addLabelIds);
+        }
+        if (!removeLabelIds.isEmpty()) {
+            request.setRemoveLabelIds(removeLabelIds);
+        }
+
+        message.setBody(request);
+    }
+
+    @SuppressWarnings("unchecked")
+    private List<String> getLabelsVariable(Exchange exchange, String 
variableName) {
+        Object value = exchange.getVariable(variableName);
+        if (value == null) {
+            return Collections.emptyList();
+        }
+        if (value instanceof List) {
+            return (List<String>) value;
+        }
+        if (value instanceof String stringValue) {
+            if (stringValue.isBlank()) {
+                return Collections.emptyList();
+            }
+            return 
Arrays.stream(stringValue.split(",")).map(String::trim).toList();
+        }
+        throw new CamelExecutionException(
+                "Exchange variable '" + variableName + "' must be a 
List<String> or a comma-separated String, but was: "
+                                          + value.getClass().getName(),
+                exchange);
+    }
+
+    private List<String> resolveLabelIds(List<String> labelNames, Map<String, 
String> labelMap, Exchange exchange) {
+        List<String> ids = new ArrayList<>(labelNames.size());
+        for (String name : labelNames) {
+            String id = labelMap.get(name);
+            if (id == null) {
+                throw new CamelExecutionException(
+                        "Label '" + name + "' not found. Available labels: " + 
labelMap.keySet(), exchange);
+            }
+            ids.add(id);
+        }
+        return ids;
+    }
+
+    private Map<String, String> fetchLabelMap(String userId) throws Exception {
+        Gmail client = getGmailClient();
+        ListLabelsResponse response = 
client.users().labels().list(userId).execute();
+        Map<String, String> map = new HashMap<>();
+        if (response.getLabels() != null) {
+            for (Label label : response.getLabels()) {
+                map.put(label.getName(), label.getId());
+            }
+        }
+        return map;
+    }
+
+    private Gmail getGmailClient() {
+        GoogleMailComponent component = 
getCamelContext().getComponent("google-mail", GoogleMailComponent.class);
+        return component.getClient(component.getConfiguration());
+    }
+}
diff --git 
a/components/camel-google/camel-google-mail/src/test/java/org/apache/camel/component/google/mail/MockGoogleMailClientFactory.java
 
b/components/camel-google/camel-google-mail/src/test/java/org/apache/camel/component/google/mail/MockGoogleMailClientFactory.java
new file mode 100644
index 000000000000..123b868be9a4
--- /dev/null
+++ 
b/components/camel-google/camel-google-mail/src/test/java/org/apache/camel/component/google/mail/MockGoogleMailClientFactory.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.google.mail;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import com.google.api.client.auth.oauth2.Credential;
+import 
com.google.api.client.googleapis.testing.auth.oauth2.MockGoogleCredential;
+import com.google.api.client.http.HttpTransport;
+import com.google.api.client.http.LowLevelHttpRequest;
+import com.google.api.client.http.LowLevelHttpResponse;
+import com.google.api.client.json.JsonFactory;
+import com.google.api.client.json.gson.GsonFactory;
+import com.google.api.client.testing.http.MockHttpTransport;
+import com.google.api.client.testing.http.MockLowLevelHttpRequest;
+import com.google.api.client.testing.http.MockLowLevelHttpResponse;
+import com.google.api.services.gmail.Gmail;
+import org.apache.camel.CamelContext;
+
+public class MockGoogleMailClientFactory implements GoogleMailClientFactory {
+
+    public static final JsonFactory JSON_FACTORY = 
GsonFactory.getDefaultInstance();
+
+    private final HttpTransport transport;
+    private final List<String> requestUrls = new ArrayList<>();
+
+    public MockGoogleMailClientFactory(String jsonContent) {
+        transport = new MockHttpTransport() {
+            @Override
+            public LowLevelHttpRequest buildRequest(String method, String url) 
{
+                requestUrls.add(url);
+                return new MockLowLevelHttpRequest() {
+                    @Override
+                    public LowLevelHttpResponse execute() {
+                        MockLowLevelHttpResponse response = new 
MockLowLevelHttpResponse();
+                        response.setContentType("application/json");
+                        response.setContent(jsonContent);
+                        return response;
+                    }
+                };
+            }
+        };
+    }
+
+    public List<String> getRequestUrls() {
+        return requestUrls;
+    }
+
+    @Override
+    public Gmail makeClient(
+            String clientId, String clientSecret, Collection<String> scopes, 
String applicationName,
+            String refreshToken, String accessToken) {
+        return makeClient();
+    }
+
+    @Override
+    public Gmail makeClient(
+            CamelContext camelContext, String serviceAccountKey, 
Collection<String> scopes,
+            String applicationName, String delegate) {
+        return makeClient();
+    }
+
+    private Gmail makeClient() {
+        Credential credential = new MockGoogleCredential.Builder().build();
+        return new Gmail.Builder(transport, JSON_FACTORY, 
credential).setApplicationName("mock").build();
+    }
+}
diff --git 
a/components/camel-google/camel-google-mail/src/test/java/org/apache/camel/component/google/mail/transform/GoogleMailUpdateMessageLabelsDataTypeTransformerTest.java
 
b/components/camel-google/camel-google-mail/src/test/java/org/apache/camel/component/google/mail/transform/GoogleMailUpdateMessageLabelsDataTypeTransformerTest.java
new file mode 100644
index 000000000000..30f4a8463f69
--- /dev/null
+++ 
b/components/camel-google/camel-google-mail/src/test/java/org/apache/camel/component/google/mail/transform/GoogleMailUpdateMessageLabelsDataTypeTransformerTest.java
@@ -0,0 +1,273 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.google.mail.transform;
+
+import java.util.List;
+
+import com.google.api.services.gmail.model.ModifyMessageRequest;
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.google.mail.GoogleMailComponent;
+import org.apache.camel.component.google.mail.GoogleMailConfiguration;
+import org.apache.camel.component.google.mail.MockGoogleMailClientFactory;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.spi.DataType;
+import org.apache.camel.support.DefaultExchange;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+class GoogleMailUpdateMessageLabelsDataTypeTransformerTest extends 
CamelTestSupport {
+
+    private static final String LABELS_RESPONSE = """
+            {
+              "labels": [
+                {"id": "INBOX", "name": "INBOX"},
+                {"id": "UNREAD", "name": "UNREAD"},
+                {"id": "Label_789", "name": "Work"},
+                {"id": "Label_456", "name": "Another Label"}
+              ]
+            }
+            """;
+
+    private GoogleMailUpdateMessageLabelsDataTypeTransformer transformer;
+    private MockGoogleMailClientFactory mockClientFactory;
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        final CamelContext context = new DefaultCamelContext();
+
+        GoogleMailConfiguration configuration = new GoogleMailConfiguration();
+        configuration.setClientId("mock-client-id");
+        configuration.setClientSecret("mock-client-secret");
+        configuration.setApplicationName("mock");
+
+        mockClientFactory = new MockGoogleMailClientFactory(LABELS_RESPONSE);
+
+        final GoogleMailComponent component = new GoogleMailComponent(context);
+        component.setConfiguration(configuration);
+        component.setClientFactory(mockClientFactory);
+
+        context.addComponent("google-mail", component);
+
+        return context;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:input")
+                        .transformDataType("google-mail:update-message-labels")
+                        .to("mock:result");
+            }
+        };
+    }
+
+    @Override
+    protected void doPostSetup() {
+        transformer = new GoogleMailUpdateMessageLabelsDataTypeTransformer();
+        transformer.setCamelContext(context);
+    }
+
+    @Test
+    void testAddAndRemoveLabels() throws Exception {
+        Exchange exchange = new DefaultExchange(context);
+        exchange.setVariable("addLabels", List.of("Work"));
+        exchange.setVariable("removeLabels", List.of("INBOX"));
+
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        ModifyMessageRequest request = 
exchange.getMessage().getBody(ModifyMessageRequest.class);
+        assertNotNull(request);
+        assertEquals(List.of("Label_789"), request.getAddLabelIds());
+        assertEquals(List.of("INBOX"), request.getRemoveLabelIds());
+    }
+
+    @Test
+    void testCommaSeparatedString() throws Exception {
+        Exchange exchange = new DefaultExchange(context);
+        exchange.setVariable("addLabels", "Work,Another Label");
+        exchange.setVariable("removeLabels", "INBOX");
+
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        ModifyMessageRequest request = 
exchange.getMessage().getBody(ModifyMessageRequest.class);
+        assertNotNull(request);
+        assertEquals(List.of("Label_789", "Label_456"), 
request.getAddLabelIds());
+        assertEquals(List.of("INBOX"), request.getRemoveLabelIds());
+    }
+
+    @Test
+    void testOnlyAddLabels() throws Exception {
+        Exchange exchange = new DefaultExchange(context);
+        exchange.setVariable("addLabels", List.of("Work"));
+
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        ModifyMessageRequest request = 
exchange.getMessage().getBody(ModifyMessageRequest.class);
+        assertNotNull(request);
+        assertEquals(List.of("Label_789"), request.getAddLabelIds());
+        assertNull(request.getRemoveLabelIds());
+    }
+
+    @Test
+    void testOnlyRemoveLabels() throws Exception {
+        Exchange exchange = new DefaultExchange(context);
+        exchange.setVariable("removeLabels", List.of("INBOX"));
+
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        ModifyMessageRequest request = 
exchange.getMessage().getBody(ModifyMessageRequest.class);
+        assertNotNull(request);
+        assertNull(request.getAddLabelIds());
+        assertEquals(List.of("INBOX"), request.getRemoveLabelIds());
+    }
+
+    @Test
+    void testNoLabelsThrowsException() {
+        Exchange exchange = new DefaultExchange(context);
+
+        assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+    }
+
+    @Test
+    void testUnknownLabelThrowsException() {
+        Exchange exchange = new DefaultExchange(context);
+        exchange.setVariable("addLabels", List.of("NonExistentLabel"));
+
+        assertThrows(CamelExecutionException.class,
+                () -> transformer.transform(exchange.getMessage(), 
DataType.ANY, DataType.ANY));
+    }
+
+    @Test
+    void testExplicitUserId() throws Exception {
+        int urlCountBefore = mockClientFactory.getRequestUrls().size();
+
+        Exchange exchange = new DefaultExchange(context);
+        exchange.getMessage().setHeader("CamelGoogleMail.userId", 
"[email protected]");
+        exchange.setVariable("addLabels", List.of("Work"));
+
+        transformer.transform(exchange.getMessage(), DataType.ANY, 
DataType.ANY);
+
+        ModifyMessageRequest request = 
exchange.getMessage().getBody(ModifyMessageRequest.class);
+        assertNotNull(request);
+        assertEquals(List.of("Label_789"), request.getAddLabelIds());
+
+        // Verify the userId was forwarded to the Gmail API
+        List<String> newUrls = 
mockClientFactory.getRequestUrls().subList(urlCountBefore,
+                mockClientFactory.getRequestUrls().size());
+        assertTrue(newUrls.stream().anyMatch(url -> 
url.contains("/users/[email protected]/")),
+                "Expected Gmail API call with userId '[email protected]', but 
URLs were: " + newUrls);
+    }
+
+    @Test
+    void testTransformerName() {
+        assertEquals("google-mail:update-message-labels", 
transformer.getName());
+    }
+
+    // E2E tests via Camel route)
+
+    @Test
+    void testAddAndRemoveLabelsViaRoute() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.reset();
+        mock.expectedMessageCount(1);
+
+        template.send("direct:input", exchange -> {
+            exchange.setVariable("addLabels", List.of("Work"));
+            exchange.setVariable("removeLabels", List.of("INBOX"));
+        });
+
+        mock.assertIsSatisfied();
+
+        Exchange received = mock.getExchanges().get(0);
+        ModifyMessageRequest request = 
received.getMessage().getBody(ModifyMessageRequest.class);
+        assertNotNull(request);
+        assertEquals(List.of("Label_789"), request.getAddLabelIds());
+        assertEquals(List.of("INBOX"), request.getRemoveLabelIds());
+    }
+
+    @Test
+    void testCommaSeparatedLabelsViaRoute() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.reset();
+        mock.expectedMessageCount(1);
+
+        template.send("direct:input", exchange -> {
+            exchange.setVariable("addLabels", "Work,Another Label");
+            exchange.setVariable("removeLabels", "INBOX");
+        });
+
+        mock.assertIsSatisfied();
+
+        Exchange received = mock.getExchanges().get(0);
+        ModifyMessageRequest request = 
received.getMessage().getBody(ModifyMessageRequest.class);
+        assertNotNull(request);
+        assertEquals(List.of("Label_789", "Label_456"), 
request.getAddLabelIds());
+        assertEquals(List.of("INBOX"), request.getRemoveLabelIds());
+    }
+
+    @Test
+    void testOnlyAddLabelsViaRoute() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.reset();
+        mock.expectedMessageCount(1);
+
+        template.send("direct:input", exchange -> {
+            exchange.setVariable("addLabels", List.of("Work"));
+        });
+
+        mock.assertIsSatisfied();
+
+        Exchange received = mock.getExchanges().get(0);
+        ModifyMessageRequest request = 
received.getMessage().getBody(ModifyMessageRequest.class);
+        assertNotNull(request);
+        assertEquals(List.of("Label_789"), request.getAddLabelIds());
+    }
+
+    @Test
+    void testOnlyRemoveLabelsViaRoute() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.reset();
+        mock.expectedMessageCount(1);
+
+        template.send("direct:input", exchange -> {
+            exchange.setVariable("removeLabels", List.of("INBOX"));
+        });
+
+        mock.assertIsSatisfied();
+
+        Exchange received = mock.getExchanges().get(0);
+        ModifyMessageRequest request = 
received.getMessage().getBody(ModifyMessageRequest.class);
+        assertNotNull(request);
+        assertNull(request.getAddLabelIds());
+        assertEquals(List.of("INBOX"), request.getRemoveLabelIds());
+    }
+}

Reply via email to