You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2022/08/09 05:37:36 UTC

[isis] branch master updated: ISIS-3114: fixes IdStringifierForSerializable to handle all Serializables

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

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new c4410ff997 ISIS-3114: fixes IdStringifierForSerializable to handle all Serializables
c4410ff997 is described below

commit c4410ff997c4c5ee71197ef246f0fb0c8cb129d6
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Aug 9 07:37:28 2022 +0200

    ISIS-3114: fixes IdStringifierForSerializable to handle all
    Serializables
---
 .../IdStringifierForSerializable.java              | 42 +++++++++------------
 .../services/urlencoding/UrlEncodingService.java   | 40 ++++++++++++++++++++
 ...rlEncodingServiceUsingBaseEncodingAbstract.java | 44 ----------------------
 .../IdStringifierForSerializable_Test.java         | 43 +++++++++++----------
 .../runtimeservices/urlencoding/MementosTest.java  | 11 +++---
 .../urlencoding/UrlEncodingServiceTest.java        |  7 ++--
 6 files changed, 88 insertions(+), 99 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/bookmark/idstringifiers/IdStringifierForSerializable.java b/api/applib/src/main/java/org/apache/isis/applib/services/bookmark/idstringifiers/IdStringifierForSerializable.java
index db2c7357a7..03224ba2a2 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/bookmark/idstringifiers/IdStringifierForSerializable.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/bookmark/idstringifiers/IdStringifierForSerializable.java
@@ -31,7 +31,7 @@ import org.apache.isis.applib.services.bookmark.IdStringifier;
 import org.apache.isis.applib.services.urlencoding.UrlEncodingService;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.base._Strings;
-import org.apache.isis.commons.internal.memento._Mementos;
+import org.apache.isis.commons.internal.resources._Serializables;
 
 import lombok.NonNull;
 
@@ -40,54 +40,46 @@ import lombok.NonNull;
 public class IdStringifierForSerializable extends IdStringifier.Abstract<Serializable> {
 
     private final UrlEncodingService codec;
-    private final _Mementos.SerializingAdapter serializer;
 
     @Inject
     public IdStringifierForSerializable(
             final @NonNull UrlEncodingService codec) {
         super(Serializable.class);
         this.codec = codec;
-        this.serializer = new _Mementos.SerializingAdapter() {
-            @Override
-            public Serializable write(final Object value) {
-                return _Casts.uncheckedCast(value);
-            }
-
-            @Override
-            public <T> T read(final Class<T> cls, final Serializable value) {
-                return _Casts.uncheckedCast(value);
-            }
-        };
     }
 
     @Override
     public boolean handles(final @NonNull Class<?> candidateValueClass) {
-        return PredefinedSerializables.isPredefinedSerializable(candidateValueClass);
+        return Serializable.class.isAssignableFrom(candidateValueClass);
     }
 
     @Override
     public String enstring(final @NonNull Serializable id) {
-        return newMemento().put("id", id).asString();
+        // even though null case is guarded by lombok - keep null check for symmetry
+        return id != null
+                ? codec.encode(_Serializables.write(id))
+                : null;
     }
 
     @Override
     public Serializable destring(
             final @NonNull String stringified,
             final @NonNull Class<?> targetEntityClass) {
-        if (_Strings.isEmpty(stringified)) {
-            return null;
-        }
-        return _Casts.uncheckedCast(parseMemento(stringified).get("id", Object.class));
-    }
 
-    // -- HELPER
+        final Class<? extends Serializable> requiredClass =
+                _Casts.uncheckedCast(targetEntityClass);
 
-    private _Mementos.Memento newMemento() {
-        return _Mementos.create(codec, serializer);
+        return destringAs(stringified, requiredClass);
     }
 
-    private _Mementos.Memento parseMemento(final String input) {
-        return _Mementos.parse(codec, serializer, input);
+    // -- HELPER
+
+    public <T extends Serializable> T destringAs(
+            final @NonNull String stringified,
+            final @NonNull Class<T> requiredClass) {
+        return _Strings.isNotEmpty(stringified)
+                ? _Serializables.read(requiredClass, codec.decode(stringified))
+                : null;
     }
 
 }
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/urlencoding/UrlEncodingService.java b/api/applib/src/main/java/org/apache/isis/applib/services/urlencoding/UrlEncodingService.java
index af94c0570c..e4661efb0b 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/urlencoding/UrlEncodingService.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/urlencoding/UrlEncodingService.java
@@ -20,6 +20,7 @@ package org.apache.isis.applib.services.urlencoding;
 
 import java.nio.charset.StandardCharsets;
 
+import org.apache.isis.commons.internal.base._Bytes;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.memento._Mementos.EncoderDecoder;
 
@@ -64,4 +65,43 @@ public interface UrlEncodingService extends EncoderDecoder {
         return _Strings.ofBytes(decode(str), StandardCharsets.UTF_8);
     }
 
+    // -- FACTORIES
+
+    /**
+     * Uses base64 with compression.
+     */
+    public static UrlEncodingService forTesting() {
+        return new UrlEncodingService() {
+
+            @Override
+            public String encode(final byte[] bytes) {
+                return _Strings.ofBytes(_Bytes.asCompressedUrlBase64.apply(bytes), StandardCharsets.UTF_8);
+            }
+
+            @Override
+            public byte[] decode(final String str) {
+                return _Bytes.ofCompressedUrlBase64.apply(_Strings.toBytes(str, StandardCharsets.UTF_8));
+            }
+        };
+    }
+
+    /**
+     * Uses base64 without compression.
+     */
+    public static UrlEncodingService forTestingNoCompression() {
+        return new UrlEncodingService() {
+
+            @Override
+            public String encode(final byte[] bytes) {
+                return _Strings.ofBytes(_Bytes.asUrlBase64.apply(bytes), StandardCharsets.UTF_8);
+            }
+
+            @Override
+            public byte[] decode(final String str) {
+                return _Bytes.ofUrlBase64.apply(_Strings.toBytes(str, StandardCharsets.UTF_8));
+            }
+        };
+
+    }
+
 }
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/urlencoding/UrlEncodingServiceUsingBaseEncodingAbstract.java b/api/applib/src/main/java/org/apache/isis/applib/services/urlencoding/UrlEncodingServiceUsingBaseEncodingAbstract.java
deleted file mode 100644
index 3fe63fa522..0000000000
--- a/api/applib/src/main/java/org/apache/isis/applib/services/urlencoding/UrlEncodingServiceUsingBaseEncodingAbstract.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *  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.isis.applib.services.urlencoding;
-
-import java.nio.charset.StandardCharsets;
-
-import org.apache.isis.commons.internal.base._Bytes;
-import org.apache.isis.commons.internal.base._Strings;
-
-/**
- * Provided as a convenient base class for providing alternative
- * implementations of {@link UrlEncodingService}.
- *
- * @since 1.x {@index}
- */
-public abstract class UrlEncodingServiceUsingBaseEncodingAbstract implements UrlEncodingService {
-
-    @Override
-    public String encode(final byte[] bytes) {
-        return _Strings.ofBytes(_Bytes.asUrlBase64.apply(bytes), StandardCharsets.UTF_8);
-    }
-
-    @Override
-    public byte[] decode(final String str) {
-        return _Bytes.ofUrlBase64.apply(_Strings.toBytes(str, StandardCharsets.UTF_8));
-    }
-
-}
diff --git a/api/applib/src/test/java/org/apache/isis/applib/services/bookmark/IdStringifierForSerializable_Test.java b/api/applib/src/test/java/org/apache/isis/applib/services/bookmark/IdStringifierForSerializable_Test.java
index fd8af4ced3..9279df0f6c 100644
--- a/api/applib/src/test/java/org/apache/isis/applib/services/bookmark/IdStringifierForSerializable_Test.java
+++ b/api/applib/src/test/java/org/apache/isis/applib/services/bookmark/IdStringifierForSerializable_Test.java
@@ -21,7 +21,6 @@
 package org.apache.isis.applib.services.bookmark;
 
 import java.io.Serializable;
