com.couchbase.lite.View Maven / Gradle / Ivy
/**
* Original iOS version by Jens Alfke
* Ported to Android by Marty Schoch
*
* Copyright (c) 2012 Couchbase, Inc. All rights reserved.
*
* 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 com.couchbase.lite;
import com.couchbase.lite.internal.InterfaceAudience;
import com.couchbase.lite.store.ViewStore;
import com.couchbase.lite.store.ViewStoreDelegate;
import com.couchbase.lite.util.Log;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Represents a view available in a database.
*/
public final class View implements ViewStoreDelegate {
public enum TDViewCollation {
TDViewCollationUnicode, TDViewCollationRaw, TDViewCollationASCII
}
// Defined in CBLView.h
private Database database;
private String name;
private Mapper mapBlock;
private Reducer reduceBlock;
private String version; // TODO: iOS version store version information in CBL_Shared.
private static ViewCompiler compiler;
private ViewStore viewStore;
///////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////
@InterfaceAudience.Private
protected View(Database database, String name, boolean create) throws CouchbaseLiteException {
this.database = database;
this.name = name;
this.viewStore = database.getStore().getViewStorage(name, create);
if (this.viewStore == null)
throw new CouchbaseLiteException(Status.NOT_FOUND);
this.viewStore.setDelegate(this);
}
///////////////////////////////////////////////////////////////////////////
// Implementation of ViewStorageDelegate
///////////////////////////////////////////////////////////////////////////
/**
* The map function that controls how index rows are created from documents.
*/
@Override
@InterfaceAudience.Public
public Mapper getMap() {
return mapBlock;
}
/**
* The optional reduce function, which aggregates together multiple rows.
*/
@Override
@InterfaceAudience.Public
public Reducer getReduce() {
return reduceBlock;
}
@Override
public String getMapVersion() {
// TODO: Should be from CBL_Shared
return version;
}
/**
* Get document type.
*/
@Override
public String getDocumentType() {
return database.getViewDocumentType(name);
}
/**
* Set document type. If the document type is set, only documents whose "type" property
* is equal to its value will be passed to the map block and indexed. This can speed up indexing.
* Just like the map block, this property is not persistent; it needs to be set at runtime before
* the view is queried. And if its value changes, the view's version also needs to change.
*/
public void setDocumentType(String docType) {
database.setViewDocumentType(docType, name);
}
///////////////////////////////////////////////////////////////////////////
// API (CBLView.h/CBLView.m)
///////////////////////////////////////////////////////////////////////////
/**
* Get the database that owns this view.
*/
@InterfaceAudience.Private
protected Database getDatabase() {
return database;
}
/**
* Get the name of the view.
*/
@InterfaceAudience.Public
public String getName() {
return name;
}
/**
* Defines a view's functions.
*
* The view's definition is given as a class that conforms to the Mapper or
* Reducer interface (or null to delete the view). The body of the block
* should call the 'emit' object (passed in as a paramter) for every key/value pair
* it wants to write to the view.
*
* Since the function itself is obviously not stored in the database (only a unique
* string idenfitying it), you must re-define the view on every launch of the app!
* If the database needs to rebuild the view but the function hasn't been defined yet,
* it will fail and the view will be empty, causing weird problems later on.
*
* It is very important that this block be a law-abiding map function! As in other
* languages, it must be a "pure" function, with no side effects, that always emits
* the same values given the same input document. That means that it should not access
* or change any external state; be careful, since callbacks make that so easy that you
* might do it inadvertently! The callback may be called on any thread, or on
* multiple threads simultaneously. This won't be a problem if the code is "pure" as
* described above, since it will as a consequence also be thread-safe.
*/
@InterfaceAudience.Public
public boolean setMapReduce(Mapper mapBlock, Reducer reduceBlock, String version) {
assert (mapBlock != null);
assert (version != null);
boolean changed = (this.version == null || !this.version.equals(version));
this.mapBlock = mapBlock;
this.reduceBlock = reduceBlock;
this.version = version;
viewStore.setVersion(version); // for SQLite
return changed;
}
/**
* Defines a view that has no reduce function.
* See setMapReduce() for more information.
*/
@InterfaceAudience.Public
public boolean setMap(Mapper mapBlock, String version) {
return setMapReduce(mapBlock, null, version);
}
/**
* Is the view's index currently out of date?
*/
@InterfaceAudience.Public
public boolean isStale() {
return (viewStore.getLastSequenceIndexed() < database.getLastSequenceNumber());
}
/**
* Get total number of rows in the view. The view's index will be updated if needed
* before returning the value.
*/
@InterfaceAudience.Public
public int getTotalRows() {
try {
updateIndex();
} catch (CouchbaseLiteException e) {
Log.e(Log.TAG_VIEW, "Update index failed when getting the total rows", e);
}
return getCurrentTotalRows();
}
/**
* Get the last sequence number indexed so far.
*/
@InterfaceAudience.Public
public long getLastSequenceIndexed() {
return viewStore.getLastSequenceIndexed();
}
/**
* Deletes the view's persistent index. It will be regenerated on the next query.
*/
@InterfaceAudience.Public
public void deleteIndex() {
viewStore.deleteIndex();
}
/**
* Deletes the view, persistently.
*
* NOTE: It should be - (void) deleteView;
*/
@InterfaceAudience.Public
public void delete() {
if (viewStore != null)
viewStore.deleteView();
if (database != null && name != null)
database.forgetView(name);
close();
}
/**
* Creates a new query object for this view. The query can be customized and then executed.
*/
@InterfaceAudience.Public
public Query createQuery() {
return new Query(database, this);
}
/**
* Utility function to use in reduce blocks. Totals an array of Numbers.
*/
@InterfaceAudience.Public
public static double totalValues(List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy