blob: 9465bfd281d747e2699656d0bf58ade98babfbe1 [file] [log] [blame]
/*
* 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.ignite.internal.table;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.BitSet;
import java.util.Iterator;
import java.util.UUID;
import org.apache.ignite.binary.BinaryObject;
import org.apache.ignite.internal.schema.SchemaDescriptor;
import org.apache.ignite.internal.schema.row.Row;
import org.apache.ignite.table.Tuple;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Adapter provides Tuple access methods and mutability for a Row.
* <p>
* Once adapter get created, it delegates all data access methods to the {@link #row}.
* <p>
* Mutability.
* Underlying Row is immutable serialized object and can't be mutated directly.
* Because of this fact, first call of {@link #set(String, Object)} method implies the Row conversion to a Tuple.
* <p>
* After the first mutation the {@link #tuple} becomes a full copy of {@link #row},
* all data access methods delegate to a {@link #tuple}, and the {@link #row} one is no longer useful.
* The adapter acts as simple schema-less tuple {@link Tuple} and {@link #schema()} return null.
* <p>
* Serialization.
* Row access methods implicitly require a context (schema) for a binary data reading, The context may be huge
* comparing to a row data, and its serialization is unwanted.
* So, Row firstly is converted to Tuple.
* <p>
* Because of after that the adapter will act as underlying tuple {@link Tuple},
* the adapter will be substituted unconditionally with the tuple itself during deserialization.
*
* @see Tuple
* @see #unmarshalRow()
* @see #writeReplace()
*/
public class MutableRowTupleAdapter extends AbstractRowTupleAdapter implements Serializable {
// Default constructor and serialVersionUID not needed because, actually,
// this object never get serialized, it's unconditionally substituted during serialization.
/** Tuple with overwritten data. */
protected Tuple tuple;
/**
* Creates mutable wrapper over row.
*
* @param row Row.
*/
public MutableRowTupleAdapter(@NotNull Row row) {
super(row);
}
/** {@inheritDoc} */
@Override public @Nullable SchemaDescriptor schema() {
return tuple != null ? null : super.schema();
}
/** {@inheritDoc} */
@Override public int columnCount() {
return tuple != null ? tuple.columnCount() : super.columnCount();
}
/** {@inheritDoc} */
@Override public String columnName(int columnIndex) {
return tuple != null ? tuple.columnName(columnIndex) : super.columnName(columnIndex);
}
/** {@inheritDoc} */
@Override public int columnIndex(@NotNull String columnName) {
return tuple != null ? tuple.columnIndex(columnName) : super.columnIndex(columnName);
}
/** {@inheritDoc} */
@Override public <T> T valueOrDefault(@NotNull String columnName, T defaultValue) {
return tuple != null ? tuple.valueOrDefault(columnName, defaultValue) : super.valueOrDefault(columnName, defaultValue);
}
/** {@inheritDoc} */
@Override public <T> T value(@NotNull String columnName) {
return tuple != null ? tuple.value(columnName) : super.value(columnName);
}
/** {@inheritDoc} */
@Override public <T> T value(int columnIndex) {
return tuple != null ? tuple.value(columnIndex) : super.value(columnIndex);
}
/** {@inheritDoc} */
@Override public BinaryObject binaryObjectValue(@NotNull String columnName) {
return tuple != null ? tuple.binaryObjectValue(columnName) : super.binaryObjectValue(columnName);
}
/** {@inheritDoc} */
@Override public BinaryObject binaryObjectValue(int columnIndex) {
return super.binaryObjectValue(columnIndex);
}
/** {@inheritDoc} */
@Override public byte byteValue(@NotNull String columnName) {
return tuple != null ? tuple.byteValue(columnName) : super.byteValue(columnName);
}
/** {@inheritDoc} */
@Override public byte byteValue(int columnIndex) {
return tuple != null ? tuple.byteValue(columnIndex) : super.byteValue(columnIndex);
}
/** {@inheritDoc} */
@Override public short shortValue(@NotNull String columnName) {
return tuple != null ? tuple.shortValue(columnName) : super.shortValue(columnName);
}
/** {@inheritDoc} */
@Override public short shortValue(int columnIndex) {
return tuple != null ? tuple.shortValue(columnIndex) : super.shortValue(columnIndex);
}
/** {@inheritDoc} */
@Override public int intValue(@NotNull String columnName) {
return tuple != null ? tuple.intValue(columnName) : super.intValue(columnName);
}
/** {@inheritDoc} */
@Override public int intValue(int columnIndex) {
return tuple != null ? tuple.intValue(columnIndex) : super.intValue(columnIndex);
}
/** {@inheritDoc} */
@Override public long longValue(@NotNull String columnName) {
return tuple != null ? tuple.longValue(columnName) : super.longValue(columnName);
}
/** {@inheritDoc} */
@Override public long longValue(int columnIndex) {
return tuple != null ? tuple.longValue(columnIndex) : super.longValue(columnIndex);
}
/** {@inheritDoc} */
@Override public float floatValue(@NotNull String columnName) {
return tuple != null ? tuple.floatValue(columnName) : super.floatValue(columnName);
}
/** {@inheritDoc} */
@Override public float floatValue(int columnIndex) {
return tuple != null ? tuple.floatValue(columnIndex) : super.floatValue(columnIndex);
}
/** {@inheritDoc} */
@Override public double doubleValue(@NotNull String columnName) {
return tuple != null ? tuple.doubleValue(columnName) : super.doubleValue(columnName);
}
/** {@inheritDoc} */
@Override public double doubleValue(int columnIndex) {
return tuple != null ? tuple.doubleValue(columnIndex) : super.doubleValue(columnIndex);
}
/** {@inheritDoc} */
@Override public String stringValue(@NotNull String columnName) {
return tuple != null ? tuple.stringValue(columnName) : super.stringValue(columnName);
}
/** {@inheritDoc} */
@Override public String stringValue(int columnIndex) {
return tuple != null ? tuple.stringValue(columnIndex) : super.stringValue(columnIndex);
}
/** {@inheritDoc} */
@Override public UUID uuidValue(@NotNull String columnName) {
return tuple != null ? tuple.uuidValue(columnName) : super.uuidValue(columnName);
}
/** {@inheritDoc} */
@Override public UUID uuidValue(int columnIndex) {
return tuple != null ? tuple.uuidValue(columnIndex) : super.uuidValue(columnIndex);
}
/** {@inheritDoc} */
@Override public BitSet bitmaskValue(@NotNull String columnName) {
return tuple != null ? tuple.bitmaskValue(columnName) : super.bitmaskValue(columnName);
}
/** {@inheritDoc} */
@Override public BitSet bitmaskValue(int columnIndex) {
return tuple != null ? tuple.bitmaskValue(columnIndex) : super.bitmaskValue(columnIndex);
}
/** {@inheritDoc} */
@Override public LocalDate dateValue(String columnName) {
return tuple != null ? tuple.dateValue(columnName) : super.dateValue(columnName);
}
/** {@inheritDoc} */
@Override public LocalDate dateValue(int columnIndex) {
return tuple != null ? tuple.dateValue(columnIndex) : super.dateValue(columnIndex);
}
/** {@inheritDoc} */
@Override public LocalTime timeValue(String columnName) {
return tuple != null ? tuple.timeValue(columnName) : super.timeValue(columnName);
}
/** {@inheritDoc} */
@Override public LocalTime timeValue(int columnIndex) {
return tuple != null ? tuple.timeValue(columnIndex) : super.timeValue(columnIndex);
}
/** {@inheritDoc} */
@Override public LocalDateTime datetimeValue(String columnName) {
return tuple != null ? tuple.datetimeValue(columnName) : super.datetimeValue(columnName);
}
/** {@inheritDoc} */
@Override public LocalDateTime datetimeValue(int columnIndex) {
return tuple != null ? tuple.datetimeValue(columnIndex) : super.datetimeValue(columnIndex);
}
/** {@inheritDoc} */
@Override public Instant timestampValue(String columnName) {
return tuple != null ? tuple.timestampValue(columnName) : super.timestampValue(columnName);
}
/** {@inheritDoc} */
@Override public Instant timestampValue(int columnIndex) {
return tuple != null ? tuple.timestampValue(columnIndex) : super.timestampValue(columnIndex);
}
/** {@inheritDoc} */
@Override public @NotNull Iterator<Object> iterator() {
return tuple != null ? tuple.iterator() : super.iterator();
}
/** {@inheritDoc} */
@Override public Tuple set(@NotNull String columnName, Object value) {
unmarshalRow();
tuple.set(columnName, value);
return this;
}
/**
* Converts immutable row to mutable tuple.
*/
private void unmarshalRow() {
if (tuple == null) {
tuple = Tuple.create(this);
row = null;
}
}
/**
* Overrides default serialization flow.
* Serialized {@code tuple} instead of {@code this}, as wrapper make no sense after tuple is fully materialized.
* <p>
* Note: The method has protected modifier and subclass access to this method follows java accessibility rules.
* Thus, class successors may obtain similar behaviour.
*
* @return Tuple to serialize.
* @throws ObjectStreamException If failed.
*/
protected Object writeReplace() throws ObjectStreamException {
unmarshalRow();
return tuple;
}
}