-import java.nio.charset.StandardCharsets;
 import java.util.stream.Stream;
 
 import org.junit.jupiter.params.ParameterizedTest;
@@ -32,45 +31,49 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 import org.apache.isis.applib.services.bookmark.idstringifiers.IdStringifierForSerializable;
 import org.apache.isis.applib.services.urlencoding.UrlEncodingService;
-import org.apache.isis.commons.internal.base._Bytes;
-import org.apache.isis.commons.internal.base._Strings;
 
+import lombok.Value;
 import lombok.val;
 
 class IdStringifierForSerializable_Test {
 
-    static final UrlEncodingService CODEC = new UrlEncodingService() {
-        @Override
-        public String encode(final byte[] bytes) {
-            return _Strings.ofBytes(_Bytes.asCompressedUrlBase64.apply(bytes), StandardCharsets.UTF_8);
-        }
+    private UrlEncodingService codec = UrlEncodingService.forTesting();
 
-        @Override
-        public byte[] decode(final String str) {
-            return _Bytes.ofCompressedUrlBase64.apply(_Strings.toBytes(str, StandardCharsets.UTF_8));
-        }
-    };
+    // -- SCENARIO
 
-    public static Stream<Arguments> roundtrip() {
+    @Value
+    static class CustomerPK implements Serializable{
+        private static final long serialVersionUID = 1L;
+        final int lower;
+        final int upper;
+    }
+
+    // -- TEST
+
+    static Stream<Arguments> roundtrip() {
         return Stream.of(
                 Arguments.of(Byte.MAX_VALUE),
                 Arguments.of(Byte.MIN_VALUE),
                 Arguments.of((byte)0),
                 Arguments.of((byte)12345),
-                Arguments.of((byte)-12345)
+                Arguments.of((byte)-12345),
+                Arguments.of(new CustomerPK(5,6))
+                // Arguments.of((Serializable)null) ... throws NPE as expected
         );
     }
 
-    static class Customer {}
-
     @ParameterizedTest
     @MethodSource()
-    void roundtrip(Serializable value) {
+    void roundtrip(final Serializable value) {
+
+        val idClass = value != null
+                ? value.getClass()
+                : void.class;
 
-        val stringifier = new IdStringifierForSerializable(CODEC);
+        val stringifier = new IdStringifierForSerializable(codec);
 
         String stringified = stringifier.enstring(value);
-        Serializable parse = stringifier.destring(stringified, Customer.class);
+        Serializable parse = stringifier.destring(stringified, idClass);
 
         assertThat(parse).isEqualTo(value);
     }
diff --git a/core/runtimeservices/src/test/java/org/apache/isis/core/runtimeservices/urlencoding/MementosTest.java b/core/runtimeservices/src/test/java/org/apache/isis/core/runtimeservices/urlencoding/MementosTest.java
index 9eead8dd53..f5c96e2d0e 100644
--- a/core/runtimeservices/src/test/java/org/apache/isis/core/runtimeservices/urlencoding/MementosTest.java
+++ b/core/runtimeservices/src/test/java/org/apache/isis/core/runtimeservices/urlencoding/MementosTest.java
@@ -33,7 +33,6 @@ import static org.hamcrest.MatcherAssert.assertThat;
 
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.urlencoding.UrlEncodingService;
-import org.apache.isis.applib.services.urlencoding.UrlEncodingServiceUsingBaseEncodingAbstract;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.memento._Mementos;
 import org.apache.isis.commons.internal.memento._Mementos.Memento;
@@ -46,23 +45,23 @@ class MementosTest {
     }
 
     UrlEncodingServiceWithCompression serviceWithCompression;
-    UrlEncodingServiceUsingBaseEncodingAbstract serviceBaseEncoding;
+    UrlEncodingService serviceBaseEncoding;
     SerializingAdapter serializingAdapter;
 
     @BeforeEach
     void setUp() throws Exception {
         serviceWithCompression = new UrlEncodingServiceWithCompression();
-        serviceBaseEncoding = new UrlEncodingServiceUsingBaseEncodingAbstract(){};
+        serviceBaseEncoding = UrlEncodingService.forTestingNoCompression();;
 
         serializingAdapter = new SerializingAdapter() {
 
             @Override
-            public Serializable write(Object value) {
+            public Serializable write(final Object value) {
                 return (Serializable) value;
             }
 
             @Override
-            public <T> T read(Class<T> cls, Serializable value) {
+            public <T> T read(final Class<T> cls, final Serializable value) {
                 return _Casts.castToOrElseNull(value, cls);
             }
         };
@@ -79,7 +78,7 @@ class MementosTest {
         roundtrip(serviceWithCompression);
     }
 
-    private void roundtrip(UrlEncodingService codec) {
+    private void roundtrip(final UrlEncodingService codec) {
         final Memento memento = _Mementos.create(codec, serializingAdapter);
 
         memento.put("someString", "a string");
diff --git a/core/runtimeservices/src/test/java/org/apache/isis/core/runtimeservices/urlencoding/UrlEncodingServiceTest.java b/core/runtimeservices/src/test/java/org/apache/isis/core/runtimeservices/urlencoding/UrlEncodingServiceTest.java
index 783da51115..76c6f1b99b 100644
--- a/core/runtimeservices/src/test/java/org/apache/isis/core/runtimeservices/urlencoding/UrlEncodingServiceTest.java
+++ b/core/runtimeservices/src/test/java/org/apache/isis/core/runtimeservices/urlencoding/UrlEncodingServiceTest.java
@@ -23,17 +23,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.apache.isis.applib.services.urlencoding.UrlEncodingService;
-import org.apache.isis.applib.services.urlencoding.UrlEncodingServiceUsingBaseEncodingAbstract;
 
 public class UrlEncodingServiceTest {
 
     UrlEncodingServiceWithCompression serviceWithCompression;
-    UrlEncodingServiceUsingBaseEncodingAbstract serviceBaseEncoding;
+    UrlEncodingService serviceBaseEncoding;
 
     @BeforeEach
     public void setUp() throws Exception {
         serviceWithCompression = new UrlEncodingServiceWithCompression();
-        serviceBaseEncoding = new UrlEncodingServiceUsingBaseEncodingAbstract(){};
+        serviceBaseEncoding = UrlEncodingService.forTestingNoCompression();
     }
 
     @Test
@@ -46,7 +45,7 @@ public class UrlEncodingServiceTest {
         roundtrip(serviceWithCompression, true);
     }
 
-    private void roundtrip(UrlEncodingService service, boolean testIsCompressing) throws Exception {
+    private void roundtrip(final UrlEncodingService service, final boolean testIsCompressing) throws Exception {
 
         final String original = "0-theme-entityPageContainer-entity-rows-2-rowContents-1-col-tabGroups-1-panel-tabPanel-rows-1-rowContents-1-col-fieldSets-1-memberGroup-properties-1-property-scalarTypeContainer-scalarIfRegular-associatedActionLinksBelow-additionalLinkList-additionalLinkItem-0-additionalLink";