| /* |
| * 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; |
| } |
| } |