public abstract class IndexProvider extends Object
indexes
that are described/defined with
IndexDefinition
objects via the session's IndexManager
. This provider uses each IndexDefinition
to
define and manage the Index
es for each workspace identified by the definition. Much of this management is the same for
all providers, so this implementation provides much of that functionality. What each custom provider must do, then, is respond
to the createIndex(org.modeshape.jcr.api.index.IndexDefinition, java.lang.String, org.modeshape.jcr.NodeTypes.Supplier, org.modeshape.jcr.cache.change.ChangeSetAdapter.NodeTypePredicate, org.modeshape.jcr.spi.index.IndexFeedback)
, updateIndex(org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.spi.index.provider.ManagedIndex, java.lang.String, org.modeshape.jcr.NodeTypes.Supplier, org.modeshape.jcr.cache.change.ChangeSetAdapter.NodeTypePredicate, org.modeshape.jcr.spi.index.IndexFeedback)
, removeIndex(org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.spi.index.provider.ManagedIndex, java.lang.String)
methods and return an appropriate ManagedIndex
object that behaves as described by the method parameters. While the Index
represents the functionality needed by the
query engine, the ManagedIndex
is the lowest-level and simplest interface to encapsulate the behavior of a single index
managed by this provider. for each Only basic functionality is provided, and subclasses specialize the behavior by overriding
several abstract methods.
Upon startup, the repository examines its configuration and sets up each of the index providers using this sequence:
initialize()
method. This method is final and delegates to doInitialize()
, which can be
specialized for any implementation-specific startup behavior.IndexDefinition
s, whether they are defined in the configuration or persisted in
the repository's system area, by calling
notify(IndexDefinitionChanges, ChangeBus, org.modeshape.jcr.NodeTypes.Supplier, Set, IndexFeedback)
. This method
processes all of the definition changes, and based upon the available workspaces, calls the createIndex(org.modeshape.jcr.api.index.IndexDefinition, java.lang.String, org.modeshape.jcr.NodeTypes.Supplier, org.modeshape.jcr.cache.change.ChangeSetAdapter.NodeTypePredicate, org.modeshape.jcr.spi.index.IndexFeedback)
,
updateIndex(org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.spi.index.provider.ManagedIndex, java.lang.String, org.modeshape.jcr.NodeTypes.Supplier, org.modeshape.jcr.cache.change.ChangeSetAdapter.NodeTypePredicate, org.modeshape.jcr.spi.index.IndexFeedback)
, and removeIndex(org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.spi.index.provider.ManagedIndex, java.lang.String)
methods for each index/workspace combination. Each of these methods can request
via the IndexFeedback
method parameter that all or parts of the repository content be scanned and re-indexed. (The
repository does the scanning efficiently: if multiple providers request that the entire repository be scanned, the repository
will index the content only once.) Also, each ManagedIndex
resulting from these methods will be given its own even
listener, and this is how the indexes are notified of changes in content (see below).
getIndexWriter()
and use the IndexWriter
to
notify the index(es) of the content.IndexManager
will alter the IndexDefinition
s index definitions. As
these changes are persisted, the repository will call the
notify(IndexDefinitionChanges, ChangeBus, org.modeshape.jcr.NodeTypes.Supplier, Set, IndexFeedback)
again, this time
with only the changes that were made to this provider's index definitions. If a new workspace is added or an existing workspace
is removed, ModeShape will called
notify(WorkspaceChanges, ChangeBus, org.modeshape.jcr.NodeTypes.Supplier, Set, IndexFeedback)
with the relevant
information to allow the provider to respond.
As sessions persist changes to content (via javax.jcr.Session#save() or by committing user transactions), the repository's
event bus will notify each ManagedIndex
(via its writing adapter
) of these
changes. This writing adapter is also used during manual re-indexing of content.
When queries are submitted, ModeShape will call getIndexPlanner()
to obtain the planner that should determine for each
portion of the query which indexes (if any) apply to that part of the query. When a particular index is to be used within a
query, ModeShape will then call getIndex(String,String)
and use it to answer the portion of the query.
Implementing custom providers is fairly straightforward: simply extend this class, provide implementations for the abstract methods, and optionally override the default implementations for the other non-final methods.
Modifier and Type | Class and Description |
---|---|
static interface |
IndexProvider.ManagedIndexOperation
An operation that performs on a managed index with the associated index definition.
|
Modifier and Type | Field and Description |
---|---|
static int |
DEFAULT_BATCH_SIZE
The default number of rows in a batch.
|
Modifier | Constructor and Description |
---|---|
protected |
IndexProvider() |
protected |
IndexProvider(IndexPlanner planner) |
Modifier and Type | Method and Description |
---|---|
int |
batchSize()
Get the default number of rows in a batch.
|
protected ExecutionContext |
context()
Get the context in which this provider executes.
|
protected ManagedIndex |
createIndex(IndexDefinition defn,
String workspaceName,
NodeTypes.Supplier nodeTypesSupplier,
ChangeSetAdapter.NodeTypePredicate matcher,
IndexFeedback feedback)
Method called when this provider needs to create a new index given the unique pair of workspace name and index definition.
|
protected abstract void |
doInitialize()
Method that should do the provider-specific initialization work.
|
protected Environment |
environment()
Get the repository's running environment
|
protected IndexUsage |
evaluateUsage(QueryContext context,
IndexCostCalculator calculator,
IndexDefinition defn)
Returns an object which is used during the planning phase to evaluate if a certain index should be used or not.
|
protected int |
getCostEstimate()
Returns a positive number representing the cost estimate of using indexes from this provider.
|
Index |
getIndex(String indexName,
String workspaceName)
Get the queryable index with the given name and applicable for the given workspace.
|
protected ManagedIndexBuilder |
getIndexBuilder(IndexDefinition defn,
String workspaceName,
NodeTypes.Supplier nodeTypesSupplier,
ChangeSetAdapter.NodeTypePredicate matcher)
Offers subclasses the possibility of providing a
ManagedIndexBuilder instance which significantly simplifies the
task of creating or updating ManagedIndex instances for providers. |
protected Iterable<ManagedIndex> |
getIndexes(String workspaceName)
Get this provider's
ManagedIndex instances for the given workspace. |
Set<String> |
getIndexNames()
Get all the index definition names belonging to this provider.
|
IndexPlanner |
getIndexPlanner()
Get the planner that, during the query planning/optimization phase, evaluates for a single source the AND-ed query
constraints and defines indexes that may be used.
|
IndexWriter |
getIndexWriter()
Get the writer that ModeShape can use to regenerate the indexes when a portion of the repository is to be re-indexed.
|
Long |
getLatestIndexUpdateTime()
Return the latest time at which this provider successfully updated its indexes.
|
ManagedIndex |
getManagedIndex(String indexName,
String workspaceName)
Get the managed index with the given name and applicable for the given workspace.
|
String |
getName()
Get the name for this provider.
|
String |
getRepositoryName()
Get the name of the repository.
|
void |
initialize()
Initialize the provider.
|
protected boolean |
isType(PropertyType propType,
PropertyType expected) |
protected Logger |
logger() |
protected boolean |
matches(ExecutionContext context,
IndexColumnDefinition defn,
Name name) |
protected boolean |
matches(ExecutionContext context,
String actual,
Name name) |
protected NameFactory |
names() |
protected NamespaceRegistry |
namespaces()
Get the namespace registry for the provider's
execution context , and which can be used to convert
qualified names (e.g., "jcr:description ") to unqualified names (or vice versa). |
void |
notify(IndexDefinitionChanges changes,
ChangeBus observable,
NodeTypes.Supplier nodeTypesSupplier,
Set<String> workspaceNames,
IndexFeedback feedback)
Signal that some of the definitions of indexes owned by this provider were changed.
|
void |
notify(NodeTypes updatedNodeTypes)
Notify the provider that the NodeTypes have changed.
|
void |
notify(WorkspaceChanges changes,
ChangeBus observable,
NodeTypes.Supplier nodeTypesSupplier,
Set<String> workspaceNames,
IndexFeedback feedback)
Signal that some workspaces were added or removed.
|
protected void |
onEachIndex(IndexProvider.ManagedIndexOperation op)
Perform the specified operation on each of the managed indexes.
|
void |
onEachIndexInWorkspace(String workspaceName,
IndexProvider.ManagedIndexOperation op)
Perform the specified operation on each of the managed indexes in the named workspace.
|
protected void |
planUseOfIndex(QueryContext context,
IndexCostCalculator calculator,
String workspaceName,
ManagedIndex index,
IndexDefinition defn)
The method that is called by the IndexProvider's
default IndexPlanner for each
managed index in the given workspace. |
protected void |
postShutdown()
Method called during #shutdown() after each of the managed indexes have been shutdown.
|
protected void |
preShutdown()
Method called immediately when #shutdown() is invoked, before any other operations are performed and before the managed
indexes are each shutdown.
|
protected void |
removeIndex(IndexDefinition oldDefn,
ManagedIndex existingIndex,
String workspaceName)
Method called when this provider needs to remove an existing index given the unique pair of workspace name and index
definition.
|
void |
shutdown()
Signal this provider that it is no longer needed and can release any resources that are being held.
|
protected ManagedIndex |
updateIndex(IndexDefinition oldDefn,
IndexDefinition updatedDefn,
ManagedIndex existingIndex,
String workspaceName,
NodeTypes.Supplier nodeTypesSupplier,
ChangeSetAdapter.NodeTypePredicate matcher,
IndexFeedback feedback)
Method called when this provider needs to update an existing index given the unique pair of workspace name and index
definition.
|
protected void |
validateDefaultColumnDefinitionType(ExecutionContext context,
IndexDefinition defn,
IndexColumnDefinition columnDefn,
Problems problems) |
void |
validateDefaultColumnTypes(ExecutionContext context,
IndexDefinition defn,
Problems problems)
Validates that if certain default columns are present in the index definition, they have a required type.
|
void |
validateProposedIndex(ExecutionContext context,
IndexDefinition defn,
NodeTypes.Supplier nodeTypesSupplier,
Problems problems)
Validate the proposed index definition, and use the supplied problems to report any issues that will prevent this provider
from creating and using an index with the given definition.
|
protected ValueFactories |
valueFactories()
Get the container for the type-specific factories useful to convert values that will be written to the index.
|
public static final int DEFAULT_BATCH_SIZE
protected IndexProvider()
protected IndexProvider(IndexPlanner planner)
protected final Logger logger()
public final String getName()
public final String getRepositoryName()
public int batchSize()
public Set<String> getIndexNames()
Set
of index namesprotected final ExecutionContext context()
initialization
by ModeShape,
and never changed.protected final Environment environment()
Environment
instance, never null.public final void initialize() throws RepositoryException
RepositoryException
- if there is a problem initializing the providerprotected abstract void doInitialize() throws RepositoryException
By the time this method is called, ModeShape will hav already set the context
, logger
, name
, and
repositoryName
plus any fields that match configuration properties for the provider.
This is an excellent place for providers to validate the provider-specific fields set by ModeShape via reflection during instantiation.
RepositoryException
- if there is a problem initializing the providerpublic final void shutdown() throws RepositoryException
RepositoryException
- if there is a problem shutting down the providerprotected void preShutdown() throws RepositoryException
RepositoryException
- if there is a problem shutting down the providerprotected void postShutdown() throws RepositoryException
RepositoryException
- if there is a problem shutting down the providerpublic void notify(NodeTypes updatedNodeTypes)
updatedNodeTypes
- the new node types; may not be nullpublic void validateProposedIndex(ExecutionContext context, IndexDefinition defn, NodeTypes.Supplier nodeTypesSupplier, Problems problems)
This should only be implemented if the provider has any particular validation requirements (for example it doesn't support
multiple columns or certain index types). The repository will perform for all index definitions some basic validations
via validateDefaultColumnTypes(ExecutionContext, IndexDefinition, Problems)
context
- the execution context in which to perform the validation; never nulldefn
- the proposed index definition; never nullnodeTypesSupplier
- the supplier for the NodeTypes object that contains information about the currently-registered
node types; never nullproblems
- the problems that should be used to report any issues with the index definition; never nullpublic void validateDefaultColumnTypes(ExecutionContext context, IndexDefinition defn, Problems problems)
context
- the execution context in which to perform the validation; never nulldefn
- the proposed index definition; never nullproblems
- the component to record any problems, errors, or warnings; may not be nullprotected void validateDefaultColumnDefinitionType(ExecutionContext context, IndexDefinition defn, IndexColumnDefinition columnDefn, Problems problems)
protected final boolean matches(ExecutionContext context, IndexColumnDefinition defn, Name name)
protected final boolean matches(ExecutionContext context, String actual, Name name)
protected final boolean isType(PropertyType propType, PropertyType expected)
public final IndexWriter getIndexWriter()
public final Index getIndex(String indexName, String workspaceName)
indexName
- the name of the index in this provider; never nullworkspaceName
- the name of the workspace; never nullpublic final ManagedIndex getManagedIndex(String indexName, String workspaceName)
indexName
- the name of the index in this provider; never nullworkspaceName
- the name of the workspace; never nullpublic Long getLatestIndexUpdateTime()
Long
instance which either contains the latest update time or null
which means that
this provider does not support incremental reindexing.protected final Iterable<ManagedIndex> getIndexes(String workspaceName)
ManagedIndex
instances for the given workspace.workspaceName
- the name of the workspace; may not be nullprotected final void onEachIndex(IndexProvider.ManagedIndexOperation op)
op
- the operation; may not be nullpublic final void onEachIndexInWorkspace(String workspaceName, IndexProvider.ManagedIndexOperation op)
workspaceName
- the name of the workspace; may not be nullop
- the operation; may not be nullprotected void planUseOfIndex(QueryContext context, IndexCostCalculator calculator, String workspaceName, ManagedIndex index, IndexDefinition defn)
default IndexPlanner
for each
managed index in the given workspace.
Subclasses can implement this method to determine and record whether the supplied index can be used by the query against
the named workspace, but usually the default implementation should be good enough. Subclasses should really only implement
the evaluateUsage(QueryContext, IndexCostCalculator, IndexDefinition)
method.
IndexUsage
class is useful to determine for a given index definition whether criteria is applicable.context
- the context of the original query; never nullcalculator
- the calculator that should be used to record plan information for the index; never nullworkspaceName
- the name of the workspace against which the query is operating; never nullindex
- the managed index in the given workspace; never nulldefn
- the definition for the index; never nullprotected IndexUsage evaluateUsage(QueryContext context, IndexCostCalculator calculator, IndexDefinition defn)
context
- the context of the original query; never nullcalculator
- the calculator that should be used to record plan information for the index; never nulldefn
- the definition for the index; never nullIndexUsage
instance, or null
which is the default and which indicates that a provider chooses
to override the planUseOfIndex(QueryContext, IndexCostCalculator, String, ManagedIndex, IndexDefinition)
methodplanUseOfIndex(QueryContext, IndexCostCalculator, String, ManagedIndex, IndexDefinition)
protected int getCostEstimate()
IndexCostCalculator.Costs
public final IndexPlanner getIndexPlanner()
This method is typically called only once after the provider has been initialized
.
protected final NamespaceRegistry namespaces()
execution context
, and which can be used to convert
qualified names (e.g., "jcr:description
") to unqualified names (or vice versa).protected final ValueFactories valueFactories()
protected final NameFactory names()
public final void notify(WorkspaceChanges changes, ChangeBus observable, NodeTypes.Supplier nodeTypesSupplier, Set<String> workspaceNames, IndexFeedback feedback)
This method examines the supplied workspace additions and removals
, and updates the internal state
of this provider. It will then call the createIndex(org.modeshape.jcr.api.index.IndexDefinition, java.lang.String, org.modeshape.jcr.NodeTypes.Supplier, org.modeshape.jcr.cache.change.ChangeSetAdapter.NodeTypePredicate, org.modeshape.jcr.spi.index.IndexFeedback)
, updateIndex(org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.spi.index.provider.ManagedIndex, java.lang.String, org.modeshape.jcr.NodeTypes.Supplier, org.modeshape.jcr.cache.change.ChangeSetAdapter.NodeTypePredicate, org.modeshape.jcr.spi.index.IndexFeedback)
, or removeIndex(org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.spi.index.provider.ManagedIndex, java.lang.String)
methods for
each of the affected indexes.
changes
- the changes in the workspaces; never nullobservable
- the Observable object with which an index can register a listener for changes; this is the only mechanism
by which the indexes can be updatednodeTypesSupplier
- the supplier from which can be very efficiently obtained the latest snapshot of
node types
useful in determining if changes on a node are to be included in an index of a particular
index node type
.workspaceNames
- the names of all workspaces in this repository; never null and likely never nullfeedback
- the feedback mechanism for this provider to signal to ModeShape that one or more indexes need to be
entirely or partially rebuilt via scanning; never nullpublic final void notify(IndexDefinitionChanges changes, ChangeBus observable, NodeTypes.Supplier nodeTypesSupplier, Set<String> workspaceNames, IndexFeedback feedback)
This method examines the supplied changes
, current workspaces, and maintains the internal
state of this provider. It will then call the createIndex(org.modeshape.jcr.api.index.IndexDefinition, java.lang.String, org.modeshape.jcr.NodeTypes.Supplier, org.modeshape.jcr.cache.change.ChangeSetAdapter.NodeTypePredicate, org.modeshape.jcr.spi.index.IndexFeedback)
, updateIndex(org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.spi.index.provider.ManagedIndex, java.lang.String, org.modeshape.jcr.NodeTypes.Supplier, org.modeshape.jcr.cache.change.ChangeSetAdapter.NodeTypePredicate, org.modeshape.jcr.spi.index.IndexFeedback)
, or removeIndex(org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.spi.index.provider.ManagedIndex, java.lang.String)
methods
for each of the affected indexes.
changes
- the changes in the definitions; never nullobservable
- the Observable object with which an index can register a listener for changes; this is the only mechanism
by which the indexes can be updatednodeTypesSupplier
- the supplier from which can be very efficiently obtained the latest snapshot of
node types
useful in determining if changes on a node are to be included in an index of a particular
index node type
.workspaceNames
- the names of all workspaces in this repository; never null and likely never nullfeedback
- the feedback mechanism for this provider to signal to ModeShape that one or more indexes need to be
entirely or partially rebuilt via scanning; never nullprotected ManagedIndex createIndex(IndexDefinition defn, String workspaceName, NodeTypes.Supplier nodeTypesSupplier, ChangeSetAdapter.NodeTypePredicate matcher, IndexFeedback feedback)
Providers may either choose to implement this method and therefore have full control over the logic of creating managed indexes
or simply implement the #getIndexBuilder(IndexDefinition, String, NodeTypes.Supplier, NodeTypePredicate)
method which is the easier route and provides some built-in defaults.
defn
- the definition of the index; never nullworkspaceName
- the name of the actual workspace to which the new index applies; never nullnodeTypesSupplier
- the supplier for the current node types cache; never nullmatcher
- the node type matcher used to determine which nodes should be included in the index, and which automatically
updates when node types are changed in the repository; may not be nullfeedback
- the feedback mechanism for this provider to signal to ModeShape that portions of the repository content
must be scanned to build/populate the new index; never nullManagedIndex
for the new index; may not be nullprotected ManagedIndex updateIndex(IndexDefinition oldDefn, IndexDefinition updatedDefn, ManagedIndex existingIndex, String workspaceName, NodeTypes.Supplier nodeTypesSupplier, ChangeSetAdapter.NodeTypePredicate matcher, IndexFeedback feedback)
Providers may either choose to implement this method and therefore have full control over the logic of updating managed indexes
or simply implement the #getIndexBuilder(IndexDefinition, String, NodeTypes.Supplier, NodeTypePredicate)
method which is the easier route and provides a built-in logic which will first destroy the existing (old) index and then
create and register a new one via the builder.
oldDefn
- the previous definition of the index; never nullupdatedDefn
- the updated definition of the index; never nullexistingIndex
- the existing index prior to this update, as returned from createIndex(org.modeshape.jcr.api.index.IndexDefinition, java.lang.String, org.modeshape.jcr.NodeTypes.Supplier, org.modeshape.jcr.cache.change.ChangeSetAdapter.NodeTypePredicate, org.modeshape.jcr.spi.index.IndexFeedback)
or updateIndex(org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.spi.index.provider.ManagedIndex, java.lang.String, org.modeshape.jcr.NodeTypes.Supplier, org.modeshape.jcr.cache.change.ChangeSetAdapter.NodeTypePredicate, org.modeshape.jcr.spi.index.IndexFeedback)
; never nullworkspaceName
- the name of the actual workspace to which the new index applies; never nullnodeTypesSupplier
- the supplier for the current node types cache; never nullmatcher
- the node type matcher used to determine which nodes should be included in the index, and which automatically
updates when node types are changed in the repository; may not be nullfeedback
- the feedback mechanism for this provider to signal to ModeShape that portions of the repository content
must be scanned to rebuild/repopulate the updated index; never nullprotected void removeIndex(IndexDefinition oldDefn, ManagedIndex existingIndex, String workspaceName)
The default implementation is to simply delegate the call to a specific index's
Lifecycle.shutdown(boolean)
method, indicating that the index should be destroyed.
oldDefn
- the previous definition of the index; never nullexistingIndex
- the existing index prior to this update, as returned from createIndex(org.modeshape.jcr.api.index.IndexDefinition, java.lang.String, org.modeshape.jcr.NodeTypes.Supplier, org.modeshape.jcr.cache.change.ChangeSetAdapter.NodeTypePredicate, org.modeshape.jcr.spi.index.IndexFeedback)
or updateIndex(org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.api.index.IndexDefinition, org.modeshape.jcr.spi.index.provider.ManagedIndex, java.lang.String, org.modeshape.jcr.NodeTypes.Supplier, org.modeshape.jcr.cache.change.ChangeSetAdapter.NodeTypePredicate, org.modeshape.jcr.spi.index.IndexFeedback)
; never nullworkspaceName
- the name of the actual workspace to which the new index applies; never nullprotected ManagedIndexBuilder getIndexBuilder(IndexDefinition defn, String workspaceName, NodeTypes.Supplier nodeTypesSupplier, ChangeSetAdapter.NodeTypePredicate matcher)
ManagedIndexBuilder
instance which significantly simplifies the
task of creating or updating ManagedIndex
instances for providers.
If a provider chooses to override this method, it does not have to override
the #createIndex(IndexDefinition, String, NodeTypes.Supplier, NodeTypePredicate, IndexFeedback)
method or
the #updateIndex(IndexDefinition, IndexDefinition, ManagedIndex, String, NodeTypes.Supplier, NodeTypePredicate, IndexFeedback)
method, as the builder instance will be used to create specific indexes and adapters, based on the index definition.
Providers can also choose to ignore this method, in which case they will have to override the
#createIndex(IndexDefinition, String, NodeTypes.Supplier, NodeTypePredicate, IndexFeedback)
and
#updateIndex(IndexDefinition, IndexDefinition, ManagedIndex, String, NodeTypes.Supplier, NodeTypePredicate, IndexFeedback)
methods.
defn
- the definition of the index; never nullworkspaceName
- the name of the actual workspace to which the new index applies; never nullnodeTypesSupplier
- the supplier for the current node types cache; never nullmatcher
- the node type matcher used to determine which nodes should be included in the index, and which automatically
updates when node types are changed in the repository; may not be nullManagedIndexBuilder
instance, or null
(the default) which indicates that a provider chooses to
ovveride both the createIndex and updateIndex methods.Copyright © 2008–2016 JBoss, a division of Red Hat. All rights reserved.