package edu.sc.seis.sod;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import edu.iris.Fissures.IfEvent.NoPreferredOrigin;
import edu.iris.Fissures.network.NetworkAttrImpl;
import edu.iris.Fissures.network.NetworkIdUtil;
import edu.iris.Fissures.network.StationIdUtil;
import edu.iris.Fissures.network.StationImpl;
import edu.sc.seis.fissuresUtil.database.NotFound;
import edu.sc.seis.fissuresUtil.exceptionHandler.GlobalExceptionHandler;
import edu.sc.seis.fissuresUtil.hibernate.NetworkDB;
import edu.sc.seis.sod.hibernate.SodDB;
import edu.sc.seis.sod.hibernate.StatefulEvent;
import edu.sc.seis.sod.subsetter.EventEffectiveTimeOverlap;
public class EventNetworkPair extends AbstractEventPair {
/** for hibernate */
protected EventNetworkPair() {}
public EventNetworkPair(StatefulEvent event, NetworkAttrImpl net) {
this(event, net, Status.get(Stage.EVENT_CHANNEL_POPULATION, Standing.INIT));
}
public EventNetworkPair(StatefulEvent event,
NetworkAttrImpl net,
Status status) {
super(event, status);
setNetwork(net);
}
public void run() {
// don't bother with station if effective time does not
// overlap event time
List<EventStationPair> alreadyInDb = SodDB.getSingleton().loadESPForNetwork(getEvent(), getNetwork());
List<EventStationPair> staPairList = new ArrayList<EventStationPair>();
try {
EventEffectiveTimeOverlap overlap = new EventEffectiveTimeOverlap(getEvent());
StationImpl[] stations = Start.getNetworkArm()
.getSuccessfulStations(getNetwork());
logger.debug("Begin EventNetworkPair ("+getEvent().getDbid()+",s "+getNetworkDbId()+") "+this);
logger.debug(stations.length+" successful stations for "+this);
for(int i = 0; i < stations.length; i++) {
logger.debug("Station successful ("+stations[i].getDbid()+") "+StationIdUtil.toString(stations[i]));
}
for(int i = 0; i < stations.length; i++) {
if(!overlap.overlaps(stations[i])) {
failLogger.info(StationIdUtil.toString(stations[i].get_id())
+ "'s station effective time does not overlap the event time.");
} else {
EventStationPair p;
try {
p = new EventStationPair(getEvent(),
NetworkDB.getSingleton().getStation(stations[i].getDbid()));
logger.debug("Created ESP "+p);
} catch(NotFound e) {
throw new RuntimeException("Should never happen but I guess it did!", e);
}
staPairList.add(p);
}
}
synchronized(WaveformArm.class) {
update(Status.get(Stage.EVENT_CHANNEL_POPULATION, Standing.SUCCESS));
Iterator<EventStationPair> it = staPairList.iterator();
while(it.hasNext()) {
EventStationPair p = it.next();
boolean found = false;
for (EventStationPair dbEsp : alreadyInDb) {
if (dbEsp.getStationDbId() == p.getStationDbId()) {
found = true;
p = dbEsp;
break;
}
}
if (found) {
if (! (p.getStatus().getStanding().equals(Standing.REJECT)
|| p.getStatus().getStanding().equals(Standing.SUCCESS))) {
p.update(Status.get(Stage.EVENT_CHANNEL_POPULATION,
Standing.INIT));
SodDB.getSession().update(p);
} else {
it.remove();
}
} else {
SodDB.getSession().save(p);
}
}
SodDB.commit();
}
SodDB.getSingleton().offerEventStationPair(staPairList);
} catch(NoPreferredOrigin e) {
// should never happen
GlobalExceptionHandler.handle(e);
update(Status.get(Stage.EVENT_CHANNEL_POPULATION,
Standing.SYSTEM_FAILURE));
failLogger.warn(this.toString(), e);
} finally {
// make sure session is closed in case of exception
SodDB.rollback();
}
logger.debug("End EventNetworkPair ("+getEvent().getDbid()+",s "+getNetworkDbId()+") "+this);
}
/**
* sets the status on this event network pair to be status and notifies its
* parent
*/
public void update(Status status) {
// this is weird, but calling the setter allows hibernate to autodetect
// a modified object
setStatus(status);
Start.getWaveformRecipe().setStatus(this);
}
public boolean equals(Object o) {
if(!(o instanceof EventNetworkPair))
return false;
EventNetworkPair ecp = (EventNetworkPair)o;
if(ecp.getEventDbId() == getEventDbId()
&& ecp.getNetworkDbId() == getNetworkDbId()) {
return true;
}
return false;
}
public int hashCode() {
int code = 47 * getNetworkDbId();
code += 23 * getEventDbId();
return code;
}
public String toString() {
return "EventNetworkPair: (" + getDbid() + ") " + getEvent() + " "
+ NetworkIdUtil.toStringNoDates(getNetwork()) + " " + getStatus();
}
public int getNetworkDbId() {
return getNetwork().getDbid();
}
public NetworkAttrImpl getNetwork() {
return networkAttr;
}
/** for use by hibernate */
protected void setNetwork(NetworkAttrImpl attr) {
this.networkAttr = attr;
}
private NetworkAttrImpl networkAttr;
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(EventNetworkPair.class);
}