/*
* Copyright 2013 cruxframework.org.
*
* 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 org.cruxframework.crux.core.client.db;
import org.cruxframework.crux.core.client.db.Cursor.CursorDirection;
import org.cruxframework.crux.core.client.db.annotation.DatabaseDef;
import org.cruxframework.crux.core.client.db.annotation.DatabaseDef.IndexDef;
import org.cruxframework.crux.core.client.db.annotation.DatabaseDef.ObjectStoreDef;
import org.cruxframework.crux.core.client.db.annotation.Store;
import org.cruxframework.crux.core.client.db.annotation.Store.Indexed;
import org.cruxframework.crux.core.client.db.annotation.Store.Key;
/**
* <p>Represents an index into this database. Indexes increases searching performance considerably.</p>
*
* <p>
* You can define an index for an object store, using three different strategies:
* </p>
* <p>
* 1) Through {@code @}{@link IndexDef} annotation os yor Database interface.
* <pre>
* {@code @}{@link DatabaseDef}(name="CruxCompanyDatabase", version=1
* objectStores={{@code @}{@link ObjectStoreDef}(targetClass=Person.class,
* indexes={{@code @}{@link IndexDef}(name="myIndex", keyPath={"name"}, unique=true)})
* }
* )
* public interface CompanyDatabase extends Database{
* }
* </pre>
* </p>
* <p>
* 2) Through {@code @}{@link IndexDef} annotation on your Store object.
* <pre>
* {@code @}{@link Store}(value=Person.STORE_NAME, indexes={{@code @}{@link IndexDef}(name="myIndex", keyPath={"name", "age"}, unique=true)})
* public class Person {
* public static final String STORE_NAME = "Person";
* private Integer id;
* private String name;
* private int age;
*
* {@code @}{@link Key}
* public Integer getId(){return id;}
* public void setId(Integer id){this.id = id;}
* public String getName(){return name;}
* public void setName(String name){this.name = name;}
* public int getAge(){return age;}
* public void setAge(int age){this.age = age;}
* }
* </pre>
* </p>
* <p>
* 3) Through {@code @}{@link Indexed} annotation on the property of your Store object.
* <pre>
* {@code @}{@link Store}(Person.STORE_NAME))
* public class Person {
* public static final String STORE_NAME = "Person";
* private Integer id;
* private String name;
* private int age;
*
* {@code @}{@link Key}
* public Integer getId(){return id;}
* public void setId(Integer id){this.id = id;}
* {@code @}{@link Indexed}(unique=true)
* public String getName(){return name;}
* public void setName(String name){this.name = name;}
* public int getAge(){return age;}
* public void setAge(int age){this.age = age;}
* }
* </pre>
* </p>
* <p>
* Once defined, you can access the index to perform faster search operations:
* </p>
* <pre>
* Transaction transaction = database.getTransaction(new String[]{Person.STORE_NAME}, Mode.readOnly);
* ObjectStore{@code <Integer, Person>} personStore = transaction.getObjectStore(Person.STORE_NAME);
* Index{@code <Integer, String, Person>} nameIndex = personStore.getIndex("name");
* nameIndex.get(35, new DatabaseRetrieveCallback{@code <Person>}() {
* {@code @}Override
* public void onSuccess(Person person){
* // ...
* }
* });
* </pre>
*
* @param <K> object key type
* @param <I> index key type. The type of the indexed column
* @param <V> object type
* @author Thiago da Rosa de Bustamante
*/
public abstract class Index<K, I, V> extends DBObject
{
/**
* Constructor
* @param db database
*/
protected Index(AbstractDatabase db)
{
super(db);
}
/**
* Retrieve the index name
* @return index name
*/
public abstract String getName();
/**
* Retrieve true if each key inside the index must be unique.
* If an unique index exists for an object store, any add or put operation that violates
* this index constraints will fail.
* @return true if index is unique
*/
public abstract boolean isUnique();
/**
* This flag affects how the index behaves when the result of evaluating the index's key path yields an Array.
* If the multiEntry flag is false, then a single record whose key is an Array is added to the index.
* If the multiEntry flag is true, then the one record is added to the index for each item in the Array.
* @return true if this is a multi entry index.
*/
public abstract boolean isMultiEntry();
/**
* Return the number of items referenced by the index.
* @param callback called when the operation complete
*/
public abstract void count(DatabaseCountCallback callback);
/**
* Return the number of items referenced by the index in the given range.
* @param keyRange an object specifying the indexed property range to count
* @param callback called when the operation complete
*/
public abstract void count(KeyRange<I> range, DatabaseCountCallback callback);
/**
* Retrieve the object associated with the given key from the index. To read the object,
* use the method onSuccess from {@link DatabaseRetrieveCallback}.
* @param key index key
* @param callback called when the operation complete
*/
public abstract void get(I key, DatabaseRetrieveCallback<V> callback);
/**
* Retrieve the object in the given keyRange from the index. To read the object,
* use the method onSuccess from {@link DatabaseRetrieveCallback}.
* @param keyRange an object specifying the indexed property range. The first item from the range will be retrieved.
* @param callback called when the operation complete
*/
public abstract void get(KeyRange<I> keyRange, DatabaseRetrieveCallback<V> callback);
/**
* Retrieve the object key associated with the given key from the index. To read the object,
* use the method onSuccess from {@link DatabaseRetrieveCallback}.
* @param key index key
* @param callback called when the operation complete
*/
public abstract void getKey(I key, DatabaseRetrieveCallback<K> callback);
/**
* Retrieve the object key in the given keyRange from the index. To read the object,
* use the method onSuccess from {@link DatabaseRetrieveCallback}.
* @param keyRange an object specifying the indexed property range. The first item from the range will be retrieved.
* @param callback called when the operation complete
*/
public abstract void getKey(KeyRange<I> keyRange, DatabaseRetrieveCallback<K> callback);
/**
* Open a cursor to iterate over the object store.
* @param callback called when the operation complete
*/
public abstract void openCursor(DatabaseCursorCallback<I, V> callback);
/**
* Open a cursor to iterate over the object store.
* @param keyRange an object specifying the indexed property range, used to filter the query.
* @param callback called when the operation complete
*/
public abstract void openCursor(KeyRange<I> keyRange, DatabaseCursorCallback<I, V> callback);
/**
* Open a cursor to iterate over the object store.
* @param keyRange an object specifying the indexed property range, used to filter the query.
* @param direction specifies the cursor iteration direction
* @param callback called when the operation complete
*/
public abstract void openCursor(KeyRange<I> keyRange, CursorDirection direction, DatabaseCursorCallback<I, V> callback);
/**
* Open a cursor to iterate over the objects keys into the store.
* @param callback called when the operation complete
*/
public abstract void openKeyCursor(DatabaseCursorCallback<I, K> callback);
/**
* Open a cursor to iterate over the objects keys into the store.
* @param keyRange an object specifying the indexed property range, used to filter the query.
* @param callback called when the operation complete
*/
public abstract void openKeyCursor(KeyRange<I> keyRange, DatabaseCursorCallback<I, K> callback);
/**
* Open a cursor to iterate over the objects keys into the store.
* @param keyRange an object specifying the indexed property range, used to filter the query.
* @param direction specifies the cursor iteration direction
* @param callback called when the operation complete
*/
public abstract void openKeyCursor(KeyRange<I> keyRange, CursorDirection direction, DatabaseCursorCallback<I, K> callback);
/**
* Creates a factory for {@link KeyRange} objects used by this index.
* @return the factory
*/
public abstract KeyRangeFactory<I> getKeyRangeFactory();
}