/*
* Copyright 2004-2009 the original author or authors.
*
* 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.compass.core.mapping.osem.builder;
import java.util.Iterator;
import org.compass.core.converter.Converter;
import org.compass.core.engine.subindex.ConstantSubIndexHash;
import org.compass.core.engine.subindex.SubIndexHash;
import org.compass.core.mapping.Mapping;
import org.compass.core.mapping.ResourceMapping;
import org.compass.core.mapping.ResourceMappingProvider;
import org.compass.core.mapping.SpellCheck;
import org.compass.core.mapping.osem.ClassMapping;
import org.compass.core.mapping.osem.ClassPropertyMetaDataMapping;
import org.compass.core.mapping.osem.ManagedId;
import org.compass.core.util.ClassUtils;
/**
* Marks a class as searchable.
* A searchable class is assoiated with an alias, and allows to perform full
* text search on it's mapped properties/fields.
*
* <p>The searchable class is associated with an alias, which can be used to
* reference the class when performing search operations, or for other
* mappings to extend it. By default, the alias name will be the class short
* name.
*
* <p>Note, a root searchable must be associated with at least one {@link SearchableIdMappingBuilder}.
*
* <p>By default, the searchable class is defined as a root class. A root class is
* a top level searchable class. A non root class can be used to define mappings
* definitions for {@link SearchableComponentMappingBuilder}, and it is preferable that classes
* that are only used as component mapping definitions, will be defined with {@link #root(boolean)}
* set to <code>false</code>.
*
* <p>A class mapping has it's own fully functional index, unless using the
* {@link #subIndex(String)} to join several searchable classes into the same
* index (when joining several searchalbe classes into the same index,
* the search will be much faster, but updates perform locks on the sub index
* level, so it might slow it down). More fine grained control can be acheived
* using {@link #subIndex(org.compass.core.engine.subindex.SubIndexHash)} allowing
* to parition the same class into several sub indexes using
* {@link org.compass.core.engine.subindex.ModuloSubIndexHash} definition.
*
* <p>A searchable class creates an internal "all" meta-data, which holds
* searchable information of all the class searchable content. Controlling
* the "all" property using the {@link SearchableAllMappingBuilder} and setting it
* using {@link #all(SearchableAllMappingBuilder)}.
*
* <p>The seachable class can have a specialized analyzer (different from the
* default one) associated with it using {@link #analyzer(String)}. Note, that this
* will associate the class statically with an analyzer. Dynamically associating
* the class with an analyzer, the {@link SearchableAnalyzerMappingBuilder} can be
* used to annotated the dynamic value for the analyzer to use.
*
* <p>The {@link #poly(boolean)} can be used to mapped polymprphic inheritance tree. This is the less
* prefable way to map an inhertiance tree, since the fact that a searchable class extend other
* searchable classes using the {@link #extendsAliases(String[])} mapping.
*
* @author kimchy
* @see OSEM#searchable(Class)
*/
public class SearchableMappingBuilder implements ResourceMappingProvider {
private final ClassMapping mapping;
/**
* Constructs a new class mapping builder for the specified class.
*/
public SearchableMappingBuilder(Class clazz) {
mapping = new ClassMapping();
mapping.setClazz(clazz);
mapping.setAlias(ClassUtils.getShortName(clazz));
mapping.setName(clazz.getName());
mapping.setRoot(true);
}
/**
* Returns the mapping.
*/
public ResourceMapping getMapping() {
return this.mapping;
}
/**
* Sets the alias of the searchable class. By default, will be set to the class short name.
* Note, the alias must be set before any addition of child mappings using <code>add</code>.
*/
public SearchableMappingBuilder alias(String alias) {
mapping.setAlias(alias);
return this;
}
/**
* Sets if the class is a root mapping or not. Root searchable classes are classes that will
* have be mapped to a sub index, and will return as actual hits from search results. Mostly.
* non root searchable classes are classes that are only used as component mappings. Defaults
* to <code>true</code>.
*/
public SearchableMappingBuilder root(boolean root) {
mapping.setRoot(root);
return this;
}
/**
* Controls if the searchable class will support unamrsahlling or not. When the searchable class
* supprots unmarshalling, then when loading to from the index, it will be constructed fully
* from the index. When it does not support unamrshalling, then only the ids of the searchable class
* will be filled.
*
* <p>When supporting unmarshalling, Compass might store additional properties in the resource that
* represents this searchable class (for example, to store the size of a collection). Note, when
* support unamrshalling is set to <code>false</code>, then one can still use the {@link org.compass.core.Resource}
* loaded from the index.
*
* <p>Defaults to the a globabl setting {@link org.compass.core.config.CompassEnvironment.Osem#SUPPORT_UNMARSHALL}
* which in turn defaults to <code>true</code>.
*/
public SearchableMappingBuilder supportUnmarshall(boolean supportUnmarshall) {
mapping.setSupportUnmarshall(supportUnmarshall);
return this;
}
/**
* Should the searchable class filter out duplicates during unmarshalling. Defaults to
* {@link org.compass.core.config.CompassEnvironment.Osem#FILTER_DUPLICATES}.
*/
public SearchableMappingBuilder filterDuplicatesDuringUnmarshalling(boolean filterDuplicatesDuringUnamrshalling) {
mapping.setFilterDuplicates(filterDuplicatesDuringUnamrshalling);
return this;
}
/**
* Used to mapped polymprphic inheritance tree. This is the less prefable way to map
* an inheritance tree, since the searchable class can extend other searchable classes
* using {@link #extendsAliases(String[])}.
*
* <p>If poly is set to <code>true</code>, the actual class implementation will be persisted
* to the index, later be used to instantiate it when un-marhsalling. If a specific class
* need to be used to instantiate all classes, use the {{@link #polyClass(Class)} to set it.
*/
public SearchableMappingBuilder poly(boolean poly) {
mapping.setPoly(poly);
return this;
}
/**
* In cases where poly is set to <code>true</code>, allows to set the class that will
* be used to instantiate in all inheritance tree cases.
*
* <p>If not set, the actual class will be saved to the index,
* later be used to instantiate it when un-marhsalling
*/
public SearchableMappingBuilder polyClass(Class polyClass) {
mapping.setPolyClass(polyClass);
return this;
}
/**
* Controls the managed id value for all the mapped properties that have no explicit setting
* of the managed id (also default to NA). The default value for the managed id is derived from
* globabl Compass settings and defaults to {@link ManagedId#NO_STORE}.
*/
public SearchableMappingBuilder managedId(ManagedId managedId) {
mapping.setManagedId(managedId);
return this;
}
/**
* Sets a sub index that will be used for this resource. Basically uses
* {@link org.compass.core.engine.subindex.ConstantSubIndexHash}.
*/
public SearchableMappingBuilder subIndex(String subIndex) {
mapping.setSubIndexHash(new ConstantSubIndexHash(subIndex));
return this;
}
/**
* Sets a custom sub index hashing strategy for the resource mapping.
*/
public SearchableMappingBuilder subIndex(SubIndexHash subIndexHash) {
mapping.setSubIndexHash(subIndexHash);
return this;
}
/**
* Sets the list of other clas mappings that this mapping will extend and inherit
* internal mappings from.
*/
public SearchableMappingBuilder extendsAliases(String... extendedAliases) {
mapping.setExtendedAliases(extendedAliases);
return this;
}
/**
* Sets the spell check mode that will be used for this class mapping (and for all the
* internal mappings that do not explicitly set their own spell check mode). If not set
* will use the global spell check setting.
*/
public SearchableMappingBuilder spellCheck(SpellCheck spellCheck) {
mapping.setSpellCheck(spellCheck);
return this;
}
/**
* The name of the analyzer that will be used to analyze ANALYZED properties. Defaults to the default analyzer
* which is one of the internal analyzers that comes with Compass. If not set, will use the <code>default</code>
* analyzer.
*
* <p>Note, that when using the class-analyzer mapping (a child mapping of class mapping)
* (for a class property value that controls the analyzer), the analyzer attribute will have no effects.
*/
public SearchableMappingBuilder analyzer(String analyzer) {
mapping.setAnalyzer(analyzer);
return this;
}
/**
* Sets the boost value for the class.
*/
public SearchableMappingBuilder boost(float boost) {
mapping.setBoost(boost);
return this;
}
/**
* Allows to set the "all" mapping definition.
*/
public SearchableMappingBuilder all(SearchableAllMappingBuilder builder) {
mapping.setAllMapping(builder.mapping);
return this;
}
/**
* Sets the mapping converter lookup name that will be used to convert the class. Defaults to
* {@link org.compass.core.converter.mapping.osem.ClassMappingConverter}.
*/
public SearchableMappingBuilder mappingConverter(String converter) {
mapping.setConverterName(converter);
return this;
}
/**
* Sets the mapping converter that will be used to convert the class. Defaults to
* {@link org.compass.core.converter.mapping.osem.ClassMappingConverter}.
*/
public SearchableMappingBuilder mappingConverter(Converter converter) {
mapping.setConverter(converter);
return this;
}
/**
* Adds an id property mapping to the searchable class.
*/
public SearchableMappingBuilder add(SearchableIdMappingBuilder builder) {
builder.mapping.setDefinedInAlias(mapping.getAlias());
for (Iterator<Mapping> it = builder.mapping.mappingsIt(); it.hasNext();) {
((ClassPropertyMetaDataMapping) it.next()).setDefinedInAlias(mapping.getAlias());
}
mapping.addMapping(builder.mapping);
return this;
}
/**
* Adds a proeprty mapping to the searchable class.
*/
public SearchableMappingBuilder add(SearchablePropertyMappingBuilder builder) {
builder.mapping.setDefinedInAlias(mapping.getAlias());
for (Iterator<Mapping> it = builder.mapping.mappingsIt(); it.hasNext();) {
((ClassPropertyMetaDataMapping) it.next()).setDefinedInAlias(mapping.getAlias());
}
mapping.addMapping(builder.mapping);
return this;
}
/**
* Adds a dynamic property mapping to searchable class.
*/
public SearchableMappingBuilder add(SearchableDynamicPropertyMappingBuilder builder) {
builder.mapping.setDefinedInAlias(mapping.getAlias());
mapping.addMapping(builder.mapping);
return this;
}
/**
* Adds an analyzer proeprty mapping to the searchable class.
*/
public SearchableMappingBuilder add(SearchableAnalyzerMappingBuilder builder) {
builder.mapping.setDefinedInAlias(mapping.getAlias());
mapping.addMapping(builder.mapping);
return this;
}
/**
* Adds a boost property mapping to the searchable class.
*/
public SearchableMappingBuilder add(SearchableBoostMappingBuilder builder) {
builder.mapping.setDefinedInAlias(mapping.getAlias());
mapping.addMapping(builder.mapping);
return this;
}
/**
* Adds a component mapping to the searchable class.
*/
public SearchableMappingBuilder add(SearchableComponentMappingBuilder builder) {
builder.mapping.setDefinedInAlias(mapping.getAlias());
mapping.addMapping(builder.mapping);
return this;
}
/**
* Adds an id component mapping to the searchable class.
*/
public SearchableMappingBuilder add(SearchableIdComponentMappingBuilder builder) {
builder.mapping.setDefinedInAlias(mapping.getAlias());
mapping.addMapping(builder.mapping);
return this;
}
/**
* Adds a reference mapping to the searchable class.
*/
public SearchableMappingBuilder add(SearchableReferenceMappingBuilder builder) {
builder.mapping.setDefinedInAlias(mapping.getAlias());
mapping.addMapping(builder.mapping);
return this;
}
/**
* Adds a constant mapping to the searchable class.
*/
public SearchableMappingBuilder add(SearchableConstantMappingBuilder builder) {
mapping.addMapping(builder.mapping);
return this;
}
/**
* Adds a dynamic meta data mapping to the searchable class.
*/
public SearchableMappingBuilder add(SearchableDynamicMetaDataMappingBuilder builder) {
mapping.addMapping(builder.mapping);
return this;
}
/**
* Addsa cascade mapping to the searchable class.
*/
public SearchableMappingBuilder add(SearchableCascadeMappingBuilder builder) {
builder.mapping.setDefinedInAlias(mapping.getAlias());
mapping.addMapping(builder.mapping);
return this;
}
/**
* Adds parent mapping to the searchable class.
*/
public SearchableMappingBuilder add(SearchableParentMappingBuilder builder) {
builder.mapping.setDefinedInAlias(mapping.getAlias());
mapping.addMapping(builder.mapping);
return this;
}
}