/* * Copyright 2015 Realm Inc. * * Licensed 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 io.realm; import org.bson.types.Decimal128; import org.bson.types.ObjectId; import java.nio.ByteBuffer; import io.realm.internal.Keep; import io.realm.internal.Property; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_BINARY; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_BOOLEAN; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_DATE; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_DECIMAL128; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_DOUBLE; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_FLOAT; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_INTEGER; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_LINKING_OBJECTS; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_LIST; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_MIXED; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_OBJECT; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_OBJECTID; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_STRING; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_TYPED_LINK; import static io.realm.RealmFieldTypeConstants.CORE_TYPE_VALUE_UUID; import static io.realm.RealmFieldTypeConstants.DICTIONARY_OFFSET; import static io.realm.RealmFieldTypeConstants.LIST_OFFSET; import static io.realm.RealmFieldTypeConstants.MAX_CORE_TYPE_VALUE; import static io.realm.RealmFieldTypeConstants.SET_OFFSET; interface RealmFieldTypeConstants { int LIST_OFFSET = Property.TYPE_ARRAY; int DICTIONARY_OFFSET = Property.TYPE_DICTIONARY; int SET_OFFSET = Property.TYPE_SET; int CORE_TYPE_VALUE_INTEGER = 0; int CORE_TYPE_VALUE_BOOLEAN = 1; int CORE_TYPE_VALUE_STRING = 2; int CORE_TYPE_VALUE_BINARY = 4; int CORE_TYPE_VALUE_DATE = 8; int CORE_TYPE_VALUE_FLOAT = 9; int CORE_TYPE_VALUE_DOUBLE = 10; int CORE_TYPE_VALUE_OBJECT = 12; int CORE_TYPE_VALUE_LIST = 13; int CORE_TYPE_VALUE_LINKING_OBJECTS = 14; int CORE_TYPE_VALUE_DECIMAL128 = 11; int CORE_TYPE_VALUE_OBJECTID = 15; int CORE_TYPE_VALUE_UUID = 17; int CORE_TYPE_VALUE_MIXED = 6; int CORE_TYPE_VALUE_TYPED_LINK = 16; int MAX_CORE_TYPE_VALUE = CORE_TYPE_VALUE_UUID; } /** * List of the types used by Realm's underlying storage engine. *

* Normally there is no reason to interact with the underlying Realm types as Realm will automatically * convert between normal Java types and the Realm types. However it is possible to access these * types through a {@link DynamicRealmObject}. */ @Keep public enum RealmFieldType { // Makes sure numbers match with . INTEGER(CORE_TYPE_VALUE_INTEGER), BOOLEAN(CORE_TYPE_VALUE_BOOLEAN), STRING(CORE_TYPE_VALUE_STRING), BINARY(CORE_TYPE_VALUE_BINARY), DATE(CORE_TYPE_VALUE_DATE), FLOAT(CORE_TYPE_VALUE_FLOAT), DOUBLE(CORE_TYPE_VALUE_DOUBLE), OBJECT(CORE_TYPE_VALUE_OBJECT), DECIMAL128(CORE_TYPE_VALUE_DECIMAL128), OBJECT_ID(CORE_TYPE_VALUE_OBJECTID), UUID(CORE_TYPE_VALUE_UUID), MIXED(CORE_TYPE_VALUE_MIXED), // Core equivalent to RealmAny TYPED_LINK(CORE_TYPE_VALUE_TYPED_LINK), // It is only used by RealmAny internally. LIST(CORE_TYPE_VALUE_LIST), LINKING_OBJECTS(CORE_TYPE_VALUE_LINKING_OBJECTS), INTEGER_LIST(CORE_TYPE_VALUE_INTEGER + LIST_OFFSET), BOOLEAN_LIST(CORE_TYPE_VALUE_BOOLEAN + LIST_OFFSET), STRING_LIST(CORE_TYPE_VALUE_STRING + LIST_OFFSET), BINARY_LIST(CORE_TYPE_VALUE_BINARY + LIST_OFFSET), DATE_LIST(CORE_TYPE_VALUE_DATE + LIST_OFFSET), FLOAT_LIST(CORE_TYPE_VALUE_FLOAT + LIST_OFFSET), DOUBLE_LIST(CORE_TYPE_VALUE_DOUBLE + LIST_OFFSET), DECIMAL128_LIST(CORE_TYPE_VALUE_DECIMAL128 + LIST_OFFSET), OBJECT_ID_LIST(CORE_TYPE_VALUE_OBJECTID + LIST_OFFSET), UUID_LIST(CORE_TYPE_VALUE_UUID + LIST_OFFSET), MIXED_LIST(CORE_TYPE_VALUE_MIXED + LIST_OFFSET), STRING_TO_INTEGER_MAP(CORE_TYPE_VALUE_INTEGER + DICTIONARY_OFFSET), STRING_TO_BOOLEAN_MAP(CORE_TYPE_VALUE_BOOLEAN + DICTIONARY_OFFSET), STRING_TO_STRING_MAP(CORE_TYPE_VALUE_STRING + DICTIONARY_OFFSET), STRING_TO_BINARY_MAP(CORE_TYPE_VALUE_BINARY + DICTIONARY_OFFSET), STRING_TO_DATE_MAP(CORE_TYPE_VALUE_DATE + DICTIONARY_OFFSET), STRING_TO_FLOAT_MAP(CORE_TYPE_VALUE_FLOAT + DICTIONARY_OFFSET), STRING_TO_DOUBLE_MAP(CORE_TYPE_VALUE_DOUBLE + DICTIONARY_OFFSET), STRING_TO_DECIMAL128_MAP(CORE_TYPE_VALUE_DECIMAL128 + DICTIONARY_OFFSET), STRING_TO_OBJECT_ID_MAP(CORE_TYPE_VALUE_OBJECTID + DICTIONARY_OFFSET), STRING_TO_UUID_MAP(CORE_TYPE_VALUE_UUID + DICTIONARY_OFFSET), STRING_TO_MIXED_MAP(CORE_TYPE_VALUE_MIXED + DICTIONARY_OFFSET), STRING_TO_LINK_MAP(CORE_TYPE_VALUE_OBJECT + DICTIONARY_OFFSET), INTEGER_SET(CORE_TYPE_VALUE_INTEGER + SET_OFFSET), BOOLEAN_SET(CORE_TYPE_VALUE_BOOLEAN + SET_OFFSET), STRING_SET(CORE_TYPE_VALUE_STRING + SET_OFFSET), BINARY_SET(CORE_TYPE_VALUE_BINARY + SET_OFFSET), DATE_SET(CORE_TYPE_VALUE_DATE + SET_OFFSET), FLOAT_SET(CORE_TYPE_VALUE_FLOAT + SET_OFFSET), DOUBLE_SET(CORE_TYPE_VALUE_DOUBLE + SET_OFFSET), DECIMAL128_SET(CORE_TYPE_VALUE_DECIMAL128 + SET_OFFSET), OBJECT_ID_SET(CORE_TYPE_VALUE_OBJECTID + SET_OFFSET), UUID_SET(CORE_TYPE_VALUE_UUID + SET_OFFSET), LINK_SET(CORE_TYPE_VALUE_OBJECT + SET_OFFSET), MIXED_SET(CORE_TYPE_VALUE_MIXED + SET_OFFSET); // Primitive array for fast mapping between between native values and their Realm type. private static final RealmFieldType[] basicTypes = new RealmFieldType[MAX_CORE_TYPE_VALUE + 1]; private static final RealmFieldType[] listTypes = new RealmFieldType[MAX_CORE_TYPE_VALUE + 1]; private static final RealmFieldType[] mapTypes = new RealmFieldType[MAX_CORE_TYPE_VALUE + 1]; private static final RealmFieldType[] setTypes = new RealmFieldType[MAX_CORE_TYPE_VALUE + 1]; static { for (RealmFieldType columnType : values()) { final int nativeValue = columnType.nativeValue; if (nativeValue < LIST_OFFSET) { basicTypes[nativeValue] = columnType; } else if (nativeValue < SET_OFFSET) { listTypes[nativeValue - LIST_OFFSET] = columnType; } else if (nativeValue < DICTIONARY_OFFSET) { setTypes[nativeValue - SET_OFFSET] = columnType; } else { mapTypes[nativeValue - DICTIONARY_OFFSET] = columnType; } } } private final int nativeValue; RealmFieldType(int nativeValue) { this.nativeValue = nativeValue; } /** * Returns the native value representing this type. * * @return the value used by the underlying storage engine to represent this type. */ public int getNativeValue() { return nativeValue; } /** * Checks if the given Java object can be converted to the underlying Realm type. * * @param obj object to test compatibility on. * @return {@code true} if object can be converted to the Realm type, {@code false} otherwise. */ public boolean isValid(Object obj) { switch (nativeValue) { case CORE_TYPE_VALUE_INTEGER: return (obj instanceof Long || obj instanceof Integer || obj instanceof Short || obj instanceof Byte); case CORE_TYPE_VALUE_BOOLEAN: return (obj instanceof Boolean); case CORE_TYPE_VALUE_STRING: return (obj instanceof String); case CORE_TYPE_VALUE_BINARY: return (obj instanceof byte[] || obj instanceof ByteBuffer); case CORE_TYPE_VALUE_DATE: return (obj instanceof java.util.Date); case CORE_TYPE_VALUE_FLOAT: return (obj instanceof Float); case CORE_TYPE_VALUE_DOUBLE: return (obj instanceof Double); case CORE_TYPE_VALUE_DECIMAL128: return (obj instanceof Decimal128); case CORE_TYPE_VALUE_OBJECTID: return (obj instanceof ObjectId); case CORE_TYPE_VALUE_UUID: return (obj instanceof java.util.UUID); case CORE_TYPE_VALUE_MIXED: return (obj instanceof RealmAny); case CORE_TYPE_VALUE_OBJECT: case CORE_TYPE_VALUE_LIST: case CORE_TYPE_VALUE_LINKING_OBJECTS: case CORE_TYPE_VALUE_INTEGER + LIST_OFFSET: case CORE_TYPE_VALUE_BOOLEAN + LIST_OFFSET: case CORE_TYPE_VALUE_STRING + LIST_OFFSET: case CORE_TYPE_VALUE_BINARY + LIST_OFFSET: case CORE_TYPE_VALUE_DATE + LIST_OFFSET: case CORE_TYPE_VALUE_FLOAT + LIST_OFFSET: case CORE_TYPE_VALUE_DOUBLE + LIST_OFFSET: case CORE_TYPE_VALUE_DECIMAL128 + LIST_OFFSET: case CORE_TYPE_VALUE_OBJECTID + LIST_OFFSET: case CORE_TYPE_VALUE_UUID + LIST_OFFSET: case CORE_TYPE_VALUE_MIXED + LIST_OFFSET: return false; case CORE_TYPE_VALUE_INTEGER + DICTIONARY_OFFSET: case CORE_TYPE_VALUE_BOOLEAN + DICTIONARY_OFFSET: case CORE_TYPE_VALUE_STRING + DICTIONARY_OFFSET: case CORE_TYPE_VALUE_BINARY + DICTIONARY_OFFSET: case CORE_TYPE_VALUE_DATE + DICTIONARY_OFFSET: case CORE_TYPE_VALUE_FLOAT + DICTIONARY_OFFSET: case CORE_TYPE_VALUE_DOUBLE + DICTIONARY_OFFSET: case CORE_TYPE_VALUE_MIXED + DICTIONARY_OFFSET: case CORE_TYPE_VALUE_OBJECTID + DICTIONARY_OFFSET: case CORE_TYPE_VALUE_UUID + DICTIONARY_OFFSET: case CORE_TYPE_VALUE_DECIMAL128 + DICTIONARY_OFFSET: case CORE_TYPE_VALUE_OBJECT + DICTIONARY_OFFSET: return false; case CORE_TYPE_VALUE_INTEGER + SET_OFFSET: case CORE_TYPE_VALUE_BOOLEAN + SET_OFFSET: case CORE_TYPE_VALUE_STRING + SET_OFFSET: case CORE_TYPE_VALUE_BINARY + SET_OFFSET: case CORE_TYPE_VALUE_DATE + SET_OFFSET: case CORE_TYPE_VALUE_FLOAT + SET_OFFSET: case CORE_TYPE_VALUE_DOUBLE + SET_OFFSET: case CORE_TYPE_VALUE_DECIMAL128 + SET_OFFSET: case CORE_TYPE_VALUE_OBJECTID + SET_OFFSET: case CORE_TYPE_VALUE_UUID + SET_OFFSET: case CORE_TYPE_VALUE_OBJECT + SET_OFFSET: case CORE_TYPE_VALUE_MIXED + SET_OFFSET: return false; default: throw new RuntimeException("Unsupported Realm type: " + this); } } /** * Converts the underlying value used by the storage engine to the proper Realm type. * * @param value the value to convert * @return the corresponding Realm type. * @throws IllegalArgumentException if value isn't valid. */ public static RealmFieldType fromNativeValue(int value) { if (0 <= value && value < basicTypes.length) { RealmFieldType e = basicTypes[value]; if (e != null) { return e; } } if (LIST_OFFSET <= value && value < SET_OFFSET) { final int elementValue = value - LIST_OFFSET; if (elementValue < listTypes.length) { RealmFieldType e = listTypes[elementValue]; if (e != null) { return e; } } } if (SET_OFFSET <= value && value < DICTIONARY_OFFSET) { final int elementValue = value - SET_OFFSET; if (elementValue < setTypes.length) { RealmFieldType e = setTypes[elementValue]; if (e != null) { return e; } } } if (DICTIONARY_OFFSET <= value) { final int elementValue = value - DICTIONARY_OFFSET; if (elementValue < mapTypes.length) { RealmFieldType e = mapTypes[elementValue]; if (e != null) { return e; } } } throw new IllegalArgumentException("Invalid native Realm type: " + value); } }