Compare commits
13 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
d67d1ba568 | 4 years ago |
|
|
fd39a7421d | 4 years ago |
|
|
a9d87baa6c | 4 years ago |
|
|
73a6150bf2 | 4 years ago |
|
|
7af889fb7e | 4 years ago |
|
|
c0a192815e | 4 years ago |
|
|
fe256ae851 | 4 years ago |
|
|
17e064ebcf | 4 years ago |
|
|
1f9a35c228 | 4 years ago |
|
|
c90b7177a2 | 4 years ago |
|
|
17994d1acd | 4 years ago |
|
|
d007cbe434 | 4 years ago |
|
|
17c99e6a5e | 4 years ago |
31 changed files with 3870 additions and 25 deletions
@ -1,3 +1,5 @@
|
||||
/bin/ |
||||
/target/ |
||||
configuration.properties |
||||
tmpd/ |
||||
*_log* |
||||
|
||||
@ -0,0 +1,93 @@
|
||||
package org.leolo.rail; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.SQLException; |
||||
import java.sql.Types; |
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.zip.GZIPInputStream; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.json.JSONObject; |
||||
import org.leolo.rail.util.TUIDDateFormat; |
||||
|
||||
public class AssoicationProcessor extends BaseProcessor implements Runnable { |
||||
|
||||
private File targetFile; |
||||
private Logger log = LogManager.getLogger(AssoicationProcessor.class); |
||||
|
||||
public AssoicationProcessor(File targetFile) { |
||||
this.targetFile = targetFile; |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
log.atInfo().log("Processing {}", targetFile.getName()); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); |
||||
TUIDDateFormat tdf = new TUIDDateFormat(); |
||||
try( |
||||
BufferedReader br = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(targetFile)))); |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("REPLACE INTO ltp_assoication VALUES(?,?,?,?,?,?,?,?,?,?,?,?)") |
||||
){ |
||||
while(true) { |
||||
String line = br.readLine(); |
||||
if(line==null) { |
||||
break; |
||||
} |
||||
JSONObject obj = new JSONObject(line); |
||||
String mainTrainUID = obj.optString("main_train_uid"); |
||||
String assocTrainUID = obj.optString("assoc_train_uid"); |
||||
java.sql.Date startDate, endDate; |
||||
try { |
||||
startDate = new java.sql.Date(sdf.parse(obj.optString("assoc_start_date")).getTime()); |
||||
endDate = new java.sql.Date(sdf.parse(obj.optString("assoc_end_date")).getTime()); |
||||
} catch (ParseException e1) { |
||||
log.warn("Unable to parse date! {}", e1.getMessage(), e1); |
||||
continue; |
||||
} |
||||
String assoc_days = obj.optString("assoc_days"); |
||||
String assoc_type = obj.optString("category"); |
||||
String location = obj.optString("location"); |
||||
String base_suffix = obj.optString("base_location_suffix"); |
||||
String assoc_suffix = obj.optString("assoc_location_suffix"); |
||||
String stp_ind = obj.optString("CIF_stp_indicator"); |
||||
String auid = mainTrainUID + assocTrainUID + location + tdf.format(startDate) + tdf.format(endDate)+stp_ind; |
||||
int hashCode = (auid+assoc_type+assoc_days).hashCode(); |
||||
setString(pstmt, 1, auid); |
||||
setString(pstmt, 2, mainTrainUID); |
||||
setString(pstmt, 3, assocTrainUID); |
||||
pstmt.setDate(4, startDate); |
||||
pstmt.setDate(5, endDate); |
||||
setString(pstmt, 6, assoc_days); |
||||
setString(pstmt, 7, assoc_type); |
||||
setString(pstmt, 8, location); |
||||
setString(pstmt, 9, base_suffix); |
||||
setString(pstmt, 10, assoc_suffix); |
||||
setString(pstmt, 11, stp_ind); |
||||
pstmt.setInt(12, hashCode); |
||||
pstmt.addBatch(); |
||||
} |
||||
pstmt.executeBatch(); |
||||
conn.commit(); |
||||
} catch (FileNotFoundException e) { |
||||
log.error(e.getMessage(), e); |
||||
} catch (IOException e) { |
||||
log.error(e.getMessage(), e); |
||||
} catch (SQLException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
if(!targetFile.delete()) { |
||||
log.warn("Unable to delete {}", targetFile.getName()); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,57 @@
|
||||
package org.leolo.rail; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import org.apache.activemq.transport.stomp.StompConnection; |
||||
|
||||
public abstract class BaseProcessingThread extends Thread implements AutoCloseable{ |
||||
|
||||
private boolean isInit = false; |
||||
protected StompConnection connection; |
||||
private String configPrefix; |
||||
|
||||
public BaseProcessingThread(String configPrefix) throws Exception { |
||||
this.configPrefix = configPrefix; |
||||
this.connection = getConnection(); |
||||
} |
||||
|
||||
protected abstract void _init(); |
||||
|
||||
@Override |
||||
public abstract void run(); |
||||
|
||||
public void init() { |
||||
_init(); |
||||
isInit = true; |
||||
} |
||||
|
||||
private StompConnection getConnection() throws Exception { |
||||
StompConnection conn = new StompConnection(); |
||||
conn.open( |
||||
ConfigurationManager.getInstance().getProperty(configPrefix+".host"), |
||||
ConfigurationManager.getInstance().getInt(configPrefix+".port") |
||||
); |
||||
conn.connect( |
||||
ConfigurationManager.getInstance().getProperty(configPrefix+".user"), |
||||
ConfigurationManager.getInstance().getProperty(configPrefix+".pwd") |
||||
); |
||||
return conn; |
||||
} |
||||
|
||||
@Override |
||||
public synchronized void start() { |
||||
if(isInit) { |
||||
super.start(); |
||||
}else { |
||||
throw new RuntimeException("Thread not init yet"); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void close() throws IOException { |
||||
connection.close(); |
||||
connection = null; |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,28 @@
|
||||
package org.leolo.rail; |
||||
|
||||
import java.sql.PreparedStatement; |
||||
import java.sql.SQLException; |
||||
import java.sql.Types; |
||||
|
||||
public abstract class BaseProcessor { |
||||
public void setString(PreparedStatement stmt, int col, String val) throws SQLException{ |
||||
if(val==null || "".equals(val.trim())) { |
||||
stmt.setNull(col, Types.CHAR); |
||||
}else { |
||||
stmt.setString(col, val); |
||||
} |
||||
} |
||||
|
||||
public void setTime(PreparedStatement stmt, int col, long time) throws SQLException{ |
||||
if(time==0) { |
||||
stmt.setNull(col, Types.TIME); |
||||
}else { |
||||
int h = (int)(time/3_600_000); |
||||
int m = (int)((time/60_000)%60); |
||||
int s = (int)((time/1_000)%60); |
||||
stmt.setString(col, h+":"+m+":"+s); |
||||
} |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,28 @@
|
||||
package org.leolo.rail; |
||||
|
||||
public enum CurrentTrainStatus { |
||||
|
||||
ACTIVATED("A"), |
||||
CANCELLED("C"), |
||||
TERMINATED("T"); |
||||
|
||||
private String code; |
||||
|
||||
private CurrentTrainStatus(String code) { |
||||
this.code = code; |
||||
} |
||||
|
||||
public String getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public static CurrentTrainStatus getCurrentTrainStatus(String code) { |
||||
for(CurrentTrainStatus cts:values()) { |
||||
if(cts.code.equals(code)) { |
||||
return cts; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,82 @@
|
||||
package org.leolo.rail; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
import org.apache.activemq.command.Endpoint; |
||||
import org.apache.activemq.transport.stomp.StompFrame; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
public class NetowrkRailProcessingThread extends BaseProcessingThread { |
||||
|
||||
private static Logger log = LogManager.getLogger(NetowrkRailProcessingThread.class); |
||||
private TrainMovementProcessor procTrainMvt = new TrainMovementProcessor(); |
||||
private VTSPProcessor procVTSP = new VTSPProcessor(); |
||||
private boolean stopThread = false; |
||||
|
||||
public NetowrkRailProcessingThread() throws Exception { |
||||
super("network"); |
||||
} |
||||
|
||||
@Override |
||||
protected void _init() { |
||||
try { |
||||
connection.subscribe(Constants.NetworkRail.TOPIC_NAME_MVT); |
||||
connection.subscribe(Constants.NetworkRail.TOPIC_NAME_VTSP); |
||||
} catch (Exception e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
|
||||
procTrainMvt.start(); |
||||
procVTSP.start(); |
||||
} |
||||
|
||||
private volatile long sleepTime = Constants.Generic.DEFAULT_SLEEP_TIME; |
||||
|
||||
private void sleep() { |
||||
try { |
||||
sleep(sleepTime); |
||||
} catch (InterruptedException e1) { |
||||
log.error(e1.getMessage(), e1); |
||||
} |
||||
sleepTime*=Constants.Generic.INCRESE_RATIO; |
||||
if(sleepTime>128000) { |
||||
log.atError().log("Failed too many times. Restart thread."); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
while(true) { |
||||
try { |
||||
if(stopThread) { |
||||
break; |
||||
} |
||||
StompFrame frm = connection.receive(); |
||||
if("ERROR".equals(frm.getAction())) { |
||||
log.error("Error message received. {}", frm.getBody()); |
||||
sleep(); |
||||
continue; |
||||
} |
||||
log.info("HDRs: {}", frm.getHeaders()); |
||||
String topic = frm.getHeaders().get("destination"); |
||||
if(Constants.NetworkRail.TOPIC_NAME_MVT.equals(topic)) { |
||||
procTrainMvt.process(frm); |
||||
}else if(Constants.NetworkRail.TOPIC_NAME_VTSP.equals(topic)) { |
||||
procVTSP.process(frm); |
||||
} |
||||
sleepTime = Constants.Generic.DEFAULT_SLEEP_TIME; |
||||
} catch (Exception e) { |
||||
log.error(e.getMessage(), e); |
||||
sleep(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void close() throws IOException { |
||||
procTrainMvt.terminate(); |
||||
super.close(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,317 @@
|
||||
package org.leolo.rail; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.sql.Types; |
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Date; |
||||
import java.util.Vector; |
||||
import java.util.zip.GZIPInputStream; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.json.JSONArray; |
||||
import org.json.JSONObject; |
||||
import org.leolo.rail.model.LocationRecordType; |
||||
import org.leolo.rail.model.ScheduleType; |
||||
import org.leolo.rail.model.TrainSchedule; |
||||
import org.leolo.rail.model.TrainScheduleLocation; |
||||
|
||||
public class ScheduleProcessor extends BaseProcessor implements Runnable { |
||||
|
||||
private Logger log = LogManager.getLogger(ScheduleProcessor.class); |
||||
private File targetFile; |
||||
|
||||
public ScheduleProcessor(File targetFile) { |
||||
this.targetFile = targetFile; |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
Vector<TrainSchedule> newSchedule = new Vector<>(); |
||||
Vector<TrainSchedule> updatedSchedule = new Vector<>(); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
||||
try( |
||||
BufferedReader br = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(targetFile)))); |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT hash_code FROM ltp_schedule WHERE suid = ?")//For checking duplication
|
||||
){ |
||||
while(true) { |
||||
String line = br.readLine(); |
||||
if(line==null) { |
||||
break; |
||||
} |
||||
JSONObject obj = new JSONObject(line); |
||||
TrainSchedule ts = new TrainSchedule(); |
||||
ts.setTrainUId(obj.optString("CIF_train_uid")); |
||||
String stpInd = obj.optString("CIF_stp_indicator"); |
||||
if("C".equals(stpInd)) |
||||
ts.setScheduleType(ScheduleType.CAN); |
||||
else if("N".equals(stpInd)) |
||||
ts.setScheduleType(ScheduleType.WTT); |
||||
else if("O".equals(stpInd)) |
||||
ts.setScheduleType(ScheduleType.OVL); |
||||
else if("P".equals(stpInd)) |
||||
ts.setScheduleType(ScheduleType.WTT); |
||||
else |
||||
log.atWarn().log("Unknow schedule type {} for train UID {}",stpInd,obj.optString("CIF_train_uid")); |
||||
try { |
||||
ts.setStartDate(sdf.parse(obj.optString("schedule_start_date"))); |
||||
ts.setEndDate(sdf.parse(obj.optString("schedule_end_date"))); |
||||
}catch(ParseException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
ts.setDays(obj.optString("schedule_days_runs")); |
||||
ts.setBankHolidayInd(obj.optString("CIF_bank_holiday_running")); |
||||
ts.setSignalId(obj.getJSONObject("schedule_segment").optString("signalling_id")); |
||||
ts.setRsid(obj.getJSONObject("schedule_segment").optString("CIF_headcode")); |
||||
ts.setTrainStatus(obj.optString("train_status")); |
||||
ts.setTrainCategory(obj.getJSONObject("schedule_segment").optString("CIF_train_category")); |
||||
ts.setSection(obj.getJSONObject("schedule_segment").optString("CIF_business_sector")); |
||||
ts.setPowerType(obj.getJSONObject("schedule_segment").optString("CIF_power_type")); |
||||
ts.setTimingLoad(obj.getJSONObject("schedule_segment").optString("CIF_timing_load")); |
||||
ts.setPlannedSpeed(obj.getJSONObject("schedule_segment").optString("CIF_speed")); |
||||
ts.setOperatingCharacter(obj.getJSONObject("schedule_segment").optString("CIF_operating_characteristics")); |
||||
ts.setClassAvailable(obj.getJSONObject("schedule_segment").optString("CIF_train_class")); |
||||
ts.setSleeper(obj.getJSONObject("schedule_segment").optString("CIF_sleepers")); |
||||
ts.setReservation(obj.getJSONObject("schedule_segment").optString("CIF_reservations")); |
||||
ts.setCatering(obj.getJSONObject("schedule_segment").optString("CIF_catering_code")); |
||||
// if()
|
||||
// ts.setUicCode(obj.getJSONObject("new_schedule_segment").optString("uic_code"));
|
||||
ts.setAtocCode(obj.optString("atoc_code")); |
||||
JSONArray locs = obj.getJSONObject("schedule_segment").optJSONArray("schedule_location"); |
||||
if(locs==null && !"C".equals(stpInd)) { |
||||
log.atWarn().log("No segments for {}",ts.getSUID()); |
||||
continue; |
||||
} |
||||
if(locs!=null) { |
||||
for(int i=0;i<locs.length();i++) { |
||||
JSONObject loc = locs.getJSONObject(i); |
||||
TrainScheduleLocation tsl = new TrainScheduleLocation(); |
||||
tsl.setTiplocCode(loc.optString("tiploc_code")); |
||||
tsl.setTiplocInstance(loc.optInt("tiploc_instance")); |
||||
tsl.setArrival(getScheduleTime(loc.optString("arrival"))); |
||||
tsl.setDeparture(getScheduleTime(loc.optString("departure"))); |
||||
tsl.setPass(getScheduleTime(loc.optString("pass"))); |
||||
tsl.setPubArrival(getScheduleTime(loc.optString("public_arrival"))); |
||||
tsl.setPubDeparture(getScheduleTime(loc.optString("public_departure"))); |
||||
tsl.setPlatform(loc.optString("platform")); |
||||
tsl.setLine(loc.optString("line")); |
||||
tsl.setPath(loc.optString("path")); |
||||
tsl.setEngineeringAllowance(getAllowanceTime(loc.optString("engineering_allowance"))); |
||||
tsl.setPathingAllowance(getAllowanceTime(loc.optString("pathing_allowance"))); |
||||
tsl.setPerformanceAllowance(getAllowanceTime(loc.optString("performance_allowance"))); |
||||
String locType = loc.optString("location_type"); |
||||
if("LO".equals(locType)) { |
||||
tsl.setRecordType(LocationRecordType.ORIGIN); |
||||
}else if("LI".equals(locType)) { |
||||
tsl.setRecordType(LocationRecordType.INTERMEDIATE); |
||||
}else if("LT".equals(locType)) { |
||||
tsl.setRecordType(LocationRecordType.TERMINATE); |
||||
} |
||||
ts.getLocations().add(tsl); |
||||
}//loop for location
|
||||
} |
||||
pstmt.setString(1, ts.getSUID()); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
if(rs.next()) { |
||||
// log.atDebug().log("SUID: {}, old hash: {}, new hash: {}", ts.getSUID(), Integer.toHexString(rs.getInt(1)), Integer.toHexString(ts.hashCode()));
|
||||
// System.exit(1000);
|
||||
if(rs.getInt(1)!=ts.hashCode()) { |
||||
updatedSchedule.add(ts); |
||||
} |
||||
}else { |
||||
newSchedule.add(ts); |
||||
} |
||||
} |
||||
}//main loop
|
||||
log.atInfo().log("New: {}; Updated:{}", newSchedule.size(), updatedSchedule.size()); |
||||
} catch (FileNotFoundException e) { |
||||
log.error(e.getMessage(), e); |
||||
} catch (IOException e) { |
||||
log.error(e.getMessage(), e); |
||||
} catch (SQLException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
//TODO: Insert/update the record
|
||||
try(Connection conn = DatabaseManager.getInstance().getConnection()){ |
||||
//New records
|
||||
try( |
||||
PreparedStatement psSch = conn.prepareStatement("INSERT INTO ltp_schedule VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); |
||||
PreparedStatement psLoc = conn.prepareStatement("INSERT INTO ltp_location VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)") |
||||
){ |
||||
for(TrainSchedule ts:newSchedule) { |
||||
setString(psSch, 1, ts.getSUID()); |
||||
setString(psSch, 2, ts.getTrainUId()); |
||||
setString(psSch, 3, ts.getScheduleType().name()); |
||||
setString(psSch, 4, sdf.format(ts.getStartDate())); |
||||
setString(psSch, 5, sdf.format(ts.getEndDate())); |
||||
setString(psSch, 6, ts.getDays()); |
||||
setString(psSch, 7, ts.getBankHolidayInd()); |
||||
setString(psSch, 8, ts.getSignalId()); |
||||
setString(psSch, 9, ts.getRsid()); |
||||
setString(psSch,10, ts.getTrainStatus()); |
||||
setString(psSch,11, ts.getTrainCategory()); |
||||
setString(psSch,12, ts.getSection()); |
||||
setString(psSch,13, ts.getPowerType()); |
||||
setString(psSch,14, ts.getTimingLoad()); |
||||
setString(psSch,15, ts.getPlannedSpeed()); |
||||
setString(psSch,16, ts.getOperatingCharacter()); |
||||
setString(psSch,17, ts.getClassAvailable()); |
||||
setString(psSch,18, ts.getSleeper()); |
||||
setString(psSch,19, ts.getReservation()); |
||||
setString(psSch,20, ts.getCatering()); |
||||
setString(psSch,21, ts.getUicCode()); |
||||
setString(psSch,22, ts.getAtocCode()); |
||||
if(ts.getLocations().size()>1) { |
||||
setString(psSch,23, ts.getLocations().get(0).getTiplocCode()); |
||||
setTime(psSch,24, ts.getLocations().get(0).getDeparture()); |
||||
setString(psSch,25, ts.getLocations().get(ts.getLocations().size()-1).getTiplocCode()); |
||||
setTime(psSch,26, ts.getLocations().get(ts.getLocations().size()-1).getArrival()); |
||||
}else { |
||||
psSch.setNull(23, Types.CHAR); |
||||
psSch.setNull(24, Types.TIME); |
||||
psSch.setNull(25, Types.CHAR); |
||||
psSch.setNull(26, Types.TIME); |
||||
} |
||||
psSch.setInt(27, ts.hashCode()); |
||||
int seq = 1; |
||||
for(TrainScheduleLocation tsl:ts.getLocations()) { |
||||
setString(psLoc, 1, ts.getSUID()); |
||||
psLoc.setInt(2, seq++); |
||||
setString(psLoc, 3, tsl.getTiplocCode()); |
||||
psLoc.setInt(4, tsl.getTiplocInstance()); |
||||
setTime(psLoc, 5, tsl.getArrival()); |
||||
setTime(psLoc, 6, tsl.getDeparture()); |
||||
setTime(psLoc, 7, tsl.getPass()); |
||||
setTime(psLoc, 8, tsl.getPubArrival()); |
||||
setTime(psLoc, 9, tsl.getPubDeparture()); |
||||
setString(psLoc,10, tsl.getPlatform()); |
||||
setString(psLoc,11, tsl.getLine()); |
||||
setString(psLoc,12, tsl.getPath()); |
||||
setTime(psLoc,13, tsl.getEngineeringAllowance()); |
||||
setTime(psLoc,14, tsl.getPathingAllowance()); |
||||
setTime(psLoc,15, tsl.getPerformanceAllowance()); |
||||
setString(psLoc,16, tsl.getRecordType().getRecordCode()); |
||||
psLoc.addBatch(); |
||||
} |
||||
psSch.executeUpdate(); |
||||
psLoc.executeBatch(); |
||||
conn.commit(); |
||||
} |
||||
}//New Records
|
||||
//Update records
|
||||
try( |
||||
PreparedStatement psSch = conn.prepareStatement("REPLACE INTO ltp_schedule VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); |
||||
PreparedStatement psDel = conn.prepareStatement("DELETE FROM ltp_location WHERE suid = ?"); |
||||
PreparedStatement psLoc = conn.prepareStatement("INSERT INTO ltp_location VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)") |
||||
){ |
||||
for(TrainSchedule ts:updatedSchedule) { |
||||
setString(psSch, 1, ts.getSUID()); |
||||
setString(psSch, 2, ts.getTrainUId()); |
||||
setString(psSch, 3, ts.getScheduleType().name()); |
||||
setString(psSch, 4, sdf.format(ts.getStartDate())); |
||||
setString(psSch, 5, sdf.format(ts.getEndDate())); |
||||
setString(psSch, 6, ts.getDays()); |
||||
setString(psSch, 7, ts.getBankHolidayInd()); |
||||
setString(psSch, 8, ts.getSignalId()); |
||||
setString(psSch, 9, ts.getRsid()); |
||||
setString(psSch,10, ts.getTrainStatus()); |
||||
setString(psSch,11, ts.getTrainCategory()); |
||||
setString(psSch,12, ts.getSection()); |
||||
setString(psSch,13, ts.getPowerType()); |
||||
setString(psSch,14, ts.getTimingLoad()); |
||||
setString(psSch,15, ts.getPlannedSpeed()); |
||||
setString(psSch,16, ts.getOperatingCharacter()); |
||||
setString(psSch,17, ts.getClassAvailable()); |
||||
setString(psSch,18, ts.getSleeper()); |
||||
setString(psSch,19, ts.getReservation()); |
||||
setString(psSch,20, ts.getCatering()); |
||||
setString(psSch,21, ts.getUicCode()); |
||||
setString(psSch,22, ts.getAtocCode()); |
||||
if(ts.getLocations().size()>1) { |
||||
setString(psSch,23, ts.getLocations().get(0).getTiplocCode()); |
||||
setTime(psSch,24, ts.getLocations().get(0).getDeparture()); |
||||
setString(psSch,25, ts.getLocations().get(ts.getLocations().size()-1).getTiplocCode()); |
||||
setTime(psSch,26, ts.getLocations().get(ts.getLocations().size()-1).getArrival()); |
||||
}else { |
||||
psSch.setNull(23, Types.CHAR); |
||||
psSch.setNull(24, Types.TIME); |
||||
psSch.setNull(25, Types.CHAR); |
||||
psSch.setNull(26, Types.TIME); |
||||
} |
||||
psSch.setInt(27, ts.hashCode()); |
||||
psDel.setString(1, ts.getSUID()); |
||||
psDel.executeUpdate(); |
||||
int seq = 1; |
||||
for(TrainScheduleLocation tsl:ts.getLocations()) { |
||||
setString(psLoc, 1, ts.getSUID()); |
||||
psLoc.setInt(2, seq++); |
||||
setString(psLoc, 3, tsl.getTiplocCode()); |
||||
psLoc.setInt(4, tsl.getTiplocInstance()); |
||||
setTime(psLoc, 5, tsl.getArrival()); |
||||
setTime(psLoc, 6, tsl.getDeparture()); |
||||
setTime(psLoc, 7, tsl.getPass()); |
||||
setTime(psLoc, 8, tsl.getPubArrival()); |
||||
setTime(psLoc, 9, tsl.getPubDeparture()); |
||||
setString(psLoc,10, tsl.getPlatform()); |
||||
setString(psLoc,11, tsl.getLine()); |
||||
setString(psLoc,12, tsl.getPath()); |
||||
setTime(psLoc,13, tsl.getEngineeringAllowance()); |
||||
setTime(psLoc,14, tsl.getPathingAllowance()); |
||||
setTime(psLoc,15, tsl.getPerformanceAllowance()); |
||||
setString(psLoc,16, tsl.getRecordType().getRecordCode()); |
||||
psLoc.addBatch(); |
||||
} |
||||
psSch.executeUpdate(); |
||||
psLoc.executeBatch(); |
||||
conn.commit(); |
||||
} |
||||
}//Updated Records
|
||||
|
||||
// log.atInfo().log("Inserted new {} record(s).",newSchedule.size());
|
||||
} catch (SQLException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
if(!targetFile.delete()) { |
||||
log.warn("Unable to delete {}", targetFile.getName()); |
||||
} |
||||
log.atInfo().log("Done processing {}", targetFile.getName()); |
||||
} |
||||
|
||||
private long getScheduleTime(String t) { |
||||
//HHMM'H'
|
||||
if("".equals(t.trim())) { |
||||
return 0; |
||||
} |
||||
int hour = Integer.parseInt(t.substring(0, 2)); |
||||
int min = Integer.parseInt(t.substring(2, 4)); |
||||
boolean half = t.length()>=5 && t.substring(4, 5).equals("H"); |
||||
return hour*3_600_000+min*60_000+(half?30_000:0); |
||||
} |
||||
|
||||
private long getAllowanceTime(String t) { |
||||
if("".equals(t.trim())) { |
||||
return 0; |
||||
} |
||||
if("H".equals(t.trim())) |
||||
return 30_000; |
||||
if(t.endsWith("H")) { |
||||
//nH
|
||||
return Integer.parseInt(t.substring(0,1))*60_000+30_000; |
||||
}else { |
||||
//nn
|
||||
return Integer.parseInt(t)*60_000; |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,113 @@
|
||||
package org.leolo.rail; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.TreeMap; |
||||
import java.util.concurrent.Callable; |
||||
import java.util.concurrent.ExecutionException; |
||||
import java.util.concurrent.ExecutorService; |
||||
import java.util.concurrent.Executors; |
||||
import java.util.concurrent.Future; |
||||
import java.util.concurrent.TimeUnit; |
||||
import java.util.concurrent.TimeoutException; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
public class ThreadPoolManager { |
||||
private static Logger log = LogManager.getLogger(ThreadPoolManager.class); |
||||
|
||||
private static ThreadPoolManager instance; |
||||
|
||||
private final Object SYNC_TOKEN = new Object(); |
||||
|
||||
public static synchronized ThreadPoolManager getInstance() { |
||||
if(instance==null) { |
||||
instance = new ThreadPoolManager(); |
||||
} |
||||
return instance; |
||||
} |
||||
|
||||
private ExecutorService pool = Executors.newFixedThreadPool( |
||||
ConfigurationManager.getInstance().getInt("pool.size", 30)); |
||||
private TreeMap<Long, Runnable> pendingJob = new TreeMap<>(); |
||||
private ThreadPoolManager() { |
||||
new Thread(()-> { |
||||
while(true) { |
||||
if(pendingJob.isEmpty()) { |
||||
try { |
||||
synchronized(SYNC_TOKEN) { |
||||
SYNC_TOKEN.wait(100); |
||||
} |
||||
}catch(InterruptedException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
continue; |
||||
} |
||||
Long key = pendingJob.firstKey(); |
||||
if(key==null || System.currentTimeMillis() < key) { |
||||
try { |
||||
synchronized(SYNC_TOKEN) { |
||||
SYNC_TOKEN.wait(100); |
||||
} |
||||
}catch(InterruptedException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
continue; |
||||
} |
||||
log.info("Running job#{}", key); |
||||
Runnable r = pendingJob.get(key); |
||||
pendingJob.remove(key); |
||||
pool.execute(r); |
||||
} |
||||
}).start(); |
||||
} |
||||
|
||||
public void execute(Runnable arg0) { |
||||
pool.execute(arg0); |
||||
} |
||||
|
||||
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) |
||||
throws InterruptedException { |
||||
return pool.invokeAll(tasks, timeout, unit); |
||||
} |
||||
|
||||
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException { |
||||
return pool.invokeAll(tasks); |
||||
} |
||||
|
||||
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) |
||||
throws InterruptedException, ExecutionException, TimeoutException { |
||||
return pool.invokeAny(tasks, timeout, unit); |
||||
} |
||||
|
||||
public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException { |
||||
return pool.invokeAny(tasks); |
||||
} |
||||
|
||||
public boolean isShutdown() { |
||||
return pool.isShutdown(); |
||||
} |
||||
|
||||
public boolean isTerminated() { |
||||
return pool.isTerminated(); |
||||
} |
||||
|
||||
public Future<?> submit(Runnable task) { |
||||
return pool.submit(task); |
||||
} |
||||
|
||||
public synchronized void schedule(Runnable task, long notBefore) { |
||||
while(true) { |
||||
if(!pendingJob.containsKey(notBefore)) { |
||||
break; |
||||
} |
||||
notBefore++; |
||||
} |
||||
pendingJob.put(notBefore, task); |
||||
synchronized(SYNC_TOKEN) { |
||||
SYNC_TOKEN.notifyAll(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,67 @@
|
||||
package org.leolo.rail; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.SQLException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.zip.GZIPInputStream; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.json.JSONObject; |
||||
import org.leolo.rail.util.TUIDDateFormat; |
||||
|
||||
public class TiplocProcessor extends BaseProcessor implements Runnable { |
||||
|
||||
private Logger log = LogManager.getLogger(TiplocProcessor.class); |
||||
private File file; |
||||
|
||||
public TiplocProcessor(File f) { |
||||
file = f; |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
log.atInfo().log("Processing {}", file.getName()); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); |
||||
TUIDDateFormat tdf = new TUIDDateFormat(); |
||||
try( |
||||
BufferedReader br = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(file)))); |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("REPLACE INTO tiploc VALUES(?,?,?,?,?,?)") |
||||
){ |
||||
while(true) { |
||||
String line = br.readLine(); |
||||
if(line==null) { |
||||
break; |
||||
} |
||||
JSONObject obj = new JSONObject(line); |
||||
setString(pstmt, 1, obj.optString("tiploc_code")); |
||||
setString(pstmt, 2, obj.optString("nalco")); |
||||
setString(pstmt, 3, obj.optString("stanox")); |
||||
setString(pstmt, 4, obj.optString("crs_code")); |
||||
setString(pstmt, 5, obj.optString("description")); |
||||
setString(pstmt, 6, obj.optString("tps_description")); |
||||
pstmt.addBatch(); |
||||
} |
||||
pstmt.executeBatch(); |
||||
conn.commit(); |
||||
} catch (FileNotFoundException e) { |
||||
log.error(e.getMessage(), e); |
||||
} catch (IOException e) { |
||||
log.error(e.getMessage(), e); |
||||
} catch (SQLException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
if(!file.delete()) { |
||||
log.warn("Unable to delete {}", file.getName()); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,371 @@
|
||||
package org.leolo.rail; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.PrintWriter; |
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.sql.Timestamp; |
||||
import java.sql.Types; |
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.LinkedList; |
||||
import java.util.Queue; |
||||
import java.util.Vector; |
||||
|
||||
import org.apache.activemq.transport.stomp.StompFrame; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.json.JSONArray; |
||||
import org.json.JSONException; |
||||
import org.json.JSONObject; |
||||
import org.leolo.rail.util.TUIDDateFormat; |
||||
|
||||
public class TrainMovementProcessor extends Thread{ |
||||
|
||||
private Logger log = LogManager.getLogger(TrainMovementProcessor.class); |
||||
private Logger logRI = LogManager.getLogger("org.leolo.RI"); |
||||
|
||||
private final Object SYNC_TOKEN = new Object(); |
||||
|
||||
private Queue<StompFrame> procQueue = new LinkedList<>(); |
||||
private boolean terminated = false; |
||||
|
||||
public void terminate() { |
||||
terminated = true; |
||||
synchronized(SYNC_TOKEN) { |
||||
SYNC_TOKEN.notifyAll(); |
||||
} |
||||
} |
||||
|
||||
public void process(StompFrame data) { |
||||
procQueue.add(data); |
||||
synchronized(SYNC_TOKEN) { |
||||
SYNC_TOKEN.notifyAll(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
logRI.debug("Started."); |
||||
while(true) { |
||||
if(terminated) { |
||||
return; |
||||
} |
||||
StompFrame data = procQueue.poll(); |
||||
if(data==null) { |
||||
synchronized(SYNC_TOKEN) { |
||||
try { |
||||
// log.debug("No more data. Sleep.");
|
||||
SYNC_TOKEN.wait(1000); |
||||
} catch (InterruptedException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
} |
||||
continue; |
||||
} |
||||
//Actually handle the data
|
||||
String msgId = data.getHeaders().get("message-id"); |
||||
log.info("Processing message {}", msgId); |
||||
if(Constants.Generic.DEBUG_MODE) { |
||||
new File("tmpd").mkdirs(); |
||||
try(PrintWriter out = new PrintWriter("tmpd/msg_"+msgId.replace(":", "-")+".json")){ |
||||
out.println(data.getBody()); |
||||
} catch (FileNotFoundException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
} |
||||
HashMap<String, ArrayList<JSONObject>> procMap = new HashMap<>(); |
||||
JSONArray procData = new JSONArray(data.getBody()); |
||||
log.info("{} entries expected", procData.length()); |
||||
for(int i=0;i<procData.length();i++) { |
||||
JSONObject obj = procData.getJSONObject(i); |
||||
String type = obj.getJSONObject("header").getString("msg_type"); |
||||
if(!procMap.containsKey(type)) { |
||||
procMap.put(type, new ArrayList<>()); |
||||
} |
||||
procMap.get(type).add(obj); |
||||
} |
||||
//[TA]0001: Train Activation
|
||||
if(procMap.containsKey("0001")) { |
||||
ThreadPoolManager.getInstance().execute(()->{ |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
||||
TUIDDateFormat tdf = new TUIDDateFormat(); |
||||
int batchSize = 0; |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmtTA = conn.prepareStatement("REPLACE INTO current_train VALUES (?,?,?,?,?,?)"); |
||||
PreparedStatement pstmtQsid = conn.prepareStatement("SELECT suid FROM all_schedule " |
||||
+ "WHERE train_uid = ? AND ? BETWEEN start_date AND end_date AND days LIKE get_wd_str(?) " |
||||
+ "ORDER BY CASE sch_type WHEN 'CAN' THEN 1 WHEN 'VAR' THEN 2 WHEN 'OVL' THEN 3 ELSE 4 END ASC LIMIT 1") |
||||
){ |
||||
for(JSONObject obj:procMap.get("0001")) { |
||||
String trainId = obj.getJSONObject("body").optString("train_id"); |
||||
String trainUid = obj.getJSONObject("body").optString("train_uid"); |
||||
Date startDate; |
||||
Date endDate; |
||||
Date opDate; |
||||
try { |
||||
startDate = sdf.parse(obj.getJSONObject("body").optString("schedule_start_date")); |
||||
endDate = sdf.parse(obj.getJSONObject("body").optString("schedule_end_date")); |
||||
opDate = sdf.parse(obj.getJSONObject("body").optString("tp_origin_timestamp")); |
||||
}catch(ParseException e) { |
||||
log.error(e.getMessage(), e); |
||||
continue; |
||||
} |
||||
String serviceCode = obj.getJSONObject("body").optString("train_service_code"); |
||||
long activationTime = obj.getJSONObject("body").optLong("creation_timestamp"); |
||||
String suid; |
||||
pstmtQsid.setString(1, trainUid); |
||||
pstmtQsid.setDate(2, new java.sql.Date(opDate.getTime())); |
||||
pstmtQsid.setDate(3, new java.sql.Date(opDate.getTime())); |
||||
try(ResultSet rs = pstmtQsid.executeQuery()){ |
||||
if(rs.next()) { |
||||
suid = rs.getString(1); |
||||
}else { |
||||
suid = trainUid + tdf.format(startDate) + tdf.format(endDate) + "V"; |
||||
} |
||||
} |
||||
log.debug("[TA] {}({}) TSC:{}", trainId, suid, serviceCode); |
||||
pstmtTA.setString(1, trainId); |
||||
pstmtTA.setString(2, suid); |
||||
pstmtTA.setDate(3, new java.sql.Date(opDate.getTime())); |
||||
pstmtTA.setString(4, serviceCode); |
||||
pstmtTA.setTimestamp(5, new Timestamp(activationTime)); |
||||
pstmtTA.setString(6, CurrentTrainStatus.ACTIVATED.getCode()); |
||||
pstmtTA.addBatch(); |
||||
batchSize++; |
||||
} |
||||
pstmtTA.executeBatch(); |
||||
conn.commit(); |
||||
log.info("[TA] Record Count : {}", batchSize); |
||||
}catch(SQLException e){ |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
}); |
||||
}//TA
|
||||
//[TC]0002: Train Cancellation
|
||||
if(procMap.containsKey("0002")) { |
||||
ThreadPoolManager.getInstance().execute(()->{ |
||||
int batchSize = 0; |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmtTC = conn.prepareStatement("REPLACE current_train_cancellation VALUES (?,?,?,?,?,?,?)"); |
||||
PreparedStatement pstmtUTA = conn.prepareStatement("UPDATE current_train SET `status` = ? WHERE train_id = ?"); |
||||
){ |
||||
pstmtUTA.setString(1, CurrentTrainStatus.CANCELLED.getCode()); |
||||
for(JSONObject obj:procMap.get("0002")) { |
||||
String train_id = obj.getJSONObject("body").optString("train_id"); |
||||
String canx_loc = obj.getJSONObject("body").optString("loc_stanox"); |
||||
String canx_reason = obj.getJSONObject("body").optString("canx_reason_code"); |
||||
String canx_type = obj.getJSONObject("body").optString("canx_type"); |
||||
String canx_dev = obj.getJSONObject("header").optString("source_dev_id"); |
||||
String canx_usr = obj.getJSONObject("header").optString("user_id"); |
||||
long canx_time = obj.getJSONObject("body").optLong("canx_timestamp"); |
||||
// log.debug("[TC] {}@{} because {} by {}@{}", train_id, canx_loc, canx_reason, canx_usr, canx_dev);
|
||||
pstmtTC.setString(1, train_id); |
||||
pstmtTC.setString(2, canx_loc); |
||||
pstmtTC.setTimestamp(3, new Timestamp(canx_time)); |
||||
pstmtTC.setString(4, canx_reason); |
||||
pstmtTC.setString(5, canx_type); |
||||
setString(pstmtTC,6, canx_dev); |
||||
setString(pstmtTC,7, canx_usr); |
||||
pstmtTC.addBatch(); |
||||
pstmtUTA.setString(2, train_id); |
||||
int rowCount = pstmtUTA.executeUpdate(); |
||||
Runnable r = new Runnable() { |
||||
|
||||
int runCount = 0; |
||||
|
||||
@Override |
||||
public void run() { |
||||
runCount++; |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmtUTA = conn.prepareStatement("UPDATE current_train SET `status` = ? WHERE train_id = ?"); |
||||
){ |
||||
pstmtUTA.setString(1, CurrentTrainStatus.CANCELLED.getCode()); |
||||
pstmtUTA.setString(2, train_id); |
||||
int rowCount = pstmtUTA.executeUpdate(); |
||||
if(rowCount==0) { |
||||
if(runCount > 5) { |
||||
log.warn("[TC] Cannot update {} [LAST]", train_id); |
||||
return; |
||||
} |
||||
log.warn("[TC] Cannot update {} (ROUND {})", train_id, runCount); |
||||
ThreadPoolManager.getInstance().schedule(this, System.currentTimeMillis()+(long)(1000*Math.pow(2, runCount))); |
||||
}else { |
||||
log.info("[TC] Successfully update {} (ROUND {})", train_id, runCount); |
||||
} |
||||
conn.commit(); |
||||
}catch(SQLException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
}; |
||||
if(rowCount==0) { |
||||
log.warn("[TC] Cannot update {}", train_id); |
||||
ThreadPoolManager.getInstance().schedule(r, System.currentTimeMillis()+1000); |
||||
} |
||||
batchSize++; |
||||
} |
||||
pstmtTC.executeBatch(); |
||||
conn.commit(); |
||||
log.info("[TC] Record Count : {}", batchSize); |
||||
}catch(SQLException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
|
||||
}); |
||||
}//TC
|
||||
//[TM]0003: Train Movement
|
||||
if(procMap.containsKey("0003")) { |
||||
ThreadPoolManager.getInstance().execute(()->{ |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmtTM = conn.prepareStatement("REPLACE INTO current_train_movement VALUES (?,?,?,?,?,?,?,?,?,?,?,?)"); |
||||
PreparedStatement pstmtUTA = conn.prepareStatement("UPDATE current_train SET `status` = ? WHERE train_id = ?"); |
||||
){ |
||||
int batchSize = 0; |
||||
for(JSONObject obj:procMap.get("0003")) { |
||||
String trainId = obj.getJSONObject("body" ).optString ("train_id"); |
||||
long movtTime = obj.getJSONObject("body" ).optLong ("actual_timestamp"); |
||||
long gbttTime = obj.getJSONObject("body" ).optLong ("gbtt_timestamp", -1); |
||||
long planTime = obj.getJSONObject("body" ).optLong ("planned_timestamp", -1); |
||||
String stanox = obj.getJSONObject("body" ).optString ("loc_stanox"); |
||||
String eventType = obj.getJSONObject("body" ).optString ("event_type"); |
||||
boolean correction= obj.getJSONObject("body" ).optBoolean("correction_ind"); |
||||
String platform = obj.getJSONObject("body" ).optString ("platform"); |
||||
String line = obj.getJSONObject("body" ).optString ("line_ind"); |
||||
String route = obj.getJSONObject("body" ).optString ("route"); |
||||
String dev = obj.getJSONObject("header").optString ("source_dev_id"); |
||||
String usr = obj.getJSONObject("header").optString ("user_id"); |
||||
boolean termInd = obj.getJSONObject("body" ).optBoolean("train_terminated", false); |
||||
// log.debug("[TM] {}@{} PLAT {}/{}{} by {}@{}{}", trainId, stanox, platform, line, route, usr, dev,termInd?"[T]":"");
|
||||
pstmtTM.setString(1, trainId); |
||||
pstmtTM.setTimestamp(2, new Timestamp(movtTime)); |
||||
if(gbttTime==-1) { |
||||
pstmtTM.setNull(3, Types.TIMESTAMP); |
||||
}else { |
||||
pstmtTM.setTimestamp(3, new Timestamp(gbttTime)); |
||||
} |
||||
if(planTime==-1) { |
||||
pstmtTM.setNull(4, Types.TIMESTAMP); |
||||
}else { |
||||
pstmtTM.setTimestamp(4, new Timestamp(planTime)); |
||||
} |
||||
pstmtTM.setString(5, stanox); |
||||
pstmtTM.setString(6, eventType); |
||||
pstmtTM.setString(7, correction?"Y":"N"); |
||||
setString(pstmtTM,8, platform); |
||||
setString(pstmtTM,9, line); |
||||
setString(pstmtTM,10, route); |
||||
setString(pstmtTM,11, dev); |
||||
setString(pstmtTM,12, usr); |
||||
pstmtTM.addBatch(); |
||||
if(termInd) { |
||||
pstmtUTA.setString(1, CurrentTrainStatus.TERMINATED.getCode()); |
||||
pstmtUTA.setString(2, trainId); |
||||
pstmtUTA.addBatch(); |
||||
} |
||||
batchSize++; |
||||
} |
||||
pstmtTM.executeBatch(); |
||||
pstmtUTA.executeBatch(); |
||||
conn.commit(); |
||||
log.info("[TM] Record Count : {}", batchSize); |
||||
}catch(SQLException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
}); |
||||
}//TM
|
||||
//[RI]0005: Train re-instatement
|
||||
if(procMap.containsKey("0005")) { |
||||
ThreadPoolManager.getInstance().execute(()->{ |
||||
int batchSize = 0; |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmtTC = conn.prepareStatement("REPLACE current_train_reinstatement VALUES (?,?,?,?,?)"); |
||||
PreparedStatement pstmtUTA = conn.prepareStatement("UPDATE current_train SET `status` = ? WHERE train_id = ?"); |
||||
){ |
||||
pstmtUTA.setString(1, CurrentTrainStatus.ACTIVATED.getCode()); |
||||
for(JSONObject obj:procMap.get("0005")) { |
||||
String train_id = obj.getJSONObject("body").optString("train_id"); |
||||
String canx_loc = obj.getJSONObject("body").optString("loc_stanox"); |
||||
String canx_dev = obj.getJSONObject("header").optString("source_dev_id"); |
||||
String canx_usr = obj.getJSONObject("header").optString("user_id"); |
||||
long canx_time = obj.getJSONObject("body").optLong("reinstatement_timestamp"); |
||||
logRI.atInfo().log("TS: {}", canx_time); |
||||
logRI.atInfo().log(obj.getJSONObject("body").toString()); |
||||
// log.debug("[TC] {}@{} because {} by {}@{}", train_id, canx_loc, canx_reason, canx_usr, canx_dev);
|
||||
pstmtTC.setString(1, train_id); |
||||
pstmtTC.setString(2, canx_loc); |
||||
pstmtTC.setTimestamp(3, new Timestamp(canx_time)); |
||||
setString(pstmtTC,4, canx_dev); |
||||
setString(pstmtTC,5, canx_usr); |
||||
pstmtTC.addBatch(); |
||||
pstmtUTA.setString(2, train_id); |
||||
int rowCount = pstmtUTA.executeUpdate(); |
||||
Runnable r = new Runnable() { |
||||
|
||||
int runCount = 0; |
||||
|
||||
@Override |
||||
public void run() { |
||||
runCount++; |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmtUTA = conn.prepareStatement("UPDATE current_train SET `status` = ? WHERE train_id = ?"); |
||||
){ |
||||
pstmtUTA.setString(1, CurrentTrainStatus.ACTIVATED.getCode()); |
||||
pstmtUTA.setString(2, train_id); |
||||
int rowCount = pstmtUTA.executeUpdate(); |
||||
if(rowCount==0) { |
||||
if(runCount > 5) { |
||||
log.warn("[RI] Cannot update {} [LAST]", train_id); |
||||
return; |
||||
} |
||||
log.warn("[RI] Cannot update {} (ROUND {})", train_id, runCount); |
||||
ThreadPoolManager.getInstance().schedule(this, System.currentTimeMillis()+(long)(1000*Math.pow(2, runCount))); |
||||
}else { |
||||
log.info("[RI] Successfully update {} (ROUND {})", train_id, runCount); |
||||
} |
||||
conn.commit(); |
||||
}catch(SQLException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
}; |
||||
if(rowCount==0) { |
||||
log.warn("[RI] Cannot update {}", train_id); |
||||
ThreadPoolManager.getInstance().schedule(r, System.currentTimeMillis()+1000); |
||||
} |
||||
batchSize++; |
||||
} |
||||
pstmtTC.executeBatch(); |
||||
conn.commit(); |
||||
log.info("[RI] Record Count : {}", batchSize); |
||||
}catch(SQLException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected void setString(PreparedStatement stmt, int col, String val) throws SQLException{ |
||||
if(val==null||"".equals(val)) { |
||||
stmt.setNull(col, Types.CHAR); |
||||
}else { |
||||
stmt.setString(col, val); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,275 @@
|
||||
package org.leolo.rail; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.PrintWriter; |
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.SQLException; |
||||
import java.sql.Types; |
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.LinkedList; |
||||
import java.util.Queue; |
||||
|
||||
import org.apache.activemq.transport.stomp.StompFrame; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.json.JSONArray; |
||||
import org.json.JSONObject; |
||||
import org.leolo.rail.model.LocationRecordType; |
||||
import org.leolo.rail.model.ScheduleType; |
||||
import org.leolo.rail.model.TrainSchedule; |
||||
import org.leolo.rail.model.TrainScheduleLocation; |
||||
|
||||
public class VTSPProcessor extends Thread { |
||||
private Logger log = LogManager.getLogger(VTSPProcessor.class); |
||||
private Logger logRI = LogManager.getLogger("org.leolo.RI"); |
||||
|
||||
private final Object SYNC_TOKEN = new Object(); |
||||
|
||||
private Queue<StompFrame> procQueue = new LinkedList<>(); |
||||
private boolean terminated = false; |
||||
|
||||
public void terminate() { |
||||
terminated = true; |
||||
synchronized(SYNC_TOKEN) { |
||||
SYNC_TOKEN.notifyAll(); |
||||
} |
||||
} |
||||
|
||||
public void process(StompFrame data) { |
||||
procQueue.add(data); |
||||
synchronized(SYNC_TOKEN) { |
||||
SYNC_TOKEN.notifyAll(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
logRI.debug("Started."); |
||||
while(true) { |
||||
if(terminated) { |
||||
return; |
||||
} |
||||
StompFrame data = procQueue.poll(); |
||||
if(data==null) { |
||||
synchronized(SYNC_TOKEN) { |
||||
try { |
||||
// log.debug("No more data. Sleep.");
|
||||
SYNC_TOKEN.wait(1000); |
||||
} catch (InterruptedException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
} |
||||
continue; |
||||
} |
||||
//Actually handle the data
|
||||
String msgId = data.getHeaders().get("message-id"); |
||||
log.info("Processing message {}", msgId); |
||||
if(true||Constants.Generic.DEBUG_MODE) { |
||||
new File("tmpd").mkdirs(); |
||||
try(PrintWriter out = new PrintWriter("tmpd/VTSP-msg_"+msgId.replace(":", "-")+".json")){ |
||||
out.println(data.getBody()); |
||||
} catch (FileNotFoundException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
} |
||||
JSONObject obj = new JSONObject(data.getBody()).getJSONObject("VSTPCIFMsgV1").optJSONObject("schedule"); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
||||
String txType = obj.optString("transaction_type"); |
||||
if("Delete".equalsIgnoreCase(txType)) { |
||||
//Remove the schedule
|
||||
TrainSchedule ts = new TrainSchedule(); |
||||
ts.setTrainUId(obj.optString("CIF_train_uid")); |
||||
ts.setScheduleType(ScheduleType.STP); |
||||
try { |
||||
ts.setStartDate(sdf.parse(obj.optString("schedule_start_date"))); |
||||
ts.setEndDate(sdf.parse(obj.optString("schedule_end_date"))); |
||||
}catch(ParseException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement psLoc = conn.prepareStatement("DELETE FROM stp_location WHERE suid = ?"); |
||||
PreparedStatement psSch = conn.prepareStatement("DELETE FROM stp_schedule WHERE suid = ?"); |
||||
){ |
||||
psLoc.setString(1, ts.getSUID()); |
||||
psSch.setString(1, ts.getSUID()); |
||||
psLoc.executeUpdate(); |
||||
psSch.executeUpdate(); |
||||
conn.commit(); |
||||
}catch(SQLException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
return; |
||||
} |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement psSch = conn.prepareStatement("INSERT INTO stp_schedule VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); |
||||
PreparedStatement psLoc = conn.prepareStatement("INSERT INTO stp_location VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)") |
||||
){ |
||||
|
||||
TrainSchedule ts = new TrainSchedule(); |
||||
ts.setTrainUId(obj.optString("CIF_train_uid")); |
||||
ts.setScheduleType(ScheduleType.STP); |
||||
try { |
||||
ts.setStartDate(sdf.parse(obj.optString("schedule_start_date"))); |
||||
ts.setEndDate(sdf.parse(obj.optString("schedule_end_date"))); |
||||
}catch(ParseException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
ts.setDays(obj.optString("schedule_days_runs")); |
||||
ts.setBankHolidayInd(obj.optString("CIF_bank_holiday_running")); |
||||
ts.setSignalId(obj.getJSONArray("schedule_segment").getJSONObject(0).optString("signalling_id")); |
||||
ts.setRsid(obj.getJSONArray("schedule_segment").getJSONObject(0).optString("CIF_headcode")); |
||||
ts.setTrainStatus(obj.optString("train_status")); |
||||
ts.setTrainCategory(obj.getJSONArray("schedule_segment").getJSONObject(0).optString("CIF_train_category")); |
||||
ts.setSection(obj.getJSONArray("schedule_segment").getJSONObject(0).optString("CIF_business_sector")); |
||||
ts.setPowerType(obj.getJSONArray("schedule_segment").getJSONObject(0).optString("CIF_power_type")); |
||||
ts.setTimingLoad(obj.getJSONArray("schedule_segment").getJSONObject(0).optString("CIF_timing_load")); |
||||
ts.setPlannedSpeed(Integer.toString((int) (obj.getJSONArray("schedule_segment").getJSONObject(0).optInt("CIF_speed")/2.24))); |
||||
ts.setOperatingCharacter(obj.getJSONArray("schedule_segment").getJSONObject(0).optString("CIF_operating_characteristics")); |
||||
ts.setClassAvailable(obj.getJSONArray("schedule_segment").getJSONObject(0).optString("CIF_train_class")); |
||||
ts.setSleeper(obj.getJSONArray("schedule_segment").getJSONObject(0).optString("CIF_sleepers")); |
||||
ts.setReservation(obj.getJSONArray("schedule_segment").getJSONObject(0).optString("CIF_reservations")); |
||||
ts.setCatering(obj.getJSONArray("schedule_segment").getJSONObject(0).optString("CIF_catering_code")); |
||||
ts.setAtocCode(obj.getJSONArray("schedule_segment").getJSONObject(0).optString("atoc_code")); |
||||
JSONArray locs = obj.getJSONArray("schedule_segment").getJSONObject(0).getJSONArray("schedule_location"); |
||||
for(int i=0;i<locs.length();i++) { |
||||
JSONObject loc = locs.getJSONObject(i); |
||||
TrainScheduleLocation tsl = new TrainScheduleLocation(); |
||||
tsl.setTiplocCode(loc.getJSONObject("location").getJSONObject("tiploc").optString("tiploc_id")); |
||||
tsl.setTiplocInstance(0); |
||||
tsl.setArrival(getScheduleTime(loc.optString("scheduled_arrival_time"))); |
||||
tsl.setDeparture(getScheduleTime(loc.optString("scheduled_departure_time"))); |
||||
tsl.setPass(getScheduleTime(loc.optString("scheduled_pass_time"))); |
||||
tsl.setPubArrival(getScheduleTime(loc.optString("public_arrival"))); |
||||
tsl.setPubDeparture(getScheduleTime(loc.optString("public_departure"))); |
||||
tsl.setPlatform(loc.optString("CIF_platform")); |
||||
tsl.setLine(loc.optString("CIF_line")); |
||||
tsl.setPath(loc.optString("CIF_path")); |
||||
tsl.setEngineeringAllowance(getAllowanceTime(loc.optString("CIF_engineering_allowance"))); |
||||
tsl.setPathingAllowance(getAllowanceTime(loc.optString("CIF_pathing_allowance"))); |
||||
tsl.setPerformanceAllowance(getAllowanceTime(loc.optString("CIF_performance_allowance"))); |
||||
// String locType = loc.optString("location_type");
|
||||
if(i==0) { |
||||
tsl.setRecordType(LocationRecordType.ORIGIN); |
||||
}else if((i+1)==locs.length()) { |
||||
tsl.setRecordType(LocationRecordType.TERMINATE); |
||||
}else{ |
||||
tsl.setRecordType(LocationRecordType.INTERMEDIATE); |
||||
} |
||||
ts.getLocations().add(tsl); |
||||
} |
||||
|
||||
setString(psSch, 1, ts.getSUID()); |
||||
setString(psSch, 2, ts.getTrainUId()); |
||||
setString(psSch, 3, ts.getScheduleType().name()); |
||||
setString(psSch, 4, sdf.format(ts.getStartDate())); |
||||
setString(psSch, 5, sdf.format(ts.getEndDate())); |
||||
setString(psSch, 6, ts.getDays()); |
||||
setString(psSch, 7, ts.getBankHolidayInd()); |
||||
setString(psSch, 8, ts.getSignalId()); |
||||
setString(psSch, 9, ts.getRsid()); |
||||
setString(psSch,10, ts.getTrainStatus()); |
||||
setString(psSch,11, ts.getTrainCategory()); |
||||
setString(psSch,12, ts.getSection()); |
||||
setString(psSch,13, ts.getPowerType()); |
||||
setString(psSch,14, ts.getTimingLoad()); |
||||
setString(psSch,15, ts.getPlannedSpeed()); |
||||
setString(psSch,16, ts.getOperatingCharacter()); |
||||
setString(psSch,17, ts.getClassAvailable()); |
||||
setString(psSch,18, ts.getSleeper()); |
||||
setString(psSch,19, ts.getReservation()); |
||||
setString(psSch,20, ts.getCatering()); |
||||
setString(psSch,21, ts.getUicCode()); |
||||
setString(psSch,22, ts.getAtocCode()); |
||||
if(ts.getLocations().size()>1) { |
||||
setString(psSch,23, ts.getLocations().get(0).getTiplocCode()); |
||||
setTime(psSch,24, ts.getLocations().get(0).getDeparture()); |
||||
setString(psSch,25, ts.getLocations().get(ts.getLocations().size()-1).getTiplocCode()); |
||||
setTime(psSch,26, ts.getLocations().get(ts.getLocations().size()-1).getArrival()); |
||||
}else { |
||||
psSch.setNull(23, Types.CHAR); |
||||
psSch.setNull(24, Types.TIME); |
||||
psSch.setNull(25, Types.CHAR); |
||||
psSch.setNull(26, Types.TIME); |
||||
} |
||||
psSch.setInt(27, ts.hashCode()); |
||||
int seq = 1; |
||||
for(TrainScheduleLocation tsl:ts.getLocations()) { |
||||
setString(psLoc, 1, ts.getSUID()); |
||||
psLoc.setInt(2, seq++); |
||||
setString(psLoc, 3, tsl.getTiplocCode()); |
||||
psLoc.setInt(4, tsl.getTiplocInstance()); |
||||
setTime(psLoc, 5, tsl.getArrival()); |
||||
setTime(psLoc, 6, tsl.getDeparture()); |
||||
setTime(psLoc, 7, tsl.getPass()); |
||||
setTime(psLoc, 8, tsl.getPubArrival()); |
||||
setTime(psLoc, 9, tsl.getPubDeparture()); |
||||
setString(psLoc,10, tsl.getPlatform()); |
||||
setString(psLoc,11, tsl.getLine()); |
||||
setString(psLoc,12, tsl.getPath()); |
||||
setTime(psLoc,13, tsl.getEngineeringAllowance()); |
||||
setTime(psLoc,14, tsl.getPathingAllowance()); |
||||
setTime(psLoc,15, tsl.getPerformanceAllowance()); |
||||
setString(psLoc,16, tsl.getRecordType().getRecordCode()); |
||||
psLoc.addBatch(); |
||||
} |
||||
psSch.executeUpdate(); |
||||
psLoc.executeBatch(); |
||||
conn.commit(); |
||||
}catch(SQLException e) { |
||||
log.atError().log(e.getMessage(),e); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
protected void setString(PreparedStatement stmt, int col, String val) throws SQLException{ |
||||
if(val==null||"".equals(val)) { |
||||
stmt.setNull(col, Types.CHAR); |
||||
}else { |
||||
stmt.setString(col, val); |
||||
} |
||||
} |
||||
|
||||
private long getScheduleTime(String t) { |
||||
//HHMMSS
|
||||
t = t.trim(); |
||||
if("".equals(t)) { |
||||
return 0; |
||||
} |
||||
int hour = Integer.parseInt(t.substring(0, 2)); |
||||
int min = Integer.parseInt(t.substring(2, 4)); |
||||
int sec = Integer.parseInt(t.substring(4, 6)); |
||||
return hour*3_600_000+min*60_000+sec; |
||||
} |
||||
|
||||
private long getAllowanceTime(String t) { |
||||
if("".equals(t.trim())) { |
||||
return 0; |
||||
} |
||||
if("H".equals(t.trim())) |
||||
return 30_000; |
||||
if(t.endsWith("H")) { |
||||
//nH
|
||||
return Integer.parseInt(t.substring(0,1))*60_000+30_000; |
||||
}else { |
||||
//nn
|
||||
return Integer.parseInt(t)*60_000; |
||||
} |
||||
} |
||||
|
||||
public void setTime(PreparedStatement stmt, int col, long time) throws SQLException{ |
||||
if(time==0) { |
||||
stmt.setNull(col, Types.TIME); |
||||
}else { |
||||
int h = (int)(time/3_600_000); |
||||
int m = (int)((time/60_000)%60); |
||||
int s = (int)((time/1_000)%60); |
||||
stmt.setString(col, h+":"+m+":"+s); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,123 @@
|
||||
package org.leolo.rail.dao; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.util.Date; |
||||
|
||||
import org.leolo.rail.DatabaseManager; |
||||
|
||||
public class MetadataDao { |
||||
|
||||
|
||||
public String getString(String key) throws SQLException{ |
||||
return getString(key, null); |
||||
} |
||||
|
||||
public String getString(String key, String defaultValue) throws SQLException{ |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT metadata_value FROM metadata WHERE metadata_name = ?"); |
||||
){ |
||||
pstmt.setString(1, key); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
if(rs.next()) { |
||||
return rs.getString("metadata_value"); |
||||
} |
||||
} |
||||
} |
||||
return defaultValue; |
||||
} |
||||
|
||||
public long getLong(String key) throws SQLException{ |
||||
return getLong(key, 0); |
||||
} |
||||
|
||||
public long getLong(String key, long defaultValue) throws SQLException{ |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT metadata_value FROM metadata WHERE metadata_name = ?"); |
||||
){ |
||||
pstmt.setString(1, key); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
if(rs.next()) { |
||||
return rs.getLong("metadata_value"); |
||||
} |
||||
} |
||||
} |
||||
return defaultValue; |
||||
} |
||||
|
||||
public Date getDate(String key) throws SQLException{ |
||||
return getDate(key, null); |
||||
} |
||||
|
||||
public Date getDate(String key, Date defaultValue) throws SQLException{ |
||||
long val = getLong(key, Long.MIN_VALUE); |
||||
if(val==Long.MIN_VALUE) { |
||||
return defaultValue; |
||||
} |
||||
return new Date(val); |
||||
} |
||||
|
||||
public void setString(String key, String value) throws SQLException{ |
||||
if(value!=null) { |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("REPLACE INTO metadata (metadata_name, metadata_value) VALUES (?,?)"); |
||||
){ |
||||
pstmt.setString(1, key); |
||||
pstmt.setString(2, value); |
||||
pstmt.executeUpdate(); |
||||
conn.commit(); |
||||
} |
||||
}else { |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("DELETE FROM metadata WHERE metadata_name=?"); |
||||
){ |
||||
pstmt.setString(1, key); |
||||
pstmt.executeUpdate(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void setLong(String key, long value) throws SQLException{ |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("REPLACE INTO metadata (metadata_name, metadata_value) VALUES (?,?)"); |
||||
){ |
||||
pstmt.setString(1, key); |
||||
pstmt.setLong(2, value); |
||||
pstmt.executeUpdate(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
|
||||
public void setDate(String key, Date value) throws SQLException{ |
||||
if(value!=null) { |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("REPLACE INTO metadata (metadata_name, metadata_value) VALUES (?,?)"); |
||||
){ |
||||
pstmt.setString(1, key); |
||||
pstmt.setLong(2, value.getTime()); |
||||
pstmt.executeUpdate(); |
||||
conn.commit(); |
||||
} |
||||
}else { |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("DELETE FROM metadata WHERE metadata_name=?"); |
||||
){ |
||||
pstmt.setString(1, key); |
||||
pstmt.executeUpdate(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,193 @@
|
||||
package org.leolo.rail.job; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.sql.Statement; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Calendar; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.leolo.rail.Constants; |
||||
import org.leolo.rail.DatabaseManager; |
||||
import org.quartz.Job; |
||||
import org.quartz.JobExecutionContext; |
||||
import org.quartz.JobExecutionException; |
||||
|
||||
public class DayEndJob implements Job { |
||||
private Logger log = LogManager.getLogger(DayEndJob.class); |
||||
|
||||
@Override |
||||
public void execute(JobExecutionContext context) throws JobExecutionException { |
||||
// TODO Auto-generated method stub
|
||||
log.atInfo().log("Start day-end job"); |
||||
try(Connection conn = DatabaseManager.getInstance().getConnection()){ |
||||
Calendar c = Calendar.getInstance(); |
||||
c.add(Calendar.DAY_OF_MONTH, -1*Constants.Generic.DATA_RETAINTION_PERIOD); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
||||
log.atInfo().log("Removing data on or before {}", sdf.format(c.getTime())); |
||||
String cutoffDate = sdf.format(c.getTime()); |
||||
//Delete LTP main records
|
||||
try( |
||||
PreparedStatement psQuery = conn.prepareStatement("SELECT suid FROM ltp_schedule WHERE end_date < ?"); |
||||
){ |
||||
psQuery.setString(1, cutoffDate); |
||||
try( |
||||
ResultSet rs = psQuery.executeQuery(); |
||||
PreparedStatement psLoc = conn.prepareStatement("DELETE FROM ltp_location WHERE suid = ?"); |
||||
PreparedStatement psSch = conn.prepareStatement("DELETE FROM ltp_schedule WHERE suid = ?"); |
||||
){ |
||||
int schCount = 0; |
||||
while(rs.next()) { |
||||
psLoc.setString(1, rs.getString(1)); |
||||
psSch.setString(1, rs.getString(1)); |
||||
psLoc.executeUpdate(); |
||||
psSch.executeUpdate(); |
||||
conn.commit(); |
||||
schCount++; |
||||
} |
||||
log.atInfo().log("Deleted {} LTP schedules.", schCount); |
||||
} |
||||
} catch (SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
}//Delete LTP main records
|
||||
try( |
||||
PreparedStatement psQuery = conn.prepareStatement("SELECT suid FROM stp_schedule WHERE end_date < ?"); |
||||
){ |
||||
psQuery.setString(1, cutoffDate); |
||||
try( |
||||
ResultSet rs = psQuery.executeQuery(); |
||||
PreparedStatement psLoc = conn.prepareStatement("DELETE FROM stp_location WHERE suid = ?"); |
||||
PreparedStatement psSch = conn.prepareStatement("DELETE FROM stp_schedule WHERE suid = ?"); |
||||
){ |
||||
int schCount = 0; |
||||
while(rs.next()) { |
||||
psLoc.setString(1, rs.getString(1)); |
||||
psSch.setString(1, rs.getString(1)); |
||||
psLoc.executeUpdate(); |
||||
psSch.executeUpdate(); |
||||
conn.commit(); |
||||
schCount++; |
||||
} |
||||
log.atInfo().log("Deleted {} STP schedules.", schCount); |
||||
} |
||||
} catch (SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
//Delete LTP association records
|
||||
try( |
||||
PreparedStatement psQuery = conn.prepareStatement("SELECT auid FROM ltp_assoication WHERE end_date < ?"); |
||||
){ |
||||
psQuery.setString(1, cutoffDate); |
||||
try( |
||||
ResultSet rs = psQuery.executeQuery(); |
||||
PreparedStatement psSch = conn.prepareStatement("DELETE FROM ltp_assoication WHERE auid = ?"); |
||||
){ |
||||
int assoCount = 0; |
||||
while(rs.next()) { |
||||
psSch.setString(1, rs.getString(1)); |
||||
psSch.executeUpdate(); |
||||
conn.commit(); |
||||
assoCount++; |
||||
} |
||||
log.atInfo().log("Deleted {} assocication.", assoCount); |
||||
} |
||||
} catch (SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
//Delete Movements
|
||||
try( |
||||
PreparedStatement psQuery = conn.prepareStatement("SELECT DISTINCT train_id FROM current_train_movement WHERE movt_time < ?"); |
||||
){ |
||||
psQuery.setString(1, cutoffDate); |
||||
int movtCount = 0; |
||||
try( |
||||
ResultSet rs = psQuery.executeQuery(); |
||||
PreparedStatement psDel = conn.prepareStatement("DELETE FROM current_train_movement WHERE train_id = ? "); |
||||
){ |
||||
while(rs.next()) { |
||||
psDel.setString(1, rs.getString(1)); |
||||
psDel.executeUpdate(); |
||||
conn.commit(); |
||||
movtCount++; |
||||
} |
||||
log.atInfo().log("Deleted movement records for {} trains.", movtCount); |
||||
|
||||
} |
||||
}catch (SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
//Delete cancellation
|
||||
try( |
||||
PreparedStatement psQuery = conn.prepareStatement("SELECT DISTINCT train_id FROM current_train_cancellation WHERE canx_time < ?"); |
||||
){ |
||||
psQuery.setString(1, cutoffDate); |
||||
int movtCount = 0; |
||||
try( |
||||
ResultSet rs = psQuery.executeQuery(); |
||||
PreparedStatement psDel = conn.prepareStatement("DELETE FROM current_train_cancellation WHERE train_id = ? "); |
||||
){ |
||||
while(rs.next()) { |
||||
psDel.setString(1, rs.getString(1)); |
||||
psDel.executeUpdate(); |
||||
conn.commit(); |
||||
movtCount++; |
||||
} |
||||
log.atInfo().log("Deleted cancellation records for {} trains.", movtCount); |
||||
|
||||
} |
||||
}catch (SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
//Delete Movements
|
||||
try( |
||||
PreparedStatement psQuery = conn.prepareStatement("SELECT DISTINCT train_id FROM current_train_reinstatement WHERE rein_time < ?"); |
||||
){ |
||||
psQuery.setString(1, cutoffDate); |
||||
int movtCount = 0; |
||||
try( |
||||
ResultSet rs = psQuery.executeQuery(); |
||||
PreparedStatement psDel = conn.prepareStatement("DELETE FROM current_train_reinstatement WHERE train_id = ? "); |
||||
){ |
||||
while(rs.next()) { |
||||
psDel.setString(1, rs.getString(1)); |
||||
psDel.executeUpdate(); |
||||
conn.commit(); |
||||
movtCount++; |
||||
} |
||||
log.atInfo().log("Deleted reinstatement records for {} trains.", movtCount); |
||||
|
||||
} |
||||
}catch (SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
//Delete activation
|
||||
try( |
||||
PreparedStatement psQuery = conn.prepareStatement("SELECT DISTINCT train_id FROM current_train WHERE op_date < ?"); |
||||
){ |
||||
psQuery.setString(1, cutoffDate); |
||||
int movtCount = 0; |
||||
try( |
||||
ResultSet rs = psQuery.executeQuery(); |
||||
PreparedStatement psDel = conn.prepareStatement("DELETE FROM current_train WHERE train_id = ? "); |
||||
){ |
||||
while(rs.next()) { |
||||
psDel.setString(1, rs.getString(1)); |
||||
psDel.executeUpdate(); |
||||
conn.commit(); |
||||
movtCount++; |
||||
} |
||||
log.atInfo().log("Deleted activation records for {} trains.", movtCount); |
||||
|
||||
} |
||||
}catch (SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
} catch (SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,190 @@
|
||||
package org.leolo.rail.job; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.File; |
||||
import java.io.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.InputStreamReader; |
||||
import java.io.PrintWriter; |
||||
import java.net.URL; |
||||
import java.net.URLConnection; |
||||
import java.sql.SQLException; |
||||
import java.util.Base64; |
||||
import java.util.Date; |
||||
import java.util.concurrent.ExecutorService; |
||||
import java.util.concurrent.TimeUnit; |
||||
import java.util.zip.GZIPInputStream; |
||||
import java.util.zip.GZIPOutputStream; |
||||
import java.util.zip.ZipException; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.json.JSONObject; |
||||
import org.leolo.rail.AssoicationProcessor; |
||||
import org.leolo.rail.ConfigurationManager; |
||||
import org.leolo.rail.Constants; |
||||
import org.leolo.rail.ScheduleProcessor; |
||||
import org.leolo.rail.TiplocProcessor; |
||||
import org.leolo.rail.Constants.Metadata; |
||||
import org.leolo.rail.Constants.Scheduler; |
||||
import org.leolo.rail.dao.MetadataDao; |
||||
import org.quartz.Job; |
||||
import org.quartz.JobExecutionContext; |
||||
import org.quartz.JobExecutionException; |
||||
import org.quartz.SchedulerException; |
||||
import org.quartz.Trigger; |
||||
import org.quartz.TriggerKey; |
||||
import org.quartz.impl.matchers.GroupMatcher; |
||||
|
||||
public class LongTermScheduleJob implements Job{ |
||||
|
||||
private Logger log = LogManager.getLogger(LongTermScheduleJob.class); |
||||
|
||||
@Override |
||||
public void execute(JobExecutionContext context) throws JobExecutionException { |
||||
MetadataDao mDao = new MetadataDao(); |
||||
log.atInfo().log("LongTermScheduleJob started."); |
||||
|
||||
try { |
||||
TriggerKey triggerKey = TriggerKey.triggerKey(Constants.Scheduler.LTSJ_CRON_TRIGGER, Constants.Scheduler.DEFAULT_GROUP_NAME); |
||||
Trigger trigger = context.getScheduler().getTrigger(triggerKey); |
||||
Date nextFireTime = trigger.getNextFireTime(); |
||||
log.info("Next fire at "+nextFireTime); |
||||
long timeToNextFire = nextFireTime.getTime() - System.currentTimeMillis(); |
||||
if(timeToNextFire > Constants.Scheduler.LTR_SKIP_THRESHOLD && !ConfigurationManager.getInstance().getBoolean("general.debug", false)) { |
||||
log.always().log("Too close to next fire time. Skipping"); |
||||
return; |
||||
} |
||||
} catch (SchedulerException e) { |
||||
log.atError().log(e.getMessage(),e); |
||||
} |
||||
InputStream fis = null; |
||||
try { |
||||
URL url = new URL(ConfigurationManager.getInstance().getProperty("network.schedule.path")); |
||||
URLConnection conn = url.openConnection(); |
||||
String userpwd = ConfigurationManager.getInstance().getProperty("network.user")+":"+ConfigurationManager.getInstance().getProperty("network.pwd"); |
||||
conn.addRequestProperty("Authorization", "Basic "+Base64.getEncoder().encodeToString(userpwd.getBytes())); |
||||
conn.connect(); |
||||
fis = conn.getInputStream(); |
||||
}catch(IOException e) { |
||||
log.error(e.getMessage(), e); |
||||
System.exit(4); |
||||
} |
||||
log.info("Connected!"); |
||||
File tempDir = new File(ConfigurationManager.getInstance().getProperty("file.temp_dir", ".")+"/nrdg"); |
||||
if(!tempDir.exists()) { |
||||
tempDir.mkdirs(); |
||||
} |
||||
int countA=0, countT=0, countS=0; |
||||
int batchA=0, batchT=0, batchS=0; |
||||
try( |
||||
GZIPInputStream gis = new GZIPInputStream(fis); |
||||
BufferedReader br = new BufferedReader(new InputStreamReader(gis)); |
||||
){ |
||||
PrintWriter ass = new PrintWriter(new GZIPOutputStream(new FileOutputStream(new File(tempDir, "ass_0")))); |
||||
PrintWriter tip = new PrintWriter(new GZIPOutputStream(new FileOutputStream(new File(tempDir, "tip_0")))); |
||||
PrintWriter sch = new PrintWriter(new GZIPOutputStream(new FileOutputStream(new File(tempDir, "sch_0")))); |
||||
int count = 0; |
||||
while(true) { |
||||
String line = br.readLine(); |
||||
if(line==null) { |
||||
break; |
||||
} |
||||
count++; |
||||
JSONObject obj = new JSONObject(line); |
||||
String objectType = obj.keys().next(); |
||||
if("JsonTimetableV1".equals(objectType)) { |
||||
|
||||
}else if("JsonAssociationV1".equals(objectType)){ |
||||
ass.println(obj.getJSONObject("JsonAssociationV1")); |
||||
countA++; |
||||
if(countA%Constants.BATCH_SIZE==0) { |
||||
ass.close(); |
||||
if(batchA%50==0) |
||||
log.info("Created batch for assoication"); |
||||
ass = new PrintWriter(new GZIPOutputStream(new FileOutputStream(new File(tempDir, "ass_"+(++batchA))))); |
||||
} |
||||
}else if("TiplocV1".equals(objectType)){ |
||||
tip.println(obj.getJSONObject("TiplocV1")); |
||||
countT++; |
||||
if(countT%Constants.BATCH_SIZE==0) { |
||||
tip.close(); |
||||
if(batchT%50==0) |
||||
log.info("Created batch for TIPLOC"); |
||||
tip = new PrintWriter(new GZIPOutputStream(new FileOutputStream(new File(tempDir, "tip_"+(++batchT))))); |
||||
} |
||||
}else if("JsonScheduleV1".equals(objectType)){ |
||||
sch.println(obj.getJSONObject("JsonScheduleV1")); |
||||
countS++; |
||||
if(countS%Constants.BATCH_SIZE==0) { |
||||
sch.close(); |
||||
if(batchS%50==0) |
||||
log.info("Created batch for schedule"); |
||||
sch = new PrintWriter(new GZIPOutputStream(new FileOutputStream(new File(tempDir, "sch_"+(++batchS))))); |
||||
} |
||||
}else if("EOF".equals(objectType)){ |
||||
//Nothing to do
|
||||
}else { |
||||
log.fatal("Unhandled type {}", objectType); |
||||
System.exit(2); |
||||
} |
||||
|
||||
} |
||||
ass.close(); |
||||
tip.close(); |
||||
sch.close(); |
||||
|
||||
log.info("Created batch for assoication"); |
||||
log.info("Created batch for TIPLOC"); |
||||
log.info("Created batch for schedule"); |
||||
log.info("Total count : {}", count); |
||||
}catch(ZipException e) { |
||||
log.error(e.getMessage(), e); |
||||
}catch(IOException e) { |
||||
log.error(e.getMessage(), e); |
||||
System.exit(1); |
||||
} |
||||
try { |
||||
fis.close(); |
||||
}catch(IOException e) { |
||||
log.fatal(e.getMessage(), e); |
||||
System.exit(1); |
||||
} |
||||
log.info("Done reading. Dispatching now. {}/{}/{}[{}/{}/{}]", countA, countT, countS, batchA, batchT, batchS); |
||||
ExecutorService threadPool = java.util.concurrent.Executors.newFixedThreadPool(1); |
||||
for(int i=0;i<=batchA;i++) { |
||||
if(i%50==0) |
||||
log.info("Queued Assoication - {}", i); |
||||
threadPool.execute(new AssoicationProcessor(new File(tempDir, "ass_"+i))); |
||||
} |
||||
for(int i=0;i<=batchT;i++) { |
||||
if(i%50==0) |
||||
log.info("Queued Tiploc - {}", i); |
||||
threadPool.execute(new TiplocProcessor(new File(tempDir, "tip_"+i))); |
||||
} |
||||
for(int i=0;i<=batchS;i++) { |
||||
if(i%50==0) |
||||
log.info("Queued Schedule - {}", i); |
||||
threadPool.execute(new ScheduleProcessor(new File(tempDir, "sch_"+i))); |
||||
} |
||||
log.info("All entry queued."); |
||||
threadPool.shutdown(); |
||||
try { |
||||
threadPool.awaitTermination(3, TimeUnit.HOURS); |
||||
} catch (InterruptedException e) { |
||||
log.error(e.getMessage(), e); |
||||
} |
||||
if(!threadPool.isTerminated()) { |
||||
log.error("Some job cannot be finished!"); |
||||
System.exit(50); |
||||
} |
||||
try { |
||||
mDao.setDate(Constants.Metadata.LAST_NETOWRK_RAIL_SCHEDULE_UPD, new Date()); |
||||
} catch (SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
log.atInfo().log("LTS job done!"); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,17 @@
|
||||
package org.leolo.rail.model; |
||||
|
||||
public enum LocationRecordType { |
||||
ORIGIN("LO"), |
||||
INTERMEDIATE("LI"), |
||||
TERMINATE("LT"); |
||||
|
||||
private String recordCode; |
||||
|
||||
private LocationRecordType(String recordCode) { |
||||
this.recordCode = recordCode; |
||||
} |
||||
|
||||
public String getRecordCode() { |
||||
return recordCode; |
||||
} |
||||
} |
||||
@ -0,0 +1,20 @@
|
||||
package org.leolo.rail.model; |
||||
|
||||
public enum ScheduleType { |
||||
WTT("P"), |
||||
OVL("O"), |
||||
VAR("V"), |
||||
STP("S"), |
||||
CAN("C"); |
||||
|
||||
private String scheduleCode; |
||||
|
||||
private ScheduleType(String scheduleCode) { |
||||
this.scheduleCode = scheduleCode; |
||||
} |
||||
|
||||
public String getScheduleCode() { |
||||
return scheduleCode; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,328 @@
|
||||
package org.leolo.rail.model; |
||||
|
||||
import java.util.Date; |
||||
import java.util.Vector; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.leolo.rail.util.TUIDDateFormat; |
||||
|
||||
public class TrainSchedule { |
||||
|
||||
private static Logger log = LogManager.getLogger(TrainSchedule.class); |
||||
|
||||
private String trainUId; |
||||
private ScheduleType scheduleType = ScheduleType.WTT; |
||||
private Date startDate; |
||||
private Date endDate; |
||||
private String days; |
||||
private String bankHolidayInd; |
||||
private String signalId; |
||||
private String rsid; |
||||
private String trainStatus; |
||||
private String trainCategory; |
||||
private String section; |
||||
private String powerType; |
||||
private String timingLoad; |
||||
private String plannedSpeed; |
||||
private String operatingCharacter; |
||||
private String classAvailable; |
||||
private String sleeper; |
||||
private String reservation; |
||||
private String catering; |
||||
private String uicCode; |
||||
private String atocCode; |
||||
private Vector<TrainScheduleLocation> locations = new Vector<>(); |
||||
public String getTrainUId() { |
||||
return trainUId; |
||||
} |
||||
public void setTrainUId(String trainUId) { |
||||
this.trainUId = trainUId; |
||||
} |
||||
public ScheduleType getScheduleType() { |
||||
return scheduleType; |
||||
} |
||||
public void setScheduleType(ScheduleType scheduleType) { |
||||
this.scheduleType = scheduleType; |
||||
} |
||||
public Date getStartDate() { |
||||
return startDate; |
||||
} |
||||
public void setStartDate(Date startDate) { |
||||
this.startDate = startDate; |
||||
} |
||||
public Date getEndDate() { |
||||
return endDate; |
||||
} |
||||
public void setEndDate(Date endDate) { |
||||
this.endDate = endDate; |
||||
} |
||||
public String getDays() { |
||||
return days; |
||||
} |
||||
public void setDays(String days) { |
||||
this.days = days; |
||||
} |
||||
public String getBankHolidayInd() { |
||||
return bankHolidayInd; |
||||
} |
||||
public void setBankHolidayInd(String bankHolidayInd) { |
||||
this.bankHolidayInd = bankHolidayInd; |
||||
} |
||||
public String getSignalId() { |
||||
return signalId; |
||||
} |
||||
public void setSignalId(String signalId) { |
||||
this.signalId = signalId; |
||||
} |
||||
public String getRsid() { |
||||
return rsid; |
||||
} |
||||
public void setRsid(String rsid) { |
||||
this.rsid = rsid; |
||||
} |
||||
public String getTrainStatus() { |
||||
return trainStatus; |
||||
} |
||||
public void setTrainStatus(String trainStatus) { |
||||
this.trainStatus = trainStatus; |
||||
} |
||||
public String getTrainCategory() { |
||||
return trainCategory; |
||||
} |
||||
public void setTrainCategory(String trainCategory) { |
||||
this.trainCategory = trainCategory; |
||||
} |
||||
public String getSection() { |
||||
return section; |
||||
} |
||||
public void setSection(String section) { |
||||
this.section = section; |
||||
} |
||||
public String getPowerType() { |
||||
return powerType; |
||||
} |
||||
public void setPowerType(String powerType) { |
||||
this.powerType = powerType; |
||||
} |
||||
public String getTimingLoad() { |
||||
return timingLoad; |
||||
} |
||||
public void setTimingLoad(String timingLoad) { |
||||
this.timingLoad = timingLoad; |
||||
} |
||||
public String getPlannedSpeed() { |
||||
return plannedSpeed; |
||||
} |
||||
public void setPlannedSpeed(String plannedSpeed) { |
||||
this.plannedSpeed = plannedSpeed; |
||||
} |
||||
public String getOperatingCharacter() { |
||||
return operatingCharacter; |
||||
} |
||||
public void setOperatingCharacter(String operatingCharacter) { |
||||
this.operatingCharacter = operatingCharacter; |
||||
} |
||||
public String getClassAvailable() { |
||||
return classAvailable; |
||||
} |
||||
public void setClassAvailable(String classAvailable) { |
||||
if(" ".equals(classAvailable)) |
||||
this.classAvailable = "B"; |
||||
else |
||||
this.classAvailable = classAvailable; |
||||
} |
||||
public String getSleeper() { |
||||
return sleeper; |
||||
} |
||||
public void setSleeper(String sleeper) { |
||||
this.sleeper = sleeper; |
||||
} |
||||
public String getReservation() { |
||||
return reservation; |
||||
} |
||||
public void setReservation(String reservation) { |
||||
this.reservation = reservation; |
||||
} |
||||
public String getCatering() { |
||||
return catering; |
||||
} |
||||
public void setCatering(String catering) { |
||||
StringBuilder sb = new StringBuilder(); |
||||
char chars[] = catering.toCharArray(); |
||||
for(int i=0;i<chars.length;i++) { |
||||
if(i!=0) sb.append(","); |
||||
sb.append(chars[i]); |
||||
} |
||||
this.catering = sb.toString(); |
||||
} |
||||
public String getUicCode() { |
||||
return uicCode; |
||||
} |
||||
public void setUicCode(String uicCode) { |
||||
this.uicCode = uicCode; |
||||
} |
||||
public String getAtocCode() { |
||||
return atocCode; |
||||
} |
||||
public void setAtocCode(String atocCode) { |
||||
this.atocCode = atocCode; |
||||
} |
||||
public Vector<TrainScheduleLocation> getLocations() { |
||||
return locations; |
||||
} |
||||
public String getSUID() { |
||||
TUIDDateFormat tdf = new TUIDDateFormat(); |
||||
return trainUId + tdf.format(startDate) + tdf.format(endDate) + scheduleType.getScheduleCode(); |
||||
} |
||||
@Override |
||||
public int hashCode() { |
||||
// log.info("startdate:{}", startDate.getTime());
|
||||
final int prime = 31; |
||||
int result = 1; |
||||
result = prime * result + ((atocCode == null) ? 0 : atocCode.hashCode()); |
||||
result = prime * result + ((bankHolidayInd == null) ? 0 : bankHolidayInd.hashCode()); |
||||
result = prime * result + ((catering == null) ? 0 : catering.hashCode()); |
||||
result = prime * result + ((classAvailable == null) ? 0 : classAvailable.hashCode()); |
||||
result = prime * result + ((days == null) ? 0 : days.hashCode()); |
||||
result = prime * result + ((endDate == null) ? 0 : endDate.hashCode()); |
||||
result = prime * result + ((operatingCharacter == null) ? 0 : operatingCharacter.hashCode()); |
||||
result = prime * result + ((plannedSpeed == null) ? 0 : plannedSpeed.hashCode()); |
||||
result = prime * result + ((powerType == null) ? 0 : powerType.hashCode()); |
||||
result = prime * result + ((reservation == null) ? 0 : reservation.hashCode()); |
||||
result = prime * result + ((rsid == null) ? 0 : rsid.hashCode()); |
||||
result = prime * result + ((scheduleType == null) ? 0 : scheduleType.name().hashCode()); |
||||
result = prime * result + ((section == null) ? 0 : section.hashCode()); |
||||
result = prime * result + ((signalId == null) ? 0 : signalId.hashCode()); |
||||
result = prime * result + ((sleeper == null) ? 0 : sleeper.hashCode()); |
||||
result = prime * result + ((startDate == null) ? 0 : startDate.hashCode()); |
||||
result = prime * result + ((timingLoad == null) ? 0 : timingLoad.hashCode()); |
||||
result = prime * result + ((trainCategory == null) ? 0 : trainCategory.hashCode()); |
||||
result = prime * result + ((trainStatus == null) ? 0 : trainStatus.hashCode()); |
||||
result = prime * result + ((trainUId == null) ? 0 : trainUId.hashCode()); |
||||
result = prime * result + ((uicCode == null) ? 0 : uicCode.hashCode()); |
||||
for(TrainScheduleLocation tsl:locations) { |
||||
// log.atDebug().log("TIPLOC: {}, hash: {}//{}", tsl.getTiplocCode(), Integer.toHexString(tsl.hashCode()), Integer.toHexString(tsl.getTiplocCode().hashCode()));
|
||||
result = prime * result + tsl.hashCode(); |
||||
} |
||||
return result; |
||||
} |
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (this == obj) |
||||
return true; |
||||
if (obj == null) |
||||
return false; |
||||
if (getClass() != obj.getClass()) |
||||
return false; |
||||
TrainSchedule other = (TrainSchedule) obj; |
||||
if (atocCode == null) { |
||||
if (other.atocCode != null) |
||||
return false; |
||||
} else if (!atocCode.equals(other.atocCode)) |
||||
return false; |
||||
if (bankHolidayInd == null) { |
||||
if (other.bankHolidayInd != null) |
||||
return false; |
||||
} else if (!bankHolidayInd.equals(other.bankHolidayInd)) |
||||
return false; |
||||
if (catering == null) { |
||||
if (other.catering != null) |
||||
return false; |
||||
} else if (!catering.equals(other.catering)) |
||||
return false; |
||||
if (classAvailable == null) { |
||||
if (other.classAvailable != null) |
||||
return false; |
||||
} else if (!classAvailable.equals(other.classAvailable)) |
||||
return false; |
||||
if (days == null) { |
||||
if (other.days != null) |
||||
return false; |
||||
} else if (!days.equals(other.days)) |
||||
return false; |
||||
if (endDate == null) { |
||||
if (other.endDate != null) |
||||
return false; |
||||
} else if (!endDate.equals(other.endDate)) |
||||
return false; |
||||
if (locations == null) { |
||||
if (other.locations != null) |
||||
return false; |
||||
} else if (!locations.equals(other.locations)) |
||||
return false; |
||||
if (operatingCharacter == null) { |
||||
if (other.operatingCharacter != null) |
||||
return false; |
||||
} else if (!operatingCharacter.equals(other.operatingCharacter)) |
||||
return false; |
||||
if (plannedSpeed == null) { |
||||
if (other.plannedSpeed != null) |
||||
return false; |
||||
} else if (!plannedSpeed.equals(other.plannedSpeed)) |
||||
return false; |
||||
if (powerType == null) { |
||||
if (other.powerType != null) |
||||
return false; |
||||
} else if (!powerType.equals(other.powerType)) |
||||
return false; |
||||
if (reservation == null) { |
||||
if (other.reservation != null) |
||||
return false; |
||||
} else if (!reservation.equals(other.reservation)) |
||||
return false; |
||||
if (rsid == null) { |
||||
if (other.rsid != null) |
||||
return false; |
||||
} else if (!rsid.equals(other.rsid)) |
||||
return false; |
||||
if (scheduleType != other.scheduleType) |
||||
return false; |
||||
if (section == null) { |
||||
if (other.section != null) |
||||
return false; |
||||
} else if (!section.equals(other.section)) |
||||
return false; |
||||
if (signalId == null) { |
||||
if (other.signalId != null) |
||||
return false; |
||||
} else if (!signalId.equals(other.signalId)) |
||||
return false; |
||||
if (sleeper == null) { |
||||
if (other.sleeper != null) |
||||
return false; |
||||
} else if (!sleeper.equals(other.sleeper)) |
||||
return false; |
||||
if (startDate == null) { |
||||
if (other.startDate != null) |
||||
return false; |
||||
} else if (!startDate.equals(other.startDate)) |
||||
return false; |
||||
if (timingLoad == null) { |
||||
if (other.timingLoad != null) |
||||
return false; |
||||
} else if (!timingLoad.equals(other.timingLoad)) |
||||
return false; |
||||
if (trainCategory == null) { |
||||
if (other.trainCategory != null) |
||||
return false; |
||||
} else if (!trainCategory.equals(other.trainCategory)) |
||||
return false; |
||||
if (trainStatus == null) { |
||||
if (other.trainStatus != null) |
||||
return false; |
||||
} else if (!trainStatus.equals(other.trainStatus)) |
||||
return false; |
||||
if (trainUId == null) { |
||||
if (other.trainUId != null) |
||||
return false; |
||||
} else if (!trainUId.equals(other.trainUId)) |
||||
return false; |
||||
if (uicCode == null) { |
||||
if (other.uicCode != null) |
||||
return false; |
||||
} else if (!uicCode.equals(other.uicCode)) |
||||
return false; |
||||
return true; |
||||
} |
||||
} |
||||
@ -0,0 +1,175 @@
|
||||
package org.leolo.rail.model; |
||||
|
||||
public class TrainScheduleLocation { |
||||
|
||||
private String tiplocCode; |
||||
private int tiplocInstance = 1; |
||||
private long arrival; |
||||
private long departure; |
||||
private long pass; |
||||
private long pubArrival; |
||||
private long pubDeparture; |
||||
private String platform; |
||||
private String line; |
||||
private String path; |
||||
private long engineeringAllowance; |
||||
private long pathingAllowance; |
||||
private long performanceAllowance; |
||||
private LocationRecordType recordType; |
||||
public String getTiplocCode() { |
||||
return tiplocCode; |
||||
} |
||||
public void setTiplocCode(String tiplocCode) { |
||||
this.tiplocCode = tiplocCode; |
||||
} |
||||
public int getTiplocInstance() { |
||||
return tiplocInstance; |
||||
} |
||||
public void setTiplocInstance(int tiplocInstance) { |
||||
this.tiplocInstance = tiplocInstance; |
||||
} |
||||
public long getArrival() { |
||||
return arrival; |
||||
} |
||||
public void setArrival(long arrival) { |
||||
this.arrival = arrival; |
||||
} |
||||
public long getDeparture() { |
||||
return departure; |
||||
} |
||||
public void setDeparture(long departure) { |
||||
this.departure = departure; |
||||
} |
||||
public long getPass() { |
||||
return pass; |
||||
} |
||||
public void setPass(long pass) { |
||||
this.pass = pass; |
||||
} |
||||
public long getPubArrival() { |
||||
return pubArrival; |
||||
} |
||||
public void setPubArrival(long pubArrival) { |
||||
this.pubArrival = pubArrival; |
||||
} |
||||
public long getPubDeparture() { |
||||
return pubDeparture; |
||||
} |
||||
public void setPubDeparture(long pubDeparture) { |
||||
this.pubDeparture = pubDeparture; |
||||
} |
||||
public String getPlatform() { |
||||
return platform; |
||||
} |
||||
public void setPlatform(String platform) { |
||||
this.platform = platform; |
||||
} |
||||
public String getLine() { |
||||
return line; |
||||
} |
||||
public void setLine(String line) { |
||||
this.line = line; |
||||
} |
||||
public String getPath() { |
||||
return path; |
||||
} |
||||
public void setPath(String path) { |
||||
this.path = path; |
||||
} |
||||
public long getEngineeringAllowance() { |
||||
return engineeringAllowance; |
||||
} |
||||
public void setEngineeringAllowance(long engineeringAllowance) { |
||||
this.engineeringAllowance = engineeringAllowance; |
||||
} |
||||
public long getPathingAllowance() { |
||||
return pathingAllowance; |
||||
} |
||||
public void setPathingAllowance(long pathingAllowance) { |
||||
this.pathingAllowance = pathingAllowance; |
||||
} |
||||
public long getPerformanceAllowance() { |
||||
return performanceAllowance; |
||||
} |
||||
public void setPerformanceAllowance(long performanceAllowance) { |
||||
this.performanceAllowance = performanceAllowance; |
||||
} |
||||
public LocationRecordType getRecordType() { |
||||
return recordType; |
||||
} |
||||
public void setRecordType(LocationRecordType recordType) { |
||||
this.recordType = recordType; |
||||
} |
||||
@Override |
||||
public int hashCode() { |
||||
final int prime = 31; |
||||
int result = 1; |
||||
result = prime * result + (int) (arrival ^ (arrival >>> 32)); |
||||
result = prime * result + (int) (departure ^ (departure >>> 32)); |
||||
result = prime * result + (int) (engineeringAllowance ^ (engineeringAllowance >>> 32)); |
||||
result = prime * result + ((line == null) ? 0 : line.hashCode()); |
||||
result = prime * result + (int) (pass ^ (pass >>> 32)); |
||||
result = prime * result + ((path == null) ? 0 : path.hashCode()); |
||||
result = prime * result + (int) (pathingAllowance ^ (pathingAllowance >>> 32)); |
||||
result = prime * result + (int) (performanceAllowance ^ (performanceAllowance >>> 32)); |
||||
result = prime * result + ((platform == null) ? 0 : platform.hashCode()); |
||||
result = prime * result + (int) (pubArrival ^ (pubArrival >>> 32)); |
||||
result = prime * result + (int) (pubDeparture ^ (pubDeparture >>> 32)); |
||||
result = prime * result + ((recordType == null) ? 0 : recordType.getRecordCode().hashCode()); |
||||
result = prime * result + ((tiplocCode == null) ? 0 : tiplocCode.hashCode()); |
||||
result = prime * result + tiplocInstance; |
||||
return result; |
||||
} |
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (this == obj) |
||||
return true; |
||||
if (obj == null) |
||||
return false; |
||||
if (getClass() != obj.getClass()) |
||||
return false; |
||||
TrainScheduleLocation other = (TrainScheduleLocation) obj; |
||||
if (arrival != other.arrival) |
||||
return false; |
||||
if (departure != other.departure) |
||||
return false; |
||||
if (engineeringAllowance != other.engineeringAllowance) |
||||
return false; |
||||
if (line == null) { |
||||
if (other.line != null) |
||||
return false; |
||||
} else if (!line.equals(other.line)) |
||||
return false; |
||||
if (pass != other.pass) |
||||
return false; |
||||
if (path == null) { |
||||
if (other.path != null) |
||||
return false; |
||||
} else if (!path.equals(other.path)) |
||||
return false; |
||||
if (pathingAllowance != other.pathingAllowance) |
||||
return false; |
||||
if (performanceAllowance != other.performanceAllowance) |
||||
return false; |
||||
if (platform == null) { |
||||
if (other.platform != null) |
||||
return false; |
||||
} else if (!platform.equals(other.platform)) |
||||
return false; |
||||
if (pubArrival != other.pubArrival) |
||||
return false; |
||||
if (pubDeparture != other.pubDeparture) |
||||
return false; |
||||
if (recordType != other.recordType) |
||||
return false; |
||||
if (tiplocCode == null) { |
||||
if (other.tiplocCode != null) |
||||
return false; |
||||
} else if (!tiplocCode.equals(other.tiplocCode)) |
||||
return false; |
||||
if (tiplocInstance != other.tiplocInstance) |
||||
return false; |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,8 @@
|
||||
/** |
||||
* |
||||
*/ |
||||
/** |
||||
* @author user |
||||
* |
||||
*/ |
||||
package org.leolo.rail.model; |
||||
@ -0,0 +1,234 @@
|
||||
package org.leolo.rail.report; |
||||
|
||||
import java.util.HashSet; |
||||
|
||||
import org.leolo.rail.model.ScheduleType; |
||||
|
||||
public class BasicTrainScheduleEntry { |
||||
private String suid; |
||||
private String trainUid; |
||||
private ScheduleType scheduleType; |
||||
private String signalId; |
||||
private String toc; |
||||
private String trainClass; |
||||
private String origin; |
||||
private long originTime; |
||||
private String destination; |
||||
private long destinationTime; |
||||
private long departTime; |
||||
private String departPlatform; |
||||
private long arriveTime; |
||||
private String arrivePlatform; |
||||
|
||||
private HashSet<BasicTrainScheduleEntry> assoicatedEntry = new HashSet<>(); |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
final int prime = 31; |
||||
int result = 1; |
||||
result = prime * result + ((arrivePlatform == null) ? 0 : arrivePlatform.hashCode()); |
||||
result = prime * result + (int) (arriveTime ^ (arriveTime >>> 32)); |
||||
result = prime * result + ((assoicatedEntry == null) ? 0 : assoicatedEntry.hashCode()); |
||||
result = prime * result + ((departPlatform == null) ? 0 : departPlatform.hashCode()); |
||||
result = prime * result + (int) (departTime ^ (departTime >>> 32)); |
||||
result = prime * result + ((destination == null) ? 0 : destination.hashCode()); |
||||
result = prime * result + (int) (destinationTime ^ (destinationTime >>> 32)); |
||||
result = prime * result + ((origin == null) ? 0 : origin.hashCode()); |
||||
result = prime * result + (int) (originTime ^ (originTime >>> 32)); |
||||
result = prime * result + ((scheduleType == null) ? 0 : scheduleType.name().hashCode()); |
||||
result = prime * result + ((signalId == null) ? 0 : signalId.hashCode()); |
||||
result = prime * result + ((suid == null) ? 0 : suid.hashCode()); |
||||
result = prime * result + ((toc == null) ? 0 : toc.hashCode()); |
||||
result = prime * result + ((trainClass == null) ? 0 : trainClass.hashCode()); |
||||
result = prime * result + ((trainUid == null) ? 0 : trainUid.hashCode()); |
||||
return result; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
if (this == obj) |
||||
return true; |
||||
if (obj == null) |
||||
return false; |
||||
if (getClass() != obj.getClass()) |
||||
return false; |
||||
BasicTrainScheduleEntry other = (BasicTrainScheduleEntry) obj; |
||||
if (arrivePlatform == null) { |
||||
if (other.arrivePlatform != null) |
||||
return false; |
||||
} else if (!arrivePlatform.equals(other.arrivePlatform)) |
||||
return false; |
||||
if (arriveTime != other.arriveTime) |
||||
return false; |
||||
if (assoicatedEntry == null) { |
||||
if (other.assoicatedEntry != null) |
||||
return false; |
||||
} else if (!assoicatedEntry.equals(other.assoicatedEntry)) |
||||
return false; |
||||
if (departPlatform == null) { |
||||
if (other.departPlatform != null) |
||||
return false; |
||||
} else if (!departPlatform.equals(other.departPlatform)) |
||||
return false; |
||||
if (departTime != other.departTime) |
||||
return false; |
||||
if (destination == null) { |
||||
if (other.destination != null) |
||||
return false; |
||||
} else if (!destination.equals(other.destination)) |
||||
return false; |
||||
if (destinationTime != other.destinationTime) |
||||
return false; |
||||
if (origin == null) { |
||||
if (other.origin != null) |
||||
return false; |
||||
} else if (!origin.equals(other.origin)) |
||||
return false; |
||||
if (originTime != other.originTime) |
||||
return false; |
||||
if (scheduleType != other.scheduleType) |
||||
return false; |
||||
if (signalId == null) { |
||||
if (other.signalId != null) |
||||
return false; |
||||
} else if (!signalId.equals(other.signalId)) |
||||
return false; |
||||
if (suid == null) { |
||||
if (other.suid != null) |
||||
return false; |
||||
} else if (!suid.equals(other.suid)) |
||||
return false; |
||||
if (toc == null) { |
||||
if (other.toc != null) |
||||
return false; |
||||
} else if (!toc.equals(other.toc)) |
||||
return false; |
||||
if (trainClass == null) { |
||||
if (other.trainClass != null) |
||||
return false; |
||||
} else if (!trainClass.equals(other.trainClass)) |
||||
return false; |
||||
if (trainUid == null) { |
||||
if (other.trainUid != null) |
||||
return false; |
||||
} else if (!trainUid.equals(other.trainUid)) |
||||
return false; |
||||
return true; |
||||
} |
||||
|
||||
public String getSuid() { |
||||
return suid; |
||||
} |
||||
|
||||
public ScheduleType getScheduleType() { |
||||
return scheduleType; |
||||
} |
||||
|
||||
public String getSignalId() { |
||||
return signalId; |
||||
} |
||||
|
||||
public String getToc() { |
||||
return toc; |
||||
} |
||||
|
||||
public String getTrainClass() { |
||||
return trainClass; |
||||
} |
||||
|
||||
public String getOrigin() { |
||||
return origin; |
||||
} |
||||
|
||||
public long getOriginTime() { |
||||
return originTime; |
||||
} |
||||
|
||||
public String getDestination() { |
||||
return destination; |
||||
} |
||||
|
||||
public long getDestinationTime() { |
||||
return destinationTime; |
||||
} |
||||
|
||||
public HashSet<BasicTrainScheduleEntry> getAssoicatedEntry() { |
||||
return assoicatedEntry; |
||||
} |
||||
|
||||
public void setSuid(String suid) { |
||||
this.suid = suid; |
||||
} |
||||
|
||||
public void setScheduleType(ScheduleType scheduleType) { |
||||
this.scheduleType = scheduleType; |
||||
} |
||||
|
||||
public void setSignalId(String signalId) { |
||||
this.signalId = signalId; |
||||
} |
||||
|
||||
public void setToc(String toc) { |
||||
this.toc = toc; |
||||
} |
||||
|
||||
public void setTrainClass(String trainClass) { |
||||
this.trainClass = trainClass; |
||||
} |
||||
|
||||
public void setOrigin(String origin) { |
||||
this.origin = origin; |
||||
} |
||||
|
||||
public void setOriginTime(long originTime) { |
||||
this.originTime = originTime; |
||||
} |
||||
|
||||
public void setDestination(String destination) { |
||||
this.destination = destination; |
||||
} |
||||
|
||||
public void setDestinationTime(long destinationTime) { |
||||
this.destinationTime = destinationTime; |
||||
} |
||||
|
||||
public String getTrainUid() { |
||||
return trainUid; |
||||
} |
||||
|
||||
public void setTrainUid(String trainUid) { |
||||
this.trainUid = trainUid; |
||||
} |
||||
|
||||
public long getDepartTime() { |
||||
return departTime; |
||||
} |
||||
|
||||
public String getDepartPlatform() { |
||||
return departPlatform; |
||||
} |
||||
|
||||
public long getArriveTime() { |
||||
return arriveTime; |
||||
} |
||||
|
||||
public String getArrivePlatform() { |
||||
return arrivePlatform; |
||||
} |
||||
|
||||
public void setDepartTime(long departTime) { |
||||
this.departTime = departTime; |
||||
} |
||||
|
||||
public void setDepartPlatform(String departPlatform) { |
||||
this.departPlatform = departPlatform; |
||||
} |
||||
|
||||
public void setArriveTime(long arriveTime) { |
||||
this.arriveTime = arriveTime; |
||||
} |
||||
|
||||
public void setArrivePlatform(String arrivePlatform) { |
||||
this.arrivePlatform = arrivePlatform; |
||||
} |
||||
} |
||||
@ -0,0 +1,740 @@
|
||||
package org.leolo.rail.report; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.io.PrintWriter; |
||||
import java.sql.Connection; |
||||
import java.sql.Date; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.text.ParseException; |
||||
import java.util.Comparator; |
||||
import java.util.HashMap; |
||||
import java.util.HashSet; |
||||
import java.util.TreeMap; |
||||
import java.util.TreeSet; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.leolo.rail.DatabaseManager; |
||||
import org.leolo.rail.model.ScheduleType; |
||||
|
||||
public class ReportGenerator { |
||||
public static Logger log = LogManager.getLogger(ReportGenerator.class); |
||||
|
||||
public static final String SQL_1 = "SELECT \r\n" + |
||||
" lts.suid suid, lts.train_uid uid, lts.sch_type sch_type, lts.signal_id signal_id, lts.atoc_code toc,\r\n" + |
||||
" lts.train_category train_category, \r\n" + |
||||
" tiploc_to_crs(lts.origin) origin, TIME_TO_SEC(lts.origin_time) origin_time,\r\n" + |
||||
" tiploc_to_crs(lts.destination) destination, TIME_TO_SEC(lts.destination_time) destination_time,\r\n" + |
||||
" TIME_TO_SEC(al1.pub_departure) pub_departure, al1.platform dPlat,\r\n"+ |
||||
" TIME_TO_SEC(al3.pub_arrival) pub_arrival, al3.platform aPlat\r\n"+ |
||||
" FROM\r\n" + |
||||
" ltp_location al1\r\n" + |
||||
" LEFT JOIN ltp_location al3 ON al1.suid = al3.suid AND al1.seq < al3.seq\r\n" + |
||||
" LEFT JOIN ltp_schedule lts ON al1.suid = lts.suid\r\n" + |
||||
" LEFT JOIN tiploc tipo ON lts.origin = tipo.tiploc_code\r\n" + |
||||
" LEFT JOIN tiploc tipd ON lts.destination = tipd.tiploc_code \r\n" + |
||||
" WHERE\r\n" + |
||||
" 1=1\r\n" + |
||||
" AND al1.tiploc_code IN (SELECT tiploc_code FROM tiploc WHERE stanox IN (SELECT stanox FROM tiploc WHERE crs = ?))\r\n" + |
||||
" AND al3.tiploc_code IN (SELECT tiploc_code FROM tiploc WHERE stanox IN (SELECT stanox FROM tiploc WHERE crs = ?))\r\n" + |
||||
" AND ? BETWEEN lts.start_date AND lts.end_date\r\n" + |
||||
" AND lts.days LIKE get_wd_str(?)\r\n" + |
||||
" AND al1.pub_departure IS NOT null\r\n" + |
||||
" AND al3.pub_arrival IS NOT NULL"; |
||||
|
||||
|
||||
|
||||
public static final String LATEX_PREMBLE_1 = "\\documentclass[a4paper]{article}\r\n" + |
||||
"\\usepackage{tocloft}\r\n" + |
||||
"\\usepackage[utf8]{inputenc}\r\n" + |
||||
"\\usepackage[margin=0.675in]{geometry}\r\n" + |
||||
"\\usepackage[colorlinks = true]{hyperref}\r\n" + |
||||
"\\usepackage{color}\r\n" + |
||||
"\\usepackage{colortbl}\r\n" + |
||||
"\\usepackage[british]{babel}\r\n" + |
||||
"\\usepackage{longtable}\r\n" + |
||||
"\\usepackage{textcomp}\r\n" + |
||||
"\\usepackage{fancyhdr}\r\n" + |
||||
"\\usepackage{ulem}\r\n" + |
||||
"\\usepackage{array}\r\n" + |
||||
"\r\n" + |
||||
"\\pagestyle{fancy}\r\n" + |
||||
"\r\n" + |
||||
"\\newcommand{\\hr}{\\noindent\\hrulefill}\r\n" + |
||||
"\\newcommand{\\dfa}{\\cftdotfill{2}}\r\n" + |
||||
"\\newcommand{\\dfb}{\\cftdotfill{4}}\r\n" + |
||||
"\\newcommand{\\pa}{\\textit{(PASS)}}\r\n" + |
||||
"\\renewcommand\\cftsecleader{\\cftdotfill{\\cftdotsep}}\r\n" + |
||||
"\r\n" + |
||||
"\\setcounter{secnumdepth}{1}\r\n" + |
||||
"\\setcounter{tocdepth}{1}\r\n" + |
||||
"\r\n" + |
||||
"\\definecolor{hl1}{gray}{0.9}\r\n" + |
||||
"\\definecolor{hl2}{gray}{0.8}\r\n" + |
||||
"\r\n" + |
||||
"\\definecolor{e1}{rgb}{0,0,1}\r\n" + |
||||
"\\definecolor{ot}{rgb}{0,0,0}\r\n" + |
||||
"\\definecolor{l1}{rgb}{1.0,0.33,0.33}\r\n" + |
||||
"\\definecolor{l2}{rgb}{1.0,0,0}\r\n" + |
||||
"\\definecolor{l3}{rgb}{0.67,0,0}"; |
||||
|
||||
public static void main(String [] args) throws ParseException, IOException { |
||||
final String ORIGIN = "RDG"; |
||||
final String DESTINATION = "PAD"; |
||||
final java.util.Date RPT_DATE = new java.text.SimpleDateFormat("yyyy-MM-dd").parse("2022-03-16"); |
||||
generateLaTeX(ORIGIN, DESTINATION, RPT_DATE); |
||||
} |
||||
|
||||
public static File generateLaTeX(String origin, String destination, java.util.Date rptDate) throws IOException{ |
||||
log.atInfo().log("{} -> {} on {}", origin, destination, rptDate); |
||||
TreeSet<String> tocList = new TreeSet<>(); |
||||
TreeSet<String> tcList = new TreeSet<>(); |
||||
TreeSet<String> locList = new TreeSet<>(); |
||||
HashMap<String, String> tocCache = new HashMap<>(); |
||||
HashMap<String, String> tcCache = new HashMap<>(); |
||||
HashMap<String, String> locCache = new HashMap<>(); |
||||
TreeSet<BasicTrainScheduleEntry> trains = new TreeSet<>(new Comparator<BasicTrainScheduleEntry>() { |
||||
|
||||
@Override |
||||
public int compare(BasicTrainScheduleEntry arg0, BasicTrainScheduleEntry arg1) { |
||||
int val = Long.compare(arg0.getDepartTime(), arg1.getDepartTime()); |
||||
if(val!=0) return val; |
||||
val = Long.compare(arg0.getArriveTime(), arg1.getArriveTime()); |
||||
if(val!=0) return val; |
||||
return Integer.compare(arg0.getScheduleType().ordinal(), arg1.getScheduleType().ordinal()); |
||||
|
||||
} |
||||
|
||||
}); |
||||
TreeSet<TrainScheduleEntry> trainGroup = new TreeSet<>(new Comparator<TrainScheduleEntry>() { |
||||
|
||||
@Override |
||||
public int compare(TrainScheduleEntry arg0, TrainScheduleEntry arg1) { |
||||
int val = Long.compare(arg0.getDepartTime(), arg1.getDepartTime()); |
||||
if(val!=0) return val; |
||||
val = Long.compare(arg0.getArriveTime(), arg1.getArriveTime()); |
||||
if(val!=0) return val; |
||||
return Integer.compare(arg0.getScheduleType().ordinal(), arg1.getScheduleType().ordinal()); |
||||
|
||||
} |
||||
|
||||
}); |
||||
HashMap<String, TrainScheduleEntry> trainGroups = new HashMap<>(); |
||||
java.sql.Date sqlDate = new java.sql.Date(rptDate.getTime()); |
||||
locList.add(origin); |
||||
locList.add(destination); |
||||
//Stage 1: get the basic train information for trains
|
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement(SQL_1) |
||||
){ |
||||
pstmt.setString(1, origin); |
||||
pstmt.setString(2, destination); |
||||
pstmt.setDate(3, sqlDate); |
||||
pstmt.setDate(4, sqlDate); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
int rowCount = 0; |
||||
while(rs.next()) { |
||||
rowCount++; |
||||
BasicTrainScheduleEntry btse = new BasicTrainScheduleEntry(); |
||||
btse.setSuid(rs.getString(1)); |
||||
btse.setTrainUid(rs.getString(2)); |
||||
btse.setScheduleType(ScheduleType.valueOf(rs.getString(3))); |
||||
btse.setSignalId(rs.getString(4)); |
||||
btse.setToc(rs.getString(5)); |
||||
btse.setTrainClass(rs.getString(6)); |
||||
btse.setOrigin(rs.getString(7)); |
||||
btse.setOriginTime(rs.getLong(8)); |
||||
btse.setDestination(rs.getString(9)); |
||||
btse.setDestinationTime(rs.getLong(10)); |
||||
btse.setDepartTime(rs.getLong(11)); |
||||
btse.setDepartPlatform(rs.getString(12)); |
||||
btse.setArriveTime(rs.getLong(13)); |
||||
btse.setArrivePlatform(rs.getString(14)); |
||||
trains.add(btse); |
||||
tocList.add(btse.getToc()); |
||||
tcList.add(btse.getTrainClass()); |
||||
locList.add(btse.getOrigin()); |
||||
locList.add(btse.getDestination()); |
||||
if(!trainGroups.containsKey(btse.getTrainUid())) { |
||||
trainGroups.put(btse.getTrainUid(), new TrainScheduleEntry()); |
||||
} |
||||
trainGroups.get(btse.getTrainUid()).addEntry(btse); |
||||
} |
||||
log.atInfo().log("{} train schedule found.", rowCount); |
||||
log.atInfo().log("{} train group formed.", trainGroups.size()); |
||||
} |
||||
}catch(SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
for(TrainScheduleEntry tse:trainGroups.values()) { |
||||
trainGroup.add(tse); |
||||
} |
||||
//Scan for earlier train arrives later
|
||||
for(TrainScheduleEntry tse:trainGroup) { |
||||
for(TrainScheduleEntry otse:trainGroup) { |
||||
if(tse.getTrainUid().equals(otse.getTrainUid())) { |
||||
continue;//No need to check with self
|
||||
} |
||||
if(tse.getDepartTime() <= otse.getDepartTime() && tse.getArriveTime() >= otse.getArriveTime() && otse.getArriveTime() > otse.getDepartTime()) { |
||||
tse.setNote("A"); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement stmt = conn.prepareStatement("SELECT tps_desc FROM tiploc WHERE crs = ?"); |
||||
){ |
||||
for(String crs:locList) { |
||||
stmt.setString(1, crs); |
||||
try(ResultSet rs = stmt.executeQuery()){ |
||||
if(rs.next()) { |
||||
locCache.put(crs, rs.getString(1)); |
||||
} |
||||
} |
||||
|
||||
} |
||||
}catch(SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
|
||||
//Generate output
|
||||
try(PrintWriter pw = new PrintWriter(new File("Z:\\output.tex"))){ |
||||
pw.print(LATEX_PREMBLE_1); |
||||
pw.println("\\begin{document}"); |
||||
pw.println("\\begin{center}\\begin{LARGE}"); |
||||
pw.println("Train running record from \\\\"+locCache.get(origin)+"\\\\to\\\\"+locCache.get(destination)+"\\\\on\\\\"+new java.text.SimpleDateFormat("dd-MM-yyyy").format(rptDate)); |
||||
pw.println("\\end{LARGE}\\end{center}"); |
||||
pw.println(); |
||||
pw.println("\\hr\r\n" + |
||||
" \r\n" + |
||||
" The information in this report is generated from data feed provided by Network Rail Infrastructure Limited.\r\n" + |
||||
" \r\n" + |
||||
" \\hr\r\n" + |
||||
" \\tableofcontents"); |
||||
//Part 1: Definations
|
||||
pw.println("\\section{Definations}"); |
||||
pw.println("\\subsection{TOC}"); |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement stmt = conn.prepareStatement("SELECT name FROM toc WHERE atoc_code = ? LIMIT 1"); |
||||
){ |
||||
int count = 0; |
||||
for(String toc:tocList) { |
||||
stmt.setString(1, toc); |
||||
try(ResultSet rs = stmt.executeQuery()){ |
||||
if(rs.next()) { |
||||
pw.print(rs.getString(1)); |
||||
if(++count%2==0) |
||||
pw.print("\\dfa "); |
||||
else |
||||
pw.print("\\dfb "); |
||||
pw.print(toc); |
||||
pw.println("\\\\"); |
||||
tocCache.put(toc, rs.getString(1)); |
||||
} |
||||
} |
||||
|
||||
} |
||||
}catch(SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
pw.println("\\subsection{Train Class}"); |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement stmt = conn.prepareStatement("SELECT category_name FROM train_category WHERE category = ? LIMIT 1"); |
||||
){ |
||||
int count = 0; |
||||
for(String tc:tcList) { |
||||
stmt.setString(1, tc); |
||||
try(ResultSet rs = stmt.executeQuery()){ |
||||
if(rs.next()) { |
||||
pw.print(rs.getString(1)); |
||||
if(++count%2==0) |
||||
pw.print("\\dfa "); |
||||
else |
||||
pw.print("\\dfb "); |
||||
pw.print(tc); |
||||
pw.println("\\\\"); |
||||
tcCache.put(tc, rs.getString(1)); |
||||
} |
||||
} |
||||
|
||||
} |
||||
}catch(SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
pw.println("\\subsection{Location}"); |
||||
int locCount = 0; |
||||
for(String loc:locList) { |
||||
pw.print(locCache.get(loc).replace("&", "\\&")); |
||||
if(++locCount%2==0) |
||||
pw.print("\\dfa "); |
||||
else |
||||
pw.print("\\dfb "); |
||||
pw.print(loc); |
||||
pw.print("\\\\"); |
||||
} |
||||
//Part 2: Print the train List
|
||||
pw.println("\\section{Train Schedule}"); |
||||
pw.println("\\begin{longtable}[l]{|c|c|c||cc|cc|cc|cc||c|c|}"); |
||||
pw.println("\\hline\r\n" + |
||||
" UID & TOC & Train class & " |
||||
+ "\\multicolumn{2}{c|}{Origin}& \\multicolumn{2}{c|}{"+origin+"} & " |
||||
+ "\\multicolumn{2}{c|}{"+destination+"} &\\multicolumn{2}{c||}{Destination} & Detail Page &Note\\\\\\hline\\endhead"); |
||||
int recCount = 0; |
||||
TrainScheduleEntry ltse = null; |
||||
for(TrainScheduleEntry tse:trainGroup) { |
||||
if(ltse!=null) { |
||||
if(getHour(ltse.getDepartTime())!=getHour(tse.getDepartTime())) { |
||||
pw.println("\\\\\\hline"); |
||||
}else { |
||||
pw.println("\\\\"); |
||||
} |
||||
} |
||||
if(tse.getSubentryCount()==1) { |
||||
//Basic layout
|
||||
pw.print(tse.getSignalId()); |
||||
pw.print("&"); |
||||
pw.print(tse.getToc()); |
||||
pw.print("&"); |
||||
pw.print(tse.getTrainClass()); |
||||
pw.print("&"); |
||||
pw.print(tse.getOrigin()); |
||||
pw.print("&"); |
||||
pw.print(getTime(tse.getOriginTime())); |
||||
pw.print("&"); |
||||
pw.print(getTime(tse.getDepartTime())); |
||||
pw.print("&\\small{"); |
||||
pw.print(tse.getDepartPlatform()); |
||||
pw.print("}&"); |
||||
pw.print(getTime(tse.getArriveTime())); |
||||
pw.print("&\\small{"); |
||||
pw.print(tse.getArrivePlatform()); |
||||
pw.print("}&"); |
||||
pw.print(tse.getDestination()); |
||||
pw.print("&"); |
||||
pw.print(getTime(tse.getDestinationTime())); |
||||
pw.print("&\\pageref{td:"); |
||||
pw.print(tse.getTrainUid()); |
||||
pw.print("}&"); |
||||
pw.print(tse.getNote()); |
||||
if(tse.getScheduleType()==ScheduleType.CAN) |
||||
pw.print("C"); |
||||
}else { |
||||
//Advance layout
|
||||
recCount++; |
||||
BasicTrainScheduleEntry assoc = tse.getAssocEntry(); |
||||
boolean hasChange = false; |
||||
//Print main record
|
||||
if(recCount%2==0) |
||||
pw.print("\\rowcolor{hl1}"); |
||||
else |
||||
pw.print("\\rowcolor{hl2}"); |
||||
if(!tse.getSignalId().equals(assoc.getSignalId())) { |
||||
hasChange = true; |
||||
pw.print("\\textcolor{red}{"); |
||||
} |
||||
pw.print(tse.getSignalId()); |
||||
if(!tse.getSignalId().equals(assoc.getSignalId())) { |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(!tse.getToc().equals(assoc.getToc())) { |
||||
hasChange = true; |
||||
pw.print("\\textcolor{red}{"); |
||||
} |
||||
pw.print(tse.getToc()); |
||||
if(!tse.getToc().equals(assoc.getToc())) { |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(!tse.getTrainClass().equals(assoc.getTrainClass())) { |
||||
hasChange = true; |
||||
pw.print("\\textcolor{red}{"); |
||||
} |
||||
pw.print(tse.getTrainClass()); |
||||
if(!tse.getTrainClass().equals(assoc.getTrainClass())) { |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(!tse.getOrigin().equals(assoc.getOrigin())) { |
||||
hasChange = true; |
||||
pw.print("\\textcolor{red}{"); |
||||
} |
||||
pw.print(tse.getOrigin()); |
||||
if(!tse.getOrigin().equals(assoc.getOrigin())) { |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(tse.getOriginTime()!=assoc.getOriginTime()) { |
||||
hasChange = true; |
||||
pw.print("\\textcolor{red}{"); |
||||
} |
||||
pw.print(getTime(tse.getOriginTime())); |
||||
if(tse.getOriginTime()!=assoc.getOriginTime()) { |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(tse.getDepartTime()!=assoc.getDepartTime()) { |
||||
hasChange = true; |
||||
pw.print("\\textcolor{red}{"); |
||||
} |
||||
pw.print(getTime(tse.getDepartTime())); |
||||
if(tse.getDepartTime()!=assoc.getDepartTime()) { |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(!tse.getDepartPlatform().equals(assoc.getDepartPlatform())) { |
||||
hasChange = true; |
||||
pw.print("\\textcolor{red}{"); |
||||
} |
||||
pw.print("\\small{"); |
||||
pw.print(tse.getDepartPlatform()); |
||||
pw.print("}"); |
||||
if(!tse.getDepartPlatform().equals(assoc.getDepartPlatform())) { |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(tse.getArriveTime()!=assoc.getArriveTime()) { |
||||
hasChange = true; |
||||
pw.print("\\textcolor{red}{"); |
||||
} |
||||
pw.print(getTime(tse.getArriveTime())); |
||||
if(tse.getArriveTime()!=assoc.getArriveTime()) { |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(!tse.getArrivePlatform().equals(assoc.getArrivePlatform())) { |
||||
hasChange = true; |
||||
pw.print("\\textcolor{red}{"); |
||||
} |
||||
pw.print("\\small{"); |
||||
pw.print(tse.getArrivePlatform()); |
||||
pw.print("}"); |
||||
if(!tse.getArrivePlatform().equals(assoc.getArrivePlatform())) { |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(!tse.getDestination().equals(assoc.getDestination())) { |
||||
hasChange = true; |
||||
pw.print("\\textcolor{red}{"); |
||||
} |
||||
pw.print(tse.getDestination()); |
||||
if(!tse.getDestination().equals(assoc.getDestination())) { |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(tse.getDestinationTime()!=assoc.getDestinationTime()) { |
||||
hasChange = true; |
||||
pw.print("\\textcolor{red}{"); |
||||
} |
||||
pw.print(getTime(tse.getDestinationTime())); |
||||
if(tse.getDestinationTime()!=assoc.getDestinationTime()) { |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&\\pageref{td:"); |
||||
pw.print(tse.getTrainUid()); |
||||
pw.print("}&"); |
||||
pw.print(tse.getNote()); |
||||
pw.print("B"); |
||||
if(tse.getScheduleType()==ScheduleType.CAN) |
||||
pw.print("C"); |
||||
if(hasChange) { |
||||
pw.print("\\\\*"); |
||||
//Print ORIGINAL record
|
||||
if(recCount%2==0) |
||||
pw.print("\\rowcolor{hl1}"); |
||||
else |
||||
pw.print("\\rowcolor{hl2}"); |
||||
if(!tse.getSignalId().equals(assoc.getSignalId())) { |
||||
hasChange = true; |
||||
pw.print("\\sout{"); |
||||
pw.print(assoc.getSignalId()); |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(!tse.getToc().equals(assoc.getToc())) { |
||||
hasChange = true; |
||||
pw.print("\\sout{"); |
||||
pw.print(assoc.getToc()); |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(!tse.getTrainClass().equals(assoc.getTrainClass())) { |
||||
hasChange = true; |
||||
pw.print("\\sout{"); |
||||
pw.print(assoc.getTrainClass()); |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(!tse.getOrigin().equals(assoc.getOrigin())) { |
||||
hasChange = true; |
||||
pw.print("\\sout{"); |
||||
pw.print(assoc.getOrigin()); |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(tse.getOriginTime()!=assoc.getOriginTime()) { |
||||
hasChange = true; |
||||
pw.print("\\sout{"); |
||||
pw.print(getTime(assoc.getOriginTime())); |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(tse.getDepartTime()!=assoc.getDepartTime()) { |
||||
hasChange = true; |
||||
pw.print("\\sout{"); |
||||
pw.print(getTime(assoc.getDepartTime())); |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(!tse.getDepartPlatform().equals(assoc.getDepartPlatform())) { |
||||
hasChange = true; |
||||
pw.print("\\sout{"); |
||||
pw.print("\\small{"); |
||||
pw.print(assoc.getDepartPlatform()); |
||||
pw.print("}"); |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(tse.getArriveTime()!=assoc.getArriveTime()) { |
||||
hasChange = true; |
||||
pw.print("\\sout{"); |
||||
pw.print(getTime(assoc.getArriveTime())); |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(!tse.getArrivePlatform().equals(assoc.getArrivePlatform())) { |
||||
hasChange = true; |
||||
pw.print("\\sout{"); |
||||
pw.print("\\small{"); |
||||
pw.print(assoc.getArrivePlatform()); |
||||
pw.print("}"); |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(!tse.getDestination().equals(assoc.getDestination())) { |
||||
hasChange = true; |
||||
pw.print("\\sout{"); |
||||
pw.print(assoc.getDestination()); |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&"); |
||||
if(tse.getDestinationTime()!=assoc.getDestinationTime()) { |
||||
hasChange = true; |
||||
pw.print("\\sout{"); |
||||
pw.print(getTime(assoc.getDestinationTime())); |
||||
pw.print("}"); |
||||
} |
||||
pw.print("&&"); |
||||
} |
||||
} |
||||
|
||||
ltse = tse; |
||||
} |
||||
pw.println("\\\\\\hline\\end{longtable}"); |
||||
pw.println("Note:\\\\"); |
||||
pw.println("A\\dfa Faster train available\\\\"); |
||||
pw.println("B\\dfb Changes to timetable applies\\\\"); |
||||
pw.println("C\\dfa Scheduled cancellation\\\\"); |
||||
pw.println("\\pageref{xx:ukn}\\dfb No train details found\\\\"); |
||||
|
||||
//Details
|
||||
pw.println("\\section{Schedule Details}"); |
||||
for(TrainScheduleEntry tse:trainGroup) { |
||||
TrainRunningRecord trr = getRunningRecord(tse.getMainSUID(), rptDate); |
||||
if(trr==null) { |
||||
log.atWarn().log("No record for {}", tse.getMainSUID()); |
||||
continue; |
||||
} |
||||
pw.println("\\subsection{"+tse.getSignalId()+" "+getTime(tse.getOriginTime())+" to "+locCache.get(tse.getDestination()).replace("&", "\\&")+"}\\label{td:"+tse.getTrainUid()+"}"); |
||||
pw.println(); |
||||
pw.println("Basic infomation\\\\"); |
||||
pw.println("From "+locCache.get(tse.getOrigin()).replace("&", "\\&")+" to "+locCache.get(tse.getDestination()).replace("&", "\\&")+"\\\\"); |
||||
pw.println("Operated by "+tocCache.get(tse.getToc())+"\\\\"); |
||||
pw.println(tcCache.get(tse.getTrainClass())+"\\\\"); |
||||
pw.println("Train UID: "+tse.getTrainUid()+"\\\\"); |
||||
try( |
||||
Connection conn = DatabaseManager.getInstance().getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT power_type, planned_speed, class, sleeper, reservation, catering, atoc_code, rsid FROM ltp_schedule WHERE suid = ?") |
||||
){ |
||||
pstmt.setString(1, tse.getMainSUID()); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
if(rs.next()) { |
||||
pw.println("Train ID: "+trr.getTrainId()+"\\\\"); |
||||
pw.println("Activated on: "+new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date(trr.getActivate()))+"\\\\"); |
||||
pw.println("Power type: "+rs.getString(1)+"\\\\"); |
||||
pw.println("Planned speed "+rs.getString(2)+"mph\\\\"); |
||||
if("".equals(rs.getString(3))||"B".equals(rs.getString(3))) { |
||||
pw.println("First class available\\\\"); |
||||
}else { |
||||
pw.println("Only ordinary class available\\\\"); |
||||
} |
||||
if(rs.getString(8)!=null) { |
||||
pw.println("National Reservation System headcode : "+rs.getString(7)+rs.getString(8)); |
||||
} |
||||
} |
||||
} |
||||
}catch(SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
pw.println(); |
||||
pw.println("\\begin{longtable}[l]{|p{5.5cm}r|ccc|ccc|lr|}"); |
||||
pw.println("\\hline\r\n" + |
||||
" \\multicolumn{2}{|c|}{Station} & \\multicolumn{3}{c|}{Arrival}& \\multicolumn{3}{c|}{Departure}&\r\n" + |
||||
" Plat. & Diff.\\\\\r\n" + |
||||
" & & GBTT & WTT & Actual & GBTT & WTT & Actual & &\\\\\\hline\\endhead"); |
||||
for(TrainRunningRecordEntry trre:trr.getEntries()) { |
||||
if(trre.getLocationName()==null) |
||||
continue; |
||||
boolean pass = false; |
||||
if(origin.equals(trre.getCrs())) |
||||
pw.print("\\rowcolor{hl1}"); |
||||
if(destination.equals(trre.getCrs())) |
||||
pw.print("\\rowcolor{hl2}"); |
||||
pw.print(trre.getLocationName().replace("&", "\\&")); |
||||
pw.print("&"); |
||||
if(trre.getCrs()!=null) |
||||
pw.print(trre.getCrs()); |
||||
pw.print("&"); |
||||
//ARRIVAL
|
||||
if(trre.getAgbtt()!=0) |
||||
pw.print(getTime(trre.getAgbtt())); |
||||
pw.print("&"); |
||||
if(trre.getAwtt()!=0) |
||||
pw.print(getTime(trre.getAwtt())); |
||||
pw.print("&"); |
||||
if(trre.getAact()!=0) |
||||
pw.print(getTime(trre.getAact())); |
||||
pw.print("&"); |
||||
//ARRIVAL
|
||||
if(trre.getDgbtt()!=0) |
||||
pw.print(getTime(trre.getDgbtt())); |
||||
else if(trre.getDwtt()!=0) { |
||||
pw.print("\\pa"); |
||||
pass = true; |
||||
} |
||||
pw.print("&"); |
||||
if(trre.getDwtt()!=0) |
||||
pw.print(getTime(trre.getDwtt())); |
||||
pw.print("&"); |
||||
if(trre.getDact()!=0) |
||||
pw.print(getTime(trre.getDact())); |
||||
pw.print("&"); |
||||
if(trre.getPlatform()!=null) |
||||
pw.print(trre.getPlatform()); |
||||
pw.print("&"); |
||||
long sch, act; |
||||
if(pass||(trre.getAgbtt()==0&&trre.getAwtt()==0&&trre.getAact()==0)) { |
||||
sch = trre.getDgbtt()!=0?trre.getDgbtt():trre.getDwtt(); |
||||
act = trre.getDact(); |
||||
}else { |
||||
sch = trre.getAgbtt()!=0?trre.getAgbtt():trre.getAwtt(); |
||||
act = trre.getAact(); |
||||
} |
||||
if(sch!=0 && !tse.getOrigin().equals(trre.getCrs())) { |
||||
int diffMin = (int)(act-sch)/60; |
||||
if(diffMin < -240) diffMin+=1440; |
||||
if(diffMin < 0) pw.print("\\textcolor{e1}{"); |
||||
else if(diffMin > 30) pw.print("\\textcolor{l3}{"); |
||||
else if(diffMin > 15) pw.print("\\textcolor{l2}{"); |
||||
else if(diffMin > 0) pw.print("\\textcolor{l1}{"); |
||||
else pw.print("\\textcolor{ot}{"); |
||||
pw.print(diffMin); |
||||
pw.print("}"); |
||||
} |
||||
pw.println("\\\\"); |
||||
|
||||
} |
||||
pw.println("\\hline\\end{longtable}"); |
||||
pw.println(); |
||||
|
||||
} |
||||
pw.println("This is the end of the report"); |
||||
pw.println("\\end{document}"); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
private static TrainRunningRecord getRunningRecord(String suid, java.util.Date opDate) { |
||||
TrainRunningRecord trr = new TrainRunningRecord(); |
||||
try(Connection conn = DatabaseManager.getInstance().getConnection()){ |
||||
//Step 1: Find the activation record
|
||||
try(PreparedStatement stmt = conn.prepareStatement("SELECT train_id, activate_time FROM current_train WHERE suid=? AND op_date=?")){ |
||||
stmt.setString(1, suid); |
||||
stmt.setDate(2, new java.sql.Date(opDate.getTime())); |
||||
try(ResultSet rs = stmt.executeQuery()){ |
||||
if(rs.next()) { |
||||
trr.setTrainId(rs.getString(1)); |
||||
trr.setActivate(rs.getTimestamp(2).getTime()); |
||||
}else { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
//Step 2: get the actual record
|
||||
try(PreparedStatement stmt = conn.prepareStatement("SELECT get_stanox_name(loc_stanox) loc, stanox_to_crs(loc_stanox) crs,\r\n" + |
||||
" TIME_TO_SEC(gbtt_time) ttt, TIME_TO_SEC(plan_time) plt, TIME_TO_SEC(movt_time) act,\r\n" + |
||||
" platform plat, CASE evnt_type WHEN 'DEPARTURE' THEN 'D' WHEN 'ARRIVAL' THEN 'A' ELSE '?' END, loc_stanox t\r\n" + |
||||
" FROM current_train_movement WHERE train_id = ? ORDER BY movt_time, evnt_type;")){ |
||||
stmt.setString(1, trr.getTrainId()); |
||||
try(ResultSet rs = stmt.executeQuery()){ |
||||
TrainRunningRecordEntry trre = new TrainRunningRecordEntry(); |
||||
while(rs.next()) { |
||||
if(!rs.getString(8).equals(trre.getStanox())) { |
||||
//Changed
|
||||
trr.getEntries().add(trre); |
||||
trre = new TrainRunningRecordEntry(); |
||||
} |
||||
trre.setCrs(rs.getString(2)); |
||||
String locName = rs.getString(1); |
||||
if(locName.length()>20) { |
||||
locName=locName |
||||
.replace("JUNCTION", "JN") |
||||
.replace("INTERNATIONAL", "INTL") |
||||
.replace("THAMESLINK", "TL"); |
||||
} |
||||
trre.setLocationName(locName); |
||||
trre.setPlatform(rs.getString(6)); |
||||
trre.setStanox(rs.getString(8)); |
||||
if("A".equals(rs.getString(7))) { |
||||
//Arrival
|
||||
trre.setAgbtt(rs.getLong(3)); |
||||
trre.setAwtt(rs.getLong(4)); |
||||
trre.setAact(rs.getLong(5)); |
||||
}else { |
||||
//Departure
|
||||
trre.setDgbtt(rs.getLong(3)); |
||||
trre.setDwtt(rs.getLong(4)); |
||||
trre.setDact(rs.getLong(5)); |
||||
} |
||||
} |
||||
trr.getEntries().add(trre); |
||||
} |
||||
} |
||||
}catch(SQLException e) { |
||||
log.atError().log(e.getMessage(), e); |
||||
} |
||||
return trr; |
||||
} |
||||
|
||||
private static String getTime(long sec) { |
||||
long h = sec/3600; |
||||
long m = (sec/60)%60; |
||||
StringBuilder sb = new StringBuilder(); |
||||
if(h<10) sb.append("0"); |
||||
sb.append(h).append(":"); |
||||
if(m<10) sb.append("0"); |
||||
sb.append(m); |
||||
return sb.toString(); |
||||
} |
||||
|
||||
private static int getHour(long sec) { |
||||
return (int) sec/3600; |
||||
} |
||||
} |
||||
@ -0,0 +1,35 @@
|
||||
package org.leolo.rail.report; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Vector; |
||||
|
||||
public class TrainRunningRecord { |
||||
private String trainId; |
||||
private long activate; |
||||
|
||||
private Vector<TrainRunningRecordEntry> entries = new Vector<>(); |
||||
|
||||
public String getTrainId() { |
||||
return trainId; |
||||
} |
||||
|
||||
|
||||
public Vector<TrainRunningRecordEntry> getEntries() { |
||||
return entries; |
||||
} |
||||
|
||||
public void setTrainId(String trainId) { |
||||
this.trainId = trainId; |
||||
} |
||||
|
||||
|
||||
public long getActivate() { |
||||
return activate; |
||||
} |
||||
|
||||
|
||||
public void setActivate(long activate) { |
||||
this.activate = activate; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,76 @@
|
||||
package org.leolo.rail.report; |
||||
|
||||
public class TrainRunningRecordEntry { |
||||
private String locationName; |
||||
private String crs; |
||||
private String stanox; |
||||
private String platform; |
||||
|
||||
private long agbtt; |
||||
private long awtt; |
||||
private long aact; |
||||
private long dgbtt; |
||||
private long dwtt; |
||||
private long dact; |
||||
public String getLocationName() { |
||||
return locationName; |
||||
} |
||||
public String getCrs() { |
||||
return crs; |
||||
} |
||||
public long getAgbtt() { |
||||
return agbtt; |
||||
} |
||||
public long getAwtt() { |
||||
return awtt; |
||||
} |
||||
public long getAact() { |
||||
return aact; |
||||
} |
||||
public long getDgbtt() { |
||||
return dgbtt; |
||||
} |
||||
public long getDwtt() { |
||||
return dwtt; |
||||
} |
||||
public long getDact() { |
||||
return dact; |
||||
} |
||||
public void setLocationName(String locationName) { |
||||
this.locationName = locationName; |
||||
} |
||||
public void setCrs(String crs) { |
||||
this.crs = crs; |
||||
} |
||||
public void setAgbtt(long agbtt) { |
||||
this.agbtt = agbtt; |
||||
} |
||||
public void setAwtt(long awtt) { |
||||
this.awtt = awtt; |
||||
} |
||||
public void setAact(long aact) { |
||||
this.aact = aact; |
||||
} |
||||
public void setDgbtt(long dgbtt) { |
||||
this.dgbtt = dgbtt; |
||||
} |
||||
public void setDwtt(long dwtt) { |
||||
this.dwtt = dwtt; |
||||
} |
||||
public void setDact(long dact) { |
||||
this.dact = dact; |
||||
} |
||||
public String getPlatform() { |
||||
return platform; |
||||
} |
||||
public void setPlatform(String platform) { |
||||
this.platform = platform; |
||||
} |
||||
public String getStanox() { |
||||
return stanox; |
||||
} |
||||
public void setStanox(String stanox) { |
||||
this.stanox = stanox; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,105 @@
|
||||
package org.leolo.rail.report; |
||||
|
||||
import java.util.HashSet; |
||||
|
||||
import org.leolo.rail.model.ScheduleType; |
||||
|
||||
public class TrainScheduleEntry { |
||||
|
||||
private HashSet<BasicTrainScheduleEntry> subEntry = new HashSet<>(); |
||||
private BasicTrainScheduleEntry mainEntry = null; |
||||
private String note = ""; |
||||
|
||||
public void addEntry(BasicTrainScheduleEntry entry) { |
||||
subEntry.add(entry); |
||||
if(mainEntry==null) { |
||||
mainEntry = entry; |
||||
}else if(entry.getScheduleType() == ScheduleType.OVL) { |
||||
mainEntry = entry; |
||||
} |
||||
} |
||||
|
||||
public int getSubentryCount() { |
||||
return subEntry.size(); |
||||
} |
||||
|
||||
public BasicTrainScheduleEntry getAssocEntry() { |
||||
for(BasicTrainScheduleEntry btse:subEntry) { |
||||
if(btse!=mainEntry) { |
||||
return btse; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public String getMainSUID() { |
||||
return mainEntry.getSuid(); |
||||
} |
||||
|
||||
public ScheduleType getScheduleType() { |
||||
return mainEntry.getScheduleType(); |
||||
} |
||||
|
||||
public String getSignalId() { |
||||
return mainEntry.getSignalId(); |
||||
} |
||||
|
||||
public String getToc() { |
||||
return mainEntry.getToc(); |
||||
} |
||||
|
||||
public String getTrainClass() { |
||||
return mainEntry.getTrainClass(); |
||||
} |
||||
|
||||
public String getOrigin() { |
||||
return mainEntry.getOrigin(); |
||||
} |
||||
|
||||
public long getOriginTime() { |
||||
return mainEntry.getOriginTime(); |
||||
} |
||||
|
||||
public String getDestination() { |
||||
return mainEntry.getDestination(); |
||||
} |
||||
|
||||
public long getDestinationTime() { |
||||
return mainEntry.getDestinationTime(); |
||||
} |
||||
|
||||
public HashSet<BasicTrainScheduleEntry> getAssoicatedEntry() { |
||||
return mainEntry.getAssoicatedEntry(); |
||||
} |
||||
|
||||
|
||||
public String getTrainUid() { |
||||
return mainEntry.getTrainUid(); |
||||
} |
||||
|
||||
|
||||
public long getDepartTime() { |
||||
return mainEntry.getDepartTime(); |
||||
} |
||||
|
||||
public String getDepartPlatform() { |
||||
return mainEntry.getDepartPlatform(); |
||||
} |
||||
|
||||
public long getArriveTime() { |
||||
return mainEntry.getArriveTime(); |
||||
} |
||||
|
||||
public String getArrivePlatform() { |
||||
return mainEntry.getArrivePlatform(); |
||||
} |
||||
|
||||
public String getNote() { |
||||
return note; |
||||
} |
||||
|
||||
public void setNote(String note) { |
||||
this.note = note; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,32 @@
|
||||
package org.leolo.rail.util; |
||||
|
||||
import java.text.DateFormat; |
||||
import java.text.FieldPosition; |
||||
import java.text.ParsePosition; |
||||
import java.util.Date; |
||||
|
||||
public class TUIDDateFormat extends DateFormat{ |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
private static final long serialVersionUID = 7274736087586430881L; |
||||
|
||||
public static final String MONTH_ID = "MBTQPHSONDUE"; |
||||
public static final String DAY_ID = "0123456789ABCDEFGHJKLMNPRSTUVWX"; |
||||
|
||||
|
||||
@Override |
||||
public StringBuffer format(Date arg0, StringBuffer arg1, FieldPosition arg2) { |
||||
// TODO Auto-generated method stub
|
||||
arg1.append(MONTH_ID.charAt(arg0.getMonth())); |
||||
arg1.append(DAY_ID.charAt(arg0.getDate()-1)); |
||||
return arg1; |
||||
} |
||||
|
||||
@Override |
||||
public Date parse(String arg0, ParsePosition arg1) { |
||||
throw new UnsupportedOperationException(); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue