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 2021/09/18 04:56:56 UTC

[isis] branch master updated: ISIS-2871: Spring managed value semantics for BufferedImage

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 9db222a  ISIS-2871: Spring managed value semantics for BufferedImage
9db222a is described below

commit 9db222ab25a0ac6e06e0e2a2c85c9f4fd5cf4303
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sat Sep 18 06:56:44 2021 +0200

    ISIS-2871: Spring managed value semantics for BufferedImage
---
 .../core/metamodel/IsisModuleCoreMetamodel.java    |   2 +
 .../isis/core/metamodel/facetapi/FacetHolder.java  |  26 ++-
 .../facets/object/value/ValueFacetSimple.java      |   4 +-
 .../vsp/ValueFacetUsingSemanticsProvider.java      |   6 +-
 .../ValueFacetUsingSemanticsProviderFactory.java   |  14 +-
 ...ageValueFacet.java => ImageValueSemantics.java} |   3 +-
 .../image/ImageValueSemanticsProviderAbstract.java | 230 ---------------------
 ...vider.java => BufferedImageValueSemantics.java} |  55 ++---
 ...ageValueFacetUsingSemanticsProviderFactory.java |  48 -----
 .../JodaLocalTimeValueFacetSimpleFactory.java      |   2 +-
 .../dflt/ProgrammingModelFacetsJava11.java         |   3 -
 .../scalars/image/JavaAwtImagePanelFactory.java    |   5 +-
 .../components/scalars/image/WicketImageUtil.java  |  36 ++--
 13 files changed, 98 insertions(+), 336 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/IsisModuleCoreMetamodel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/IsisModuleCoreMetamodel.java
index b4420db..69f75e4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/IsisModuleCoreMetamodel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/IsisModuleCoreMetamodel.java
@@ -31,6 +31,7 @@ import org.apache.isis.core.metamodel.facets.value.bigdecimal.BigDecimalValueSem
 import org.apache.isis.core.metamodel.facets.value.blobs.BlobValueSemantics;
 import org.apache.isis.core.metamodel.facets.value.booleans.BooleanValueSemantics;
 import org.apache.isis.core.metamodel.facets.value.clobs.ClobValueSemantics;
+import org.apache.isis.core.metamodel.facets.value.imageawt.BufferedImageValueSemantics;
 import org.apache.isis.core.metamodel.facets.value.localrespath.LocalResourcePathValueSemantics;
 import org.apache.isis.core.metamodel.facets.value.markup.MarkupValueSemantics;
 import org.apache.isis.core.metamodel.facets.value.password.PasswordValueSemantics;
@@ -94,6 +95,7 @@ import org.apache.isis.core.security.IsisModuleCoreSecurity;
         BigDecimalValueSemantics.class,
         StringValueSemantics.class,
         PasswordValueSemantics.class,
+        BufferedImageValueSemantics.class,
         BlobValueSemantics.class,
         ClobValueSemantics.class,
         MarkupValueSemantics.class,
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetHolder.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetHolder.java
index ed90e3d..ffd1e7b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetHolder.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetHolder.java
@@ -23,7 +23,10 @@ import java.util.function.Predicate;
 import java.util.stream.Stream;
 
 import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.adapters.ValueSemanticsProvider;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.core.metamodel.context.HasMetaModelContext;
+import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
 
 import lombok.NonNull;
 import lombok.val;
