/* * Copyright 2010 Outerthought bvba * * 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.lilyproject.indexer.model.indexerconf; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import com.google.common.base.Predicate; import org.lilyproject.repository.api.FieldType; import org.lilyproject.repository.api.Record; import org.lilyproject.repository.api.RepositoryException; import org.lilyproject.repository.api.SchemaId; import org.lilyproject.repository.api.Scope; import org.lilyproject.util.repo.SystemFields; import org.lilyproject.util.repo.VTaggedRecord; // TODO for safety should consider making some of the returned lists immutable /** * The configuration for the indexer, describes how record types should be mapped * onto index documents. * * <p>Fields and vtags are identified by ID in this object model. * * <p>The IndexerConf is constructed by the {@link LilyIndexerConfBuilder}. Some essential * validation is done by that builder which would not be done in case of direct * construction. */ public class LilyIndexerConf { private IndexRecordFilter recordFilter; private IndexFields indexFields; private List<DynamicIndexField> dynamicFields = new ArrayList<DynamicIndexField>(); private Set<SchemaId> vtags = new HashSet<SchemaId>(); private Formatters formatters = new Formatters(); private SystemFields systemFields; private boolean containsDerefExpression = false; protected void setRecordFilter(IndexRecordFilter recordFilter) { this.recordFilter = recordFilter; for (IndexCase indexCase : recordFilter.getAllIndexCases()) { vtags.addAll(indexCase.getVersionTags()); } } /** * @return null if there is no matching IndexCase */ public IndexCase getIndexCase(String table, Record record) { return recordFilter.getIndexCase(table, record); } public IndexFields getIndexFields() { return indexFields; } public IndexRecordFilter getRecordFilter() { return recordFilter; } public void setIndexFields(IndexFields indexFields) { this.indexFields = indexFields; indexFields.visitAll(new Predicate<MappingNode>() { @Override public boolean apply(MappingNode node) { if (node instanceof IndexField) { IndexField indexField = (IndexField) node; if (indexField.getValue() instanceof DerefValue) { containsDerefExpression = true; } } else if (node instanceof ForEachNode) { containsDerefExpression = true; } return true; } }); } protected void addDynamicIndexField(DynamicIndexField field) { dynamicFields.add(field); } public List<DynamicIndexField> getDynamicFields() { return dynamicFields; } public boolean containsDerefExpressions() { return containsDerefExpression; } /** * Returns the set of all known vtags, thus all the vtags that are relevant to indexing. */ public Set<SchemaId> getVtags() { return vtags; } public Formatters getFormatters() { return formatters; } public SystemFields getSystemFields() { return systemFields; } public void setSystemFields(SystemFields systemFields) { this.systemFields = systemFields; } public boolean changesAffectIndex(VTaggedRecord vtRecord, Scope scope) throws InterruptedException, RepositoryException { Set<FieldType> changedFields = vtRecord.getRecordEventHelper().getUpdatedFieldsByScope().get(scope); // Check <fields> boolean affects = indexFields.isIndexAffectedByUpdate(vtRecord, scope); if (affects) { return true; } // Check dynamic fields for (FieldType fieldType : changedFields) { // If there are lots of dynamic index fields, or lots of fields which are not indexed at all (thus // leading to lots of invocations of this method), than maybe we need to review this for performance. for (DynamicIndexField field : dynamicFields) { if (field.matches(fieldType).match) { return true; } } } return false; } }