package edu.sc.seis.sod.source.network;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import edu.iris.Fissures.model.MicroSecondDate;
import edu.iris.Fissures.model.TimeInterval;
import edu.iris.Fissures.model.UnitImpl;
import edu.sc.seis.fissuresUtil.chooser.ClockUtil;
import edu.sc.seis.sod.subsetter.Subsetter;
import edu.sc.seis.sod.subsetter.channel.ChannelCode;
import edu.sc.seis.sod.subsetter.channel.ChannelOR;
import edu.sc.seis.sod.subsetter.channel.ChannelSubsetter;
import edu.sc.seis.sod.subsetter.channel.SiteCode;
import edu.sc.seis.sod.subsetter.network.NetworkCode;
import edu.sc.seis.sod.subsetter.network.NetworkOR;
import edu.sc.seis.sod.subsetter.network.NetworkSubsetter;
import edu.sc.seis.sod.subsetter.station.StationCode;
import edu.sc.seis.sod.subsetter.station.StationOR;
import edu.sc.seis.sod.subsetter.station.StationSubsetter;
public class NetworkQueryConstraints {
public NetworkQueryConstraints(List<String> constrainingNetworkCodes,
List<String> constrainingStationCodes,
List<String> constrainingLocationCodes,
List<String> constrainingChannelCodes) {
this.constrainingNetworkCodes = constrainingNetworkCodes;
this.constrainingStationCodes = constrainingStationCodes;
this.constrainingLocationCodes = constrainingLocationCodes;
this.constrainingChannelCodes = constrainingChannelCodes;
}
/**
* Given a network subsetter, return a string array consisting of all the
* network codes this subsetter accepts. If it doesn't constrain network
* based only on codes possibly in an OR, an empty array is returned.
*/
public NetworkQueryConstraints(NetworkSubsetter attrSubsetter,
StationSubsetter stationSubsetter,
List<ChannelSubsetter> channelSubsetterList,
edu.iris.Fissures.TimeRange timeRange) {
if (timeRange != null) {
this.beginConstraint = new MicroSecondDate(timeRange.start_time);
this.endConstraint = new MicroSecondDate(timeRange.end_time);
if (endConstraint.after(ClockUtil.now().subtract(new TimeInterval(1, UnitImpl.HOUR)))) {
endConstraint = null;
}
}
constrainingNetworkCodes = new ArrayList<String>();
if(attrSubsetter == null) {
// nothing
} else if(attrSubsetter instanceof NetworkOR) {
NetworkSubsetter[] kids = ((NetworkOR)attrSubsetter).getNetworkSubsetters();
for(int i = 0; i < kids.length; i++) {
if(kids[i] instanceof NetworkCode) {
constrainingNetworkCodes.add(((NetworkCode)kids[i]).getCode());
} else {
constrainingNetworkCodes.clear();
break;
}
}
} else if(attrSubsetter instanceof NetworkCode) {
constrainingNetworkCodes.add(((NetworkCode)attrSubsetter).getCode());
} else {
// nothing
}
constrainingStationCodes = new ArrayList<String>();
if(stationSubsetter == null) {
// nothing
} else if(stationSubsetter instanceof StationOR) {
List<Subsetter> kids = ((StationOR)stationSubsetter).getSubsetters();
for (Subsetter subsetter : kids) {
if(subsetter instanceof StationCode) {
constrainingStationCodes.add(((StationCode)subsetter).getCode());
} else {
constrainingStationCodes.clear();
break;
}
}
} else if(stationSubsetter instanceof StationCode) {
constrainingStationCodes.add(((StationCode)stationSubsetter).getCode());
} else {
// nothing
}
constrainingChannelCodes = new ArrayList<String>();
constrainingLocationCodes = new ArrayList<String>();
List<ChannelSubsetter> onlySiteList = new ArrayList<ChannelSubsetter>();
List<ChannelSubsetter> onlyChanList = new ArrayList<ChannelSubsetter>();
Iterator<ChannelSubsetter> it = channelSubsetterList.iterator();
boolean secondMightBeChan = false;
if (it.hasNext()) {
ChannelSubsetter first = it.next();
if (first instanceof ChannelOR) {
boolean isAllChannelCode = true;
boolean isAllSiteCode = true;
List<Subsetter> chanOrList = ((ChannelOR)first).getSubsetters();
for (Subsetter subsetter2 : chanOrList) {
if (subsetter2 instanceof ChannelCode) {
isAllSiteCode = false;
} else if (subsetter2 instanceof SiteCode) {
isAllChannelCode = false;
} else {
isAllChannelCode = false;
isAllSiteCode = false;
break;
}
}
if (isAllSiteCode) {
onlySiteList.add(first);
secondMightBeChan = true; // might be only chan subsetters in second
}
if (isAllChannelCode) {
onlyChanList.add(first);
}
} else if ( first instanceof SiteCode) {
onlySiteList.add(first);
secondMightBeChan = true; // might be only chan subsetters in second
} else if ( first instanceof ChannelCode) {
onlyChanList.add(first);
}
if (it.hasNext() && secondMightBeChan) {
ChannelSubsetter second = it.next();
if (second instanceof ChannelOR) {
boolean isAllChannelCode = true;
List<Subsetter> chanOrList = ((ChannelOR)second).getSubsetters();
for (Subsetter subsetter2 : chanOrList) {
if (subsetter2 instanceof ChannelCode) {
// so far ok
} else {
isAllChannelCode = false;
break;
}
}
if (isAllChannelCode) {
onlyChanList.add(second);
}
} else if ( second instanceof ChannelCode) {
onlyChanList.add(second);
}
}
}
if(onlyChanList.size() == 0 || onlyChanList.size() > 1) {
// nothing
} else if(onlyChanList.size() == 1 && onlyChanList.get(0) instanceof ChannelOR) {
List<Subsetter> kids = ((ChannelOR)onlyChanList.get(0)).getSubsetters();
for (Subsetter subsetter : kids) {
if(subsetter instanceof ChannelCode) {
constrainingChannelCodes.add(((ChannelCode)subsetter).getCode());
} else {
constrainingChannelCodes.clear();
break;
}
}
} else if(onlyChanList.size() == 1 && onlyChanList.get(0) instanceof ChannelCode) {
constrainingChannelCodes.add(((ChannelCode)onlyChanList.get(0)).getCode());
}
if(onlySiteList.size() == 0 || onlySiteList.size() > 1) {
// nothing
} else if(onlySiteList.size() == 1 && onlySiteList.get(0) instanceof ChannelOR) {
List<Subsetter> kids = ((ChannelOR)onlySiteList.get(0)).getSubsetters();
for (Subsetter subsetter : kids) {
if(subsetter instanceof SiteCode) {
constrainingLocationCodes.add(((SiteCode)subsetter).getCode());
} else {
constrainingLocationCodes.clear();
break;
}
}
} else if(onlySiteList.size() == 1 && onlySiteList.get(0) instanceof SiteCode) {
constrainingLocationCodes.add(((SiteCode)onlySiteList.get(0)).getCode());
}
}
public List<String> getConstrainingNetworkCodes() {
return constrainingNetworkCodes;
}
public List<String> getConstrainingStationCodes() {
return constrainingStationCodes;
}
public List<String> getConstrainingLocationCodes() {
return constrainingLocationCodes;
}
public List<String> getConstrainingChannelCodes() {
return constrainingChannelCodes;
}
public MicroSecondDate getConstrainingBeginTime() {
return beginConstraint;
}
public MicroSecondDate getConstrainingEndTime() {
return endConstraint;
}
List<String> constrainingNetworkCodes = new ArrayList<String>();
List<String> constrainingStationCodes = new ArrayList<String>();
List<String> constrainingLocationCodes = new ArrayList<String>();
List<String> constrainingChannelCodes = new ArrayList<String>();
MicroSecondDate beginConstraint;
MicroSecondDate endConstraint;
}