This is an automated email from the ASF dual-hosted git repository. ahuber pushed a commit to branch v2 in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/v2 by this push: new 22ac7b9 ISIS-2006: extending applib with universal source/sink and 'try' 22ac7b9 is described below commit 22ac7b957e529883282f84b845e1031307a6c4fc Author: Andi Huber <ahu...@apache.org> AuthorDate: Mon Nov 12 15:39:26 2018 +0100 ISIS-2006: extending applib with universal source/sink and 'try' introduces AnyIn - universal source introduces AnyOut - universal sink introduces AnyOutBuffer - universal in-memory sink introduces Try - immutable holder for either a result or an exception --- .../java/org/apache/isis/applib/anyio/AnyIn.java | 73 +++++++++++++++++++ .../isis/applib/anyio/AnyIn_InputStream.java | 56 +++++++++++++++ .../java/org/apache/isis/applib/anyio/AnyOut.java | 68 ++++++++++++++++++ .../org/apache/isis/applib/anyio/AnyOutBuffer.java | 62 ++++++++++++++++ .../isis/applib/anyio/AnyOut_OutputStream.java | 55 ++++++++++++++ .../java/org/apache/isis/applib/anyio/Try.java | 74 +++++++++++++++++++ .../isis/applib/client/RestfulClientConfig.java | 84 +++++++++++++++++++++- 7 files changed, 471 insertions(+), 1 deletion(-) diff --git a/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyIn.java b/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyIn.java new file mode 100644 index 0000000..7e5d6dc --- /dev/null +++ b/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyIn.java @@ -0,0 +1,73 @@ +/* + * 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.anyio; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.apache.isis.commons.internal.base._Strings; + +/** + * Universal data source. + * + * @since 2.0.0-M2 + */ +public interface AnyIn { + + // -- INTERFACE + + <T> Try<T> tryApplyInputStream(Function<InputStream, Try<T>> inputConsumer); + + // -- FACTORIES + + static AnyIn ofTryInputStream(final Supplier<Try<InputStream>> inputStreamSupplier) { + return new AnyIn_InputStream(inputStreamSupplier); + } + + static AnyIn ofFile(final File file) { + return ofTryInputStream(()->{ + try { + InputStream fis = new FileInputStream(file); + return Try.success(fis); + } catch (FileNotFoundException e) { + return Try.failure(e); + } + }); + } + + static AnyIn ofInputStream(final Supplier<InputStream> inputStreamSupplier) { + return ofTryInputStream(()->Try.success(inputStreamSupplier.get())); + } + + static AnyIn ofBytes(final byte[] bytes) { + return ofInputStream(()->new ByteArrayInputStream(bytes)); + } + + static AnyIn ofString(final String string, Charset charset) { + return ofBytes(_Strings.toBytes(string, charset)); + } + +} + diff --git a/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyIn_InputStream.java b/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyIn_InputStream.java new file mode 100644 index 0000000..9d980e8 --- /dev/null +++ b/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyIn_InputStream.java @@ -0,0 +1,56 @@ +/* + * 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.anyio; + +import java.io.IOException; +import java.io.InputStream; +import java.util.function.Function; +import java.util.function.Supplier; + +class AnyIn_InputStream implements AnyIn { + + private final Supplier<Try<InputStream>> inputStreamSupplier; + + public AnyIn_InputStream(Supplier<Try<InputStream>> inputStreamSupplier) { + this.inputStreamSupplier = inputStreamSupplier; + } + + @Override + public <T> Try<T> tryApplyInputStream(Function<InputStream, Try<T>> inputConsumer) { + + Try<InputStream> try_is = inputStreamSupplier.get(); + if(try_is.isFailure()) { + return Try.failure(try_is.getFailure()); + } + + try(InputStream is = try_is.getResult()) { + + Try<T> _try = inputConsumer.apply(is); + return _try; + + } catch (IOException e) { + + return Try.failure(e); + + } + + } + +} + diff --git a/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyOut.java b/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyOut.java new file mode 100644 index 0000000..5577b8c --- /dev/null +++ b/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyOut.java @@ -0,0 +1,68 @@ +/* + * 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.anyio; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * Universal data sink. + * + * @since 2.0.0-M2 + */ +public interface AnyOut { + + // -- INTERFACE + + <T> Try<T> tryApplyOutputStream(Function<OutputStream, Try<T>> outputConsumer); + + // -- FACTORIES + + static AnyOut ofTryOutputStream(final Supplier<Try<OutputStream>> outputStreamSupplier) { + return new AnyOut_OutputStream(outputStreamSupplier); + } + + static AnyOut ofFile(final File file) { + return ofTryOutputStream(()->{ + try { + OutputStream fos = new FileOutputStream(file); + return Try.success(fos); + } catch (FileNotFoundException e) { + return Try.failure(e); + } + }); + } + + static AnyOut ofOutputStream(final Supplier<OutputStream> outputStreamSupplier) { + return ofTryOutputStream(()->Try.success(outputStreamSupplier.get())); + } + + static AnyOutBuffer buffer(final int buffersize) { + return new AnyOutBuffer(buffersize); + } + + static AnyOutBuffer buffer16k() { + return buffer(1024*16); + } + +} diff --git a/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyOutBuffer.java b/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyOutBuffer.java new file mode 100644 index 0000000..b4f3e29 --- /dev/null +++ b/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyOutBuffer.java @@ -0,0 +1,62 @@ +/* + * 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.anyio; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.function.Function; + +import org.apache.isis.commons.internal.base._Strings; + +/** + * Universal in-memory sink, that can be read from after having been written to. + * + * @since 2.0.0-M2 + */ +public class AnyOutBuffer implements AnyOut { + + private final ByteArrayOutputStream buffer; + private Try<?> lastTry; + + AnyOutBuffer(int buffersize) { + buffer = new ByteArrayOutputStream(buffersize); + } + + @Override + public <T> Try<T> tryApplyOutputStream(Function<OutputStream, Try<T>> outputConsumer) { + if(lastTry!=null) { + throw new IllegalStateException("Buffer was already written to."); + } + Try<T> _try = outputConsumer.apply(buffer); + return _try; + } + + public Try<byte[]> tryReadBytes(){ + if(lastTry!=null && lastTry.isFailure()) { + return Try.failure(lastTry.getFailure()); + } + return Try.success(buffer.toByteArray()); + } + + public Try<CharSequence> tryReadCharacters(Charset charset){ + return tryReadBytes().map(bytes->_Strings.ofBytes(bytes, charset)); + } + +} diff --git a/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyOut_OutputStream.java b/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyOut_OutputStream.java new file mode 100644 index 0000000..ae45bef --- /dev/null +++ b/core/applib/src/main/java/org/apache/isis/applib/anyio/AnyOut_OutputStream.java @@ -0,0 +1,55 @@ +/* + * 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.anyio; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.function.Function; +import java.util.function.Supplier; + +class AnyOut_OutputStream implements AnyOut { + + private final Supplier<Try<OutputStream>> outputStreamSupplier; + + public AnyOut_OutputStream(Supplier<Try<OutputStream>> outputStreamSupplier) { + this.outputStreamSupplier = outputStreamSupplier; + } + + @Override + public <T> Try<T> tryApplyOutputStream(Function<OutputStream, Try<T>> outputConsumer) { + + Try<OutputStream> try_os = outputStreamSupplier.get(); + if(try_os.isFailure()) { + return Try.failure(try_os.getFailure()); + } + + try(OutputStream os = try_os.getResult()) { + + Try<T> _try = outputConsumer.apply(os); + return _try; + + } catch (IOException e) { + + return Try.failure(e); + + } + } + + +} diff --git a/core/applib/src/main/java/org/apache/isis/applib/anyio/Try.java b/core/applib/src/main/java/org/apache/isis/applib/anyio/Try.java new file mode 100644 index 0000000..1a59caa --- /dev/null +++ b/core/applib/src/main/java/org/apache/isis/applib/anyio/Try.java @@ -0,0 +1,74 @@ +/* + * 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.anyio; + +import java.util.function.Function; + +/** + * Immutable data class, holds either a result or a failure object. + * + * @since 2.0.0-M2 + * + * @param <T> + */ +public final class Try<T> { + + private final T result; + private final Exception failure; + + public static <T> Try<T> success(T result) { + return new Try<>(result, null); + } + + public static <T> Try<T> failure(Exception failure) { + return new Try<>(null, failure); + } + + private Try(T result, Exception failure) { + this.result = result; + this.failure = failure; + } + + public boolean isSuccess() { + return failure==null; + } + + public boolean isFailure() { + return failure!=null; + } + + public Exception getFailure() { + return failure; + } + + public T getResult() { + return result; + } + + public void throwIfFailure() throws Exception { + if(isFailure()) { + throw failure; + } + } + + public <R> Try<R> map(Function<T, R> mapper) { + return isSuccess() ? Try.success(mapper.apply(getResult())) : Try.failure(getFailure()); + } + +} diff --git a/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClientConfig.java b/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClientConfig.java index cdd9b84..12d8327 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClientConfig.java +++ b/core/applib/src/main/java/org/apache/isis/applib/client/RestfulClientConfig.java @@ -18,10 +18,19 @@ */ package org.apache.isis.applib.client; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.transform.stream.StreamSource; + +import org.apache.isis.applib.anyio.AnyIn; +import org.apache.isis.applib.anyio.AnyOut; +import org.apache.isis.applib.anyio.Try; /** * @@ -96,6 +105,79 @@ public class RestfulClientConfig { this.useRequestDebugLogging = useRequestDebugLogging; } - // -- + // -- MARSHALLING + + public static Marshaller createMarshaller() throws JAXBException { + Marshaller marshaller = JAXBContext.newInstance(RestfulClientConfig.class).createMarshaller(); + return marshaller; + } + + public static Unmarshaller createUnmarshaller() throws JAXBException { + Unmarshaller unmarshaller = JAXBContext.newInstance(RestfulClientConfig.class).createUnmarshaller(); + return unmarshaller; + } + + // -- READ + + /** + * Tries to read the RestfulClientConfig from universal source {@code in}. + * @param in - universal source {@link AnyIn} + * @return + */ + public static Try<RestfulClientConfig> tryRead(AnyIn in) { + + return in.tryApplyInputStream(is->{ + + try { + StreamSource source = new StreamSource(is); + RestfulClientConfig clientConfig = createUnmarshaller() + .unmarshal(source, RestfulClientConfig.class).getValue(); + + return Try.success(clientConfig); + + } catch (JAXBException e) { + + return Try.failure(e); + } + + }); + + } + + // -- WRITE + + /** + * Tries to write this RestfulClientConfig to universal sink {@code output}. + * @param output - universal sink {@link AnyOut} + * @return + */ + public Try<Void> tryWrite(AnyOut output) { + return output.tryApplyOutputStream(os->{ + + try { + + createMarshaller().marshal(this, os); + return Try.success(null); + + } catch (JAXBException e) { + + return Try.failure(e); + } + + }); + } + + /** + * Writes this RestfulClientConfig to universal sink {@code output}. + * @param output - universal sink {@link AnyOut} + * @throws Exception + */ + public void write(AnyOut output) throws Exception { + + Try<Void> _try = tryWrite(output); + _try.throwIfFailure(); + + } + }