blob: de0b2d0d3d3ccd8d568fc8e6a7ce5be42583f7e4 [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.binary;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Date;
import java.util.UUID;
import org.apache.ignite.binary.BinaryObjectException;
import org.apache.ignite.internal.binary.streams.BinaryByteBufferInputStream;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.binary.BinaryObject;
import org.apache.ignite.binary.BinaryField;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Implementation of binary field descriptor.
*/
public class BinaryFieldImpl implements BinaryFieldEx {
/** Binary context that created this field. */
private final BinaryContext ctx;
/** Type ID. */
private final int typeId;
/** Well-known object schemas. */
@GridToStringExclude
private final BinarySchemaRegistry schemas;
/** Field name. */
private final String fieldName;
/** Pre-calculated field ID. */
private final int fieldId;
/**
* Constructor.
*
* @param ctx Binary context.
* @param typeId Type ID.
* @param schemas Schemas.
* @param fieldName Field name.
* @param fieldId Field ID.
*/
public BinaryFieldImpl(
BinaryContext ctx,
int typeId,
BinarySchemaRegistry schemas,
String fieldName,
int fieldId
) {
assert ctx != null;
assert typeId != 0;
assert schemas != null;
assert fieldId != 0;
this.ctx = ctx;
this.typeId = typeId;
this.schemas = schemas;
this.fieldName = fieldName;
this.fieldId = fieldId;
}
/** {@inheritDoc} */
@Override public String name() {
return fieldName;
}
/**
* @return Field ID.
*/
public int fieldId() {
return fieldId;
}
/** {@inheritDoc} */
@Override public boolean exists(BinaryObject obj) {
BinaryObjectExImpl obj0 = (BinaryObjectExImpl)obj;
return fieldOrder(obj0) != BinarySchema.ORDER_NOT_FOUND;
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override public <T> T value(BinaryObject obj) {
BinaryObjectExImpl obj0 = (BinaryObjectExImpl)obj;
int order = fieldOrder(obj0);
return order != BinarySchema.ORDER_NOT_FOUND ? (T)obj0.fieldByOrder(order) : null;
}
/** {@inheritDoc} */
@Override public int typeId() {
return typeId;
}
/** {@inheritDoc} */
@Override public boolean writeField(BinaryObject obj, ByteBuffer buf) {
BinaryObjectExImpl obj0 = (BinaryObjectExImpl)obj;
int order = fieldOrder(obj0);
return obj0.writeFieldByOrder(order, buf);
}
/** {@inheritDoc} */
@Override public <F> F readField(ByteBuffer buf) {
ByteOrder oldOrder = buf.order();
try {
buf.order(ByteOrder.LITTLE_ENDIAN);
int pos = buf.position();
byte hdr = buf.get();
Object val;
switch (hdr) {
case GridBinaryMarshaller.INT:
val = buf.getInt();
break;
case GridBinaryMarshaller.LONG:
val = buf.getLong();
break;
case GridBinaryMarshaller.BOOLEAN:
val = buf.get() != 0;
break;
case GridBinaryMarshaller.SHORT:
val = buf.getShort();
break;
case GridBinaryMarshaller.BYTE:
val = buf.get();
break;
case GridBinaryMarshaller.CHAR:
val = buf.getChar();
break;
case GridBinaryMarshaller.FLOAT:
val = buf.getFloat();
break;
case GridBinaryMarshaller.DOUBLE:
val = buf.getDouble();
break;
case GridBinaryMarshaller.STRING: {
int dataLen = buf.getInt();
byte[] data = new byte[dataLen];
buf.get(data);
val = new String(data, 0, dataLen, UTF_8);
break;
}
case GridBinaryMarshaller.DATE: {
long time = buf.getLong();
val = new Date(time);
break;
}
case GridBinaryMarshaller.TIMESTAMP: {
long time = buf.getLong();
int nanos = buf.getInt();
Timestamp ts = new Timestamp(time);
ts.setNanos(ts.getNanos() + nanos);
val = ts;
break;
}
case GridBinaryMarshaller.TIME: {
long time = buf.getLong();
val = new Time(time);
break;
}
case GridBinaryMarshaller.UUID: {
long most = buf.getLong();
long least = buf.getLong();
val = new UUID(most, least);
break;
}
case GridBinaryMarshaller.DECIMAL: {
int scale = buf.getInt();
int dataLen = buf.getInt();
byte[] data = new byte[dataLen];
buf.get(data);
boolean negative = data[0] < 0;
if (negative)
data[0] &= 0x7F;
BigInteger intVal = new BigInteger(data);
if (negative)
intVal = intVal.negate();
val = new BigDecimal(intVal, scale);
break;
}
case GridBinaryMarshaller.NULL:
val = null;
break;
default:
// Restore buffer position.
buf.position(pos);
val = BinaryUtils.unmarshal(BinaryByteBufferInputStream.create(buf), ctx, null);
break;
}
return (F)val;
}
finally {
buf.order(oldOrder);
}
}
/**
* Get relative field offset.
*
* @param obj Object.
* @return Field offset.
*/
public int fieldOrder(BinaryObjectExImpl obj) {
if (typeId != obj.typeId()) {
throw new BinaryObjectException("Failed to get field because type ID of passed object differs" +
" from type ID this " + BinaryField.class.getSimpleName() + " belongs to [expected=" + typeId +
", actual=" + obj.typeId() + ']');
}
int schemaId = obj.schemaId();
if (schemaId == 0)
return BinarySchema.ORDER_NOT_FOUND;
BinarySchema schema = schemas.schema(schemaId);
if (schema == null) {
schema = obj.createSchema();
schemas.addSchema(schemaId, schema);
}
assert schema != null;
return schema.order(fieldId);
}
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(BinaryFieldImpl.class, this);
}
}