Package org.lilyproject.indexer.model.util

Source Code of org.lilyproject.indexer.model.util.IndexRecordFilterUtil

/*
* Copyright 2012 NGDATA nv
*
* 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.util;

import org.lilyproject.repository.api.FieldType;
import org.lilyproject.repository.api.LRepository;
import org.lilyproject.repository.api.QName;
import org.lilyproject.repository.api.Record;
import org.lilyproject.repository.api.RecordId;
import org.lilyproject.repository.api.RepositoryException;
import org.lilyproject.repository.api.TypeManager;
import org.lilyproject.util.Pair;
import org.lilyproject.util.repo.RecordEvent;

public class IndexRecordFilterUtil {
    private IndexRecordFilterUtil() {
    }

    /**
     * Returns Record instances that can be used to evaluate an IndexerConf's IndexRecordFilter. The record
     * instances are created based on state stored in the RecordEvent by the IndexRecordFilterHook.
     *
     * <p>The IndexRecordFilterHook puts the fields & record type info needed by each of the
     * indexes known at that time in the RecordEvent.</p>
     *
     * <p>Of course, it can happen that indexerconfs have been changed, or new indexes have been added,
     * since the RecordEvent was created. It can also be that the 'new' record state stored in
     * the RecordEvent doesn't correspond to the record state you would get now when reading the
     * record. It is up to the caller to decide how to deal with these situations.</p>
     *
     * <p>This method returns always two Record instances: the old and new record state, even if
     * there would be no old instance (in case of record creation) or new (in case of record deletion).
     * In those cases, the Record objects will be empty, hence will be more generic, and hence
     * will only match IndexRecordFilter's that match all records anyway, so they won't match
     * more filters than either the old or new record state would match.</p>
     */
    public static Pair<Record,Record> getOldAndNewRecordForRecordFilterEvaluation(RecordId recordId, RecordEvent recordEvent,
            LRepository repository) throws RepositoryException, InterruptedException {

        //
        // Create the 'old' and 'new' Record instances.
        //
        // The RecordEvent contains the fields & record type info needed by the filters of the different
        // indexes, this is taken care of by IndexRecordFilterHook.
        //
        // Of course, it can happen that indexerconfs have been changed, or new indexes have been added,
        // since the event was created, and then this information will be missing. We could check for that
        // and in case of doubt send the event to the index anyway. This approach however also has the
        // disadvantage that, in case there are a lot of outstanding events in the queue, that they
        // might be sent to indexes that only expect a low update rate. Besides, it also complicates the
        // code. So we go for the simple approach: when the indexerconfs change, there is a transition
        // period to be expected, and one might need to rebuild indexes.
        //

        RecordEvent.IndexRecordFilterData idxSel = recordEvent.getIndexRecordFilterData();
        if (idxSel != null) {
            Record newRecord = idxSel.getNewRecordExists() ? repository.getRecordFactory().newRecord(recordId) : null;
            Record oldRecord = idxSel.getOldRecordExists() ? repository.getRecordFactory().newRecord(recordId) : null;

            TypeManager typeManager = repository.getTypeManager();

            if (idxSel.getFieldChanges() != null) {
                for (RecordEvent.FieldChange fieldChange : idxSel.getFieldChanges()) {
                    FieldType fieldType = typeManager.getFieldTypeById(fieldChange.getId());
                    QName name = fieldType.getName();

                    if (fieldChange.getNewValue() != null) {
                        Object value = fieldType.getValueType().read(fieldChange.getNewValue());
                        newRecord.setField(name, value);
                    }

                    if (fieldChange.getOldValue() != null) {
                        Object value = fieldType.getValueType().read(fieldChange.getOldValue());
                        oldRecord.setField(name, value);
                    }
                }
            }

            if (idxSel.getNewRecordType() != null) {
                newRecord.setRecordType(typeManager.getRecordTypeById(idxSel.getNewRecordType(), null).getName());
            }

            if (idxSel.getOldRecordType() != null) {
                oldRecord.setRecordType(typeManager.getRecordTypeById(idxSel.getOldRecordType(), null).getName());
            }

            return Pair.create(oldRecord, newRecord);
        }

        return Pair.create(null, null);
    }
}
TOP

Related Classes of org.lilyproject.indexer.model.util.IndexRecordFilterUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.