/*
* This file is part of ReadonlyREST.
*
* ReadonlyREST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ReadonlyREST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ReadonlyREST. If not, see http://www.gnu.org/licenses/
*/
package org.elasticsearch.plugin.readonlyrest.requestcontext;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.plugin.readonlyrest.ESContext;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* Created by sscarduzio on 14/04/2017.
*/
public abstract class Delayed {
private final Logger logger;
protected final String name;
private final ESContext context;
private final List<Runnable> effects = new LinkedList<>();
private final List<Delayed> delegates = new LinkedList<>();
private Boolean committed = false;
private Boolean delegated = false;
public Delayed(String name, ESContext context) {
this.logger = context.logger(getClass());
this.name = name;
this.context = context;
}
public void delay(Runnable r) {
effects.add(r);
}
public int size() {
return effects.size();
}
public void commit() {
if (committed) {
throw context.rorException(name + " > already committed!");
}
committed = true;
logger.debug(name + " > Committing " + effects.size() + " effects");
Iterator<Runnable> it = effects.iterator();
while (it.hasNext()) {
Runnable eff = it.next();
try {
eff.run();
}catch(Throwable t){
t.printStackTrace();
}
finally {
logger.debug(name + " > committed.");
}
it.remove();
}
delegates.forEach(Delayed::commit);
}
public void reset() {
logger.debug(name + " > resetting!!! ");
effects.clear();
committed = false;
delegates.forEach(d -> {
d.reset();
d.committed = false;
});
}
/**
* Replace this effects queue with the ambassador's queue
* That is, when the ambassador commits/resets, also this instance's effects are committed/reset.
*
* @param ambassador the Delayed instance we are delegating our commit/reset to.
*/
public void delegateTo(Delayed ambassador) {
if (delegated) {
throw context.rorException(name + " > Already delegated, cannot delegate twice.");
}
logger.debug(name + " > delegating effects to " + ambassador.name);
if (!this.effects.isEmpty()) {
ambassador.effects.addAll(this.effects);
}
ambassador.delegates.add(this);
delegated = true;
}
}