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/ |
/bin/ |
||||||
/target/ |
/target/ |
||||||
configuration.properties |
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