com.amazon.ion.BufferConfiguration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ion-java Show documentation
Show all versions of ion-java Show documentation
A Java implementation of the Amazon Ion data notation.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package com.amazon.ion;
/**
* Provides logic common to all BufferConfiguration implementations.
* @param the type of the concrete subclass of this BufferConfiguration.
*/
public abstract class BufferConfiguration> {
/**
* Functional interface for handling oversized values.
*/
@FunctionalInterface
public interface OversizedValueHandler {
/**
* Invoked each time a user value exceeds the buffer size limit specified. This is recoverable. If the
* implementation wishes to recover, it should simply return normally from this method. The oversized value will
* be flushed from the buffer; normal processing will resume with the next value. If the implementation wishes
* to abort processing immediately, it may throw an exception from this method.
*/
void onOversizedValue();
}
/**
* Functional interface for reporting processed data.
*/
@FunctionalInterface
public interface DataHandler {
/**
* Invoked whenever the bytes from a value are processed, regardless of whether the bytes are buffered or
* skipped due to the value being oversized.
* @param numberOfBytes the number of bytes processed.
*/
void onData(int numberOfBytes);
}
/**
* Provides logic common to all BufferConfiguration Builder implementations.
* @param the type of BufferConfiguration.
* @param the type of Builder that builds BufferConfiguration subclasses of type `Configuration`.
*/
public static abstract class Builder<
Configuration extends BufferConfiguration,
BuilderType extends BufferConfiguration.Builder
> {
/**
* Large enough that most streams will never need to grow the buffer. NOTE: this only needs to be large
* enough to exceed the length of the longest top-level value plus any system values that precede it.
*/
static final int DEFAULT_INITIAL_BUFFER_SIZE = 32 * 1024; // bytes
/**
* The initial size of the lookahead buffer, in bytes.
*/
private int initialBufferSize = DEFAULT_INITIAL_BUFFER_SIZE;
/**
* The maximum number of bytes that will be buffered.
*/
private int maximumBufferSize = Integer.MAX_VALUE;
/**
* The handler that will be notified when oversized values are encountered.
*/
private OversizedValueHandler oversizedValueHandler = null;
/**
* The handler that will be notified when data is processed.
*/
private DataHandler dataHandler = null;
/**
* Sets the initial size of the buffer that will be used to hold the data between top-level values. Default:
* 32KB.
*
* @param initialBufferSizeInBytes the value.
* @return this Builder.
*/
public final BuilderType withInitialBufferSize(final int initialBufferSizeInBytes) {
initialBufferSize = initialBufferSizeInBytes;
return (BuilderType) this;
}
/**
* @return the initial size of the buffer, in bytes.
*/
public final int getInitialBufferSize() {
return initialBufferSize;
}
/**
* Sets the handler that will be notified when oversized values are encountered. If the maximum buffer size is
* finite (see {@link #withMaximumBufferSize(int)}, this handler is required to be non-null.
*
* @param handler the handler.
* @return this builder.
*/
public final BuilderType onOversizedValue(final OversizedValueHandler handler) {
oversizedValueHandler = handler;
return (BuilderType) this;
}
/**
* Sets the handler that will be notified when data is processed. The handler may be null, in which case the
* number of bytes processed will not be reported.
*
* @param handler the handler.
* @return this builder.
*/
public final BuilderType onData(final DataHandler handler) {
dataHandler = handler;
return (BuilderType) this;
}
/**
* @return the handler that will be notified when oversized values are encountered.
*/
public final OversizedValueHandler getOversizedValueHandler() {
return oversizedValueHandler;
}
/**
* @return the handler that will be notified when data is processed.
*/
public final DataHandler getDataHandler() {
return dataHandler;
}
/**
* Set the maximum size of the buffer. For binary Ion, the minimum value is 5 because all valid binary Ion data
* begins with a 4-byte Ion version marker and the smallest value is 1 byte. For text Ion, the minimum value is
* 2 because the smallest text Ion value is 1 byte and the smallest delimiter is 1 byte.
* Default: Integer.MAX_VALUE.
*
* @param maximumBufferSizeInBytes the value.
* @return this builder.
*/
public final BuilderType withMaximumBufferSize(final int maximumBufferSizeInBytes) {
maximumBufferSize = maximumBufferSizeInBytes;
return (BuilderType) this;
}
/**
* @return the maximum number of bytes that will be buffered.
*/
public int getMaximumBufferSize() {
return maximumBufferSize;
}
/**
* Gets the minimum allowed maximum buffer size.
* @return the value.
*/
public abstract int getMinimumMaximumBufferSize();
/**
* @return the no-op {@link OversizedValueHandler} for the type of BufferConfiguration that this Builder builds.
*/
public abstract OversizedValueHandler getNoOpOversizedValueHandler();
/**
* @return an {@link OversizedValueHandler} that always throws a runtime exception.
*/
public abstract OversizedValueHandler getThrowingOversizedValueHandler();
/**
* @return the no-op {@link DataHandler} for the type of BufferConfiguration that this Builder builds.
*/
public abstract DataHandler getNoOpDataHandler();
/**
* Creates a new BufferConfiguration from the Builder's current settings.
* @return a new instance.
*/
public abstract Configuration build();
}
/**
* The initial size of the buffer, in bytes.
*/
private final int initialBufferSize;
/**
* The maximum number of bytes that may be buffered.
*/
private final int maximumBufferSize;
/**
* The handler that will be notified when oversized values are encountered.
*/
private final OversizedValueHandler oversizedValueHandler;
/**
* The handler that will be notified when data is processed.
*/
private final DataHandler dataHandler;
/**
* Constructs an instance from the given Builder.
* @param builder the builder containing the settings to apply to the new configuration.
*/
protected BufferConfiguration(Builder builder) {
initialBufferSize = builder.getInitialBufferSize();
maximumBufferSize = builder.getMaximumBufferSize();
if (initialBufferSize > maximumBufferSize) {
throw new IllegalArgumentException("Initial buffer size may not exceed the maximum buffer size.");
}
if (maximumBufferSize < builder.getMinimumMaximumBufferSize()) {
throw new IllegalArgumentException(String.format(
"Maximum buffer size must be at least %d bytes.", builder.getMinimumMaximumBufferSize()
));
}
if (builder.getOversizedValueHandler() == null) {
requireUnlimitedBufferSize();
oversizedValueHandler = builder.getThrowingOversizedValueHandler();
} else {
oversizedValueHandler = builder.getOversizedValueHandler();
}
if (builder.getDataHandler() == null) {
dataHandler = builder.getNoOpDataHandler();
} else {
dataHandler = builder.getDataHandler();
}
}
/**
* Requires that the maximum buffer size not be limited.
*/
protected void requireUnlimitedBufferSize() {
if (maximumBufferSize < Integer.MAX_VALUE) {
throw new IllegalArgumentException(
"Must specify an OversizedValueHandler when a maximum buffer size is specified."
);
}
}
/**
* @return the initial size of the buffer, in bytes.
*/
public final int getInitialBufferSize() {
return initialBufferSize;
}
/**
* @return the maximum number of bytes that will be buffered.
*/
public final int getMaximumBufferSize() {
return maximumBufferSize;
}
/**
* @return the handler that will be notified when oversized values are encountered.
*/
public final OversizedValueHandler getOversizedValueHandler() {
return oversizedValueHandler;
}
/**
* @return the handler that will be notified when data is processed.
*/
public final DataHandler getDataHandler() {
return dataHandler;
}
}