/* * 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 java.util.Map; import java.util.Set; import io.realm.internal.ColumnIndices; import io.realm.internal.ColumnInfo; import io.realm.internal.Table; /** * Class for interacting with the Realm schema using a dynamic API. This makes it possible * to add, delete and change the classes in the Realm. * <p> * All changes must happen inside a write transaction for the particular Realm. * * @see RealmMigration */ public abstract class RealmSchema { private ColumnIndices columnIndices; // Cached field look up /** * Release the schema and any of native resources it might hold. */ public abstract void close(); /** * Returns the Realm schema for a given class. * * @param className name of the class * @return schema object for that class or {@code null} if the class doesn't exists. */ public abstract RealmObjectSchema get(String className); /** * Returns the {@link RealmObjectSchema}s for all RealmObject classes that can be saved in this Realm. * * @return the set of all classes in this Realm or no RealmObject classes can be saved in the Realm. */ public abstract Set<RealmObjectSchema> getAll(); /** * Adds a new class to the Realm. * * @param className name of the class. * @return a Realm schema object for that class. */ public abstract RealmObjectSchema create(String className); /** * Removes a class from the Realm. All data will be removed. Removing a class while other classes point * to it will throw an {@link IllegalStateException}. Removes those classes or fields first. * * @param className name of the class to remove. */ public abstract void remove(String className); /** * Renames a class already in the Realm. * * @param oldClassName old class name. * @param newClassName new class name. * @return a schema object for renamed class. */ public abstract RealmObjectSchema rename(String oldClassName, String newClassName); /** * Checks if a given class already exists in the schema. * * @param className class name to check. * @return {@code true} if the class already exists. {@code false} otherwise. */ public abstract boolean contains(String className); abstract Table getTable(Class<? extends RealmModel> clazz); abstract Table getTable(String className); abstract RealmObjectSchema getSchemaForClass(Class<? extends RealmModel> clazz); abstract RealmObjectSchema getSchemaForClass(String className); /** * Set the column index cache for this schema. * * @param columnIndices the column index cache */ final void setInitialColumnIndices(ColumnIndices columnIndices) { if (this.columnIndices != null) { throw new IllegalStateException("An instance of ColumnIndices is already set."); } this.columnIndices = new ColumnIndices(columnIndices, true); } /** * Set the column index cache for this schema. * * @param version the schema version * @param columnInfoMap the column info map */ final void setInitialColumnIndices(long version, Map<Class<? extends RealmModel>, ColumnInfo> columnInfoMap) { if (this.columnIndices != null) { throw new IllegalStateException("An instance of ColumnIndices is already set."); } columnIndices = new ColumnIndices(version, columnInfoMap); } /** * Updates all {@link ColumnInfo} elements in {@code columnIndices}. * <p> * The ColumnInfo elements are shared between all {@link RealmObject}s created by the Realm instance * which owns this RealmSchema. Updating them also means updating indices information in those {@link RealmObject}s. * * @param schemaVersion new schema version. */ void updateColumnIndices(ColumnIndices schemaVersion) { columnIndices.copyFrom(schemaVersion); } final boolean isProxyClass(Class<? extends RealmModel> modelClass, Class<? extends RealmModel> testee) { return modelClass.equals(testee); } /** * Sometimes you need ColumnIndicies that can be passed between threads. * Setting the mutable flag false creates an instance that is effectively final. * * @return a new, thread-safe copy of this Schema's ColumnIndices. * @see ColumnIndices for the effectively final contract. */ final ColumnIndices getImmutableColumnIndicies() { checkIndices(); return new ColumnIndices(columnIndices, false); } final boolean haveColumnInfo() { return columnIndices != null; } final long getSchemaVersion() { checkIndices(); return columnIndices.getSchemaVersion(); } final ColumnInfo getColumnInfo(Class<? extends RealmModel> clazz) { checkIndices(); return columnIndices.getColumnInfo(clazz); } protected final ColumnInfo getColumnInfo(String className) { checkIndices(); return columnIndices.getColumnInfo(className); } private void checkIndices() { if (!haveColumnInfo()) { throw new IllegalStateException("Attempt to use column index before set."); } } }