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 e0d5938510 ISIS-3300: support file i/o for Blob and Clob (convenience)
e0d5938510 is described below

commit e0d59385101b09d1c452c2124a29eca9ef0a98b0
Author: Andi Huber <ahu...@apache.org>
AuthorDate: Thu Dec 1 18:41:23 2022 +0100

    ISIS-3300: support file i/o for Blob and Clob (convenience)
---
 .../org/apache/causeway/applib/value/Blob.java     | 56 ++++++++++++++++++++--
 .../org/apache/causeway/applib/value/Clob.java     | 54 +++++++++++++++++++++
 .../domainmodel/MetaModelRegressionTest.java       | 18 +++----
 3 files changed, 113 insertions(+), 15 deletions(-)

diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/value/Blob.java 
b/api/applib/src/main/java/org/apache/causeway/applib/value/Blob.java
index 2acada6c29..794df8b10c 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/value/Blob.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/value/Blob.java
@@ -20,6 +20,9 @@ package org.apache.causeway.applib.value;
 
 import java.awt.image.BufferedImage;
 import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -36,11 +39,14 @@ import javax.inject.Named;
 import javax.xml.bind.annotation.adapters.XmlAdapter;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
+import org.springframework.lang.Nullable;
+
 import org.apache.causeway.applib.CausewayModuleApplib;
 import org.apache.causeway.applib.annotation.Value;
 import org.apache.causeway.applib.jaxb.PrimitiveJaxbAdapters;
 import org.apache.causeway.applib.util.ZipReader;
 import org.apache.causeway.applib.util.ZipWriter;
+import org.apache.causeway.commons.functional.Try;
 import org.apache.causeway.commons.internal.base._Bytes;
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
@@ -113,6 +119,28 @@ public final class Blob implements NamedWithMimeType {
         return new Blob(fileName, mimeType.getMimeType(), content);
     }
 
+    /**
+     * Returns a new {@link Blob} of given {@code name}, {@code mimeType} and 
content from {@code file},
+     * wrapped with a {@link Try}.
+     * <p>
+     * {@code name} may or may not include the desired filename extension, it
+     * is guaranteed, that the resulting {@link Blob} has the appropriate 
extension
+     * as constraint by the given {@code mimeType}.
+     * <p>
+     * For more fine-grained control use one of the {@link Blob} constructors 
directly.
+     * @param name - may or may not include the desired filename extension
+     * @param mimeType
+     * @param file - the file to be opened for reading
+     * @return new {@link Blob}
+     */
+    public static Try<Blob> tryRead(final String name, final CommonMimeType 
mimeType, final File file) {
+        return Try.call(()->{
+            try(val fis = new FileInputStream(file)){
+                return Blob.of(name, mimeType, _Bytes.ofKeepOpen(fis));
+            }
+        });
+    }
+
      // --
 
     private final MimeType mimeType;
