package edu.sc.seis.sod.source.event;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import edu.iris.Fissures.model.TimeInterval;
import edu.sc.seis.fissuresUtil.cache.CacheEvent;
import edu.sc.seis.fissuresUtil.chooser.ClockUtil;
import edu.sc.seis.fissuresUtil.time.MicroSecondTimeRange;
import edu.sc.seis.sod.ConfigurationException;
import edu.sc.seis.sod.SodUtil;
public class DelayedEventSource extends AbstractEventSource implements EventSource {
protected DelayedEventSource(TimeInterval delay, EventSource source) {
super("delayed "+source.getName(), source.getRetries());
this.delay = delay;
this.wrappedSource = source;
}
public DelayedEventSource(Element config) throws ConfigurationException {
super(config, "delayedEventSouce");
delay = SodUtil.loadTimeInterval(SodUtil.getElement(config, "delay"));
NodeList children = config.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if(node instanceof Element) {
Element el = (Element)node;
if (el.getLocalName().equals("name")) {
description = SodUtil.getNestedText(el);
} else if (el.getLocalName().equals("delay")) {
// handled above
} else {
Object o = SodUtil.load(el, "event"); // loads something from source.event package
if (o instanceof EventSource) {
wrappedSource = (EventSource)o;
break;
}
}
}
}
}
public String getDescription() {
if (description != null) {
return description;
}
return "Delayed ("+wrappedSource.getDescription()+") delayed "+delay;
}
public MicroSecondTimeRange getEventTimeRange() {
return wrappedSource.getEventTimeRange();
}
public TimeInterval getWaitBeforeNext() {
TimeInterval waitTime = wrappedSource.getWaitBeforeNext();
for (CacheEvent ce : delayedEvents) {
TimeInterval deTime = ce.getOrigin().getTime().add(delay).subtract(ClockUtil.now());
if (deTime.lessThan(waitTime)) {
waitTime = deTime;
}
}
return waitTime;
}
public boolean hasNext() {
return delayedEvents.size() != 0 || wrappedSource.hasNext();
}
public CacheEvent[] next() {
logger.debug("next: "+delayedEvents.size()+" delayed.");
List<CacheEvent> out = new ArrayList<CacheEvent>();
Iterator<CacheEvent> it = delayedEvents.iterator();
while(it.hasNext()) {
CacheEvent cacheEvent = it.next();
if (checkEvent(cacheEvent)) {
out.add(cacheEvent);
it.remove();
}
}
if (out.size() != 0) {
return out.toArray(new CacheEvent[0]);
}
if (wrappedSource.hasNext()) {
CacheEvent[] wrapEvents = wrappedSource.next();
for (int i = 0; i < wrapEvents.length; i++) {
if (checkEvent(wrapEvents[i])) {
out.add(wrapEvents[i]);
} else {
delayedEvents.add(wrapEvents[i]);
}
}
}
return out.toArray(new CacheEvent[0]);
}
public boolean checkEvent(CacheEvent e) {
return ClockUtil.now().subtract(delay).after(e.getOrigin().getTime());
}
String description = null;
EventSource wrappedSource;
TimeInterval delay;
LinkedList<CacheEvent> delayedEvents = new LinkedList<CacheEvent>();
private static Logger logger = LoggerFactory.getLogger(DelayedEventSource.class);
}