package org.netmelody.cieye.server.observation;
import static com.google.common.cache.CacheLoader.from;
import java.util.Map;
import org.netmelody.cieye.core.domain.CiServerType;
import org.netmelody.cieye.core.domain.Feature;
import org.netmelody.cieye.core.domain.TargetId;
import org.netmelody.cieye.core.observation.CiSpy;
import org.netmelody.cieye.core.observation.CommunicationNetwork;
import org.netmelody.cieye.core.observation.KnownOffendersDirectory;
import org.netmelody.cieye.core.observation.ObservationAgency;
import org.netmelody.cieye.server.CiSpyIntermediary;
import org.netmelody.cieye.server.ObservationAgencyFetcher;
import org.netmelody.cieye.server.TargetGroupBriefing;
import com.google.common.base.Function;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import com.google.common.collect.Maps;
public final class IntelligenceAgency implements CiSpyIntermediary {
public static IntelligenceAgency create(CommunicationNetwork network,
KnownOffendersDirectory directory,
ObservationAgencyFetcher foreignAgencies) {
IntelligenceAgency agency = new IntelligenceAgency(network, directory, foreignAgencies);
return agency;
}
private final Map<CiServerType, ObservationAgency> agencies = Maps.newHashMap();
private final LoadingCache<Feature, PollingSpyHandler> handlers =
CacheBuilder.newBuilder().removalListener(new RemovalListener<Feature, PollingSpyHandler>() {
@Override
public void onRemoval(RemovalNotification<Feature, PollingSpyHandler> notification) {
notification.getValue().endMission();
}
}).build(from(new Function<Feature, PollingSpyHandler>() {
@Override
public PollingSpyHandler apply(Feature feature) {
return createSpyFor(feature);
}
}));
private final CommunicationNetwork network;
private final KnownOffendersDirectory directory;
private final ObservationAgencyFetcher foreignAgencies;
private IntelligenceAgency(CommunicationNetwork network, KnownOffendersDirectory directory, ObservationAgencyFetcher foreignAgencies) {
this.network = network;
this.directory = directory;
this.foreignAgencies = foreignAgencies;
}
private PollingSpyHandler spyFor(Feature feature) {
ObservationAgency latestAgency = foreignAgencies.agencyFor(feature.type());
ObservationAgency currentAgency = agencies.get(feature.type());
if (currentAgency != latestAgency) {
agencies.put(feature.type(), latestAgency);
handlers.invalidate(feature);
}
return handlers.getUnchecked(feature);
}
private PollingSpyHandler createSpyFor(Feature feature) {
final ObservationAgency agency = foreignAgencies.agencyFor(feature.type());
final CiSpy spy = agency.provideSpyFor(feature, network, directory);
return new PollingSpyHandler(spy, feature);
}
@Override
public TargetGroupBriefing briefingOn(Feature feature) {
PollingSpyHandler spy = spyFor(feature);
return new TargetGroupBriefing(spy.statusOf(feature), spy.millisecondsUntilNextUpdate(feature));
}
@Override
public boolean passNoteOn(Feature feature, TargetId targetId, String note) {
PollingSpyHandler spy = spyFor(feature);
return spy.takeNoteOf(targetId, note);
}
}