Variant.java
/*
* 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.arrow.variant;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.util.Objects;
import java.util.UUID;
import org.apache.arrow.memory.ArrowBuf;
import org.apache.arrow.variant.holders.NullableVariantHolder;
/**
* Wrapper around parquet-variant's Variant implementation.
*
* <p>This wrapper exists to isolate the parquet-variant dependency from Arrow's public API,
* allowing the vector module to expose variant functionality without requiring users to depend on
* parquet-variant directly. It also ensures that nested variant values (from arrays and objects)
* are consistently wrapped.
*/
public class Variant {
private final org.apache.parquet.variant.Variant delegate;
/** Creates a Variant from raw metadata and value byte arrays. */
public Variant(byte[] metadata, byte[] value) {
this.delegate = new org.apache.parquet.variant.Variant(value, metadata);
}
/** Creates a Variant by copying data from ArrowBuf instances. */
public Variant(
ArrowBuf metadataBuffer,
int metadataStart,
int metadataEnd,
ArrowBuf valueBuffer,
int valueStart,
int valueEnd) {
byte[] metadata = new byte[metadataEnd - metadataStart];
byte[] value = new byte[valueEnd - valueStart];
metadataBuffer.getBytes(metadataStart, metadata);
valueBuffer.getBytes(valueStart, value);
this.delegate = new org.apache.parquet.variant.Variant(value, metadata);
}
private Variant(org.apache.parquet.variant.Variant delegate) {
this.delegate = delegate;
}
/** Constructs a Variant from a NullableVariantHolder. */
public Variant(NullableVariantHolder holder) {
this(
holder.metadataBuffer,
holder.metadataStart,
holder.metadataEnd,
holder.valueBuffer,
holder.valueStart,
holder.valueEnd);
}
public ByteBuffer getValueBuffer() {
return delegate.getValueBuffer();
}
public ByteBuffer getMetadataBuffer() {
return delegate.getMetadataBuffer();
}
public boolean getBoolean() {
return delegate.getBoolean();
}
public byte getByte() {
return delegate.getByte();
}
public short getShort() {
return delegate.getShort();
}
public int getInt() {
return delegate.getInt();
}
public long getLong() {
return delegate.getLong();
}
public double getDouble() {
return delegate.getDouble();
}
public BigDecimal getDecimal() {
return delegate.getDecimal();
}
public float getFloat() {
return delegate.getFloat();
}
public ByteBuffer getBinary() {
return delegate.getBinary();
}
public UUID getUUID() {
return delegate.getUUID();
}
public String getString() {
return delegate.getString();
}
public Type getType() {
return Type.fromParquet(delegate.getType());
}
public int numObjectElements() {
return delegate.numObjectElements();
}
public Variant getFieldByKey(String key) {
org.apache.parquet.variant.Variant result = delegate.getFieldByKey(key);
return result != null ? wrap(result) : null;
}
public ObjectField getFieldAtIndex(int idx) {
org.apache.parquet.variant.Variant.ObjectField field = delegate.getFieldAtIndex(idx);
return new ObjectField(field.key, wrap(field.value));
}
public int numArrayElements() {
return delegate.numArrayElements();
}
public Variant getElementAtIndex(int index) {
org.apache.parquet.variant.Variant result = delegate.getElementAtIndex(index);
return result != null ? wrap(result) : null;
}
private static Variant wrap(org.apache.parquet.variant.Variant parquetVariant) {
return new Variant(parquetVariant);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Variant variant = (Variant) o;
return delegate.getMetadataBuffer().equals(variant.delegate.getMetadataBuffer())
&& delegate.getValueBuffer().equals(variant.delegate.getValueBuffer());
}
@Override
public int hashCode() {
return Objects.hash(delegate.getMetadataBuffer(), delegate.getValueBuffer());
}
@Override
public String toString() {
return "Variant{type=" + getType() + '}';
}
public enum Type {
OBJECT,
ARRAY,
NULL,
BOOLEAN,
BYTE,
SHORT,
INT,
LONG,
STRING,
DOUBLE,
DECIMAL4,
DECIMAL8,
DECIMAL16,
DATE,
TIMESTAMP_TZ,
TIMESTAMP_NTZ,
FLOAT,
BINARY,
TIME,
TIMESTAMP_NANOS_TZ,
TIMESTAMP_NANOS_NTZ,
UUID;
static Type fromParquet(org.apache.parquet.variant.Variant.Type parquetType) {
return Type.valueOf(parquetType.name());
}
}
public static final class ObjectField {
public final String key;
public final Variant value;
public ObjectField(String key, Variant value) {
this.key = key;
this.value = value;
}
}
}