@@ -167,10 +195,9 @@ public final class Blob implements NamedWithMimeType {
 
     /**
      * Does not close the OutputStream.
-     * @param os
-     * @throws IOException
      */
-    public void writeBytesTo(final OutputStream os) throws IOException {
+    @SneakyThrows
+    public void writeBytesTo(final @Nullable OutputStream os) {
         if(os==null) {
             return;
         }
@@ -179,12 +206,33 @@ public final class Blob implements NamedWithMimeType {
         }
     }
 
+    /**
+     * Writes this {@link Blob} to the file represented by
+     * the specified <code>File</code> object.
+     * <p>
+     * If the file exists but is a directory rather than a regular file, does
+     * not exist but cannot be created, or cannot be opened for any other
+     * reason then a <code>FileNotFoundException</code> is thrown.
+     *
+     * @param      file the file to be opened for writing; if 
<code>null</code> this method does nothing
+     * @see        java.io.FileOutputStream
+     */
+    @SneakyThrows
+    public void writeTo(final @Nullable File file) {
+        if(file==null) {
+            return; // just ignore
+        }
+        try(val os = new FileOutputStream(file)){
+            writeBytesTo(os);
+        }
+    }
+
     /**
      * The {@link InputStream} involved is closed after consumption.
      * @param consumer
      * @throws IOException
      */
-    public void consume(final Consumer<InputStream> consumer) throws 
IOException {
+    public void consume(final @NonNull Consumer<InputStream> consumer) throws 
IOException {
      // null to empty
         val bytes = Optional.ofNullable(getBytes())
                 .orElse(new byte[0]);
diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/value/Clob.java 
b/api/applib/src/main/java/org/apache/causeway/applib/value/Clob.java
index 80a047ab76..5e7cb3f9d7 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/value/Clob.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/value/Clob.java
@@ -18,7 +18,11 @@
  */
 package org.apache.causeway.applib.value;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.nio.charset.Charset;
@@ -31,9 +35,12 @@ import javax.inject.Named;
 import javax.xml.bind.annotation.adapters.XmlAdapter;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
+import org.springframework.lang.Nullable;
+
 import org.apache.causeway.applib.CausewayModuleApplib;
 import org.apache.causeway.applib.annotation.Value;
 import org.apache.causeway.applib.jaxb.PrimitiveJaxbAdapters;
+import org.apache.causeway.commons.functional.Try;
 import org.apache.causeway.commons.internal.base._Strings;
 
 import lombok.NonNull;
@@ -107,6 +114,30 @@ public final class Clob implements NamedWithMimeType {
         return new Clob(fileName, mimeType.getMimeType(), content);
     }
 
+    /**
+     * Returns a new {@link Clob} of given {@code name}, {@code mimeType} and 
content from {@code file},
+     * wrapped with a {@link Try}.
+     * <p>
+     * {@code name} may or may not include the desired filename extension, it
+     * is guaranteed, that the resulting {@link Clob} has the appropriate 
extension
+     * as constraint by the given {@code mimeType}.
+     * <p>
+     * For more fine-grained control use one of the {@link Clob} constructors 
directly.
+     * @param name - may or may not include the desired filename extension
+     * @param mimeType
+     * @param file - the file to be opened for reading
+     * @param charset - {@link Charset} to use for reading given file
+     * @return new {@link Clob}
+     */
+    public static Try<Clob> tryRead(final String name, final CommonMimeType 
mimeType, final File file,
+            final @NonNull Charset charset) {
+        return Try.call(()->{
+            try(val fis = new FileInputStream(file)){
+                return Clob.of(name, mimeType, _Strings.read(fis, charset));
+            }
+        });
+    }
+
     // --
 
     public Clob(final String name, final String primaryType, final String 
subType, final char[] chars) {
@@ -173,6 +204,29 @@ public final class Clob implements NamedWithMimeType {
         }
     }
 
+    /**
+     * Writes this {@link Clob} to the file represented by
+     * the specified <code>File</code> object.
+     * <p>
+     * If the file exists but is a directory rather than a regular file, does
+     * not exist but cannot be created, or cannot be opened for any other
+     * reason then a <code>FileNotFoundException</code> is thrown.
+     *
+     * @param      file the file to be opened for writing; if 
<code>null</code> this method does nothing
+     * @param charset - {@link Charset} to use for writing to given file
+     * @see        java.io.FileOutputStream
+     * @see        java.io.OutputStreamWriter
+     */
+    @SneakyThrows
+    public void writeTo(final @Nullable File file, final @NonNull Charset 
charset) {
+        if(file==null) {
+            return; // just ignore
+        }
+        try(val os = new FileOutputStream(file)){
+            writeCharsTo(new OutputStreamWriter(os, StandardCharsets.UTF_8));
+        }
+    }
+
     @SneakyThrows
     public String asString() {
         val sw = new StringWriter();
diff --git 
a/regressiontests/stable-domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/MetaModelRegressionTest.java
 
b/regressiontests/stable-domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/MetaModelRegressionTest.java
index 609c515296..90a9ef0825 100644
--- 
a/regressiontests/stable-domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/MetaModelRegressionTest.java
+++ 
b/regressiontests/stable-domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/MetaModelRegressionTest.java
@@ -18,7 +18,6 @@
  */
 package org.apache.causeway.testdomain.domainmodel;
 
-import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
 
@@ -44,7 +43,6 @@ import 
org.apache.causeway.testdomain.conf.Configuration_headless;
 import 
org.apache.causeway.testdomain.model.good.Configuration_usingValidDomain;
 
 import lombok.SneakyThrows;
-import lombok.val;
 
 @SpringBootTest(
         classes = {
@@ -81,17 +79,15 @@ class MetaModelRegressionTest {
         // disable if rename, as the .zip file needs to be updated.
         // Assumptions.assumeThat(getClass().getName()).contains("causeway");
 
-        Blob metaModelZip = 
factoryService.mixin(MetaModelServiceMenu.downloadMetaModelXml.class,
-                metaModelServiceMenu).act("metamodel.xml", namespaces(), true);
-        val xml = asXml(metaModelZip);
+        final Blob metaModelZip = factoryService
+                .mixin(MetaModelServiceMenu.downloadMetaModelXml.class, 
metaModelServiceMenu)
+                .act("metamodel.xml", namespaces(), true);
+        final String xml = metaModelZip
+                .unZip(CommonMimeType.XML)
+                .toClob(StandardCharsets.UTF_8)
+                .asString();
 
         Approvals.verify(xml, options());
-
-    }
-
-    private static String asXml(final Blob zip) throws IOException {
-        val clob = 
zip.unZip(CommonMimeType.XML).toClob(StandardCharsets.UTF_8);
-        return clob.asString();
     }
 
     private Options options() {

Reply via email to