package org.sef4j.core.helpers.export.senders;
import java.util.List;
import org.sef4j.core.api.EventSender;
import org.sef4j.core.helpers.export.ExportFragmentList;
import org.sef4j.core.helpers.export.ExportFragmentsProvider;
import org.sef4j.core.helpers.export.ExportFragmentsProviderDef;
import org.sef4j.core.helpers.tasks.PollingEventProvider.AbstractPollingEventProvider;
import org.sef4j.core.util.factorydef.AbstractSharedObjByDefFactory;
import org.sef4j.core.util.factorydef.DependencyObjectCreationContext;
import org.sef4j.core.util.factorydef.ObjectByDefRepositories;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableList;
/**
* class for collecting data or incremental changes to export as event "ExportFragmentList<T>"
*
* <PRE>
* exporter.sendEventsForCollectedFragments():
* { ls=collectFragments(); sendEvents(ls) }
* / \
* <--/ \-->
* ls=providers.provideFragments() targetSender.sendEvents(ls)
*
* +-----------------------+
* FragmentProvider(s) <(*)---- | |------(1)> targetEventSender
* /\ +------------------ |
* | +----------------------> ... - --------->
* +---+---+ +-----------------------+
* | | |
* Provider1
* (example: Json PerfStats per CallTreeNode
* if modified since > 5mn)
*
* Provider2 (example: Json PendingCount
* if modified since > 1mn )
*
* Provider3 (..)
* </PRE>
*
* @see EventSenderFragmentsExporterTask for using with a PeriodicTask
*
* @param <T> type of fragments to export (example: String for JSon fragments)
*/
public class ExportFragmentsPollingEventProvider<T> extends AbstractPollingEventProvider<ExportFragmentList<T>> {
private static final Logger LOG = LoggerFactory.getLogger(ExportFragmentsPollingEventProvider.class);
private List<ExportFragmentsProvider<T>> fragmentProviders;
// ------------------------------------------------------------------------
public ExportFragmentsPollingEventProvider(String displayName,
List<ExportFragmentsProvider<T>> fragmentProviders) {
super(displayName);
this.fragmentProviders = fragmentProviders;
}
// ------------------------------------------------------------------------
@Override
public void poll() {
sendEventsForMarkAndCollectChanges();
}
public ExportFragmentList<T> collectFragmentsToExport() {
ExportFragmentList<T> res = new ExportFragmentList<T>();
for (ExportFragmentsProvider<T> provider : fragmentProviders) {
try {
provider.provideFragments(res);
} catch(Exception ex) {
LOG.error("Failed to collect fragments for " + displayName
+ " from fragment provider: " + provider + "... ignore, no rethrow!", ex);
}
}
return res;
}
protected ExportFragmentList<T> markAndCollectFragmentChanges() {
ExportFragmentList<T> changedFragments = new ExportFragmentList<T>();
for (ExportFragmentsProvider<T> provider : fragmentProviders) {
try {
provider.markAndCollectChanges(changedFragments);
} catch(Exception ex) {
LOG.error("Failed to collect fragment changes for " + displayName
+ " from fragment provider: " + provider + "... ignore, no rethrow!", ex);
}
}
return changedFragments;
}
public void sendEventsForCollectedFragments() {
sendEventsForCollectedFragments(this);
}
public void sendEventsForCollectedFragments(EventSender<ExportFragmentList<T>> to) {
ExportFragmentList<T> fragments = collectFragmentsToExport();
to.sendEvent(fragments);
}
public void sendEventsForMarkAndCollectChanges() {
ExportFragmentList<T> changedFragments = markAndCollectFragmentChanges();
if (! changedFragments.isEmpty()) {
super.sendEvent(changedFragments);
}
}
// ------------------------------------------------------------------------
@Override
public String toString() {
return "ExportFragmentsEventProvider[" + displayName + "]";
}
// ------------------------------------------------------------------------
public static class Builder<T> {
protected String displayName;
private List<ExportFragmentsProvider<T>> fragmentProviders;
public ExportFragmentsPollingEventProvider<T> build() {
return new ExportFragmentsPollingEventProvider<T>(displayName, fragmentProviders);
}
public Builder<T> withDisplayName(String displayName) {
this.displayName = displayName;
return this;
}
public Builder<T> withFragmentProviders(List<ExportFragmentsProvider<T>> fragmentProviders) {
this.fragmentProviders = fragmentProviders;
return this;
}
}
// ------------------------------------------------------------------------
public static class ExportFragmentsPollingEventProviderFactory<T>
extends AbstractSharedObjByDefFactory<ExportFragmentsPollingEventProviderDef, ExportFragmentsPollingEventProvider<T>> {
@SuppressWarnings("rawtypes")
public static ExportFragmentsPollingEventProviderFactory<?> instance() {
return new ExportFragmentsPollingEventProviderFactory();
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void registerInstance(ObjectByDefRepositories to) {
to.registerFactoryFor(ExportFragmentsPollingEventProviderDef.class,
new ExportFragmentsPollingEventProviderFactory());
}
public ExportFragmentsPollingEventProviderFactory() {
super("ExportFragmentsPollingEventProvider", ExportFragmentsPollingEventProviderDef.class);
}
@Override
public ExportFragmentsPollingEventProvider<T> create(
ExportFragmentsPollingEventProviderDef def,
DependencyObjectCreationContext ctx) {
ImmutableList<ExportFragmentsProviderDef> fragmentProviderDefs = def.getFragmentProviderDefs();
List<ExportFragmentsProvider<T>> fragmentProviders =
ctx.getOrCreateDependencyByDefs("fragmentProviders", fragmentProviderDefs);
String displayName = ctx.getCurrObjectDisplayName();
return new ExportFragmentsPollingEventProvider<T>(displayName, fragmentProviders);
}
}
}