001/*
002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Thierry Delprat
018 *     Benoit Delbosc
019 */
020package org.nuxeo.elasticsearch.commands;
021
022import java.util.ArrayList;
023import java.util.HashSet;
024import java.util.List;
025import java.util.Set;
026
027import org.apache.commons.logging.Log;
028import org.apache.commons.logging.LogFactory;
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.elasticsearch.commands.IndexingCommand.Type;
031
032/*
033 * This class holds a list of indexing commands and manages de-duplication
034 */
035public class IndexingCommands {
036
037    protected final List<IndexingCommand> commands = new ArrayList<>();
038
039    protected final Set<Type> commandTypes = new HashSet<>();
040
041    protected DocumentModel targetDocument;
042
043    protected static final Log log = LogFactory.getLog(IndexingCommands.class);
044
045    protected IndexingCommands() {
046        //
047    }
048
049    public IndexingCommands(DocumentModel targetDocument) {
050        this.targetDocument = targetDocument;
051    }
052
053    public void add(Type type, boolean sync, boolean recurse) {
054        IndexingCommand cmd = new IndexingCommand(targetDocument, type, sync, recurse);
055        add(cmd);
056    }
057
058    protected IndexingCommand find(Type command) {
059        for (IndexingCommand cmd : commands) {
060            if (cmd.type == command) {
061                return cmd;
062            }
063        }
064        return null;
065    }
066
067    protected void add(IndexingCommand command) {
068        if (command == null) {
069            return;
070        }
071        if (commandTypes.contains(command.type)) {
072            IndexingCommand existing = find(command.type);
073            if (existing.merge(command)) {
074                return;
075            }
076        } else if (commandTypes.contains(Type.INSERT)) {
077            if (command.type == Type.DELETE) {
078                // index and delete in the same tx
079                clear();
080            } else if (command.isSync()) {
081                // switch to sync if possible
082                find(Type.INSERT).makeSync();
083            }
084            // we already have an index command, don't care about the new command
085            return;
086        }
087        if (command.type == Type.DELETE) {
088            // no need to keep event before delete.
089            clear();
090        }
091        commands.add(command);
092        commandTypes.add(command.type);
093    }
094
095    protected void clear() {
096        commands.clear();
097        commandTypes.clear();
098    }
099
100    public DocumentModel getTargetDocument() {
101        return targetDocument;
102    }
103
104    public boolean contains(Type command) {
105        return commandTypes.contains(command);
106    }
107
108    public List<IndexingCommand> getCommands() {
109        return commands;
110    }
111
112}