@@ -47,7 +50,7 @@ public interface FacetHolder extends HasMetaModelContext {
      */
     <T extends Facet> T getFacet(Class<T> facetType);
 
-    // -- LOOKUP
+    // -- FACET LOOKUP
 
     default <T extends Facet> Optional<T> lookupFacet(
             final @NonNull Class<T> facetType) {
@@ -65,6 +68,27 @@ public interface FacetHolder extends HasMetaModelContext {
         return lookupFacet(facetType, facet->!facet.getPrecedence().isFallback());
     }
 
+    // -- VALUE SEMANTICS LOOKUP
+
+    //TODO support qualified selection honoring (@Qualifier) ... all the logic is in ValueFacet
+    default boolean hasValueSemantics(
+            final @NonNull Class<?> requiredType) {
+        return lookupFacet(ValueFacet.class).stream()
+        .map(ValueFacet::getValueSemantics)
+        .flatMap(Can<ValueSemanticsProvider<?>>::stream)
+        .anyMatch(valueSemantics->requiredType.isAssignableFrom(valueSemantics.getClass()));
+    }
+
+    //TODO support qualified selection honoring (@Qualifier) ... all the logic is in ValueFacet
+    default <T> Stream<T> streamValueSemantics(
+            final @NonNull Class<T> requiredType) {
+        return lookupFacet(ValueFacet.class).stream()
+        .map(ValueFacet::getValueSemantics)
+        .flatMap(Can<ValueSemanticsProvider<?>>::stream)
+        .filter(valueSemantics->requiredType.isAssignableFrom(valueSemantics.getClass()))
+        .map(requiredType::cast);
+    }
+
     // -- CONTAINS
 
     /**
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/ValueFacetSimple.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/ValueFacetSimple.java
index 39bfcdc..83b57f4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/ValueFacetSimple.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/ValueFacetSimple.java
@@ -21,8 +21,8 @@ package org.apache.isis.core.metamodel.facets.object.value;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 
-public class ValueFacetSimple
-extends ValueFacetAbstract {
+public class ValueFacetSimple<T>
+extends ValueFacetAbstract<T> {
 
     public ValueFacetSimple(final FacetHolder holder) {
         super(Can.empty(), holder, Precedence.LOW);
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueFacetUsingSemanticsProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueFacetUsingSemanticsProvider.java
index eaf4d84..b716341 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueFacetUsingSemanticsProvider.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueFacetUsingSemanticsProvider.java
@@ -23,11 +23,11 @@ import org.apache.isis.commons.collections.Can;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.object.value.ValueFacetAbstract;
 
-public class ValueFacetUsingSemanticsProvider
-extends ValueFacetAbstract {
+public class ValueFacetUsingSemanticsProvider<T>
+extends ValueFacetAbstract<T> {
 
     public ValueFacetUsingSemanticsProvider(
-            final Can<ValueSemanticsProvider<?>> valueSemantics,
+            final Can<ValueSemanticsProvider<T>> valueSemantics,
             final FacetHolder holder) {
 
         super(valueSemantics, holder, Precedence.DEFAULT);
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueFacetUsingSemanticsProviderFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueFacetUsingSemanticsProviderFactory.java
index 4e43b58..b54d182 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueFacetUsingSemanticsProviderFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueFacetUsingSemanticsProviderFactory.java
@@ -21,7 +21,6 @@ package org.apache.isis.core.metamodel.facets.object.value.vsp;
 import org.apache.isis.applib.adapters.DefaultsProvider;
 import org.apache.isis.applib.adapters.EncoderDecoder;
 import org.apache.isis.applib.adapters.Parser;
-import org.apache.isis.applib.adapters.Renderer;
 import org.apache.isis.applib.adapters.ValueSemanticsProvider;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
@@ -54,18 +53,18 @@ extends FacetFactoryAbstract {
     }
 
     protected final void addAllFacetsForValueSemantics(
-            final Can<ValueSemanticsProvider<?>> valueSemantics,
+            final Can<ValueSemanticsProvider<T>> valueSemantics,
             final FacetHolder holder) {
 
-        val valueFacet = new ValueFacetUsingSemanticsProvider(valueSemantics, holder);
+        val valueFacet = new ValueFacetUsingSemanticsProvider<>(valueSemantics, holder);
         installRelatedFacets(valueFacet, valueSemantics, holder);
     }
 
     // -- HELPER
 
     private void installRelatedFacets(
-            final ValueFacet<?> valueFacet,
-            final Can<ValueSemanticsProvider<?>> semanticsProviders,
+            final ValueFacet<T> valueFacet,
+            final Can<ValueSemanticsProvider<T>> semanticsProviders,
             final FacetHolder holder) {
 
         FacetUtil.addFacet(valueFacet);
@@ -80,6 +79,7 @@ extends FacetFactoryAbstract {
             final EncoderDecoder<?> encoderDecoder = semanticsProvider.getEncoderDecoder();
             if (encoderDecoder != null) {
                 //getServiceInjector().injectServicesInto(encoderDecoder);
+                //FIXME convert to using value-facet
                 holder.addFacet(new EncodableFacetUsingEncoderDecoder(encoderDecoder, holder));
             }
 
@@ -89,10 +89,11 @@ extends FacetFactoryAbstract {
             if (parser != null) {
 
                 //holder.getServiceInjector().injectServicesInto(parser);
-
+               //FIXME convert to using value-facet
                 holder.addFacet(new TypicalLengthFacetUsingParser(parser, holder));
                 final int maxLength = parser.maxLength();
                 if(maxLength >=0) {
+                   //FIXME convert to using value-facet
                     holder.addFacet(new MaxLengthFacetUsingParser(parser, holder));
                 }
             }
@@ -101,6 +102,7 @@ extends FacetFactoryAbstract {
             final DefaultsProvider<?> defaultsProvider = semanticsProvider.getDefaultsProvider();
             if (defaultsProvider != null) {
                 //holder.getServiceInjector().injectServicesInto(defaultsProvider);
+                //FIXME convert to using value-facet
                 holder.addFacet(new DefaultedFacetUsingDefaultsProvider(defaultsProvider, holder));
             }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/image/ImageValueFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/image/ImageValueSemantics.java
similarity index 92%
rename from core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/image/ImageValueFacet.java
rename to core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/image/ImageValueSemantics.java
index 3ac262b..e93eb24 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/image/ImageValueFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/image/ImageValueSemantics.java
@@ -21,10 +21,9 @@ package org.apache.isis.core.metamodel.facets.value.image;
 import java.awt.image.BufferedImage;
 import java.util.Optional;
 
-import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 
-public interface ImageValueFacet extends Facet {
+public interface ImageValueSemantics {
 
     int getHeight(ManagedObject object);
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/image/ImageValueSemanticsProviderAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/image/ImageValueSemanticsProviderAbstract.java
deleted file mode 100644
index 292968d..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/image/ImageValueSemanticsProviderAbstract.java
+++ /dev/null
@@ -1,230 +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.core.metamodel.facets.value.image;
-
-import org.apache.isis.applib.adapters.Parser;
-import org.apache.isis.applib.adapters.ValueSemanticsProvider;
-import org.apache.isis.applib.exceptions.unrecoverable.UnexpectedCallException;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.object.value.vsp.ValueSemanticsProviderAndFacetAbstract;
-
-public abstract class ImageValueSemanticsProviderAbstract<T>
-extends ValueSemanticsProviderAndFacetAbstract<T>
-implements ImageValueFacet {
-
-    private static final int TYPICAL_LENGTH = 18;
-    private static final Object DEFAULT_VALUE = null; // no default
-
-    @SuppressWarnings("unchecked")
-    public ImageValueSemanticsProviderAbstract(final FacetHolder holder, final Class<T> adaptedClass) {
-        super(ImageValueFacet.class, holder, adaptedClass, TYPICAL_LENGTH, -1, Immutability.NOT_IMMUTABLE, EqualByContent.NOT_HONOURED, (T) DEFAULT_VALUE);
-    }
-
-    /**
-     * Returns null to indicate that this value does not parse entry strings
-     */
-    @Override
-    public Parser<T> getParser() {
-        return null;
-    }
-
-    @Override
-    protected T doParse(final ValueSemanticsProvider.Context context, final String entry) {
-        throw new UnexpectedCallException();
-    }
-
-    @Override
-    public String asTitleString(final T value) {
-        return "image";
-    }
-
-    // -- DEPRECATED
-
-    //  protected abstract T setPixels(int[][] pixels);
-    //  public void setMask(final String mask) {}
-    //  public String getIconName() {return null;}
-
-//    @Override
-//    protected String doEncode(final Object object) {
-//        final int[][] image = getPixels(object);
-//        final int lines = image.length;
-//        final int width = image[0].length;
-//        final StringBuffer encodeData = new StringBuffer(lines * width * 4);
-//        encodePixel(lines, encodeData);
-//        encodePixel(width, encodeData);
-//        for (int line = 0; line < lines; line++) {
-//            for (int pixel = 0; pixel < width; pixel++) {
-//                encodePixel(image[line][pixel], encodeData);
-//            }
-//        }
-//        return encodeData.toString();
-//    }
-
-
-//    @Override
-//    public T doRestore(final String data) {
-//        final int lines = decodePixel(data, 0);
-//        final int width = decodePixel(data, 1);
-//        final int[][] imageData = new int[lines][width];
-//        int offset = 2;
-//        for (int line = 0; line < lines; line++) {
-//            for (int pixel = 0; pixel < width; pixel++) {
-//                imageData[line][pixel] = decodePixel(data, offset++);
-//                imageData[line][pixel] = imageData[line][pixel] | 0xFF000000;
-//            }
-//        }
-//        final T image = setPixels(imageData);
-//        return image;
-//    }
-
-
-//  public T restoreFromByteArray(final byte[] byteArray) {
-//  final int[] flatIntArray = new int[byteArray.length / 4];
-//  for (int i = 0; i < flatIntArray.length; i++) {
-//      flatIntArray[i] = byteArrayToInt(byteArray, i * 4);
-//  }
-//  return setPixels(inflate(flatIntArray));
-//}
-//
-//private int[] flatten(final ManagedObject object) {
-//  final int[][] image = getPixels(object);
-//  final int[] flatArray = new int[(getHeight(object) * getWidth(object)) + 2];
-//  int flatIndex = 0;
-//  flatArray[flatIndex++] = getHeight(object);
-//  flatArray[flatIndex++] = getWidth(object);
-//  for (int i = 0; i < getHeight(object); i++) {
-//      for (int j = 0; j < getWidth(object); j++) {
-//          flatArray[flatIndex++] = image[i][j];
-//      }
-//  }
-//  return flatArray;
-//}
-//
-//private static int[][] inflate(final int[] flatIntArray) {
-//  int flatIndex = 0;
-//  final int height = flatIntArray[flatIndex++];
-//  final int width = flatIntArray[flatIndex++];
-//
-//  final int[][] newImage = new int[height][width];
-//
-//  for (int i = 0; i < height; i++) {
-//      for (int j = 0; j < width; j++) {
-//          newImage[i][j] = flatIntArray[flatIndex++];
-//      }
-//  }
-//  return newImage;
-//}
-
-//  protected BufferedImage createImage(final int[][] pixels) {
-//  final int lines = pixels.length;
-//  final int width = pixels[0].length;
-//  final int[] pix = new int[lines * width];
-//  int offset = 0;
-//  for (int line = 0; line < lines; line++) {
-//      System.arraycopy(pixels[line], 0, pix, offset, width);
-//      offset += width;
-//  }
-//  final MemoryImageSource source = new MemoryImageSource(width, lines, pix, 0, width);
-//  return java.awt.Toolkit.getDefaultToolkit().createImage(source);
-//}
-//
-//private int decodePixel(final String data, final int item) {
-//  final int offset = item * 4;
-//  int pixel = 0;
-//  for (int i = 0; i < 4; i++) {
-//      final char c = data.charAt(offset + i);
-//      final int b = (REVERSE_BASE_64_CHARS[c] & 0xff);
-//      if (i == 0 && b >= 32) {
-//          pixel = 0xff;
-//      }
-//      pixel = (pixel << 6) + b;
-//  }
-//  return pixel;
-//}
-
-//  public byte[] getAsByteArray(final ManagedObject object) {
-//  final int[] flatIntArray = flatten(object);
-//  final byte[] byteArray = new byte[flatIntArray.length * 4];
-//  for (int i = 0; i < flatIntArray.length; i++) {
-//      final int value = flatIntArray[i];
-//      byteArray[i * 4] = (byte) ((value >> 24) & 0xff);
-//      byteArray[i * 4 + 1] = (byte) ((value >> 16) & 0xff);
-//      byteArray[i * 4 + 2] = (byte) ((value >> 8) & 0xff);
-//      byteArray[i * 4 + 3] = (byte) (value & 0xff);
-//  }
-//  return byteArray;
-//}
-//
-//private static int byteArrayToInt(final byte[] byteArray, final int offset) {
-//  int value = 0;
-//  for (int i = 0; i < 4; i++) {
-//      final int shift = (4 - 1 - i) * 8;
-//      value += (byteArray[i + offset] & 0x000000FF) << shift;
-//  }
-//  return value;
-//}
-
-//  protected abstract int[][] getPixels(Object object);
-//
-//  protected int[][] grabPixels(final Image image) {
-//      final int width = image.getWidth(null);
-//      final int lines = image.getHeight(null);
-//      final int pixels[] = new int[width * lines];
-//      final PixelGrabber grabber = new PixelGrabber(image, 0, 0, width, lines, pixels, 0, width);
-//      grabber.setColorModel(ColorModel.getRGBdefault());
-//      try {
-//          if (grabber.grabPixels() && (grabber.status() & ImageObserver.ALLBITS) != 0) {
-//              final int[][] array = new int[lines][width];
-//              int srcPos = 0;
-//              for (int line = 0; line < lines; line++) {
-//                  array[line] = new int[width];
-//                  System.arraycopy(pixels, srcPos, array[line], 0, width);
-//                  for (int pixel = 0; pixel < array[line].length; pixel++) {
-//                      array[line][pixel] = array[line][pixel] | 0xFF000000;
-//                  }
-//                  srcPos += width;
-//              }
-//              return array;
-//          }
-//          // TODO what happens if the grab fails?
-//          return new int[lines][width];
-//      } catch (final InterruptedException e) {
-//          // Restore interrupted state...
-//          Thread.currentThread().interrupt();
-//          throw new IsisException(e);
-//      }
-//  }
-
-//  private void encodePixel(final int pixel, final StringBuffer encodeData) {
-//  // TODO the encoding is poor as the negative numbers are not dealt with
-//  // properly because the 6 MSBs
-//  // are not included.
-//  if (pixel > 0x7FFFFF || pixel < -0x7FFFFF) {
-//      // throw new IsisException("" + pixel);
-//  }
-//  for (int i = 3; i >= 0; i--) {
-//      final int bitsToShift = i * 6;
-//      final int c = pixel >> bitsToShift;
-//      final char cc = BASE_64_CHARS[c & 0x3F];
-//      encodeData.append(cc);
-//  }
-//}
-
-
-}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/imageawt/JavaAwtImageValueSemanticsProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/imageawt/BufferedImageValueSemantics.java
similarity index 83%
rename from core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/imageawt/JavaAwtImageValueSemanticsProvider.java
rename to core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/imageawt/BufferedImageValueSemantics.java
index 669b08f..04b165e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/imageawt/JavaAwtImageValueSemanticsProvider.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/imageawt/BufferedImageValueSemantics.java
@@ -21,38 +21,30 @@ package org.apache.isis.core.metamodel.facets.value.imageawt;
 import java.awt.image.BufferedImage;
 import java.util.Optional;
 
+import javax.inject.Named;
+
 import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Component;
 
+import org.apache.isis.applib.adapters.AbstractValueSemanticsProvider;
+import org.apache.isis.applib.adapters.EncoderDecoder;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.image._Images;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.value.image.ImageValueSemanticsProviderAbstract;
+import org.apache.isis.core.metamodel.facets.value.image.ImageValueSemantics;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
 
-public class JavaAwtImageValueSemanticsProvider
-extends ImageValueSemanticsProviderAbstract<BufferedImage> {
+@Component
+@Named("isis.val.BufferedImageValueSemantics")
+public class BufferedImageValueSemantics
+extends AbstractValueSemanticsProvider<BufferedImage>
+implements
+    ImageValueSemantics,
+    EncoderDecoder<BufferedImage> {
 
-    public JavaAwtImageValueSemanticsProvider(final FacetHolder holder) {
-        super(holder, BufferedImage.class);
-    }
+    // -- ENCODER DECODER
 
     @Override
-    public int getWidth(final @Nullable ManagedObject object) {
-        return unwrap(object).map(BufferedImage::getWidth).orElse(0);
-    }
-
-    @Override
-    public int getHeight(final @Nullable ManagedObject object) {
-        return unwrap(object).map(BufferedImage::getHeight).orElse(0);
-    }
-
-    @Override
-    public Optional<BufferedImage> getImage(final @Nullable ManagedObject object) {
-        return unwrap(object);
-    }
-
-    @Override @Nullable
     public String toEncodedString(final @Nullable BufferedImage image) {
         if(image==null) {
             return null;
@@ -60,7 +52,7 @@ extends ImageValueSemanticsProviderAbstract<BufferedImage> {
         return _Images.toBase64(image);
     }
 
-    @Override @Nullable
+    @Override
     public BufferedImage fromEncodedString(final @Nullable String base64ImageData) {
         if(_Strings.isNullOrEmpty(base64ImageData)) {
             return null;
@@ -70,6 +62,23 @@ extends ImageValueSemanticsProviderAbstract<BufferedImage> {
         /*sonar-ignore-off*/
     }
 
+    // -- FACET
+
+    @Override
+    public int getWidth(final @Nullable ManagedObject object) {
+        return unwrap(object).map(BufferedImage::getWidth).orElse(0);
+    }
+
+    @Override
+    public int getHeight(final @Nullable ManagedObject object) {
+        return unwrap(object).map(BufferedImage::getHeight).orElse(0);
+    }
+
+    @Override
+    public Optional<BufferedImage> getImage(final @Nullable ManagedObject object) {
+        return unwrap(object);
+    }
+
     // -- HELPER
 
     private Optional<BufferedImage> unwrap(final @Nullable ManagedObject adapter) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/imageawt/JavaAwtImageValueFacetUsingSemanticsProviderFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/imageawt/JavaAwtImageValueFacetUsingSemanticsProviderFactory.java
deleted file mode 100644
index bf9a055..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/imageawt/JavaAwtImageValueFacetUsingSemanticsProviderFactory.java
+++ /dev/null
@@ -1,48 +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.core.metamodel.facets.value.imageawt;
-
-import java.awt.image.BufferedImage;
-
-import javax.inject.Inject;
-
-import org.apache.isis.core.metamodel.context.MetaModelContext;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.object.value.vsp.ValueFacetUsingSemanticsProviderFactory;
-
-public class JavaAwtImageValueFacetUsingSemanticsProviderFactory
-extends ValueFacetUsingSemanticsProviderFactory<BufferedImage> {
-
-    @Inject
-    public JavaAwtImageValueFacetUsingSemanticsProviderFactory(final MetaModelContext mmc) {
-        super(mmc);
-    }
-
-    @Override
-    public void process(final ProcessClassContext processClassContext) {
-        final Class<?> type = processClassContext.getCls();
-        final FacetHolder holder = processClassContext.getFacetHolder();
-
-        if (!BufferedImage.class.isAssignableFrom(type)) {
-            return;
-        }
-        addValueFacet(new JavaAwtImageValueSemanticsProvider(holder));
-    }
-
-}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/timejodalocal/JodaLocalTimeValueFacetSimpleFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/timejodalocal/JodaLocalTimeValueFacetSimpleFactory.java
index 0c38c23..3f2836b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/timejodalocal/JodaLocalTimeValueFacetSimpleFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/timejodalocal/JodaLocalTimeValueFacetSimpleFactory.java
@@ -47,7 +47,7 @@ extends ValueFacetUsingSemanticsProviderFactory<LocalDate> {
 
         val facetHolder = processClassContext.getFacetHolder();
         addFacet(
-                new ValueFacetSimple(facetHolder));
+                new ValueFacetSimple<LocalDate>(facetHolder));
     }
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava11.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava11.java
index e55ad99..5f3e75d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava11.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava11.java
@@ -97,7 +97,6 @@ import org.apache.isis.core.metamodel.facets.value.doubles.DoublePrimitiveValueF
 import org.apache.isis.core.metamodel.facets.value.doubles.DoubleWrapperValueFacetUsingSemanticsProviderFactory;
 import org.apache.isis.core.metamodel.facets.value.floats.FloatPrimitiveValueFacetUsingSemanticsProviderFactory;
 import org.apache.isis.core.metamodel.facets.value.floats.FloatWrapperValueFacetUsingSemanticsProviderFactory;
-import org.apache.isis.core.metamodel.facets.value.imageawt.JavaAwtImageValueFacetUsingSemanticsProviderFactory;
 import org.apache.isis.core.metamodel.facets.value.integer.IntPrimitiveValueFacetUsingSemanticsProviderFactory;
 import org.apache.isis.core.metamodel.facets.value.integer.IntWrapperValueFacetUsingSemanticsProviderFactory;
 import org.apache.isis.core.metamodel.facets.value.longs.LongPrimitiveValueFacetUsingSemanticsProviderFactory;
@@ -283,8 +282,6 @@ extends ProgrammingModelAbstract {
         addFactory(FacetProcessingOrder.G1_VALUE_TYPES, new JavaSqlTimeStampValueFacetUsingSemanticsProviderFactory(mmc));
         addFactory(FacetProcessingOrder.G1_VALUE_TYPES, new JavaUtilDateValueFacetUsingSemanticsProviderFactory(mmc));
 
-        addFactory(FacetProcessingOrder.G1_VALUE_TYPES, new JavaAwtImageValueFacetUsingSemanticsProviderFactory(mmc));
-
         // jodatime values
         addFactory(FacetProcessingOrder.G1_VALUE_TYPES, new JodaLocalDateValueFacetUsingSemanticsProviderFactory(mmc));
         addFactory(FacetProcessingOrder.G1_VALUE_TYPES, new JodaLocalDateTimeValueFacetUsingSemanticsProviderFactory(mmc));
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/image/JavaAwtImagePanelFactory.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/image/JavaAwtImagePanelFactory.java
index 427a5d8..84b3863 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/image/JavaAwtImagePanelFactory.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/image/JavaAwtImagePanelFactory.java
@@ -21,7 +21,7 @@ package org.apache.isis.viewer.wicket.ui.components.scalars.image;
 import org.apache.wicket.Component;
 import org.apache.wicket.model.IModel;
 
-import org.apache.isis.core.metamodel.facets.value.image.ImageValueFacet;
+import org.apache.isis.core.metamodel.facets.value.image.ImageValueSemantics;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.viewer.common.model.components.ComponentType;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
@@ -42,7 +42,8 @@ public class JavaAwtImagePanelFactory extends ComponentFactoryAbstract {
         }
         final ScalarModel scalarModel = (ScalarModel) model;
         final ObjectSpecification specification = scalarModel.getTypeOfSpecification();
-        return appliesIf(specification != null && specification.containsFacet(ImageValueFacet.class));
+        return appliesIf(specification != null
+                && specification.hasValueSemantics(ImageValueSemantics.class));
     }
 
     @Override
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/image/WicketImageUtil.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/image/WicketImageUtil.java
index 07412b4..cbe4779 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/image/WicketImageUtil.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/image/WicketImageUtil.java
@@ -21,20 +21,20 @@ package org.apache.isis.viewer.wicket.ui.components.scalars.image;
 import java.awt.image.BufferedImage;
 import java.util.Optional;
 
-import org.springframework.lang.Nullable;
-
 import org.apache.wicket.extensions.markup.html.image.resource.ThumbnailImageResource;
 import org.apache.wicket.markup.html.image.Image;
 import org.apache.wicket.markup.html.image.NonCachingImage;
 import org.apache.wicket.markup.html.image.resource.BufferedDynamicImageResource;
+import org.springframework.lang.Nullable;
 
 import org.apache.isis.applib.value.Blob;
-import org.apache.isis.core.metamodel.facets.value.image.ImageValueFacet;
+import org.apache.isis.commons.internal.base._NullSafe;
+import org.apache.isis.core.metamodel.facets.value.image.ImageValueSemantics;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 
 import lombok.NonNull;
-import lombok.val;
 import lombok.experimental.UtilityClass;
 
 @UtilityClass
@@ -48,12 +48,12 @@ public class WicketImageUtil {
             return Optional.empty();
         }
 
-        val imageResource = new BufferedDynamicImageResource();
+        final var imageResource = new BufferedDynamicImageResource();
         imageResource.setImage(buffImg);
 
-        val thumbnailImageResource = new ThumbnailImageResource(imageResource, 300);
+        final var thumbnailImageResource = new ThumbnailImageResource(imageResource, 300);
 
-        val wicketImage = new NonCachingImage(id, thumbnailImageResource);
+        final var wicketImage = new NonCachingImage(id, thumbnailImageResource);
         wicketImage.setOutputMarkupId(true);
 
         return Optional.of(wicketImage);
@@ -65,26 +65,32 @@ public class WicketImageUtil {
             final @NonNull String id,
             final @Nullable Blob blob) {
 
-        val buffImg = Optional.ofNullable(blob)
+        final var buffImg = Optional.ofNullable(blob)
         .flatMap(Blob::asImage)
         .orElse(null);
 
         return asWicketImage(id, buffImg);
     }
 
-    public static Optional<Image> asWicketImage(
+    public Optional<Image> asWicketImage(
             final @NonNull String id,
             final @NonNull ScalarModel model) {
 
-      val imageValueFacet = model.getTypeOfSpecification().getFacet(ImageValueFacet.class);
-      val adapter = model.getObject();
-      if(imageValueFacet==null
-              || ManagedObjects.isNullOrUnspecifiedOrEmpty(adapter)) {
+      final ManagedObject adapter = model.getObject();
+      if(ManagedObjects.isNullOrUnspecifiedOrEmpty(adapter)) {
           return Optional.empty();
       }
 
-      val buffImg = imageValueFacet.getImage(adapter).orElse(null);
-      return asWicketImage(id, buffImg);
+      final var spec = model.getTypeOfSpecification();
+
+      return spec.streamValueSemantics(ImageValueSemantics.class)
+      .map(imageValueSemantics->imageValueSemantics.getImage(adapter).orElse(null))
+      .filter(_NullSafe::isPresent)
+      .map(buffImg->asWicketImage(id, buffImg).orElse(null))
+      .filter(_NullSafe::isPresent)
+      .findFirst();
+
     }
 
+
 }