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

davsclaus 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 8a18bdb0a6bd CAMEL-25359: camel-barcode - return the hint maps as 
read-only views (#27586)
8a18bdb0a6bd is described below

commit 8a18bdb0a6bd1c94d9fbe1be08cd9ae682be85f9
Author: allthingssecurity <[email protected]>
AuthorDate: Sat Oct 10 01:20:54 2026 +0530

    CAMEL-25359: camel-barcode - return the hint maps as read-only views 
(#27586)
    
    getWriterHintMap() and getReaderHintMap() returned the live hint maps, so a
    hint put into or removed from them was lost when the data format (re)started
    and recomputed its hints. They now return read-only live views, so such a
    change fails with UnsupportedOperationException instead of being lost, and
    addToHintMap/removeFromHintMap are documented as the way to change the 
hints.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../camel/catalog/docs/barcode-dataformat.adoc     |  8 ++-
 .../src/main/docs/barcode-dataformat.adoc          |  8 ++-
 .../dataformat/barcode/BarcodeDataFormat.java      | 22 ++++++--
 .../dataformat/barcode/BarcodeDataFormatTest.java  | 65 ++++++++++++++++++++++
 .../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc    |  6 ++
 5 files changed, 99 insertions(+), 10 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/barcode-dataformat.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/barcode-dataformat.adoc
index 0e6798e72d1a..5dd023395359 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/barcode-dataformat.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/barcode-dataformat.adoc
@@ -66,17 +66,19 @@ The default values are:
 DataFormat code = new BarcodeDataFormat();
 ----
 
-If you want to use zxing hints, you can use the 'addToHintMap' method of
+If you want to use ZXing hints, you can use the 'addToHintMap' method of
 your BarcodeDataFormat instance:
 
 ._Java-only: Java data format configuration API_
 [source,java]
 ----
-code.addToHintMap(DecodeHintType.TRY_HARDER, Boolean.true);
+code.addToHintMap(DecodeHintType.TRY_HARDER, Boolean.TRUE);
 ----
 
 The hints can be added before the data format is started (for example when the 
route is configured).
-For possible hints, please consult the xzing documentation.
+To remove a hint, such as a default one, use the 'removeFromHintMap' method.
+The maps returned by 'getWriterHintMap' and 'getReaderHintMap' are read-only.
+For possible hints, please consult the ZXing documentation.
 
 === Marshalling
 
diff --git a/components/camel-barcode/src/main/docs/barcode-dataformat.adoc 
b/components/camel-barcode/src/main/docs/barcode-dataformat.adoc
index 0e6798e72d1a..5dd023395359 100644
--- a/components/camel-barcode/src/main/docs/barcode-dataformat.adoc
+++ b/components/camel-barcode/src/main/docs/barcode-dataformat.adoc
@@ -66,17 +66,19 @@ The default values are:
 DataFormat code = new BarcodeDataFormat();
 ----
 
-If you want to use zxing hints, you can use the 'addToHintMap' method of
+If you want to use ZXing hints, you can use the 'addToHintMap' method of
 your BarcodeDataFormat instance:
 
 ._Java-only: Java data format configuration API_
 [source,java]
 ----
-code.addToHintMap(DecodeHintType.TRY_HARDER, Boolean.true);
+code.addToHintMap(DecodeHintType.TRY_HARDER, Boolean.TRUE);
 ----
 
 The hints can be added before the data format is started (for example when the 
route is configured).
-For possible hints, please consult the xzing documentation.
+To remove a hint, such as a default one, use the 'removeFromHintMap' method.
+The maps returned by 'getWriterHintMap' and 'getReaderHintMap' are read-only.
+For possible hints, please consult the ZXing documentation.
 
 === Marshalling
 
diff --git 
a/components/camel-barcode/src/main/java/org/apache/camel/dataformat/barcode/BarcodeDataFormat.java
 
b/components/camel-barcode/src/main/java/org/apache/camel/dataformat/barcode/BarcodeDataFormat.java
index 995cf47e6790..1ab95a87603f 100644
--- 
a/components/camel-barcode/src/main/java/org/apache/camel/dataformat/barcode/BarcodeDataFormat.java
+++ 
b/components/camel-barcode/src/main/java/org/apache/camel/dataformat/barcode/BarcodeDataFormat.java
@@ -19,6 +19,7 @@ package org.apache.camel.dataformat.barcode;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.charset.StandardCharsets;
+import java.util.Collections;
 import java.util.EnumMap;
 import java.util.EnumSet;
 import java.util.Map;
@@ -80,6 +81,13 @@ public class BarcodeDataFormat extends ServiceSupport 
implements DataFormat, Dat
      */
     private final Map<DecodeHintType, Object> readerHintMap = new 
EnumMap<>(DecodeHintType.class);
 
+    /**
+     * The read-only live views of the hint maps returned by the getters, 
created once so that every call returns the
+     * same instance.
+     */
+    private final Map<EncodeHintType, Object> writerHintMapView = 
Collections.unmodifiableMap(writerHintMap);
+    private final Map<DecodeHintType, Object> readerHintMapView = 
Collections.unmodifiableMap(readerHintMap);
+
     /**
      * The hints added by the user, which are applied on top of the optimized 
hints.
      */
@@ -313,17 +321,23 @@ public class BarcodeDataFormat extends ServiceSupport 
implements DataFormat, Dat
     }
 
     /**
-     * The writer (encode) hint map.
+     * The writer (encode) hint map, as a read-only live view: it shows the 
later changes made with
+     * {@link #addToHintMap(EncodeHintType, Object)} and {@link 
#removeFromHintMap(EncodeHintType)}, and the hints
+     * computed again when the data format starts or restarts. Use these 
methods to change it, as only the changes made
+     * with them are applied again when the hints are computed again.
      */
     public final Map<EncodeHintType, Object> getWriterHintMap() {
-        return writerHintMap;
+        return writerHintMapView;
     }
 
     /**
-     * The reader (decode) hint map.
+     * The reader (decode) hint map, as a read-only live view: it shows the 
later changes made with
+     * {@link #addToHintMap(DecodeHintType, Object)} and {@link 
#removeFromHintMap(DecodeHintType)}, and the hints
+     * computed again when the data format starts or restarts. Use these 
methods to change it, as only the changes made
+     * with them are applied again when the hints are computed again.
      */
     public final Map<DecodeHintType, Object> getReaderHintMap() {
-        return readerHintMap;
+        return readerHintMapView;
     }
 
     public BarcodeFormat getBarcodeFormat() {
diff --git 
a/components/camel-barcode/src/test/java/org/apache/camel/dataformat/barcode/BarcodeDataFormatTest.java
 
b/components/camel-barcode/src/test/java/org/apache/camel/dataformat/barcode/BarcodeDataFormatTest.java
index 870ac12961b8..e1b890a30ed7 100644
--- 
a/components/camel-barcode/src/test/java/org/apache/camel/dataformat/barcode/BarcodeDataFormatTest.java
+++ 
b/components/camel-barcode/src/test/java/org/apache/camel/dataformat/barcode/BarcodeDataFormatTest.java
@@ -22,11 +22,14 @@ import java.util.Map;
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.DecodeHintType;
 import com.google.zxing.EncodeHintType;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
@@ -229,6 +232,68 @@ public class BarcodeDataFormatTest {
         }
     }
 
+    /**
+     * A change made through the maps returned by the getters would bypass the 
hints tracked by
+     * {@code addToHintMap}/{@code removeFromHintMap}, and be lost when the 
data format starts again, so the maps are
+     * read-only.
+     */
+    @Test
+    final void testHintMapsAreReadOnly() throws IOException {
+        try (BarcodeDataFormat instance = new BarcodeDataFormat()) {
+            instance.start();
+            Map<EncodeHintType, Object> writerHints = 
instance.getWriterHintMap();
+            Map<DecodeHintType, Object> readerHints = 
instance.getReaderHintMap();
+
+            assertThrows(UnsupportedOperationException.class, () -> 
writerHints.put(EncodeHintType.MARGIN, 10));
+            assertThrows(UnsupportedOperationException.class, () -> 
writerHints.remove(EncodeHintType.ERROR_CORRECTION));
+            assertThrows(UnsupportedOperationException.class, 
writerHints::clear);
+            assertThrows(UnsupportedOperationException.class, () -> 
readerHints.put(DecodeHintType.PURE_BARCODE, true));
+            assertThrows(UnsupportedOperationException.class, () -> 
readerHints.remove(DecodeHintType.TRY_HARDER));
+            assertThrows(UnsupportedOperationException.class, 
readerHints::clear);
+
+            assertEquals(Map.of(EncodeHintType.ERROR_CORRECTION, 
ErrorCorrectionLevel.H), instance.getWriterHintMap());
+            assertEquals(Map.of(DecodeHintType.TRY_HARDER, Boolean.TRUE), 
instance.getReaderHintMap());
+        }
+    }
+
+    /**
+     * The maps returned by the getters are live views: a map obtained before 
a change shows it afterwards, including
+     * the hints computed again when the data format starts and restarts.
+     */
+    @Test
+    final void testHintMapsAreLiveViews() throws IOException {
+        try (BarcodeDataFormat instance = new BarcodeDataFormat()) {
+            Map<EncodeHintType, Object> writerHints = 
instance.getWriterHintMap();
+            Map<DecodeHintType, Object> readerHints = 
instance.getReaderHintMap();
+
+            instance.addToHintMap(EncodeHintType.MARGIN, 5);
+            instance.addToHintMap(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
+            assertEquals(Map.of(EncodeHintType.MARGIN, 5), writerHints);
+            assertEquals(Map.of(DecodeHintType.PURE_BARCODE, Boolean.TRUE), 
readerHints);
+
+            instance.start();
+            assertEquals(Map.of(EncodeHintType.ERROR_CORRECTION, 
ErrorCorrectionLevel.H, EncodeHintType.MARGIN, 5),
+                    writerHints);
+            assertEquals(Map.of(DecodeHintType.TRY_HARDER, Boolean.TRUE, 
DecodeHintType.PURE_BARCODE, Boolean.TRUE),
+                    readerHints);
+
+            instance.removeFromHintMap(EncodeHintType.ERROR_CORRECTION);
+            instance.removeFromHintMap(DecodeHintType.TRY_HARDER);
+            assertEquals(Map.of(EncodeHintType.MARGIN, 5), writerHints);
+            assertEquals(Map.of(DecodeHintType.PURE_BARCODE, Boolean.TRUE), 
readerHints);
+
+            instance.stop();
+            instance.addToHintMap(EncodeHintType.MARGIN, 7);
+            instance.start();
+            assertEquals(Map.of(EncodeHintType.MARGIN, 7), writerHints);
+            assertEquals(Map.of(DecodeHintType.PURE_BARCODE, Boolean.TRUE), 
readerHints);
+
+            // every call returns the same view
+            assertSame(writerHints, instance.getWriterHintMap());
+            assertSame(readerHints, instance.getReaderHintMap());
+        }
+    }
+
     /**
      * Helper to check the saved parameters.
      */
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index 6cb1f2aad4a6..5fc3dada618f 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -960,6 +960,12 @@ instead of the `?` characters, so it must decode them as 
UTF-8. Text that ISO-88
 before, byte for byte, and a `CHARACTER_SET` hint takes precedence. The 
documented default encoding is now
 "ISO-8859-1, or UTF-8 when needed" instead of "UTF-8".
 
+=== camel-barcode - the hint maps are read-only (Breaking change)
+
+The maps returned by `BarcodeDataFormat.getWriterHintMap()` and 
`getReaderHintMap()` are now read-only views, so
+changing them throws an `UnsupportedOperationException`. Such changes were 
lost when the data format started (again),
+since the hints are computed at start. Use `addToHintMap` and 
`removeFromHintMap` instead.
+
 === camel-bindy - fixed-length records with characters outside the BMP
 
 Since Camel 3.1 a fixed-length record is read by counting code points (or 
graphemes with

Reply via email to