Compare commits
56 Commits
master
...
feature-nr
63 changed files with 5812 additions and 104 deletions
@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="AutoImportSettings"> |
||||
<option name="autoReloadType" value="SELECTIVE" /> |
||||
</component> |
||||
<component name="ChangeListManager"> |
||||
<list default="true" id="b9554e7b-3332-419c-960c-8bfbee0d5311" name="Changes" comment=""> |
||||
<change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" /> |
||||
<change afterPath="$PROJECT_DIR$/.idea/aws.xml" afterDir="false" /> |
||||
<change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" /> |
||||
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" /> |
||||
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> |
||||
<change afterPath="$PROJECT_DIR$/pom.xml" afterDir="false" /> |
||||
<change afterPath="$PROJECT_DIR$/src/main/java/org/leolo/nrdatad/App.java" afterDir="false" /> |
||||
<change afterPath="$PROJECT_DIR$/src/test/java/org/leolo/AppTest.java" afterDir="false" /> |
||||
</list> |
||||
<option name="SHOW_DIALOG" value="false" /> |
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" /> |
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" /> |
||||
<option name="LAST_RESOLUTION" value="IGNORE" /> |
||||
</component> |
||||
<component name="Git.Settings"> |
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" /> |
||||
</component> |
||||
<component name="ProjectId" id="2GCtKiOdhwqUrJrlolmjYzZXLwa" /> |
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true" /> |
||||
<component name="ProjectViewState"> |
||||
<option name="flattenPackages" value="true" /> |
||||
<option name="hideEmptyMiddlePackages" value="true" /> |
||||
<option name="showLibraryContents" value="true" /> |
||||
</component> |
||||
<component name="PropertiesComponent"><![CDATA[{ |
||||
"keyToString": { |
||||
"RunOnceActivity.OpenProjectViewOnStart": "true", |
||||
"RunOnceActivity.ShowReadmeOnStart": "true", |
||||
"WebServerToolWindowFactoryState": "false" |
||||
} |
||||
}]]></component> |
||||
<component name="RunManager"> |
||||
<configuration name="Main" type="Application" factoryName="Application"> |
||||
<option name="MAIN_CLASS_NAME" value="org.leolo.nrdatad.App" /> |
||||
<module name="nr-data-damon" /> |
||||
<extension name="software.aws.toolkits.jetbrains.core.execution.JavaAwsConnectionExtension"> |
||||
<option name="credential" /> |
||||
<option name="region" /> |
||||
<option name="useCurrentConnection" value="false" /> |
||||
</extension> |
||||
<method v="2"> |
||||
<option name="Make" enabled="true" /> |
||||
</method> |
||||
</configuration> |
||||
</component> |
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" /> |
||||
<component name="TaskManager"> |
||||
<task active="true" id="Default" summary="Default task"> |
||||
<changelist id="b9554e7b-3332-419c-960c-8bfbee0d5311" name="Changes" comment="" /> |
||||
<created>1665904334835</created> |
||||
<option name="number" value="Default" /> |
||||
<option name="presentableId" value="Default" /> |
||||
<updated>1665904334835</updated> |
||||
<workItem from="1665904336661" duration="319000" /> |
||||
</task> |
||||
<servers /> |
||||
</component> |
||||
<component name="TypeScriptGeneratedFilesManager"> |
||||
<option name="version" value="3" /> |
||||
</component> |
||||
<component name="Vcs.Log.Tabs.Properties"> |
||||
<option name="TAB_STATES"> |
||||
<map> |
||||
<entry key="MAIN"> |
||||
<value> |
||||
<State /> |
||||
</value> |
||||
</entry> |
||||
</map> |
||||
</option> |
||||
</component> |
||||
</project> |
||||
@ -1,11 +1,148 @@
|
||||
package org.leolo.nrdatad; |
||||
|
||||
|
||||
import org.apache.commons.cli.*; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.leolo.nrdatad.cron.ScheduleImportJob; |
||||
import org.leolo.nrdatad.db.CorpusDao; |
||||
import org.leolo.nrdatad.db.DatabaseManager; |
||||
import org.leolo.nrdatad.cron.ReferenceDataJob; |
||||
import org.leolo.nrdatad.model.Corpus; |
||||
import org.quartz.*; |
||||
import org.quartz.impl.StdSchedulerFactory; |
||||
|
||||
import java.io.IOException; |
||||
import java.lang.reflect.InvocationTargetException; |
||||
import java.sql.SQLException; |
||||
import java.util.Collection; |
||||
|
||||
/** |
||||
* Hello world! |
||||
* |
||||
*/ |
||||
public class App { |
||||
|
||||
Logger log = LogManager.getLogger(); |
||||
|
||||
private ConfigurationManager config = ConfigurationManager.getInstance(); |
||||
private Scheduler scheduler; |
||||
public static void main( String[] args ) { |
||||
System.out.println( "Hello World!" ); |
||||
Option confFile = Option.builder() |
||||
.required(false) |
||||
.hasArg(true) |
||||
.argName("fileName") |
||||
.option("c") |
||||
.longOpt("config-file") |
||||
.build(); |
||||
Options opts = new Options(); |
||||
opts.addOption(confFile); |
||||
String confPath = "nrdatad.conf"; |
||||
try { |
||||
CommandLine cli = new DefaultParser().parse(opts, args); |
||||
if(cli.hasOption(confFile)){ |
||||
confPath = cli.getOptionValue(confFile); |
||||
} |
||||
} catch (ParseException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
new App().run(confPath); |
||||
} |
||||
|
||||
private void run(String configPath){ |
||||
log.always().log("System Started."); |
||||
|
||||
try { |
||||
config.loadConfiguration(configPath); |
||||
} catch (IOException e) { |
||||
log.atError().withThrowable(e).log("Unable to load confog file"); |
||||
return; |
||||
} |
||||
// log.atDebug()
|
||||
if(config.getProperty("general.debug","false").equals("true")){ |
||||
for(String key:config.stringPropertyNames()){ |
||||
if(key.endsWith("pwd")){ |
||||
log.atDebug().log("Config: {} : ****({} chars)", key, config.getProperty(key).length()); |
||||
|
||||
}else{ |
||||
log.atDebug().log("Config: {} : {}", key, config.getProperty(key)); |
||||
|
||||
} |
||||
} |
||||
} |
||||
String databaseManagerClass = config.getProperty("db.manager","org.leolo.nrdatad.db.DatabaseManager"); |
||||
log.atInfo().log("Creating database manager {}", databaseManagerClass); |
||||
try { |
||||
config.setDatabaseManager((DatabaseManager) Class.forName(databaseManagerClass).getConstructor().newInstance()); |
||||
} catch ( |
||||
InstantiationException|IllegalAccessException|InvocationTargetException| |
||||
NoSuchMethodException|ClassNotFoundException e |
||||
) { |
||||
log.atFatal().log("Unable to create instance of {}", databaseManagerClass); |
||||
System.exit(1); |
||||
return; |
||||
} catch (ClassCastException e){ |
||||
log.atFatal().log("{} is not a DatabaseManager", databaseManagerClass); |
||||
System.exit(1); |
||||
return; |
||||
} |
||||
config.getDatabaseManager().initPool(); |
||||
if(config.getDatabaseManager().checkConnection()) |
||||
log.atInfo().log("Database connected!"); |
||||
else{ |
||||
log.atFatal().log("Unable to connect to database."); |
||||
System.exit(1); |
||||
return; |
||||
} |
||||
loadCronJob(); |
||||
new Thread(()->{testRefData();}).start(); |
||||
while(true); |
||||
} |
||||
|
||||
private void testRefData() { |
||||
log.atInfo().log("Testing reference data"); |
||||
ConfigurationManager conf = ConfigurationManager.getInstance(); |
||||
CorpusDao.Query query = new CorpusDao.QueryBuilder() |
||||
.addCrsCode("ECR").addCrsCode("VIC") |
||||
.addDescription("croydon").build(); |
||||
try { |
||||
Collection<Corpus> list = conf.getDatabaseManager().getCORPUSDao().executeQuery(query); |
||||
log.atDebug().log("{} entries found", list.size()); |
||||
for(Corpus corpus:list){ |
||||
log.atDebug().log("Found entry : {}", corpus); |
||||
} |
||||
} catch (SQLException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
|
||||
private void loadCronJob() { |
||||
log.atDebug().log("Start loading cron jobs"); |
||||
try { |
||||
scheduler = StdSchedulerFactory.getDefaultScheduler(); |
||||
scheduler.start(); |
||||
if(ConfigurationManager.getInstance().getProperty(Constants.Configuration.ALWAYS_RUN_REF_DATA,"").equals("true")){ |
||||
log.atInfo().log("Loading Reference data now"); |
||||
scheduler.scheduleJob( |
||||
JobBuilder.newJob(ReferenceDataJob.class).withIdentity("J-OF-"+Constants.CronJob.REFERENCE_DATA).build(), |
||||
TriggerBuilder.newTrigger().withIdentity("T-OF-"+Constants.CronJob.REFERENCE_DATA).startAt(DateBuilder.evenSecondDateAfterNow()).build() |
||||
); |
||||
} |
||||
scheduler.scheduleJob( |
||||
JobBuilder.newJob(ReferenceDataJob.class).withIdentity("J-CW-"+Constants.CronJob.REFERENCE_DATA).build(), |
||||
TriggerBuilder.newTrigger().withIdentity("T-CW-"+Constants.CronJob.REFERENCE_DATA) |
||||
.withSchedule(CronScheduleBuilder.cronSchedule("* 10 1 ? * 1")).build() |
||||
); |
||||
if(ConfigurationManager.getInstance().getProperty(Constants.Configuration.ALWAYS_RUN_LTP,"").equals("true")){ |
||||
log.atInfo().log("Loading Schedule data now"); |
||||
scheduler.scheduleJob( |
||||
JobBuilder.newJob(ScheduleImportJob.class).withIdentity("J-OF-"+Constants.CronJob.SCHEDULE_IMPORT).build(), |
||||
TriggerBuilder.newTrigger().withIdentity("T-OF-"+Constants.CronJob.SCHEDULE_IMPORT).startAt(DateBuilder.evenSecondDateAfterNow()).build() |
||||
); |
||||
} |
||||
} catch (SchedulerException e) { |
||||
log.atFatal().withThrowable(e).log("Unable to create cron jobs"); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,159 @@
|
||||
package org.leolo.nrdatad; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.leolo.nrdatad.db.DatabaseManager; |
||||
|
||||
import java.io.FileReader; |
||||
import java.io.IOException; |
||||
import java.io.PrintStream; |
||||
import java.io.PrintWriter; |
||||
import java.util.*; |
||||
import java.util.function.BiConsumer; |
||||
|
||||
public final class ConfigurationManager { |
||||
private static ConfigurationManager instance; |
||||
Logger logger = LogManager.getLogger(); |
||||
Properties prop = new Properties(); |
||||
|
||||
private boolean hasCachedEthAddress = false; |
||||
private String cachedEthAddress = null; |
||||
|
||||
private DatabaseManager databaseManager; |
||||
|
||||
public DatabaseManager getDatabaseManager() { |
||||
return databaseManager; |
||||
} |
||||
|
||||
public void setDatabaseManager(DatabaseManager databaseManager) { |
||||
this.databaseManager = databaseManager; |
||||
} |
||||
|
||||
public synchronized static ConfigurationManager getInstance(){ |
||||
if(instance==null){ |
||||
instance = new ConfigurationManager(); |
||||
} |
||||
return instance; |
||||
} |
||||
|
||||
private ConfigurationManager(){ |
||||
|
||||
} |
||||
|
||||
public void loadConfiguration(String configPath) throws IOException{ |
||||
logger.atInfo().log("Loading configuration file {}.", configPath); |
||||
try(FileReader reader = new FileReader(configPath)) { |
||||
prop.load(reader); |
||||
} |
||||
logger.atInfo().log("Loaded {} setting(s)", prop.size()); |
||||
} |
||||
|
||||
public Object setProperty(String key, String value) { |
||||
return prop.setProperty(key, value); |
||||
} |
||||
|
||||
public String getProperty(String key) { |
||||
return prop.getProperty(key); |
||||
} |
||||
|
||||
public String getProperty(String key, String defaultValue) { |
||||
return prop.getProperty(key, defaultValue); |
||||
} |
||||
|
||||
public Enumeration<?> propertyNames() { |
||||
return prop.propertyNames(); |
||||
} |
||||
|
||||
public Set<String> stringPropertyNames() { |
||||
return prop.stringPropertyNames(); |
||||
} |
||||
|
||||
public void list(PrintStream out) { |
||||
prop.list(out); |
||||
} |
||||
|
||||
public void list(PrintWriter out) { |
||||
prop.list(out); |
||||
} |
||||
|
||||
public int size() { |
||||
return prop.size(); |
||||
} |
||||
|
||||
public boolean isEmpty() { |
||||
return prop.isEmpty(); |
||||
} |
||||
|
||||
public Enumeration<Object> keys() { |
||||
return prop.keys(); |
||||
} |
||||
|
||||
public Enumeration<Object> elements() { |
||||
return prop.elements(); |
||||
} |
||||
|
||||
public boolean contains(Object value) { |
||||
return prop.contains(value); |
||||
} |
||||
|
||||
public boolean containsValue(Object value) { |
||||
return prop.containsValue(value); |
||||
} |
||||
|
||||
public boolean containsKey(Object key) { |
||||
return prop.containsKey(key); |
||||
} |
||||
|
||||
public Set<Object> keySet() { |
||||
return prop.keySet(); |
||||
} |
||||
|
||||
public Collection<Object> values() { |
||||
return prop.values(); |
||||
} |
||||
|
||||
public Set<Map.Entry<Object, Object>> entrySet() { |
||||
return prop.entrySet(); |
||||
} |
||||
|
||||
protected void clear(){ |
||||
prop.clear(); |
||||
} |
||||
|
||||
public Object getOrDefault(Object key, Object defaultValue) { |
||||
return prop.getOrDefault(key, defaultValue); |
||||
} |
||||
|
||||
public void forEach(BiConsumer<? super Object, ? super Object> action) { |
||||
prop.forEach(action); |
||||
} |
||||
|
||||
//Special handling for getting the ethernet address
|
||||
public String getEthAddress(){ |
||||
if(hasCachedEthAddress){ |
||||
return cachedEthAddress; |
||||
} |
||||
String addr = prop.getProperty("uuid.ethAddr"); |
||||
if (addr == null){ |
||||
//There are no ethernet address available. Return null
|
||||
hasCachedEthAddress = true; |
||||
return null; |
||||
} |
||||
StringBuilder sb = new StringBuilder(); |
||||
for(char ch:addr.toCharArray()){ |
||||
if(ch>='0'&&ch<='9'){ |
||||
sb.append(ch); |
||||
}else if ((ch >= 'a' && ch <= 'f') ||(ch>='A'&&ch<='F')) { |
||||
sb.append(Character.toLowerCase(ch)); |
||||
} |
||||
} |
||||
if(sb.length()==12){ |
||||
cachedEthAddress = sb.toString(); |
||||
hasCachedEthAddress = true; |
||||
return cachedEthAddress; |
||||
}else{ |
||||
hasCachedEthAddress=true; |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,28 @@
|
||||
package org.leolo.nrdatad; |
||||
|
||||
public final class Constants { |
||||
public static class Metadata{ |
||||
public static final String LAST_LTP = "01-last-ltp-time"; |
||||
} |
||||
|
||||
public static class CronJob{ |
||||
public static final String REFERENCE_DATA = "refd"; |
||||
public static final String SCHEDULE_IMPORT = "scji"; |
||||
|
||||
public static final int SCHEDULE_BATCH_SIZE = 10000; |
||||
} |
||||
|
||||
public static class Configuration { |
||||
public static final String ALWAYS_RUN_LTP = "cron.ltp.always"; |
||||
public static final String ALWAYS_RUN_REF_DATA = "cron.ref.always"; |
||||
public static final String NETWORK_RAIL_USER = "network.user"; |
||||
public static final String NETWORK_RAIL_PASSWORD = "network.pwd"; |
||||
public static final String TEMP_DIR = "file.temp_dir"; |
||||
} |
||||
|
||||
public static class NetworkRailURI{ |
||||
public static final String CORPUS_URL = "https://datafeeds.networkrail.co.uk/ntrod/SupportingFileAuthenticate?type=CORPUS"; |
||||
public static final String SMART_URL = "https://datafeeds.networkrail.co.uk/ntrod/SupportingFileAuthenticate?type=SMART"; |
||||
public static final String SCHEDULE_URL = "https://datafeeds.networkrail.co.uk/ntrod/CifFileAuthenticate?type=CIF_ALL_FULL_DAILY&day=toc-full"; |
||||
} |
||||
} |
||||
@ -0,0 +1,102 @@
|
||||
package org.leolo.nrdatad.cron; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.json.JSONArray; |
||||
import org.json.JSONObject; |
||||
import org.leolo.nrdatad.ConfigurationManager; |
||||
import org.leolo.nrdatad.Constants; |
||||
import org.leolo.nrdatad.db.CorpusDao; |
||||
import org.leolo.nrdatad.model.Corpus; |
||||
import org.leolo.nrdatad.model.Smart; |
||||
import org.leolo.nrdatad.util.HttpUtil; |
||||
import org.quartz.Job; |
||||
import org.quartz.JobExecutionContext; |
||||
import org.quartz.JobExecutionException; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.URISyntaxException; |
||||
import java.sql.SQLException; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
|
||||
public class ReferenceDataJob implements Job { |
||||
|
||||
Logger log = LogManager.getLogger(); |
||||
|
||||
@Override |
||||
public void execute(JobExecutionContext context) throws JobExecutionException { |
||||
log.atInfo().log("Load reference data triggered at {}", context.getFireTime()); |
||||
//There are 2 different kind of reference data. Create 2 thread and deal with them
|
||||
new Thread(()->{processCORPUS();}).start(); |
||||
new Thread(()->{processSMART();}).start(); |
||||
} |
||||
|
||||
private void processSMART() { |
||||
ConfigurationManager conf = ConfigurationManager.getInstance(); |
||||
log.atInfo().log("Loading SMART"); |
||||
String json = null; |
||||
try { |
||||
json = HttpUtil.sendHttpRequestForGZipFile( |
||||
Constants.NetworkRailURI.SMART_URL, |
||||
conf.getProperty(Constants.Configuration.NETWORK_RAIL_USER), |
||||
conf.getProperty(Constants.Configuration.NETWORK_RAIL_PASSWORD) |
||||
); |
||||
} catch (IOException|URISyntaxException e) { |
||||
log.atError().withThrowable(e).log("Error when getting CORPUS data"); |
||||
return; |
||||
} |
||||
JSONObject rootObj = new JSONObject(json); |
||||
JSONArray rootArray = rootObj.getJSONArray("BERTHDATA"); |
||||
log.atInfo().log("{} entries found", rootArray.length()); |
||||
Collection<Smart> smarts = new ArrayList<>(); |
||||
for (int i = 0; i < rootArray.length(); i++) { |
||||
JSONObject obj = rootArray.getJSONObject(i); |
||||
Smart smart = Smart.parseJSON(obj); |
||||
if(!smart.checkEnums()){ |
||||
log.atInfo().log("Improper SMART record: {}", obj); |
||||
continue; |
||||
} |
||||
smarts.add(smart); |
||||
} |
||||
try { |
||||
conf.getDatabaseManager().getSmartDao().truncateTable(); |
||||
conf.getDatabaseManager().getSmartDao().addAll(smarts); |
||||
} catch (SQLException e) { |
||||
log.atError().withThrowable(e).log("Unable to insert records"); |
||||
} |
||||
log.atInfo().log("Done inserting SMART"); |
||||
} |
||||
|
||||
private void processCORPUS(){ |
||||
ConfigurationManager conf = ConfigurationManager.getInstance(); |
||||
log.atInfo().log("Loading CORPUS"); |
||||
String json = null; |
||||
try { |
||||
json = HttpUtil.sendHttpRequestForGZipFile( |
||||
Constants.NetworkRailURI.CORPUS_URL, |
||||
conf.getProperty(Constants.Configuration.NETWORK_RAIL_USER), |
||||
conf.getProperty(Constants.Configuration.NETWORK_RAIL_PASSWORD) |
||||
); |
||||
} catch (IOException|URISyntaxException e) { |
||||
log.atError().withThrowable(e).log("Error when getting CORPUS data"); |
||||
return; |
||||
} |
||||
JSONObject rootObj = new JSONObject(json); |
||||
JSONArray rootArray = rootObj.getJSONArray("TIPLOCDATA"); |
||||
log.atInfo().log("{} entries found", rootArray.length()); |
||||
ArrayList<Corpus> corpusList = new ArrayList<>(); |
||||
for(int i=0;i<rootArray.length();i++){ |
||||
JSONObject obj = rootArray.getJSONObject(i); |
||||
corpusList.add(Corpus.parseJSON(obj)); |
||||
} |
||||
log.atInfo().log("Going to replace the data"); |
||||
try { |
||||
CorpusDao cDao = conf.getDatabaseManager().getCORPUSDao(); |
||||
cDao.replaceAll(corpusList); |
||||
} catch (SQLException e) { |
||||
log.atError().withThrowable(e).log("Unable to insert records"); |
||||
} |
||||
log.atInfo().log("Done inserting CORPUS"); |
||||
} |
||||
} |
||||
@ -0,0 +1,227 @@
|
||||
package org.leolo.nrdatad.cron; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.json.JSONObject; |
||||
import org.leolo.nrdatad.ConfigurationManager; |
||||
import org.leolo.nrdatad.Constants; |
||||
import org.leolo.nrdatad.model.ScheduleAssociation; |
||||
import org.leolo.nrdatad.model.Tiploc; |
||||
import org.leolo.nrdatad.util.HttpUtil; |
||||
import org.leolo.nrdatad.util.TUIDDateFormat; |
||||
import org.quartz.Job; |
||||
import org.quartz.JobExecutionContext; |
||||
import org.quartz.JobExecutionException; |
||||
|
||||
import java.io.*; |
||||
import java.net.URISyntaxException; |
||||
import java.sql.SQLException; |
||||
import java.util.ArrayList; |
||||
import java.util.concurrent.ExecutorService; |
||||
import java.util.concurrent.Executors; |
||||
import java.util.concurrent.TimeUnit; |
||||
import java.util.zip.GZIPInputStream; |
||||
import java.util.zip.GZIPOutputStream; |
||||
|
||||
public class ScheduleImportJob implements Job { |
||||
Logger log = LogManager.getLogger(); |
||||
|
||||
private File baseTempDir; |
||||
private ConfigurationManager conf = ConfigurationManager.getInstance(); |
||||
|
||||
public static final String TYPE_HEADER = "JsonTimetableV1"; |
||||
public static final String TYPE_ASSOCIATION = "JsonAssociationV1"; |
||||
public static final String TYPE_TIPLOC = "TiplocV1"; |
||||
public static final String TYPE_SCHEDULE = "JsonScheduleV1"; |
||||
public static final String TYPE_EOF = "EOF"; |
||||
|
||||
|
||||
@Override |
||||
public void execute(JobExecutionContext context) throws JobExecutionException { |
||||
log.atInfo().log("Loading schedule from SCHEDULE stream"); |
||||
final String RUN_ID = Long.toHexString(System.currentTimeMillis()&0xffffff); |
||||
log.atInfo().log("RUN_ID is {}", RUN_ID); |
||||
baseTempDir = new File(conf.getProperty(Constants.Configuration.TEMP_DIR)+"/nrdatad/SCHEDULE-"+RUN_ID); |
||||
baseTempDir.mkdirs(); |
||||
ExecutorService threadPool = Executors.newFixedThreadPool(5); |
||||
int countH = 0, countA=0, countT=0, countS=0; |
||||
int batchH = 0, batchA=0, batchT=0, batchS=0; |
||||
try(BufferedReader br = new BufferedReader(new InputStreamReader(HttpUtil.getHttpGZipStream( |
||||
Constants.NetworkRailURI.SCHEDULE_URL, |
||||
conf.getProperty(Constants.Configuration.NETWORK_RAIL_USER), |
||||
conf.getProperty(Constants.Configuration.NETWORK_RAIL_PASSWORD) |
||||
))) |
||||
){ |
||||
PrintWriter pa = new PrintWriter(new GZIPOutputStream(new FileOutputStream(new File(baseTempDir, "A_0")))); |
||||
PrintWriter pt = new PrintWriter(new GZIPOutputStream(new FileOutputStream(new File(baseTempDir, "T_0")))); |
||||
PrintWriter ps = new PrintWriter(new GZIPOutputStream(new FileOutputStream(new File(baseTempDir, "S_0")))); |
||||
int count = 0; |
||||
while(true){ |
||||
String line = br.readLine(); |
||||
if(line==null){ |
||||
break; |
||||
} |
||||
JSONObject obj = new JSONObject(line); |
||||
String objectType = obj.keys().next(); |
||||
count++; |
||||
if(TYPE_HEADER.equals(objectType)){ |
||||
//TODO: Deal with the header.
|
||||
countH++; |
||||
} else if (TYPE_ASSOCIATION.equals(objectType)){ |
||||
pa.println(obj.getJSONObject(TYPE_ASSOCIATION)); |
||||
if(++countA%Constants.CronJob.SCHEDULE_BATCH_SIZE==0){ |
||||
log.atInfo().log("New batch for association."); |
||||
pa.flush(); |
||||
pa.close(); |
||||
final int OLD_BATCH = batchA; |
||||
threadPool.execute(()->{processAssociation("A_"+OLD_BATCH);}); |
||||
pa = new PrintWriter(new GZIPOutputStream(new FileOutputStream(new File(baseTempDir, "A_"+(++batchA))))); |
||||
} |
||||
} else if (TYPE_TIPLOC.equals(objectType)) { |
||||
pt.println(obj.getJSONObject(TYPE_TIPLOC)); |
||||
if(++countT%Constants.CronJob.SCHEDULE_BATCH_SIZE==0){ |
||||
log.atInfo().log("New batch for tiploc."); |
||||
pt.flush(); |
||||
pt.close(); |
||||
final int OLD_BATCH = batchT; |
||||
threadPool.execute(()->{processTiploc("T_"+OLD_BATCH);}); |
||||
pt = new PrintWriter(new GZIPOutputStream(new FileOutputStream(new File(baseTempDir, "T_"+(++batchT))))); |
||||
} |
||||
} else if (TYPE_SCHEDULE.equals(objectType)) { |
||||
ps.println(obj.getJSONObject(TYPE_SCHEDULE)); |
||||
if(++countS%Constants.CronJob.SCHEDULE_BATCH_SIZE==0){ |
||||
log.atInfo().log("New batch for schedule."); |
||||
ps.flush(); |
||||
ps.close(); |
||||
ps = new PrintWriter(new GZIPOutputStream(new FileOutputStream(new File(baseTempDir, "S_"+(++batchS))))); |
||||
} |
||||
} else if (TYPE_EOF.equals(objectType)) { |
||||
log.atInfo().log("EOF found!"); |
||||
} else { |
||||
log.atInfo().log("Unmatched type {}", objectType); |
||||
} |
||||
} |
||||
pa.flush(); |
||||
pa.close(); |
||||
pt.flush(); |
||||
pt.close(); |
||||
ps.flush(); |
||||
ps.close(); |
||||
final int OLD_BATCH_A = batchA; |
||||
threadPool.execute(()->{processAssociation("A_"+OLD_BATCH_A);}); |
||||
final int OLD_BATCH_T = batchT; |
||||
threadPool.execute(()->{processTiploc("T_"+OLD_BATCH_T);}); |
||||
log.atInfo().log("There are {} records on total. Including {} headers, {} association, {} TIPLOC and {} schedules", count, countH, countA, countT, countS); |
||||
}catch (IOException | URISyntaxException e){ |
||||
log.atError().withThrowable(e).log("Unable to read SCHEDULE feed"); |
||||
return; |
||||
} |
||||
threadPool.shutdown(); |
||||
try { |
||||
threadPool.awaitTermination(12, TimeUnit.HOURS); |
||||
} catch (InterruptedException e) { |
||||
log.atWarn().log("SCHEDULE import job interrupted"); |
||||
} |
||||
} |
||||
|
||||
private void processAssociation(String file){ |
||||
log.atDebug().log("Processing {}",file); |
||||
try( |
||||
BufferedReader br = new BufferedReader( |
||||
new InputStreamReader( |
||||
new GZIPInputStream( |
||||
new FileInputStream( |
||||
new File(baseTempDir, file) |
||||
) |
||||
) |
||||
) |
||||
); |
||||
PrintWriter pw = new PrintWriter(new File(baseTempDir, file+"_v")) |
||||
){ |
||||
int count = 0; |
||||
ArrayList<ScheduleAssociation> scheduleAssociations = new ArrayList<>(); |
||||
TUIDDateFormat tuidDateFormat = new TUIDDateFormat(); |
||||
while(true){ |
||||
String line = br.readLine(); |
||||
if(line == null){ |
||||
break; |
||||
} |
||||
ScheduleAssociation sa = ScheduleAssociation.parseJSON(line); |
||||
scheduleAssociations.add(sa); |
||||
pw.println(sa.getMainUid()+","+sa.getAssoUid()+","+sa.getAssociationLocation()+","+ |
||||
tuidDateFormat.format(sa.getStartDate())+","+ |
||||
tuidDateFormat.format(sa.getEndDate())+","+ |
||||
sa.getStpIndicator()); |
||||
if(scheduleAssociations.size()>1000){ |
||||
try{ |
||||
ConfigurationManager.getInstance().getDatabaseManager().getTrainAssociationDao().replaceAll(scheduleAssociations); |
||||
} catch (SQLException e){ |
||||
log.atWarn().withThrowable(e).log("Unable to update records. {}",file); |
||||
} |
||||
log.atDebug().log("Processed a batch of associations"); |
||||
scheduleAssociations.clear(); |
||||
} |
||||
} |
||||
try{ |
||||
ConfigurationManager.getInstance().getDatabaseManager().getTrainAssociationDao().replaceAll(scheduleAssociations); |
||||
} catch (SQLException e){ |
||||
log.atWarn().withThrowable(e).log("Unable to update records. {}", file); |
||||
} |
||||
log.atDebug().log("Processed last batch of associations"); |
||||
} catch (IOException e){ |
||||
log.atError().withThrowable(e).log("Error when reading file."); |
||||
} |
||||
try{ |
||||
new File(baseTempDir, file).delete(); |
||||
} catch (Exception e){ |
||||
log.atWarn().withThrowable(e).log("Unable to remove temp file {}", file); |
||||
} |
||||
} |
||||
|
||||
private void processTiploc(String file){ |
||||
log.atDebug().log("Processing {}",file); |
||||
try( |
||||
BufferedReader br = new BufferedReader( |
||||
new InputStreamReader( |
||||
new GZIPInputStream( |
||||
new FileInputStream( |
||||
new File(baseTempDir, file) |
||||
) |
||||
) |
||||
) |
||||
) |
||||
){ |
||||
int count = 0; |
||||
ArrayList<Tiploc> tiplocs = new ArrayList<>(); |
||||
while(true){ |
||||
String line = br.readLine(); |
||||
if(line == null){ |
||||
break; |
||||
} |
||||
tiplocs.add(Tiploc.parseJSON(line)); |
||||
if(tiplocs.size()>1000){ |
||||
try{ |
||||
ConfigurationManager.getInstance().getDatabaseManager().getTiplocDao().replaceAll(tiplocs); |
||||
} catch (SQLException e){ |
||||
log.atWarn().withThrowable(e).log("Unable to update records."); |
||||
} |
||||
log.atDebug().log("Processed a batch of TIPLOCs"); |
||||
tiplocs.clear(); |
||||
} |
||||
} |
||||
try{ |
||||
ConfigurationManager.getInstance().getDatabaseManager().getTiplocDao().replaceAll(tiplocs); |
||||
} catch (SQLException e){ |
||||
log.atWarn().withThrowable(e).log("Unable to update records."); |
||||
} |
||||
log.atDebug().log("Processed last batch of TIPLOCs"); |
||||
} catch (IOException e){ |
||||
log.atError().withThrowable(e).log("Error when reading file."); |
||||
} |
||||
try{ |
||||
new File(baseTempDir, file).delete(); |
||||
} catch (Exception e){ |
||||
log.atWarn().withThrowable(e).log("Unable to remove temp file {}", file); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,69 @@
|
||||
package org.leolo.nrdatad.db; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.jetbrains.annotations.Nullable; |
||||
|
||||
import java.sql.*; |
||||
import java.util.Calendar; |
||||
|
||||
public abstract class BaseDao { |
||||
|
||||
public enum ReplaceResult { |
||||
INSERTED, |
||||
UPDATED, |
||||
NO_ACTION; |
||||
} |
||||
|
||||
private DatabaseManager manager; |
||||
|
||||
public BaseDao(DatabaseManager manager){ |
||||
this.manager = manager; |
||||
} |
||||
|
||||
protected Connection getConnection() throws SQLException{ |
||||
return manager.getConnection(); |
||||
} |
||||
|
||||
protected void setString(PreparedStatement stmt, int pos, @Nullable String data) throws SQLException{ |
||||
if(data==null||data.strip().length()==0){ |
||||
stmt.setNull(pos, Types.CHAR); |
||||
}else{ |
||||
stmt.setString(pos, data); |
||||
} |
||||
} |
||||
|
||||
protected void setInt(PreparedStatement stmt, int pos, int val) throws SQLException{ |
||||
stmt.setInt(pos, val); |
||||
} |
||||
|
||||
protected void setDate(PreparedStatement stmt, int pos, @Nullable java.util.Date data) throws SQLException{ |
||||
if(data==null){ |
||||
stmt.setNull(pos, Types.DATE); |
||||
} else { |
||||
stmt.setTimestamp(pos, new Timestamp(data.getTime())); |
||||
} |
||||
} |
||||
|
||||
protected void setDate(PreparedStatement stmt, int pos, @Nullable java.util.Date data, @NotNull Calendar calendar) throws SQLException{ |
||||
if(data==null){ |
||||
stmt.setNull(pos, Types.DATE); |
||||
} else { |
||||
stmt.setTimestamp(pos, new Timestamp(data.getTime()), calendar); |
||||
} |
||||
} |
||||
|
||||
protected String getQueryParams(int count){ |
||||
if(count <= 0){ |
||||
throw new IllegalArgumentException("count must be greater than 0"); |
||||
} |
||||
StringBuilder sb = new StringBuilder(); |
||||
for(int i=0;i<count;i++){ |
||||
if(i>0){ |
||||
sb.append(","); |
||||
} |
||||
sb.append("?"); |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,146 @@
|
||||
package org.leolo.nrdatad.db; |
||||
|
||||
import org.leolo.nrdatad.model.Corpus; |
||||
|
||||
import java.sql.SQLException; |
||||
import java.util.*; |
||||
|
||||
public abstract class CorpusDao extends BaseDao{ |
||||
|
||||
public CorpusDao(DatabaseManager manager) { |
||||
super(manager); |
||||
} |
||||
|
||||
public static class QueryBuilder{ |
||||
private Set<String> stanox = new HashSet<>(); |
||||
private Set<String> uicCode = new HashSet<>(); |
||||
private Set<String> crsCode = new HashSet<>(); |
||||
private Set<String> tiplocCode = new HashSet<>(); |
||||
private Set<String> nlcCode = new HashSet<>(); |
||||
private Set<String> description = new HashSet<>(); |
||||
SearchMode searchMode = SearchMode.MATCH_ALL_GROUP; |
||||
|
||||
public QueryBuilder setSearchMode(SearchMode searchMode) { |
||||
this.searchMode = searchMode; |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addStanox(String stanox){ |
||||
this.stanox.add(stanox); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addUicCode(String uicCode){ |
||||
this.uicCode.add(uicCode); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addCrsCode(String crsCode){ |
||||
this.crsCode.add(crsCode); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addTiplocCode(String tiplocCode){ |
||||
this.tiplocCode.add(tiplocCode); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addNlcCode(String nlcCode){ |
||||
this.nlcCode.add(nlcCode); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addDescription(String description){ |
||||
this.description.add(description); |
||||
return this; |
||||
} |
||||
|
||||
public Query build(){ |
||||
return new Query(stanox, uicCode, crsCode, tiplocCode, nlcCode, description, searchMode); |
||||
} |
||||
} |
||||
|
||||
public static class Query{ |
||||
private Set<String> stanox = new HashSet<>(); |
||||
private Set<String> uicCode = new HashSet<>(); |
||||
private Set<String> crsCode = new HashSet<>(); |
||||
private Set<String> tiplocCode = new HashSet<>(); |
||||
private Set<String> nlcCode = new HashSet<>(); |
||||
private Set<String> description = new HashSet<>(); |
||||
SearchMode searchMode = SearchMode.MATCH_ALL_GROUP; |
||||
|
||||
private Query(Set<String> stanox, Set<String> uicCode, Set<String> crsCode, Set<String> tiplocCode, Set<String> nlcCode, Set<String> description, SearchMode searchMode) { |
||||
this.stanox = Collections.unmodifiableSet(stanox); |
||||
this.uicCode = Collections.unmodifiableSet(uicCode); |
||||
this.crsCode = Collections.unmodifiableSet(crsCode); |
||||
this.tiplocCode = Collections.unmodifiableSet(tiplocCode); |
||||
this.nlcCode = Collections.unmodifiableSet(nlcCode); |
||||
this.description = Collections.unmodifiableSet(description); |
||||
this.searchMode = searchMode; |
||||
} |
||||
|
||||
public Set<String> getStanox() { |
||||
return stanox; |
||||
} |
||||
|
||||
public Set<String> getUicCode() { |
||||
return uicCode; |
||||
} |
||||
|
||||
public Set<String> getCrsCode() { |
||||
return crsCode; |
||||
} |
||||
|
||||
public Set<String> getTiplocCode() { |
||||
return tiplocCode; |
||||
} |
||||
|
||||
public Set<String> getNlcCode() { |
||||
return nlcCode; |
||||
} |
||||
|
||||
public Set<String> getDescription() { |
||||
return description; |
||||
} |
||||
|
||||
public SearchMode getSearchMode() { |
||||
return searchMode; |
||||
} |
||||
} |
||||
|
||||
public abstract Collection<Corpus> executeQuery(Query query) throws SQLException; |
||||
|
||||
public abstract void add(Corpus corpus) throws SQLException; |
||||
|
||||
public void addAll(Collection<Corpus> datas) throws SQLException { |
||||
for(Corpus corpus: datas){ |
||||
add(corpus); |
||||
} |
||||
} |
||||
|
||||
public abstract void truncateTable() throws SQLException; |
||||
public abstract boolean hasNlcCode(String nlcCode) throws SQLException; |
||||
public abstract void update(Corpus corpus) throws SQLException; |
||||
public void replace(Corpus corpus) throws SQLException{ |
||||
if(corpus.getNlcCode()==null || !hasNlcCode(corpus.getNlcCode())){ |
||||
add(corpus); |
||||
}else{ |
||||
update(corpus); |
||||
} |
||||
} |
||||
|
||||
public void replaceAll(Collection<Corpus> datas) throws SQLException{ |
||||
for(Corpus corpus: datas){ |
||||
replace(corpus); |
||||
} |
||||
} |
||||
|
||||
public abstract Collection<Corpus> searchCORPUSByStanoxCode(String stanoxCode) throws SQLException; |
||||
public abstract Collection<Corpus> searchCORPUSByUicCode(String uicCode) throws SQLException; |
||||
public abstract Collection<Corpus> searchCORPUSByCrsCode(String crsCode) throws SQLException; |
||||
public abstract Collection<Corpus> searchCORPUSByTiplocCode(String tiplocCode) throws SQLException; |
||||
public abstract Corpus searchCORPUSByNlcCode(String nlcCode) throws SQLException; |
||||
public abstract List<Corpus> searchCORPUSByName(String name) throws SQLException; |
||||
|
||||
public abstract Corpus delete(String nlcCode) throws SQLException; |
||||
} |
||||
@ -0,0 +1,23 @@
|
||||
package org.leolo.nrdatad.db; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.SQLException; |
||||
|
||||
public interface DatabaseManager { |
||||
|
||||
public void initPool(); |
||||
|
||||
public boolean checkConnection(); |
||||
|
||||
public Connection getConnection() throws SQLException; |
||||
|
||||
public MetadataDao getMetadataDao(); |
||||
|
||||
public CorpusDao getCORPUSDao(); |
||||
|
||||
public SmartDao getSmartDao(); |
||||
|
||||
public TiplocDao getTiplocDao(); |
||||
|
||||
public TrainAssociationDao getTrainAssociationDao(); |
||||
} |
||||
@ -0,0 +1,42 @@
|
||||
package org.leolo.nrdatad.db; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.leolo.nrdatad.ConfigurationManager; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.SQLException; |
||||
import java.util.Set; |
||||
import java.util.function.BiConsumer; |
||||
|
||||
public abstract class MetadataDao extends BaseDao { |
||||
|
||||
Logger log = LogManager.getLogger(); |
||||
|
||||
public MetadataDao(DatabaseManager manager){ |
||||
super(manager); |
||||
} |
||||
|
||||
public abstract String getMetadata(String key, String defaultValue) throws SQLException; |
||||
|
||||
public String getMetadata(String key) throws SQLException{ |
||||
return getMetadata(key, null); |
||||
} |
||||
|
||||
public abstract void updateMetadata(String key, @NotNull String value) throws SQLException; |
||||
|
||||
public abstract Set<String> getKeys() throws SQLException; |
||||
|
||||
public abstract void forEach(BiConsumer<String, String> action) throws SQLException; |
||||
|
||||
public boolean containsKey(String key) throws SQLException{ |
||||
return getKeys().contains(key); |
||||
} |
||||
|
||||
public int entryCount() throws SQLException{ |
||||
return getKeys().size(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,65 @@
|
||||
package org.leolo.nrdatad.db; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
|
||||
public class ParameterStore extends ArrayList<String> { |
||||
|
||||
@Override |
||||
public int indexOf(Object o) { |
||||
return super.indexOf(o)+1; |
||||
} |
||||
|
||||
public void addAllObject(@NotNull Collection<?> c){ |
||||
for(Object obj:c){ |
||||
add(c.toString()); |
||||
} |
||||
} |
||||
|
||||
public void addObject(Object obj){ |
||||
add(obj==null?null:obj.toString()); |
||||
} |
||||
|
||||
@Override |
||||
public int lastIndexOf(Object o) { |
||||
return super.lastIndexOf(o)+1; |
||||
} |
||||
|
||||
@Override |
||||
public String get(int index) { |
||||
return super.get(index-1); |
||||
} |
||||
|
||||
@Override |
||||
public String set(int index, String element) { |
||||
return super.set(index-1, element); |
||||
} |
||||
|
||||
@Override |
||||
public void add(int index, String element) { |
||||
super.add(index-1, element); |
||||
} |
||||
|
||||
@Override |
||||
public String remove(int index) { |
||||
return super.remove(index-1); |
||||
} |
||||
|
||||
@Override |
||||
public boolean addAll(int index, Collection<? extends String> c) { |
||||
return super.addAll(index-1, c); |
||||
} |
||||
|
||||
@Override |
||||
protected void removeRange(int fromIndex, int toIndex) { |
||||
super.removeRange(fromIndex-1, toIndex-1); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> subList(int fromIndex, int toIndex) { |
||||
return super.subList(fromIndex-1, toIndex-1); |
||||
} |
||||
} |
||||
@ -0,0 +1,17 @@
|
||||
package org.leolo.nrdatad.db; |
||||
|
||||
public enum SearchMode { |
||||
|
||||
/** |
||||
* Indicate all condition must be matched |
||||
*/ |
||||
MATCH_ALL, |
||||
/** |
||||
* Indicate at least one condition in every group must be matched |
||||
*/ |
||||
MATCH_ALL_GROUP, |
||||
/** |
||||
* Indicate at least one condition must be matched. |
||||
*/ |
||||
MATCH_ANY; |
||||
} |
||||
@ -0,0 +1,229 @@
|
||||
package org.leolo.nrdatad.db; |
||||
|
||||
import org.leolo.nrdatad.model.Corpus; |
||||
import org.leolo.nrdatad.model.Smart; |
||||
import org.leolo.nrdatad.model.SmartEvent; |
||||
import org.leolo.nrdatad.model.SmartStepType; |
||||
import org.leolo.nrdatad.util.Range; |
||||
|
||||
import java.sql.SQLException; |
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.HashSet; |
||||
import java.util.Set; |
||||
|
||||
public abstract class SmartDao extends BaseDao{ |
||||
|
||||
public SmartDao(DatabaseManager manager) { |
||||
super(manager); |
||||
} |
||||
|
||||
public abstract void add(Smart smart) throws SQLException; |
||||
|
||||
public abstract void truncateTable() throws SQLException; |
||||
|
||||
public void addAll(Collection<Smart> smarts) throws SQLException{ |
||||
for(Smart smart: smarts){ |
||||
add(smart); |
||||
} |
||||
} |
||||
|
||||
public abstract Collection<Smart> searchSmartByBerth(String fromBerth, String toBerth) throws SQLException; |
||||
|
||||
public abstract Collection<Smart> searchFromByBerth(String fromBerth) throws SQLException; |
||||
|
||||
public abstract Collection<Smart> searchToBerth(String toBerth) throws SQLException; |
||||
|
||||
public abstract Collection<Smart> searchSmartByBerthLine(String fromBerth, String toBerth, String fromLine, String toLine) throws SQLException; |
||||
public abstract Collection<Smart> searchSmartByFromBerthLine(String fromBerth,String fromLine) throws SQLException; |
||||
public abstract Collection<Smart> searchSmartByToBerthLine(String toBerth, String toLine) throws SQLException; |
||||
|
||||
public abstract Collection<Smart> searchSmartByStanox(String stanox) throws SQLException; |
||||
|
||||
|
||||
public abstract Collection<Smart> executeQuery(Query query) throws SQLException; |
||||
|
||||
|
||||
public static class QueryBuilder{ |
||||
private Set<String> td = new HashSet<>(); |
||||
private Set<String> fromBerth = new HashSet<>(); |
||||
private Set<String> toBerth = new HashSet<>(); |
||||
private Set<String> fromLine = new HashSet<>(); |
||||
private Set<String> toLine = new HashSet<>(); |
||||
private Set<Range<Integer>> berthOffset = new HashSet<>(); |
||||
private Set<String> platform = new HashSet<>(); |
||||
private Set<SmartEvent> event = new HashSet<>(); |
||||
private Set<String> route = new HashSet<>(); |
||||
private Set<String> stanox = new HashSet<>(); |
||||
private Set<String> stationName = new HashSet<>(); |
||||
private Set<SmartStepType> stepType = new HashSet<>(); |
||||
private Set<String> comment = new HashSet<>(); |
||||
private SearchMode searchMode = SearchMode.MATCH_ALL_GROUP; |
||||
|
||||
public QueryBuilder addTd(String td){ |
||||
this.td.add(td); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addFromBerth(String fromBerth){ |
||||
this.fromBerth.add(fromBerth); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addToBerth(String toBerth){ |
||||
this.toBerth.add(toBerth); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addFromLine(String fromLine){ |
||||
this.fromLine.add(fromLine); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addToLine(String toLine){ |
||||
this.toLine.add(toLine); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addBerthOffset(int bound1, int bound2){ |
||||
this.berthOffset.add(new Range<>(bound1, bound2)); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addPlatform(String platform){ |
||||
this.platform.add(platform); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addEvent(SmartEvent event){ |
||||
this.event.add(event); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addRoute(String route){ |
||||
this.route.add(route); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addStanox(String stanox){ |
||||
this.stanox.add(stanox); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addStationName(String stationName){ |
||||
this.stationName.add(stationName); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addStepType(SmartStepType stepType){ |
||||
this.stepType.add(stepType); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder addComment(String comment){ |
||||
this.comment.add(comment); |
||||
return this; |
||||
} |
||||
|
||||
public QueryBuilder setSearchMode(SearchMode searchMode){ |
||||
this.searchMode=searchMode; |
||||
return this; |
||||
} |
||||
|
||||
public Query build(){ |
||||
return new Query(td, fromBerth, toBerth, fromLine, toLine, berthOffset, platform, event, route, stanox, stationName, stepType, comment, searchMode); |
||||
} |
||||
} |
||||
|
||||
public static class Query{ |
||||
|
||||
private Set<String> td; |
||||
private Set<String> fromBerth; |
||||
private Set<String> toBerth; |
||||
private Set<String> fromLine; |
||||
private Set<String> toLine; |
||||
private Set<Range<Integer>> berthOffset; |
||||
private Set<String> platform; |
||||
private Set<SmartEvent> event; |
||||
private Set<String> route; |
||||
private Set<String> stanox; |
||||
private Set<String> stationName; |
||||
private Set<SmartStepType> stepType; |
||||
private Set<String> comment; |
||||
private SearchMode searchMode = SearchMode.MATCH_ALL_GROUP; |
||||
|
||||
public Query(Set<String> td, Set<String> fromBerth, Set<String> toBerth, Set<String> fromLine, Set<String> toLine, Set<Range<Integer>> berthOffset, Set<String> platform, Set<SmartEvent> event, Set<String> route, Set<String> stanox, Set<String> stationName, Set<SmartStepType> stepType, Set<String> comment, SearchMode searchMode) { |
||||
this.td = Collections.unmodifiableSet(td); |
||||
this.fromBerth = Collections.unmodifiableSet(fromBerth); |
||||
this.toBerth = Collections.unmodifiableSet(toBerth); |
||||
this.fromLine = Collections.unmodifiableSet(fromLine); |
||||
this.toLine = Collections.unmodifiableSet(toLine); |
||||
this.berthOffset = Collections.unmodifiableSet(berthOffset); |
||||
this.platform = Collections.unmodifiableSet(platform); |
||||
this.event = Collections.unmodifiableSet(event); |
||||
this.route = Collections.unmodifiableSet(route); |
||||
this.stanox = Collections.unmodifiableSet(stanox); |
||||
this.stationName = Collections.unmodifiableSet(stationName); |
||||
this.stepType = Collections.unmodifiableSet(stepType); |
||||
this.comment = Collections.unmodifiableSet(comment); |
||||
this.searchMode = searchMode; |
||||
} |
||||
|
||||
public Set<String> getTd() { |
||||
return td; |
||||
} |
||||
|
||||
public Set<String> getFromBerth() { |
||||
return fromBerth; |
||||
} |
||||
|
||||
public Set<String> getToBerth() { |
||||
return toBerth; |
||||
} |
||||
|
||||
public Set<String> getFromLine() { |
||||
return fromLine; |
||||
} |
||||
|
||||
public Set<String> getToLine() { |
||||
return toLine; |
||||
} |
||||
|
||||
public Set<Range<Integer>> getBerthOffset() { |
||||
return berthOffset; |
||||
} |
||||
|
||||
public Set<String> getPlatform() { |
||||
return platform; |
||||
} |
||||
|
||||
public Set<SmartEvent> getEvent() { |
||||
return event; |
||||
} |
||||
|
||||
public Set<String> getRoute() { |
||||
return route; |
||||
} |
||||
|
||||
public Set<String> getStanox() { |
||||
return stanox; |
||||
} |
||||
|
||||
public Set<String> getStationName() { |
||||
return stationName; |
||||
} |
||||
|
||||
public Set<SmartStepType> getStepType() { |
||||
return stepType; |
||||
} |
||||
|
||||
public Set<String> getComment() { |
||||
return comment; |
||||
} |
||||
|
||||
public SearchMode getSearchMode() { |
||||
return searchMode; |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,41 @@
|
||||
package org.leolo.nrdatad.db; |
||||
|
||||
import org.leolo.nrdatad.model.Tiploc; |
||||
|
||||
import java.sql.SQLException; |
||||
import java.util.Collection; |
||||
|
||||
public abstract class TiplocDao extends BaseDao{ |
||||
|
||||
public TiplocDao(DatabaseManager manager) { |
||||
super(manager); |
||||
} |
||||
|
||||
public abstract void insert(Tiploc tiploc) throws SQLException; |
||||
|
||||
public void insertAll(Collection<Tiploc> tiplocs) throws SQLException{ |
||||
for(Tiploc tiploc: tiplocs){ |
||||
insert(tiploc); |
||||
} |
||||
} |
||||
|
||||
public abstract boolean hasTiploc(String tiplocCode) throws SQLException; |
||||
|
||||
public void replace(Tiploc tiploc) throws SQLException{ |
||||
if(hasTiploc(tiploc.getTiplocCode())){ |
||||
update(tiploc); |
||||
} else { |
||||
insert(tiploc); |
||||
} |
||||
} |
||||
|
||||
public abstract void update(Tiploc tiploc) throws SQLException; |
||||
|
||||
public void replaceAll(Collection<Tiploc> tiplocs) throws SQLException{ |
||||
for(Tiploc tiploc:tiplocs){ |
||||
replace(tiploc); |
||||
} |
||||
} |
||||
|
||||
public abstract void truncateTable() throws SQLException; |
||||
} |
||||
@ -0,0 +1,63 @@
|
||||
package org.leolo.nrdatad.db; |
||||
|
||||
import org.leolo.nrdatad.model.ScheduleAssociation; |
||||
|
||||
import java.sql.SQLException; |
||||
import java.util.Collection; |
||||
|
||||
public abstract class TrainAssociationDao extends BaseDao{ |
||||
|
||||
|
||||
|
||||
public TrainAssociationDao(DatabaseManager manager) { |
||||
super(manager); |
||||
} |
||||
|
||||
public abstract void insert(ScheduleAssociation scheduleAssociation) throws SQLException; |
||||
|
||||
public abstract boolean hasTrainAssociation(String auid) throws SQLException; |
||||
|
||||
public final boolean hasTrainAssociation(ScheduleAssociation scheduleAssociation) throws SQLException { |
||||
return hasTrainAssociation(scheduleAssociation.getAuid()); |
||||
} |
||||
|
||||
public abstract void update(ScheduleAssociation scheduleAssociation) throws SQLException; |
||||
|
||||
public abstract void updateLastCheck(String auid) throws SQLException; |
||||
|
||||
public final void updateLastCheck(ScheduleAssociation scheduleAssociation) throws SQLException{ |
||||
updateLastCheck(scheduleAssociation.getAuid()); |
||||
} |
||||
|
||||
public abstract ReplaceResult replace(ScheduleAssociation scheduleAssociation) throws SQLException; |
||||
|
||||
public abstract int getHashCode(String auid) throws SQLException; |
||||
|
||||
public final int getHashCode(ScheduleAssociation scheduleAssociation) throws SQLException{ |
||||
return getHashCode(scheduleAssociation.getAuid()); |
||||
} |
||||
|
||||
public void insertAll(Collection<ScheduleAssociation> scheduleAssociations) throws SQLException{ |
||||
for(ScheduleAssociation scheduleAssociation:scheduleAssociations){ |
||||
insert(scheduleAssociation); |
||||
} |
||||
} |
||||
|
||||
public void updateAll(Collection<ScheduleAssociation> scheduleAssociations) throws SQLException{ |
||||
for (ScheduleAssociation scheduleAssociation:scheduleAssociations){ |
||||
update(scheduleAssociation); |
||||
} |
||||
} |
||||
|
||||
public void updateAllLastCheck(Collection<ScheduleAssociation> scheduleAssociations) throws SQLException{ |
||||
for (ScheduleAssociation scheduleAssociation:scheduleAssociations){ |
||||
updateLastCheck(scheduleAssociation); |
||||
} |
||||
} |
||||
|
||||
public void replaceAll(Collection<ScheduleAssociation> scheduleAssociations) throws SQLException{ |
||||
for (ScheduleAssociation scheduleAssociation:scheduleAssociations){ |
||||
replace(scheduleAssociation); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,379 @@
|
||||
package org.leolo.nrdatad.db.mariadb; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.leolo.nrdatad.db.DatabaseManager; |
||||
import org.leolo.nrdatad.db.ParameterStore; |
||||
import org.leolo.nrdatad.db.SearchMode; |
||||
import org.leolo.nrdatad.model.Corpus; |
||||
|
||||
import java.sql.*; |
||||
import java.util.*; |
||||
|
||||
public class CorpusDaoImpl extends org.leolo.nrdatad.db.CorpusDao { |
||||
|
||||
Logger log = LogManager.getLogger(); |
||||
|
||||
public CorpusDaoImpl(DatabaseManager manager) { |
||||
super(manager); |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Corpus> executeQuery(org.leolo.nrdatad.db.CorpusDao.Query query) throws SQLException { |
||||
Vector<Corpus> corpuses = new Vector<>(); |
||||
ParameterStore params = new ParameterStore(); |
||||
StringBuilder sql = new StringBuilder(); |
||||
if(query.getSearchMode()== SearchMode.MATCH_ALL_GROUP || query.getSearchMode()==SearchMode.MATCH_ANY){ |
||||
sql.append("SELECT * FROM corpus WHERE "); |
||||
String keyWord; |
||||
if(query.getSearchMode() == SearchMode.MATCH_ALL_GROUP){ |
||||
sql.append("1=1 "); |
||||
keyWord = "AND "; |
||||
}else{ |
||||
sql.append("1=0 "); |
||||
keyWord = "OR "; |
||||
} |
||||
if(query.getStanox().size()>0){ |
||||
sql.append(keyWord).append("stanox IN (") |
||||
.append(getQueryParams(query.getStanox().size())).append(") "); |
||||
params.addAll(query.getStanox()); |
||||
} |
||||
if(query.getUicCode().size()>0){ |
||||
sql.append(keyWord).append("uic_code IN (") |
||||
.append(getQueryParams(query.getUicCode().size())).append(") "); |
||||
params.addAll(query.getUicCode()); |
||||
} |
||||
if(query.getCrsCode().size()>0){ |
||||
sql.append(keyWord).append("crs_code IN (") |
||||
.append(getQueryParams(query.getCrsCode().size())).append(") "); |
||||
params.addAll(query.getCrsCode()); |
||||
} |
||||
if(query.getTiplocCode().size()>0){ |
||||
sql.append(keyWord).append("tiploc_code IN (") |
||||
.append(getQueryParams(query.getTiplocCode().size())).append(") "); |
||||
params.addAll(query.getTiplocCode()); |
||||
} |
||||
if(query.getNlcCode().size()>0){ |
||||
sql.append(keyWord).append("nlc_code IN(") |
||||
.append(getQueryParams(query.getNlcCode().size())).append(") "); |
||||
params.addAll(query.getNlcCode()); |
||||
} |
||||
if(query.getDescription().size()>0){ |
||||
sql.append(keyWord).append("("); |
||||
boolean hasDesc = false; |
||||
for(String str:query.getDescription()){ |
||||
if(hasDesc){ |
||||
sql.append("OR "); |
||||
} |
||||
sql.append("(`desc` LIKE ? OR short_desc LIKE ? ) "); |
||||
hasDesc = true; |
||||
params.add("%"+str+"%"); |
||||
params.add("%"+str+"%"); |
||||
} |
||||
sql.append(") "); |
||||
} |
||||
log.atDebug().log("SQL={}",sql); |
||||
}else{ |
||||
log.always().log("Search mode {} is yet to be implemented.", query.getSearchMode()); |
||||
} |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement(sql.toString()) |
||||
){ |
||||
for(int i=1;i<=params.size();i++){ |
||||
log.atDebug().log("Param {} = {}", i, params.get(i)); |
||||
setString(pstmt, i, params.get(i)); |
||||
} |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
while(rs.next()){ |
||||
corpuses.add(parseCORPUS(rs)); |
||||
} |
||||
} |
||||
} |
||||
return corpuses; |
||||
} |
||||
|
||||
@Override |
||||
public void add(@NotNull Corpus corpus) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement( |
||||
"INSERT INTO corpus (stanox, uic_code, crs_code, tiploc_code, nlc_code, `desc`, short_desc) " + |
||||
"VALUES (?,?,?,?,?,?,?)") |
||||
){ |
||||
setString(pstmt, 1, corpus.getStanoxCode()); |
||||
setString(pstmt, 2, corpus.getUicCode()); |
||||
setString(pstmt, 3, corpus.getCrsCode()); |
||||
setString(pstmt, 4, corpus.getTiplocCode()); |
||||
setString(pstmt, 5, corpus.getNlcCode()); |
||||
setString(pstmt, 6, corpus.getLongDescription()); |
||||
setString(pstmt, 7, corpus.getShortDescription()); |
||||
pstmt.executeUpdate(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void addAll(@NotNull Collection<Corpus> datas) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement( |
||||
"INSERT INTO corpus (stanox, uic_code, crs_code, tiploc_code, nlc_code, `desc`, short_desc) " + |
||||
"VALUES (?,?,?,?,?,?,?)") |
||||
){ |
||||
for(Corpus corpus:datas) { |
||||
setString(pstmt, 1, corpus.getStanoxCode()); |
||||
setString(pstmt, 2, corpus.getUicCode()); |
||||
setString(pstmt, 3, corpus.getCrsCode()); |
||||
setString(pstmt, 4, corpus.getTiplocCode()); |
||||
setString(pstmt, 5, corpus.getNlcCode()); |
||||
setString(pstmt, 6, corpus.getLongDescription()); |
||||
setString(pstmt, 7, corpus.getShortDescription()); |
||||
pstmt.addBatch(); |
||||
} |
||||
pstmt.executeBatch(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void replaceAll(@NotNull Collection<Corpus> datas) throws SQLException { |
||||
int totalCount = 0, insertCount = 0, updateCount = 0; |
||||
HashSet<String> pendingInsert = new HashSet<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement psIns = conn.prepareStatement( |
||||
"INSERT INTO corpus (stanox, uic_code, crs_code, tiploc_code, `desc`, short_desc, nlc_code) " + |
||||
"VALUES (?,?,?,?,?,?,?)"); |
||||
PreparedStatement psUpd = conn.prepareStatement( |
||||
"UPDATE corpus " + |
||||
"SET stanox=?, uic_code=?, crs_code=?, tiploc_code=?, `desc`=?, short_desc=? " + |
||||
"WHERE nlc_code = ?" |
||||
) |
||||
){ |
||||
for(Corpus corpus:datas){ |
||||
totalCount++; |
||||
Corpus existing = searchCORPUSByNlcCode(corpus.getNlcCode()); |
||||
PreparedStatement stmt = null; |
||||
if(corpus.equals(existing)){ |
||||
continue; |
||||
}else if(existing==null){ |
||||
if(pendingInsert.contains(corpus.getNlcCode())){ |
||||
continue; |
||||
} |
||||
pendingInsert.add(corpus.getNlcCode()); |
||||
stmt = psIns; |
||||
insertCount++; |
||||
}else{ |
||||
stmt = psUpd; |
||||
updateCount++; |
||||
} |
||||
setString(stmt, 1, corpus.getStanoxCode()); |
||||
setString(stmt, 2, corpus.getUicCode()); |
||||
setString(stmt, 3, corpus.getCrsCode()); |
||||
setString(stmt, 4, corpus.getTiplocCode()); |
||||
setString(stmt, 5, corpus.getLongDescription()); |
||||
setString(stmt, 6, corpus.getShortDescription()); |
||||
setString(stmt, 7, corpus.getNlcCode()); |
||||
stmt.addBatch(); |
||||
} |
||||
if(insertCount>0){ |
||||
psIns.executeBatch(); |
||||
log.atInfo().log("Inserted {} CORPUS records", insertCount); |
||||
} |
||||
if(updateCount>0){ |
||||
psUpd.executeBatch(); |
||||
log.atInfo().log("Updated {} CORPUS records", updateCount); |
||||
} |
||||
if(insertCount==0 && updateCount==0){ |
||||
log.atInfo().log("CORPUS data already up to date. "); |
||||
}else{ |
||||
conn.commit(); |
||||
log.atInfo().log("Done committing CORPUS data"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void truncateTable() throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
Statement stmt = conn.createStatement() |
||||
){ |
||||
stmt.executeQuery("TRUNCATE TABLE corpus"); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean hasNlcCode(String nlcCode) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT 1 FROM corpus WHERE nlc_code = ?") |
||||
){ |
||||
pstmt.setString(1, nlcCode); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
return rs.next(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void update(Corpus corpus) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement( |
||||
"UPDATE corpus " + |
||||
"SET stanox=?, uic_code=?, crs_code=?, tiploc_code=?, `desc`=?, short_desc=? " + |
||||
"WHERE nlc_code = ?" |
||||
) |
||||
){ |
||||
setString(pstmt, 1, corpus.getStanoxCode()); |
||||
setString(pstmt, 2, corpus.getUicCode()); |
||||
setString(pstmt, 3, corpus.getCrsCode()); |
||||
setString(pstmt, 4, corpus.getTiplocCode()); |
||||
setString(pstmt, 5, corpus.getLongDescription()); |
||||
setString(pstmt, 6, corpus.getShortDescription()); |
||||
setString(pstmt, 7, corpus.getNlcCode()); |
||||
pstmt.executeUpdate(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Corpus> searchCORPUSByStanoxCode(String stanoxCode) throws SQLException { |
||||
Collection<Corpus> corpuses = new Vector<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM corpus WHERE stanox = ?") |
||||
){ |
||||
pstmt.setString(1, stanoxCode); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
while(rs.next()){ |
||||
corpuses.add(parseCORPUS(rs)); |
||||
} |
||||
} |
||||
} |
||||
return corpuses; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Corpus> searchCORPUSByUicCode(String uicCode) throws SQLException { |
||||
Collection<Corpus> corpuses = new Vector<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM corpus WHERE uic_code = ?") |
||||
){ |
||||
pstmt.setString(1, uicCode); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
while(rs.next()){ |
||||
corpuses.add(parseCORPUS(rs)); |
||||
} |
||||
} |
||||
} |
||||
return corpuses; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Corpus> searchCORPUSByCrsCode(String crsCode) throws SQLException { |
||||
Collection<Corpus> corpuses = new Vector<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM corpus WHERE crs_code = ?") |
||||
){ |
||||
pstmt.setString(1, crsCode); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
while(rs.next()){ |
||||
corpuses.add(parseCORPUS(rs)); |
||||
} |
||||
} |
||||
} |
||||
return corpuses; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Corpus> searchCORPUSByTiplocCode(String tiplocCode) throws SQLException { |
||||
Collection<Corpus> corpuses = new Vector<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM corpus WHERE tiploc_code = ?") |
||||
){ |
||||
pstmt.setString(1, tiplocCode); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
while(rs.next()){ |
||||
corpuses.add(parseCORPUS(rs)); |
||||
} |
||||
} |
||||
} |
||||
return corpuses; |
||||
} |
||||
|
||||
@Override |
||||
public Corpus searchCORPUSByNlcCode(String nlcCode) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM corpus WHERE nlc_code = ?") |
||||
){ |
||||
pstmt.setString(1, nlcCode); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
if(rs.next()){ |
||||
return parseCORPUS(rs); |
||||
} |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public List<Corpus> searchCORPUSByName(String name) throws SQLException { |
||||
|
||||
List<Corpus> corpuses = new Vector<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement( |
||||
"SELECT * FROM corpus WHERE " + |
||||
"match(`desc`) against (?) OR " + |
||||
"match(short_desc) against (?) " + |
||||
"ORDER BY match(`desc`) against (?)+match(short_desc) against (?)" |
||||
) |
||||
){ |
||||
pstmt.setString(1, name); |
||||
pstmt.setString(2, name); |
||||
pstmt.setString(3, name); |
||||
pstmt.setString(4, name); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
while(rs.next()){ |
||||
corpuses.add(parseCORPUS(rs)); |
||||
} |
||||
} |
||||
} |
||||
return corpuses; |
||||
} |
||||
|
||||
private Corpus parseCORPUS(ResultSet rs) throws SQLException{ |
||||
Corpus corpus = new Corpus(); |
||||
corpus.setStanoxCode(rs.getString("stanox")); |
||||
corpus.setUicCode(rs.getString("uic_code")); |
||||
corpus.setCrsCode(rs.getString("crs_code")); |
||||
corpus.setTiplocCode(rs.getString("tiploc_code")); |
||||
corpus.setNlcCode(rs.getString("nlc_code")); |
||||
corpus.setLongDescription(rs.getString("desc")); |
||||
corpus.setShortDescription(rs.getString("short_desc")); |
||||
return corpus; |
||||
} |
||||
|
||||
@Override |
||||
public Corpus delete(String nlcCode) throws SQLException { |
||||
Corpus deletedEntry = searchCORPUSByNlcCode(nlcCode); |
||||
if(deletedEntry!=null){ |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement stmt = conn.prepareStatement("DELETE FROM corpus WHERE nlc_code = ?") |
||||
){ |
||||
stmt.setString(1, nlcCode); |
||||
stmt.executeUpdate(); |
||||
} |
||||
} |
||||
return deletedEntry; |
||||
} |
||||
} |
||||
@ -0,0 +1,88 @@
|
||||
package org.leolo.nrdatad.db.mariadb; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.leolo.nrdatad.ConfigurationManager; |
||||
import org.leolo.nrdatad.db.*; |
||||
import org.mariadb.jdbc.MariaDbPoolDataSource; |
||||
|
||||
import java.sql.*; |
||||
|
||||
public class DatabaseManager implements org.leolo.nrdatad.db.DatabaseManager{ |
||||
Logger logger = LogManager.getLogger(); |
||||
private MariaDbPoolDataSource ds; |
||||
@Override |
||||
public void initPool() { |
||||
logger.atDebug().log("Start initialize the database pool"); |
||||
ConfigurationManager conf = ConfigurationManager.getInstance(); |
||||
if( |
||||
!conf.containsKey("db.host")|| |
||||
!conf.containsKey("db.user")|| |
||||
!conf.containsKey("db.pwd")|| |
||||
!conf.containsKey("db.name") |
||||
) { |
||||
logger.atFatal().log("Missing required property"); |
||||
System.exit(1); |
||||
return; |
||||
} |
||||
String url = "jdbc:mariadb://"+conf.getProperty("db.host")+ |
||||
":"+conf.getProperty("db.port", "3306")+ |
||||
"/"+conf.getProperty("db.name"); |
||||
logger.atDebug().log("URL={}",url); |
||||
try { |
||||
ds = new MariaDbPoolDataSource(url); |
||||
// ds.setMinPoolSize(1);
|
||||
// ds.setMaxPoolSize(Integer.parseInt(conf.getOrDefault("db.poolsize", "20").toString()));
|
||||
ds.setUser(conf.getProperty("db.user").toString()); |
||||
ds.setPassword(conf.getProperty("db.pwd").toString()); |
||||
} catch (SQLException e) { |
||||
logger.atFatal().withThrowable(e).log("Cannot connect to DB"); |
||||
System.exit(-2); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean checkConnection() { |
||||
try( |
||||
Connection conn = ds.getConnection(); |
||||
Statement stmt = conn.createStatement(); |
||||
ResultSet rs = stmt.executeQuery("SELECT 1") |
||||
){ |
||||
return rs.next(); |
||||
}catch(SQLException e){ |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Connection getConnection() throws SQLException{ |
||||
Connection conn = ds.getConnection(); |
||||
conn.setAutoCommit(false); |
||||
return conn; |
||||
} |
||||
|
||||
@Override |
||||
public MetadataDao getMetadataDao() { |
||||
return new MetadataDaoImpl(this); |
||||
} |
||||
|
||||
@Override |
||||
public CorpusDao getCORPUSDao() { |
||||
return new CorpusDaoImpl(this); |
||||
} |
||||
|
||||
@Override |
||||
public SmartDao getSmartDao() { |
||||
return new SmartDaoImpl(this); |
||||
} |
||||
|
||||
@Override |
||||
public TiplocDao getTiplocDao() { |
||||
return new TiplocDaoImpl(this); |
||||
} |
||||
|
||||
@Override |
||||
public TrainAssociationDao getTrainAssociationDao() { |
||||
return new TrainAssociationDaoImpl(this); |
||||
} |
||||
} |
||||
@ -0,0 +1,116 @@
|
||||
package org.leolo.nrdatad.db.mariadb; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
|
||||
import java.sql.*; |
||||
import java.util.HashSet; |
||||
import java.util.Set; |
||||
import java.util.TreeMap; |
||||
import java.util.function.BiConsumer; |
||||
|
||||
public class MetadataDaoImpl extends org.leolo.nrdatad.db.MetadataDao { |
||||
|
||||
private static Object SYNC_TOKEN = new Object(); |
||||
|
||||
public MetadataDaoImpl(DatabaseManager manager){ |
||||
super(manager); |
||||
} |
||||
|
||||
@Override |
||||
public String getMetadata(String key, String defaultValue) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT value FROM metadata WHERE `key` = ?") |
||||
){ |
||||
pstmt.setString(1, key); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
if(rs.next()){ |
||||
return rs.getString(1); |
||||
} |
||||
} |
||||
} |
||||
return defaultValue; |
||||
} |
||||
|
||||
@Override |
||||
public void updateMetadata(@NotNull String key, @NotNull String value) throws SQLException { |
||||
synchronized (SYNC_TOKEN) { |
||||
if (containsKey(key)) { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("UPDATE metadata SET value = ? WHERE `key` = ?") |
||||
){ |
||||
pstmt.setString(1, value); |
||||
pstmt.setString(2, key); |
||||
pstmt.executeUpdate(); |
||||
} |
||||
} else { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO metadata (`key`, value) VALUES (?,?)") |
||||
){ |
||||
pstmt.setString(1, key); |
||||
pstmt.setString(2, value); |
||||
pstmt.executeUpdate(); |
||||
|
||||
} |
||||
|
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> getKeys() throws SQLException { |
||||
HashSet<String> set = new HashSet<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
Statement stmt = conn.createStatement(); |
||||
ResultSet rs = stmt.executeQuery("SELECT `key` FROM metadata") |
||||
){ |
||||
while(rs.next()){ |
||||
set.add(rs.getString(1)); |
||||
} |
||||
} |
||||
return set; |
||||
} |
||||
|
||||
@Override |
||||
public void forEach(BiConsumer<String, String> action) throws SQLException { |
||||
TreeMap<String, String> map = new TreeMap<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
Statement stmt = conn.createStatement(); |
||||
ResultSet rs = stmt.executeQuery("SELECT `key`, value FROM metadata") |
||||
){ |
||||
while(rs.next()){ |
||||
map.put(rs.getString(1), rs.getString(2)); |
||||
} |
||||
} |
||||
map.forEach(action); |
||||
} |
||||
|
||||
@Override |
||||
public boolean containsKey(String key) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT 1 FROM metadata WHERE `key` = ?") |
||||
){ |
||||
pstmt.setString(1, key); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
return rs.next(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public int entryCount() throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
Statement stmt = conn.createStatement(); |
||||
ResultSet rs = stmt.executeQuery("SELECT COUNT(1) FROM metadata") |
||||
){ |
||||
rs.next(); |
||||
return rs.getInt(1); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,322 @@
|
||||
package org.leolo.nrdatad.db.mariadb; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.leolo.nrdatad.db.DatabaseManager; |
||||
import org.leolo.nrdatad.db.ParameterStore; |
||||
import org.leolo.nrdatad.db.SearchMode; |
||||
import org.leolo.nrdatad.model.Smart; |
||||
import org.leolo.nrdatad.model.SmartEvent; |
||||
import org.leolo.nrdatad.model.SmartStepType; |
||||
import org.leolo.nrdatad.util.Range; |
||||
|
||||
import java.sql.*; |
||||
import java.util.Collection; |
||||
import java.util.Vector; |
||||
|
||||
public class SmartDaoImpl extends org.leolo.nrdatad.db.SmartDao { |
||||
Logger log = LogManager.getLogger(); |
||||
|
||||
public SmartDaoImpl(DatabaseManager manager) { |
||||
super(manager); |
||||
} |
||||
|
||||
@Override |
||||
public void add(Smart smart) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement( |
||||
"INSERT INTO smart (" + |
||||
"td, from_berth, to_berth, from_line, to_line, breth_offset, platform, event, route, " + |
||||
"stanox, station_name, step_type, comment" + |
||||
") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)") |
||||
){ |
||||
setString(pstmt, 1, smart.getTd()); |
||||
setString(pstmt, 2, smart.getFromBerth()); |
||||
setString(pstmt, 3, smart.getToBerth()); |
||||
setString(pstmt, 4, smart.getFromLine()); |
||||
setString(pstmt, 5, smart.getToLine()); |
||||
setInt (pstmt, 6, smart.getBerthOffset()); |
||||
setString(pstmt, 7, smart.getPlatform()); |
||||
setString(pstmt, 8, smart.getEvent().getCode()); |
||||
setString(pstmt, 9, smart.getRoute()); |
||||
setString(pstmt, 10, smart.getStanox()); |
||||
setString(pstmt, 11, smart.getStationName()); |
||||
setString(pstmt, 12, smart.getStepType().getCode()); |
||||
setString(pstmt, 13, smart.getComment()); |
||||
pstmt.executeUpdate(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void addAll(Collection<Smart> smarts) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement( |
||||
"INSERT INTO smart (" + |
||||
"td, from_berth, to_berth, from_line, to_line, breth_offset, platform, event, route, " + |
||||
"stanox, station_name, step_type, comment" + |
||||
") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)") |
||||
){ |
||||
for(Smart smart:smarts){ |
||||
setString(pstmt, 1, smart.getTd()); |
||||
setString(pstmt, 2, smart.getFromBerth()); |
||||
setString(pstmt, 3, smart.getToBerth()); |
||||
setString(pstmt, 4, smart.getFromLine()); |
||||
setString(pstmt, 5, smart.getToLine()); |
||||
setInt (pstmt, 6, smart.getBerthOffset()); |
||||
setString(pstmt, 7, smart.getPlatform()); |
||||
setString(pstmt, 8, smart.getEvent().getCode()); |
||||
setString(pstmt, 9, smart.getRoute()); |
||||
setString(pstmt, 10, smart.getStanox()); |
||||
setString(pstmt, 11, smart.getStationName()); |
||||
setString(pstmt, 12, smart.getStepType().getCode()); |
||||
setString(pstmt, 13, smart.getComment()); |
||||
pstmt.addBatch(); |
||||
} |
||||
pstmt.executeBatch(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void truncateTable() throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
Statement stmt = conn.createStatement() |
||||
){ |
||||
stmt.executeUpdate("TRUNCATE TABLE smart"); |
||||
} |
||||
} |
||||
|
||||
private Smart parseResultSet(ResultSet rs) throws SQLException{ |
||||
Smart smart = new Smart(); |
||||
smart.setSmartId(rs.getInt("smart_id")); |
||||
smart.setTd(rs.getString("td")); |
||||
smart.setFromBerth(rs.getString("from_berth")); |
||||
smart.setToBerth(rs.getString("to_berth")); |
||||
smart.setFromLine(rs.getString("from_line")); |
||||
smart.setToLine(rs.getString("to_line")); |
||||
smart.setBerthOffset(rs.getInt("berth_offset")); |
||||
smart.setPlatform(rs.getString("platform")); |
||||
smart.setEvent(SmartEvent.parseCode(rs.getString("event"))); |
||||
smart.setRoute(rs.getString("route")); |
||||
smart.setStanox(rs.getString("stanox")); |
||||
smart.setStationName(rs.getString("station_name")); |
||||
smart.setStepType(SmartStepType.parseCode(rs.getString("step_type"))); |
||||
smart.setComment(rs.getString("comment")); |
||||
return smart; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Smart> searchSmartByBerth(String fromBerth, String toBerth) throws SQLException { |
||||
Vector<Smart> vector = new Vector<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM smart WHERE from_berth = ? AND to_berth = ?"); |
||||
){ |
||||
pstmt.setString(1, fromBerth); |
||||
pstmt.setString(2, toBerth); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
vector.add(parseResultSet(rs)); |
||||
} |
||||
} |
||||
return vector; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Smart> searchFromByBerth(String fromBerth) throws SQLException { |
||||
Vector<Smart> vector = new Vector<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM smart WHERE from_berth =?"); |
||||
){ |
||||
pstmt.setString(1, fromBerth); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
vector.add(parseResultSet(rs)); |
||||
} |
||||
} |
||||
return vector; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Smart> searchToBerth(String toBerth) throws SQLException {Vector<Smart> vector = new Vector<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM smart WHERE to_berth = ?"); |
||||
){ |
||||
pstmt.setString(1, toBerth); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
vector.add(parseResultSet(rs)); |
||||
} |
||||
} |
||||
return vector; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Smart> searchSmartByBerthLine(String fromBerth, String toBerth, String fromLine, String toLine) throws SQLException { |
||||
Vector<Smart> vector = new Vector<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement( |
||||
"SELECT * FROM smart WHERE from_berth = ? AND to_berth = ? AND from_line = ? AND to_line = ?"); |
||||
){ |
||||
pstmt.setString(1, fromBerth); |
||||
pstmt.setString(2, toBerth); |
||||
pstmt.setString(3, fromLine); |
||||
pstmt.setString(4, toLine); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
vector.add(parseResultSet(rs)); |
||||
} |
||||
} |
||||
return vector; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Smart> searchSmartByFromBerthLine(String fromBerth, String fromLine) throws SQLException { |
||||
Vector<Smart> vector = new Vector<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement( |
||||
"SELECT * FROM smart WHERE from_berth = ? AND to_berth = ? AND from_line = ? AND to_line = ?"); |
||||
){ |
||||
pstmt.setString(1, fromBerth); |
||||
pstmt.setString(2, fromLine); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
vector.add(parseResultSet(rs)); |
||||
} |
||||
} |
||||
return vector; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Smart> searchSmartByToBerthLine(String toBerth, String toLine) throws SQLException { |
||||
Vector<Smart> vector = new Vector<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement( |
||||
"SELECT * FROM smart WHERE from_berth = ? AND to_berth = ? AND from_line = ? AND to_line = ?"); |
||||
){ |
||||
pstmt.setString(1, toBerth); |
||||
pstmt.setString(2, toLine); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
vector.add(parseResultSet(rs)); |
||||
} |
||||
} |
||||
return vector; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Smart> searchSmartByStanox(String stanox) throws SQLException {Vector<Smart> vector = new Vector<>(); |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement( |
||||
"SELECT * FROM smart WHERE stanox = ?"); |
||||
){ |
||||
pstmt.setString(1, stanox); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
vector.add(parseResultSet(rs)); |
||||
} |
||||
} |
||||
return vector; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Smart> executeQuery(Query query) throws SQLException { |
||||
Vector<Smart> smarts = new Vector<>(); |
||||
ParameterStore ps = new ParameterStore(); |
||||
StringBuilder sql = new StringBuilder(); |
||||
if(query.getSearchMode()== SearchMode.MATCH_ALL_GROUP || query.getSearchMode()==SearchMode.MATCH_ANY){ |
||||
sql.append("SELECT * FROM smart WHERE "); |
||||
String keyWord; |
||||
if(query.getSearchMode() == SearchMode.MATCH_ALL_GROUP){ |
||||
sql.append("1=1 "); |
||||
keyWord = "AND "; |
||||
}else{ |
||||
sql.append("1=0 "); |
||||
keyWord = "OR "; |
||||
} |
||||
if(query.getTd().size()>0){ |
||||
sql.append(keyWord).append("td IN (").append(getQueryParams(query.getTd().size())).append(") "); |
||||
ps.addAll(query.getTd()); |
||||
} |
||||
if(query.getFromBerth().size()>0){ |
||||
sql.append(keyWord).append("from_berth IN(").append(getQueryParams(query.getFromBerth().size())).append(") "); |
||||
ps.addAll(query.getFromBerth()); |
||||
} |
||||
if(query.getToBerth().size()>0){ |
||||
sql.append(keyWord).append("to_berth IN(").append(getQueryParams(query.getToBerth().size())).append(") "); |
||||
ps.addAll(query.getToBerth()); |
||||
} |
||||
if(query.getFromLine().size()>0){ |
||||
sql.append(keyWord).append("from_line IN(").append(getQueryParams(query.getFromLine().size())).append(") "); |
||||
ps.addAll(query.getFromLine()); |
||||
} |
||||
if (query.getToLine().size()>0){ |
||||
sql.append(keyWord).append("to_line (").append(getQueryParams(query.getToLine().size())).append(") "); |
||||
ps.addAll(query.getToLine()); |
||||
} |
||||
if (query.getBerthOffset().size()>0){ |
||||
sql.append(keyWord).append("(1=0 "); |
||||
for(Range<Integer> range: query.getBerthOffset()){ |
||||
sql.append("OR (berth_offset BETWEEN ? AND ?) "); |
||||
ps.addObject(range.getLowerBound()); |
||||
ps.addObject(range.getUpperBound()); |
||||
} |
||||
sql.append(") "); |
||||
} |
||||
if(query.getPlatform().size()>0){ |
||||
sql.append(keyWord).append("platform IN(").append(getQueryParams(query.getPlatform().size())).append(") "); |
||||
ps.addAll(query.getPlatform()); |
||||
} |
||||
if(query.getEvent().size()>0){ |
||||
sql.append(keyWord).append("event IN(").append(getQueryParams(query.getEvent().size())).append(") "); |
||||
ps.addAllObject(query.getEvent()); |
||||
} |
||||
if(query.getRoute().size()>0){ |
||||
sql.append(keyWord).append("route IN(").append(getQueryParams(query.getRoute().size())).append(") "); |
||||
ps.addAll(query.getRoute()); |
||||
} |
||||
if(query.getStanox().size()>0){ |
||||
sql.append(keyWord).append("stanox IN(").append(getQueryParams(query.getStanox().size())).append(") "); |
||||
ps.addAll(query.getStanox()); |
||||
} |
||||
if(query.getStationName().size()>0){ |
||||
sql.append(keyWord).append("(1=0 "); |
||||
for(String stationName: query.getStationName()){ |
||||
sql.append("OR station_name LIKE ? "); |
||||
ps.add("%"+stationName+"%"); |
||||
} |
||||
sql.append(") "); |
||||
} |
||||
if(query.getStepType().size()>0){ |
||||
sql.append(keyWord).append("step_type IN(").append(getQueryParams(query.getStepType().size())).append(") "); |
||||
ps.addAllObject(query.getStepType()); |
||||
} |
||||
if(query.getComment().size()>0){ |
||||
sql.append(keyWord).append("(1=0 "); |
||||
for(String comment: query.getComment()){ |
||||
sql.append("OR comment LIKE ? "); |
||||
ps.add("%"+comment+"%"); |
||||
} |
||||
sql.append(") "); |
||||
} |
||||
} |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement(sql.toString()) |
||||
){ |
||||
for(int i=1;i<=ps.size();i++){ |
||||
log.atDebug().log("Param {} = {}", i, ps.get(i)); |
||||
setString(pstmt, i, ps.get(i)); |
||||
} |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
while(rs.next()){ |
||||
smarts.add(parseResultSet(rs)); |
||||
} |
||||
} |
||||
} |
||||
return smarts; |
||||
} |
||||
} |
||||
@ -0,0 +1,131 @@
|
||||
package org.leolo.nrdatad.db.mariadb; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.leolo.nrdatad.db.DatabaseManager; |
||||
import org.leolo.nrdatad.db.TiplocDao; |
||||
import org.leolo.nrdatad.model.Tiploc; |
||||
|
||||
import java.sql.*; |
||||
import java.util.Collection; |
||||
|
||||
public class TiplocDaoImpl extends TiplocDao { |
||||
|
||||
private Logger log = LogManager.getLogger(); |
||||
|
||||
public TiplocDaoImpl(DatabaseManager manager) { |
||||
super(manager); |
||||
} |
||||
|
||||
@Override |
||||
public void insert(Tiploc tiploc) throws SQLException { |
||||
try ( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO tiploc (tiploc_code, nalco, stanox, crs_code, description, tps_description) VALUES (?,?,?,?,?,?)") |
||||
) { |
||||
setString(pstmt, 1, tiploc.getTiplocCode()); |
||||
setString(pstmt, 2, tiploc.getNalco()); |
||||
setString(pstmt, 3, tiploc.getStanox()); |
||||
setString(pstmt, 4, tiploc.getCrsCode()); |
||||
setString(pstmt, 5, tiploc.getDescription()); |
||||
setString(pstmt, 6, tiploc.getTpsDescription()); |
||||
pstmt.executeUpdate(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void insertAll(Collection<Tiploc> tiplocs) throws SQLException { |
||||
try ( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO tiploc (tiploc_code, nalco, stanox, crs_code, description, tps_description) VALUES (?,?,?,?,?,?)") |
||||
) { |
||||
for(Tiploc tiploc:tiplocs) { |
||||
setString(pstmt, 1, tiploc.getTiplocCode()); |
||||
setString(pstmt, 2, tiploc.getNalco()); |
||||
setString(pstmt, 3, tiploc.getStanox()); |
||||
setString(pstmt, 4, tiploc.getCrsCode()); |
||||
setString(pstmt, 5, tiploc.getDescription()); |
||||
setString(pstmt, 6, tiploc.getTpsDescription()); |
||||
pstmt.addBatch(); |
||||
} |
||||
pstmt.executeBatch(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void replaceAll(Collection<Tiploc> tiplocs) throws SQLException { |
||||
try ( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement psIns = conn.prepareStatement("INSERT INTO tiploc (tiploc_code, nalco, stanox, crs_code, description, tps_description) VALUES (?,?,?,?,?,?)"); |
||||
PreparedStatement psUpd = conn.prepareStatement("UPDATE tiploc SET nalco=?, stanox=?, crs_code=?, description=?, tps_description=? WHERE tiploc_code=?") |
||||
) { |
||||
for(Tiploc tiploc:tiplocs) { |
||||
if(hasTiploc(tiploc.getTiplocCode())){ |
||||
setString(psUpd, 1, tiploc.getNalco()); |
||||
setString(psUpd, 2, tiploc.getStanox()); |
||||
setString(psUpd, 3, tiploc.getCrsCode()); |
||||
setString(psUpd, 4, tiploc.getDescription()); |
||||
setString(psUpd, 5, tiploc.getTpsDescription()); |
||||
setString(psUpd, 6, tiploc.getTiplocCode()); |
||||
psUpd.addBatch(); |
||||
|
||||
} else { |
||||
setString(psIns, 1, tiploc.getTiplocCode()); |
||||
setString(psIns, 2, tiploc.getNalco()); |
||||
setString(psIns, 3, tiploc.getStanox()); |
||||
setString(psIns, 4, tiploc.getCrsCode()); |
||||
setString(psIns, 5, tiploc.getDescription()); |
||||
setString(psIns, 6, tiploc.getTpsDescription()); |
||||
psIns.addBatch(); |
||||
} |
||||
} |
||||
psIns.executeBatch(); |
||||
psUpd.executeBatch(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean hasTiploc(String tiplocCode) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT 1 FROM tiploc WHERE tiploc_code = ?") |
||||
){ |
||||
pstmt.setString(1, tiplocCode); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
return rs.next(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void update(Tiploc tiploc) throws SQLException { |
||||
try ( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("UPDATE tiploc SET nalco=?, stanox=?, crs_code=?, description=?, tps_description=? WHERE tiploc_code=?") |
||||
) { |
||||
setString(pstmt, 1, tiploc.getNalco()); |
||||
setString(pstmt, 2, tiploc.getStanox()); |
||||
setString(pstmt, 3, tiploc.getCrsCode()); |
||||
setString(pstmt, 4, tiploc.getDescription()); |
||||
setString(pstmt, 5, tiploc.getTpsDescription()); |
||||
setString(pstmt, 6, tiploc.getTiplocCode()); |
||||
pstmt.executeUpdate(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void truncateTable() throws SQLException{ |
||||
try( |
||||
Connection conn = getConnection(); |
||||
Statement stmt = conn.createStatement() |
||||
){ |
||||
log.atInfo().log("Truncating table tiploc"); |
||||
stmt.executeQuery("TRUNCATE TABLE tiploc"); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,248 @@
|
||||
package org.leolo.nrdatad.db.mariadb; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.leolo.nrdatad.db.DatabaseManager; |
||||
import org.leolo.nrdatad.db.TrainAssociationDao; |
||||
import org.leolo.nrdatad.exception.NoSuchRecordException; |
||||
import org.leolo.nrdatad.model.ScheduleAssociation; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.util.Collection; |
||||
|
||||
public class TrainAssociationDaoImpl extends TrainAssociationDao { |
||||
|
||||
private Logger log = LogManager.getLogger(); |
||||
|
||||
public TrainAssociationDaoImpl(DatabaseManager manager) { |
||||
super(manager); |
||||
} |
||||
|
||||
@Override |
||||
public void insert(ScheduleAssociation scheduleAssociation) throws SQLException { |
||||
try ( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO train_association (" + |
||||
"auid, main_uid, asso_uid, start_date, end_date, " + //1-5
|
||||
"asso_days, asso_type, date_ind, asso_loc, base_suffix, " + //6-10
|
||||
"asso_suffix, stp_ind, hash_code, last_chk) " + //11-14
|
||||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())") |
||||
){ |
||||
fillInsertPreparedStatement(pstmt, scheduleAssociation); |
||||
pstmt.executeUpdate(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public boolean hasTrainAssociation(String auid) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT 1 FROM train_association WHERE auid = ?") |
||||
){ |
||||
setString(pstmt, 1, auid); |
||||
try(ResultSet rs = pstmt.executeQuery()){ |
||||
return rs.next(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void update(ScheduleAssociation scheduleAssociation) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("UPDATE train_association SET " + |
||||
"main_uid=?, asso_uid=?, start_date=?, end_date=?, asso_days=?," + |
||||
"asso_type=?,date_ind=?,asso_loc=?,base_suffix=?, asso_suffix=?," + |
||||
"stp_ind=?, hash_code=?,last_chk=NOW() WHERE auid=?") |
||||
){ |
||||
fillUpdatePreparedStatement(pstmt, scheduleAssociation); |
||||
pstmt.executeUpdate(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void updateLastCheck(String auid) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("UPDATE train_association SET last_chk = NOW() WHERE auid = ?") |
||||
){ |
||||
setString(pstmt,1, auid); |
||||
pstmt.executeUpdate(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public ReplaceResult replace(ScheduleAssociation scheduleAssociation) throws SQLException { |
||||
Object checkResult = _getHashCode(scheduleAssociation.getAuid()); |
||||
if(checkResult==null){ |
||||
insert(scheduleAssociation); |
||||
return ReplaceResult.INSERTED; |
||||
} else if (((int)checkResult) == scheduleAssociation.hashCode()){ |
||||
updateLastCheck(scheduleAssociation); |
||||
return ReplaceResult.NO_ACTION; |
||||
} else { |
||||
update(scheduleAssociation); |
||||
return ReplaceResult.UPDATED; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public int getHashCode(String auid) throws SQLException { |
||||
Object result = _getHashCode(auid); |
||||
if(result instanceof Integer){ |
||||
return (Integer) result; |
||||
} |
||||
throw new NoSuchRecordException(); |
||||
} |
||||
|
||||
private Object _getHashCode(String auid) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("SELECT hash_code FROM train_association WHERE auid = ?") |
||||
){ |
||||
setString(pstmt, 1, auid); |
||||
try (ResultSet rs = pstmt.executeQuery()){ |
||||
if(rs.next()){ |
||||
return rs.getInt(1); |
||||
} |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public void insertAll(Collection<ScheduleAssociation> scheduleAssociations) throws SQLException { |
||||
try ( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO train_association (" + |
||||
"auid, main_uid, asso_uid, start_date, end_date, " + //1-5
|
||||
"asso_days, asso_type, date_ind, asso_loc, base_suffix, " + //6-10
|
||||
"asso_suffix, stp_ind, hash_code, last_chk) " + //11-14
|
||||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())") |
||||
){ |
||||
for(ScheduleAssociation scheduleAssociation:scheduleAssociations) { |
||||
fillInsertPreparedStatement(pstmt, scheduleAssociation); |
||||
pstmt.addBatch(); |
||||
} |
||||
pstmt.executeBatch(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void updateAll(Collection<ScheduleAssociation> scheduleAssociations) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("UPDATE train_association SET " + |
||||
"main_uid=?, asso_uid=?, start_date=?, end_date=?, asso_days=?," + |
||||
"asso_type=?,date_ind=?,asso_loc=?,base_suffix=?, asso_suffix=?," + |
||||
"stp_ind=?, hash_code=?,last_chk=NOW() WHERE auid=?") |
||||
){ |
||||
for(ScheduleAssociation scheduleAssociation:scheduleAssociations) { |
||||
fillUpdatePreparedStatement(pstmt, scheduleAssociation); |
||||
pstmt.addBatch(); |
||||
} |
||||
pstmt.executeBatch(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
private void fillUpdatePreparedStatement(PreparedStatement pstmt, ScheduleAssociation scheduleAssociation) throws SQLException { |
||||
setString(pstmt, 1, scheduleAssociation.getMainUid()); |
||||
setString(pstmt, 2, scheduleAssociation.getAssoUid()); |
||||
setDate(pstmt, 3, scheduleAssociation.getStartDate()); |
||||
setDate(pstmt, 4, scheduleAssociation.getEndDate()); |
||||
setString(pstmt, 5, scheduleAssociation.getAssoDays()); |
||||
setString(pstmt, 6, scheduleAssociation.getAssociationCategory()==null?"":scheduleAssociation.getAssociationCategory().getCode()); |
||||
setInt(pstmt, 7, scheduleAssociation.getAssociationDate()); |
||||
setString(pstmt, 8, scheduleAssociation.getAssociationLocation()); |
||||
setString(pstmt, 9, scheduleAssociation.getBaseLocationSuffix()); |
||||
setString(pstmt, 10, scheduleAssociation.getAssocLocationSuffix()); |
||||
setString(pstmt, 11, scheduleAssociation.getStpIndicator()==null?"":scheduleAssociation.getStpIndicator().getCode()); |
||||
setInt(pstmt, 12, scheduleAssociation.hashCode()); |
||||
setString(pstmt, 13, scheduleAssociation.getAuid()); |
||||
} |
||||
|
||||
@Override |
||||
public void updateAllLastCheck(Collection<ScheduleAssociation> scheduleAssociations) throws SQLException { |
||||
try( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement pstmt = conn.prepareStatement("UPDATE train_association SET last_chk = NOW() WHERE auid = ?") |
||||
){ |
||||
for(ScheduleAssociation scheduleAssociation:scheduleAssociations) { |
||||
setString(pstmt, 1, scheduleAssociation.getAuid()); |
||||
pstmt.addBatch(); |
||||
} |
||||
pstmt.executeBatch(); |
||||
conn.commit(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void replaceAll(Collection<ScheduleAssociation> scheduleAssociations) throws SQLException { |
||||
int insCount = 0; |
||||
int updCount = 0; |
||||
int nopCount = 0; |
||||
try ( |
||||
Connection conn = getConnection(); |
||||
PreparedStatement psIns = conn.prepareStatement("INSERT IGNORE INTO train_association (" + |
||||
"auid, main_uid, asso_uid, start_date, end_date, " + //1-5
|
||||
"asso_days, asso_type, date_ind, asso_loc, base_suffix, " + //6-10
|
||||
"asso_suffix, stp_ind, hash_code, last_chk) " + //11-14
|
||||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())"); |
||||
PreparedStatement psUpd = conn.prepareStatement("UPDATE train_association SET " + |
||||
"main_uid=?, asso_uid=?, start_date=?, end_date=?, asso_days=?," + |
||||
"asso_type=?,date_ind=?,asso_loc=?,base_suffix=?, asso_suffix=?," + |
||||
"stp_ind=?, hash_code=?,last_chk=NOW() WHERE auid=?"); |
||||
|
||||
PreparedStatement psNop = conn.prepareStatement("UPDATE train_association SET last_chk = NOW() WHERE auid = ?") |
||||
){ |
||||
for(ScheduleAssociation scheduleAssociation:scheduleAssociations){ |
||||
Object checkResult = _getHashCode(scheduleAssociation.getAuid()); |
||||
if(checkResult==null){ |
||||
//Insert
|
||||
fillInsertPreparedStatement(psIns, scheduleAssociation); |
||||
psIns.addBatch(); |
||||
insCount++; |
||||
} else if (((int)checkResult) == scheduleAssociation.hashCode()){ |
||||
//NOP
|
||||
setString(psNop, 1, scheduleAssociation.getAuid()); |
||||
psNop.addBatch(); |
||||
nopCount++; |
||||
} else { |
||||
//Update
|
||||
fillUpdatePreparedStatement(psUpd, scheduleAssociation); |
||||
psUpd.addBatch(); |
||||
updCount++; |
||||
} |
||||
} |
||||
psIns.executeBatch(); |
||||
psNop.executeBatch(); |
||||
psUpd.executeBatch(); |
||||
conn.commit(); |
||||
log.atDebug().log("Batch info: {} Inserted. {} Updated. {} NOP.", insCount, updCount, nopCount); |
||||
} |
||||
} |
||||
|
||||
private void fillInsertPreparedStatement(PreparedStatement psIns, ScheduleAssociation scheduleAssociation) throws SQLException { |
||||
setString(psIns, 1, scheduleAssociation.getAuid()); |
||||
setString(psIns, 2, scheduleAssociation.getMainUid()); |
||||
setString(psIns, 3, scheduleAssociation.getAssoUid()); |
||||
setDate(psIns, 4, scheduleAssociation.getStartDate()); |
||||
setDate(psIns, 5, scheduleAssociation.getEndDate()); |
||||
setString(psIns, 6, scheduleAssociation.getAssoDays()); |
||||
setString(psIns, 7, scheduleAssociation.getAssociationCategory()==null?"":scheduleAssociation.getAssociationCategory().getCode()); |
||||
setInt(psIns, 8, scheduleAssociation.getAssociationDate()); |
||||
setString(psIns, 9, scheduleAssociation.getAssociationLocation()); |
||||
setString(psIns, 10, scheduleAssociation.getBaseLocationSuffix()); |
||||
setString(psIns, 11, scheduleAssociation.getAssocLocationSuffix()); |
||||
setString(psIns, 12, scheduleAssociation.getStpIndicator()==null?"":scheduleAssociation.getStpIndicator().getCode()); |
||||
setInt(psIns, 13, scheduleAssociation.hashCode()); |
||||
} |
||||
} |
||||
@ -0,0 +1,37 @@
|
||||
package org.leolo.nrdatad.exception; |
||||
|
||||
import java.sql.SQLException; |
||||
|
||||
public class NoSuchRecordException extends SQLException { |
||||
|
||||
public NoSuchRecordException(String reason, String SQLState, int vendorCode) { |
||||
super(reason, SQLState, vendorCode); |
||||
} |
||||
|
||||
public NoSuchRecordException(String reason, String SQLState) { |
||||
super(reason, SQLState); |
||||
} |
||||
|
||||
public NoSuchRecordException(String reason) { |
||||
super(reason); |
||||
} |
||||
|
||||
public NoSuchRecordException() { |
||||
} |
||||
|
||||
public NoSuchRecordException(Throwable cause) { |
||||
super(cause); |
||||
} |
||||
|
||||
public NoSuchRecordException(String reason, Throwable cause) { |
||||
super(reason, cause); |
||||
} |
||||
|
||||
public NoSuchRecordException(String reason, String sqlState, Throwable cause) { |
||||
super(reason, sqlState, cause); |
||||
} |
||||
|
||||
public NoSuchRecordException(String reason, String sqlState, int vendorCode, Throwable cause) { |
||||
super(reason, sqlState, vendorCode, cause); |
||||
} |
||||
} |
||||
@ -0,0 +1,27 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
public enum AssociationCategory { |
||||
JOIN("JJ"), |
||||
DIVIDE("VV"), |
||||
NEXT("NP"); |
||||
|
||||
private String code; |
||||
|
||||
private AssociationCategory(String code){ |
||||
this.code = code; |
||||
} |
||||
|
||||
public String getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public static AssociationCategory parseCode(String code){ |
||||
if(code==null) |
||||
return null; |
||||
for(AssociationCategory ac: AssociationCategory.values()){ |
||||
if(code.equalsIgnoreCase(ac.code)) |
||||
return ac; |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
@ -0,0 +1,115 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
import org.json.JSONObject; |
||||
|
||||
import java.util.Objects; |
||||
|
||||
public class Corpus { |
||||
|
||||
private String stanoxCode; |
||||
private String uicCode; |
||||
private String crsCode; |
||||
private String tiplocCode; |
||||
private String nlcCode; |
||||
|
||||
private String longDescription; |
||||
private String shortDescription; |
||||
|
||||
public String getStanoxCode() { |
||||
return stanoxCode; |
||||
} |
||||
|
||||
public void setStanoxCode(String stanoxCode) { |
||||
this.stanoxCode = stanoxCode; |
||||
} |
||||
|
||||
public String getUicCode() { |
||||
return uicCode; |
||||
} |
||||
|
||||
public void setUicCode(String uicCode) { |
||||
this.uicCode = uicCode; |
||||
} |
||||
|
||||
public String getCrsCode() { |
||||
return crsCode; |
||||
} |
||||
|
||||
public void setCrsCode(String crsCode) { |
||||
this.crsCode = crsCode; |
||||
} |
||||
|
||||
public String getTiplocCode() { |
||||
return tiplocCode; |
||||
} |
||||
|
||||
public void setTiplocCode(String tiplocCode) { |
||||
this.tiplocCode = tiplocCode; |
||||
} |
||||
|
||||
public String getNlcCode() { |
||||
return nlcCode; |
||||
} |
||||
|
||||
public void setNlcCode(String nlcCode) { |
||||
this.nlcCode = nlcCode; |
||||
} |
||||
|
||||
public String getLongDescription() { |
||||
return longDescription; |
||||
} |
||||
|
||||
public void setLongDescription(String longDescription) { |
||||
this.longDescription = longDescription; |
||||
} |
||||
|
||||
public String getShortDescription() { |
||||
return shortDescription; |
||||
} |
||||
|
||||
public void setShortDescription(String shortDescription) { |
||||
this.shortDescription = shortDescription; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object o) { |
||||
if (this == o) return true; |
||||
if (o == null || getClass() != o.getClass()) return false; |
||||
Corpus corpus = (Corpus) o; |
||||
return Objects.equals(stanoxCode, corpus.stanoxCode) && Objects.equals(uicCode, corpus.uicCode) && Objects.equals(crsCode, corpus.crsCode) && Objects.equals(tiplocCode, corpus.tiplocCode) && Objects.equals(nlcCode, corpus.nlcCode) && Objects.equals(longDescription, corpus.longDescription) && Objects.equals(shortDescription, corpus.shortDescription); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return Objects.hash(stanoxCode, uicCode, crsCode, tiplocCode, nlcCode, longDescription, shortDescription); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "CORPUS{" + |
||||
"stanoxCode='" + stanoxCode + '\'' + |
||||
", uicCode='" + uicCode + '\'' + |
||||
", crsCode='" + crsCode + '\'' + |
||||
", tiplocCode='" + tiplocCode + '\'' + |
||||
", nlcCode='" + nlcCode + '\'' + |
||||
", longDescription='" + longDescription + '\'' + |
||||
", shortDescription='" + shortDescription + '\'' + |
||||
'}'; |
||||
} |
||||
|
||||
public static Corpus parseJSON(JSONObject obj){ |
||||
Corpus corpus = new Corpus(); |
||||
corpus.setStanoxCode(obj.optString("STANOX")); |
||||
corpus.setUicCode(obj.optString("UIC")); |
||||
corpus.setCrsCode(obj.optString("3ALPHA")); |
||||
corpus.setTiplocCode(obj.optString("TIPLOC")); |
||||
corpus.setNlcCode(obj.optString("NLC")); |
||||
corpus.setLongDescription(obj.optString("NLCDESC")); |
||||
corpus.setShortDescription(obj.optString("NLCDESC16")); |
||||
return corpus; |
||||
} |
||||
|
||||
public static Corpus parseJSON(String json){ |
||||
return parseJSON(new JSONObject(json)); |
||||
} |
||||
} |
||||
@ -0,0 +1,192 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.json.JSONException; |
||||
import org.json.JSONObject; |
||||
import org.leolo.nrdatad.util.TUIDDateFormat; |
||||
|
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Date; |
||||
|
||||
public class ScheduleAssociation { |
||||
private static Logger log = LogManager.getLogger(); |
||||
|
||||
private String mainUid; |
||||
private String assoUid; |
||||
private Date startDate; |
||||
private Date endDate; |
||||
private String assoDays; |
||||
private AssociationCategory associationCategory; |
||||
private int associationDate; |
||||
private String associationLocation; |
||||
private String baseLocationSuffix; |
||||
private String assocLocationSuffix; |
||||
private ShortTermPlanningIndicator stpIndicator; |
||||
|
||||
private TUIDDateFormat tuidDateFormat = new TUIDDateFormat(); |
||||
|
||||
public String getAuid(){ |
||||
return mainUid+assoUid+associationLocation+tuidDateFormat.format(startDate)+tuidDateFormat.format(endDate)+stpIndicator.getCode(); |
||||
} |
||||
|
||||
public String getMainUid() { |
||||
return mainUid; |
||||
} |
||||
|
||||
public void setMainUid(String mainUid) { |
||||
this.mainUid = mainUid; |
||||
} |
||||
|
||||
public String getAssoUid() { |
||||
return assoUid; |
||||
} |
||||
|
||||
public void setAssoUid(String assoUid) { |
||||
this.assoUid = assoUid; |
||||
} |
||||
|
||||
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 getAssoDays() { |
||||
return assoDays; |
||||
} |
||||
|
||||
public void setAssoDays(String assoDays) { |
||||
this.assoDays = assoDays; |
||||
} |
||||
|
||||
public AssociationCategory getAssociationCategory() { |
||||
return associationCategory; |
||||
} |
||||
|
||||
public void setAssociationCategory(AssociationCategory associationCategory) { |
||||
this.associationCategory = associationCategory; |
||||
} |
||||
|
||||
public int getAssociationDate() { |
||||
return associationDate; |
||||
} |
||||
|
||||
public void setAssociationDate(int associationDate) { |
||||
this.associationDate = associationDate; |
||||
} |
||||
|
||||
public String getAssociationLocation() { |
||||
return associationLocation; |
||||
} |
||||
|
||||
public void setAssociationLocation(String associationLocation) { |
||||
this.associationLocation = associationLocation; |
||||
} |
||||
|
||||
public String getBaseLocationSuffix() { |
||||
return baseLocationSuffix; |
||||
} |
||||
|
||||
public void setBaseLocationSuffix(String baseLocationSuffix) { |
||||
this.baseLocationSuffix = baseLocationSuffix; |
||||
} |
||||
|
||||
public String getAssocLocationSuffix() { |
||||
return assocLocationSuffix; |
||||
} |
||||
|
||||
public void setAssocLocationSuffix(String assocLocationSuffix) { |
||||
this.assocLocationSuffix = assocLocationSuffix; |
||||
} |
||||
|
||||
public ShortTermPlanningIndicator getStpIndicator() { |
||||
return stpIndicator; |
||||
} |
||||
|
||||
public void setStpIndicator(ShortTermPlanningIndicator stpIndicator) { |
||||
this.stpIndicator = stpIndicator; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object o) { |
||||
if (this == o) return true; |
||||
if (o == null || getClass() != o.getClass()) return false; |
||||
|
||||
ScheduleAssociation that = (ScheduleAssociation) o; |
||||
|
||||
if (associationDate != that.associationDate) return false; |
||||
if (!mainUid.equals(that.mainUid)) return false; |
||||
if (!assoUid.equals(that.assoUid)) return false; |
||||
if (!startDate.equals(that.startDate)) return false; |
||||
if (!endDate.equals(that.endDate)) return false; |
||||
if (!assoDays.equals(that.assoDays)) return false; |
||||
if (associationCategory != that.associationCategory) return false; |
||||
if (!associationLocation.equals(that.associationLocation)) return false; |
||||
if (baseLocationSuffix != null ? !baseLocationSuffix.equals(that.baseLocationSuffix) : that.baseLocationSuffix != null) |
||||
return false; |
||||
if (assocLocationSuffix != null ? !assocLocationSuffix.equals(that.assocLocationSuffix) : that.assocLocationSuffix != null) |
||||
return false; |
||||
return stpIndicator == that.stpIndicator; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
int result = mainUid.hashCode(); |
||||
result = 31 * result + assoUid.hashCode(); |
||||
result = 31 * result + startDate.hashCode(); |
||||
result = 31 * result + endDate.hashCode(); |
||||
result = 31 * result + assoDays.hashCode(); |
||||
result = 31 * result + (associationCategory==null?0:associationCategory.name().hashCode()); |
||||
result = 31 * result + associationDate; |
||||
result = 31 * result + associationLocation.hashCode(); |
||||
result = 31 * result + (baseLocationSuffix != null ? baseLocationSuffix.hashCode() : 0); |
||||
result = 31 * result + (assocLocationSuffix != null ? assocLocationSuffix.hashCode() : 0); |
||||
result = 31 * result + (stpIndicator==null?0:stpIndicator.name().hashCode()); |
||||
return result; |
||||
} |
||||
|
||||
public static ScheduleAssociation parseJSON(String obj) throws JSONException { |
||||
return parseJSON(new JSONObject(obj)); |
||||
} |
||||
|
||||
public static ScheduleAssociation parseJSON(JSONObject obj) throws JSONException { |
||||
ScheduleAssociation scheduleAssociation = new ScheduleAssociation(); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); |
||||
scheduleAssociation.mainUid=obj.optString("main_train_uid").strip(); |
||||
scheduleAssociation.assoUid=obj.optString("assoc_train_uid").strip(); |
||||
try { |
||||
scheduleAssociation.startDate=sdf.parse(obj.optString("assoc_start_date")); |
||||
scheduleAssociation.endDate=sdf.parse(obj.optString("assoc_end_date")); |
||||
} catch (ParseException e) { |
||||
log.atWarn().withThrowable(e).log("Unable to parse date"); |
||||
} |
||||
scheduleAssociation.assoDays=obj.optString("assoc_days"); |
||||
scheduleAssociation.associationCategory = AssociationCategory.parseCode(obj.optString("category")); |
||||
String dateIndicator = obj.optString("date_indicator"); |
||||
if("N".equals(dateIndicator)){ |
||||
scheduleAssociation.associationDate = 1; |
||||
} else if ("P".equals(dateIndicator)) { |
||||
scheduleAssociation.associationDate = -1; |
||||
}else { |
||||
scheduleAssociation.associationDate = 0; |
||||
} |
||||
scheduleAssociation.associationLocation = obj.optString("location").strip(); |
||||
scheduleAssociation.baseLocationSuffix = obj.optString("base_location_suffix"); |
||||
scheduleAssociation.assocLocationSuffix = obj.optString("assoc_location_suffix"); |
||||
scheduleAssociation.stpIndicator = ShortTermPlanningIndicator.parseCode(obj.optString("CIF_stp_indicator")); |
||||
return scheduleAssociation; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,30 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
public enum ShortTermPlanningIndicator { |
||||
|
||||
CANCELLATION("C"), |
||||
NEW("N"), |
||||
OVERLAY("O"), |
||||
PERMANENT("P"); |
||||
|
||||
private String code; |
||||
|
||||
private ShortTermPlanningIndicator(String code){ |
||||
this.code = code; |
||||
} |
||||
|
||||
public String getCode() { |
||||
return code; |
||||
} |
||||
|
||||
|
||||
public static ShortTermPlanningIndicator parseCode(String code){ |
||||
if(code==null) |
||||
return null; |
||||
for(ShortTermPlanningIndicator stpi: ShortTermPlanningIndicator.values()){ |
||||
if(code.equalsIgnoreCase(stpi.code)) |
||||
return stpi; |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
@ -0,0 +1,180 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
import org.json.JSONObject; |
||||
import org.leolo.nrdatad.util.JSONUtil; |
||||
|
||||
public class Smart { |
||||
|
||||
private int smartId; |
||||
private String td; |
||||
private String fromBerth; |
||||
private String toBerth; |
||||
private String fromLine; |
||||
private String toLine; |
||||
private int berthOffset; |
||||
private String platform; |
||||
private SmartEvent event; |
||||
private String route; |
||||
private String stanox; |
||||
private String stationName; |
||||
private SmartStepType stepType; |
||||
private String comment; |
||||
|
||||
public int getSmartId() { |
||||
return smartId; |
||||
} |
||||
|
||||
public void setSmartId(int smartId) { |
||||
this.smartId = smartId; |
||||
} |
||||
|
||||
public String getTd() { |
||||
return td; |
||||
} |
||||
|
||||
public void setTd(String td) { |
||||
this.td = td; |
||||
} |
||||
|
||||
public String getFromBerth() { |
||||
return fromBerth; |
||||
} |
||||
|
||||
public void setFromBerth(String fromBerth) { |
||||
this.fromBerth = fromBerth; |
||||
} |
||||
|
||||
public String getToBerth() { |
||||
return toBerth; |
||||
} |
||||
|
||||
public void setToBerth(String toBerth) { |
||||
this.toBerth = toBerth; |
||||
} |
||||
|
||||
public String getFromLine() { |
||||
return fromLine; |
||||
} |
||||
|
||||
public void setFromLine(String fromLine) { |
||||
this.fromLine = fromLine; |
||||
} |
||||
|
||||
public String getToLine() { |
||||
return toLine; |
||||
} |
||||
|
||||
public void setToLine(String toLine) { |
||||
this.toLine = toLine; |
||||
} |
||||
|
||||
public int getBerthOffset() { |
||||
return berthOffset; |
||||
} |
||||
|
||||
public void setBerthOffset(int berthOffset) { |
||||
this.berthOffset = berthOffset; |
||||
} |
||||
|
||||
public String getPlatform() { |
||||
return platform; |
||||
} |
||||
|
||||
public void setPlatform(String platform) { |
||||
this.platform = platform; |
||||
} |
||||
|
||||
public SmartEvent getEvent() { |
||||
return event; |
||||
} |
||||
|
||||
public void setEvent(SmartEvent event) { |
||||
this.event = event; |
||||
} |
||||
|
||||
public String getRoute() { |
||||
return route; |
||||
} |
||||
|
||||
public void setRoute(String route) { |
||||
this.route = route; |
||||
} |
||||
|
||||
public String getStanox() { |
||||
return stanox; |
||||
} |
||||
|
||||
public void setStanox(String stanox) { |
||||
this.stanox = stanox; |
||||
} |
||||
|
||||
public String getStationName() { |
||||
return stationName; |
||||
} |
||||
|
||||
public void setStationName(String stationName) { |
||||
this.stationName = stationName; |
||||
} |
||||
|
||||
public SmartStepType getStepType() { |
||||
return stepType; |
||||
} |
||||
|
||||
public void setStepType(SmartStepType stepType) { |
||||
this.stepType = stepType; |
||||
} |
||||
|
||||
public String getComment() { |
||||
return comment; |
||||
} |
||||
|
||||
public void setComment(String comment) { |
||||
this.comment = comment; |
||||
} |
||||
|
||||
public static Smart parseJSON(String json){ |
||||
return parseJSON(new JSONObject(json)); |
||||
} |
||||
|
||||
public static Smart parseJSON(JSONObject obj) { |
||||
Smart smart = new Smart(); |
||||
smart.td = obj.optString("TD"); |
||||
smart.fromBerth = obj.optString("FROMBERTH"); |
||||
smart.toBerth = obj.optString("TOBERTH"); |
||||
smart.fromLine = obj.optString("FROMLINE"); |
||||
smart.toLine = obj.optString("TOLINE"); |
||||
smart.berthOffset = JSONUtil.parseInt(obj.optString("BERTHOFFSET")); |
||||
smart.platform = obj.optString("PLATFORM"); |
||||
smart.event = SmartEvent.parseCode(obj.optString("EVENT")); |
||||
smart.route = obj.optString("ROUTE"); |
||||
smart.stanox = obj.optString("STANOX"); |
||||
smart.stationName = obj.optString("STANME"); |
||||
smart.stepType = SmartStepType.parseCode(obj.optString("STEPTYPE")); |
||||
smart.comment = obj.optString("COMMENT"); |
||||
return smart; |
||||
} |
||||
|
||||
public boolean checkEnums(){ |
||||
return event!=null && stepType!=null; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Smart{" + |
||||
"smartId=" + smartId + |
||||
", td='" + td + '\'' + |
||||
", fromBerth='" + fromBerth + '\'' + |
||||
", toBerth='" + toBerth + '\'' + |
||||
", fromLine='" + fromLine + '\'' + |
||||
", toLine='" + toLine + '\'' + |
||||
", berthOffset=" + berthOffset + |
||||
", platform='" + platform + '\'' + |
||||
", event=" + event + |
||||
", route='" + route + '\'' + |
||||
", stanox='" + stanox + '\'' + |
||||
", stationName='" + stationName + '\'' + |
||||
", stepType=" + stepType + |
||||
", comment='" + comment + '\'' + |
||||
'}'; |
||||
} |
||||
} |
||||
@ -0,0 +1,33 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
|
||||
public enum SmartEvent { |
||||
ARRIVE_UP ("A"), |
||||
DEPART_UP ("B"), |
||||
ARRIVE_DOWN("C"), |
||||
DEPART_DOWN("D"); |
||||
|
||||
|
||||
private String code; |
||||
|
||||
private SmartEvent(String code){ |
||||
this.code = code; |
||||
} |
||||
|
||||
public String getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public static SmartEvent parseCode(@NotNull String code){ |
||||
if(code==null) |
||||
return null; |
||||
for(SmartEvent se: SmartEvent.values()){ |
||||
if(code.equalsIgnoreCase(se.code)){ |
||||
return se; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,65 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
|
||||
public enum SmartStepType { |
||||
/** |
||||
* This is a move between directly adjacent berths, and is the preferred type of movement. The time reported to |
||||
* TRUST is the time that the train enters the 'to' berth. |
||||
*/ |
||||
BETWEEN("B"), |
||||
/** |
||||
* This is used to record a time for a train going in either direction (up or down) from the specified berth to any |
||||
* other berth. The time reported to TRUST is the time that the train leaves the 'from' berth. |
||||
*/ |
||||
FROM("F"), |
||||
/** |
||||
* This is the opposite of the 'F' step type. It is used to record a time for a train from any berth to the |
||||
* specified berth. The time reported to TRUST is the time that the train enters the 'to' berth. |
||||
*/ |
||||
TO("T"), |
||||
/** |
||||
* This is used to specify the route a train is taking, usually when departing a station or junction. |
||||
* |
||||
* For example, if a 'D' move is specified as 0101 to 0407, and a train moves between berths 0101, 0203, 0305 and |
||||
* 0407, the move will be reported for the time the train left the first berth. |
||||
*/ |
||||
INTERMEDIATE_FIRST("D"), |
||||
/** |
||||
* This is used to report on a movement where the only indication is a cancel message. For example, when a train |
||||
* leaves Network Rail infrastructure and moves in to a siding or area not covered by a train describer, the only |
||||
* message that will be received is a Clearout (CB) message. |
||||
*/ |
||||
CLEAROUT("C"), |
||||
/** |
||||
* This is the opposite of the 'C' step type. It is used to report on a movement where the only indication is |
||||
* an interpose message. For example, when a train arrives on Network Rail infrastructure from a siding. The time |
||||
* reported to TRUST is the time that the interpose happened. |
||||
*/ |
||||
INTERPOSE("I"), |
||||
/** |
||||
* This is similar to the 'D' move, but usually used for arrivals. The time reported to TRUST is the time the last |
||||
* berth step was made. |
||||
*/ |
||||
INTERMEDIATE("E"); |
||||
|
||||
private String code; |
||||
|
||||
private SmartStepType(String code){ |
||||
this.code = code; |
||||
} |
||||
|
||||
public String getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public static SmartStepType parseCode(@NotNull String code){ |
||||
if(code==null) |
||||
return null; |
||||
for(SmartStepType sst: SmartStepType.values()){ |
||||
if(code.equalsIgnoreCase(sst.code)) |
||||
return sst; |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
@ -0,0 +1,75 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
import org.json.JSONObject; |
||||
|
||||
public class Tiploc { |
||||
private String tiplocCode; |
||||
private String nalco; |
||||
private String stanox; |
||||
private String description; |
||||
private String tpsDescription; |
||||
private String crsCode; |
||||
|
||||
public String getTiplocCode() { |
||||
return tiplocCode; |
||||
} |
||||
|
||||
public void setTiplocCode(String tiplocCode) { |
||||
this.tiplocCode = tiplocCode; |
||||
} |
||||
|
||||
public String getNalco() { |
||||
return nalco; |
||||
} |
||||
|
||||
public void setNalco(String nalco) { |
||||
this.nalco = nalco; |
||||
} |
||||
|
||||
public String getStanox() { |
||||
return stanox; |
||||
} |
||||
|
||||
public void setStanox(String stanox) { |
||||
this.stanox = stanox; |
||||
} |
||||
|
||||
public String getDescription() { |
||||
return description; |
||||
} |
||||
|
||||
public void setDescription(String description) { |
||||
this.description = description; |
||||
} |
||||
|
||||
public String getTpsDescription() { |
||||
return tpsDescription; |
||||
} |
||||
|
||||
public void setTpsDescription(String tpsDescription) { |
||||
this.tpsDescription = tpsDescription; |
||||
} |
||||
|
||||
public String getCrsCode() { |
||||
return crsCode; |
||||
} |
||||
|
||||
public void setCrsCode(String crsCode) { |
||||
this.crsCode = crsCode; |
||||
} |
||||
|
||||
public static Tiploc parseJSON(String json){ |
||||
return parseJSON(new JSONObject(json)); |
||||
} |
||||
|
||||
public static Tiploc parseJSON(JSONObject obj){ |
||||
Tiploc tiploc = new Tiploc(); |
||||
tiploc.tpsDescription = obj.optString("tps_description"); |
||||
tiploc.crsCode = obj.optString("crs_code"); |
||||
tiploc.description = obj.optString("description"); |
||||
tiploc.stanox = obj.optString("stanox"); |
||||
tiploc.tiplocCode = obj.optString("tiploc_code"); |
||||
tiploc.nalco = obj.optString("nalco"); |
||||
return tiploc; |
||||
} |
||||
} |
||||
@ -0,0 +1,138 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
import org.json.JSONObject; |
||||
import org.leolo.nrdatad.util.DateUtil; |
||||
import org.leolo.nrdatad.util.TUIDDateFormat; |
||||
|
||||
import java.util.Date; |
||||
|
||||
public class TrainSchedule { |
||||
|
||||
private int scheduleVersion = UNKNOWN_VERSION_NUMBER; |
||||
|
||||
public static final int UNKNOWN_VERSION_NUMBER = -1; |
||||
|
||||
private String runsOnBankHoliday; |
||||
private String trainStatus;//TODO: change it into enum
|
||||
private String trainUid; |
||||
private String runsOn; |
||||
private ShortTermPlanningIndicator shortTermPlanningIndicator; |
||||
private String atocCode; |
||||
private String uicCode; |
||||
private String tractionClass; |
||||
private Date startDate; |
||||
private Date endDate; |
||||
private TrainScheduleSector sector; |
||||
|
||||
public String getSUID(){ |
||||
TUIDDateFormat tuiddf = new TUIDDateFormat(); |
||||
return trainUid+tuiddf.format(startDate)+tuiddf.format(endDate)+shortTermPlanningIndicator.getCode(); |
||||
} |
||||
|
||||
public String getRunsOnBankHoliday() { |
||||
return runsOnBankHoliday; |
||||
} |
||||
|
||||
public void setRunsOnBankHoliday(String runsOnBankHoliday) { |
||||
this.runsOnBankHoliday = runsOnBankHoliday; |
||||
} |
||||
|
||||
public String getTrainStatus() { |
||||
return trainStatus; |
||||
} |
||||
|
||||
public void setTrainStatus(String trainStatus) { |
||||
this.trainStatus = trainStatus; |
||||
} |
||||
|
||||
public String getTrainUid() { |
||||
return trainUid; |
||||
} |
||||
|
||||
public void setTrainUid(String trainUid) { |
||||
this.trainUid = trainUid; |
||||
} |
||||
|
||||
public String getRunsOn() { |
||||
return runsOn; |
||||
} |
||||
|
||||
public void setRunsOn(String runsOn) { |
||||
this.runsOn = runsOn; |
||||
} |
||||
|
||||
public ShortTermPlanningIndicator getShortTermPlanningIndicator() { |
||||
return shortTermPlanningIndicator; |
||||
} |
||||
|
||||
public void setShortTermPlanningIndicator(ShortTermPlanningIndicator shortTermPlanningIndicator) { |
||||
this.shortTermPlanningIndicator = shortTermPlanningIndicator; |
||||
} |
||||
|
||||
public String getAtocCode() { |
||||
return atocCode; |
||||
} |
||||
|
||||
public void setAtocCode(String atocCode) { |
||||
this.atocCode = atocCode; |
||||
} |
||||
|
||||
public String getUicCode() { |
||||
return uicCode; |
||||
} |
||||
|
||||
public void setUicCode(String uicCode) { |
||||
this.uicCode = uicCode; |
||||
} |
||||
|
||||
public String getTractionClass() { |
||||
return tractionClass; |
||||
} |
||||
|
||||
public void setTractionClass(String tractionClass) { |
||||
this.tractionClass = tractionClass; |
||||
} |
||||
|
||||
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 TrainScheduleSector getSector() { |
||||
return sector; |
||||
} |
||||
|
||||
public void setSector(TrainScheduleSector sector) { |
||||
this.sector = sector; |
||||
} |
||||
|
||||
public static TrainSchedule parseJSON(String json){ |
||||
return parseJSON(new JSONObject(json)); |
||||
} |
||||
|
||||
public static TrainSchedule parseJSON(JSONObject object){ |
||||
TrainSchedule ts = new TrainSchedule(); |
||||
ts.runsOnBankHoliday = object.optString("CIF_bank_holiday_running"); |
||||
ts.trainUid = object.optString("CIF_train_uid"); |
||||
ts.runsOn = object.optString("schedule_days_runs"); |
||||
ts.shortTermPlanningIndicator = ShortTermPlanningIndicator.parseCode(object.optString("CIF_stp_indicator")); |
||||
ts.atocCode = object.optString("atoc_code"); |
||||
ts.startDate = DateUtil.parseDate(object.optString("schedule_start_date")); |
||||
ts.endDate = DateUtil.parseDate(object.optString("schedule_end_date")); |
||||
ts.sector = TrainScheduleSector.parseJSON(object.getJSONObject("schedule_segment")); |
||||
return ts; |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,207 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
import org.json.JSONObject; |
||||
import org.leolo.nrdatad.util.TimeUtil; |
||||
|
||||
public class TrainScheduleLocation { |
||||
|
||||
public static final int UNKNOWN_RECORD_SEQUENCE = -1; |
||||
private int recordSequence = UNKNOWN_RECORD_SEQUENCE; |
||||
private TrainScheduleSector recordSector; |
||||
private TrainScheduleLocationRecordIdentity recordIdentity; |
||||
private String tiploc; |
||||
private int tiplocInstance = UNKNOWN_RECORD_SEQUENCE; |
||||
private long wttArrival; |
||||
private long wttDeparture; |
||||
private long wttPass; |
||||
private long publicArrival; |
||||
private long publicDeparture; |
||||
private String platform; |
||||
/** |
||||
* Line used for departure |
||||
*/ |
||||
private String line; |
||||
/** |
||||
* Path used for arrival |
||||
*/ |
||||
private String path; |
||||
/** |
||||
* This is extra time to allow for a speed restriction on the railway. |
||||
* |
||||
* It may also be called 'Box Time', as the Working Timetable encloses engineering allowances in a box or square brackets. |
||||
*/ |
||||
private long engineeringAllowance; |
||||
/** |
||||
* This is extra time to ensure the train path doesn't conflict with others at a junction, or where trains running at different speeds are operating over a route. |
||||
* |
||||
* It may also be called 'Circle Time', as the Working Timetable encloses pathing allowances in a circle or brackets. |
||||
*/ |
||||
private long pathingAllowance; |
||||
/** |
||||
* This is extra time to provide a margin or buffer for late running on a day-to-day basis. |
||||
* |
||||
* It may also be called 'Diamond Time', as the Working Timetable encloses performance allowances in a diamond or angle-brackets. |
||||
*/ |
||||
private long performanceAllowance; |
||||
|
||||
public int getRecordSequence() { |
||||
return recordSequence; |
||||
} |
||||
|
||||
public void setRecordSequence(int recordSequence) { |
||||
this.recordSequence = recordSequence; |
||||
} |
||||
|
||||
public TrainScheduleLocationRecordIdentity getRecordIdentity() { |
||||
return recordIdentity; |
||||
} |
||||
|
||||
public void setRecordIdentity(TrainScheduleLocationRecordIdentity recordIdentity) { |
||||
this.recordIdentity = recordIdentity; |
||||
} |
||||
|
||||
public String getTiploc() { |
||||
return tiploc; |
||||
} |
||||
|
||||
public void setTiploc(String tiploc) { |
||||
this.tiploc = tiploc; |
||||
} |
||||
|
||||
public int getTiplocInstance() { |
||||
return tiplocInstance; |
||||
} |
||||
|
||||
public void setTiplocInstance(int tiplocInstance) { |
||||
this.tiplocInstance = tiplocInstance; |
||||
} |
||||
|
||||
public long getWttArrival() { |
||||
return wttArrival; |
||||
} |
||||
|
||||
public void setWttArrival(long wttArrival) { |
||||
this.wttArrival = wttArrival; |
||||
} |
||||
|
||||
public long getWttDeparture() { |
||||
return wttDeparture; |
||||
} |
||||
|
||||
public void setWttDeparture(long wttDeparture) { |
||||
this.wttDeparture = wttDeparture; |
||||
} |
||||
|
||||
public long getWttPass() { |
||||
return wttPass; |
||||
} |
||||
|
||||
public void setWttPass(long wttPass) { |
||||
this.wttPass = wttPass; |
||||
} |
||||
|
||||
public long getPublicArrival() { |
||||
return publicArrival; |
||||
} |
||||
|
||||
public void setPublicArrival(long publicArrival) { |
||||
this.publicArrival = publicArrival; |
||||
} |
||||
|
||||
public long getPublicDeparture() { |
||||
return publicDeparture; |
||||
} |
||||
|
||||
public void setPublicDeparture(long publicDeparture) { |
||||
this.publicDeparture = publicDeparture; |
||||
} |
||||
|
||||
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 TrainScheduleSector getRecordSector() { |
||||
return recordSector; |
||||
} |
||||
|
||||
public void setRecordSector(TrainScheduleSector recordSector) { |
||||
this.recordSector = recordSector; |
||||
} |
||||
|
||||
public static TrainScheduleLocation parseJSON(String json){ |
||||
return parseJSON(new JSONObject(json), UNKNOWN_RECORD_SEQUENCE); |
||||
} |
||||
|
||||
public static TrainScheduleLocation parseJSON(String json, int recordSequence){ |
||||
return parseJSON(new JSONObject(json), recordSequence); |
||||
} |
||||
|
||||
public static TrainScheduleLocation parseJSON(JSONObject object){ |
||||
return parseJSON(object, UNKNOWN_RECORD_SEQUENCE); |
||||
} |
||||
|
||||
public static TrainScheduleLocation parseJSON(JSONObject object, int recordSequence){ |
||||
TrainScheduleLocation tsl = new TrainScheduleLocation(); |
||||
tsl.recordSequence = recordSequence; |
||||
tsl.tiploc = object.optString("tiploc_code"); |
||||
tsl.tiplocInstance = object.optInt("tiploc_instance", UNKNOWN_RECORD_SEQUENCE); |
||||
tsl.wttArrival = TimeUtil.parseTime(object.optString("arrival")); |
||||
tsl.wttDeparture = TimeUtil.parseTime(object.optString("departure")); |
||||
tsl.wttPass = TimeUtil.parseTime(object.optString("pass")); |
||||
tsl.publicArrival = TimeUtil.parseTime(object.optString("public_arrival")); |
||||
tsl.publicDeparture = TimeUtil.parseTime(object.optString("public_departure")); |
||||
tsl.platform = object.optString("platform"); |
||||
tsl.line = object.optString("line"); |
||||
tsl.path = object.optString("path"); |
||||
tsl.engineeringAllowance = TimeUtil.parseTime(object.optString("engineering_allowance")); |
||||
tsl.pathingAllowance = TimeUtil.parseTime(object.optString("pathing_allowance")); |
||||
tsl.performanceAllowance = TimeUtil.parseTime(object.optString("performance_allowance")); |
||||
tsl.recordIdentity = TrainScheduleLocationRecordIdentity.parseCode(object.optString("location_type")); |
||||
|
||||
return tsl; |
||||
} |
||||
} |
||||
@ -0,0 +1,27 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
public enum TrainScheduleLocationRecordIdentity { |
||||
|
||||
ORIGINATE("LO"), |
||||
INTERMEDIATE("LI"), |
||||
TERMINATE("LT"); |
||||
|
||||
private String code; |
||||
|
||||
private TrainScheduleLocationRecordIdentity(String code) { |
||||
this.code = code; |
||||
} |
||||
|
||||
public static TrainScheduleLocationRecordIdentity parseCode(String code) { |
||||
if (code == null) { |
||||
return null; |
||||
} |
||||
for (TrainScheduleLocationRecordIdentity e : TrainScheduleLocationRecordIdentity.values()) { |
||||
if (e.code.equalsIgnoreCase(code)) { |
||||
return e; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,252 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
import org.json.JSONArray; |
||||
import org.json.JSONObject; |
||||
import org.leolo.nrdatad.util.JSONUtil; |
||||
|
||||
import java.util.List; |
||||
import java.util.Vector; |
||||
|
||||
public class TrainScheduleSector { |
||||
/** |
||||
* A sequence number of the schedule sector which are belongs to same schedule |
||||
*/ |
||||
private int sectorId; |
||||
/** |
||||
* Service brand |
||||
*/ |
||||
private String serviceBranding; |
||||
/** |
||||
* Train category |
||||
*/ |
||||
private String trainCategory; |
||||
/** |
||||
* Formerly used to denote the business sector running the service; now represent the Portion ID for services which join or split |
||||
*/ |
||||
private String businessSector; |
||||
/** |
||||
* Planned speed of the train service |
||||
*/ |
||||
private int speed; |
||||
/** |
||||
* Reservation recommendations: |
||||
* <ul> |
||||
* <li>A - Reservations compulsory</li> |
||||
* <li>E - Reservations for bicycles essential</li> |
||||
* <li>R - Reservations recommended</li> |
||||
* <li>S - Reservations possible from any station</li> |
||||
* </ul> |
||||
*/ |
||||
private String reservation; |
||||
/** |
||||
* Up to two characters from the following: |
||||
* <ul> |
||||
* <li>C - Buffet Service</li> |
||||
* <li>F - Restaurant Car available for First Class passengers</li> |
||||
* <li>H - Hot food available</li> |
||||
* <li>M - Meal included for First Class passengers</li> |
||||
* <li>P - Wheelchair only reservations</li> |
||||
* <li>R - Restaurant</li> |
||||
* <li>T - Trolley service</li> |
||||
* </ul> |
||||
*/ |
||||
private String catering; |
||||
/** |
||||
* Power type |
||||
*/ |
||||
private String powerType; |
||||
/** |
||||
* Timing load |
||||
*/ |
||||
private String timingLoad; |
||||
/** |
||||
* Signalling ID, also referred to as headcode, not to be confused with below. For passenger services, this is the headcode of the service. For anonymous freight services this will be blank. |
||||
*/ |
||||
private String signalId; |
||||
/** |
||||
* National Reservation System headcode, designated by train operator, not to be confused with signal ID. |
||||
*/ |
||||
private String headcode; |
||||
/** |
||||
* Operating characteristics |
||||
*/ |
||||
private String operatingCharacteristic; |
||||
/** |
||||
* Sleeping accommodation available: |
||||
* <ul> |
||||
* <li>B - First and standard class</li> |
||||
* <li>F - First Class only</li> |
||||
* <li>S - Standard class only</li> |
||||
* </ul> |
||||
*/ |
||||
private String sleeper; |
||||
/** |
||||
* Divides trains into service groups and used for revenue reasons |
||||
*/ |
||||
private String trainServiceCode; |
||||
/** |
||||
* Seating classes available: |
||||
* <ul> |
||||
* <li><span style="font-style: italic;">Blank</span> or B - First and standard</li> |
||||
* <li>S - Standard class only</li> |
||||
* </ul> |
||||
*/ |
||||
private String trainClass; |
||||
|
||||
private List<TrainScheduleLocation> scheduleLocations = new Vector<>(); |
||||
|
||||
public int getSectorId() { |
||||
return sectorId; |
||||
} |
||||
|
||||
public void setSectorId(int sectorId) { |
||||
this.sectorId = sectorId; |
||||
} |
||||
|
||||
public String getServiceBranding() { |
||||
return serviceBranding; |
||||
} |
||||
|
||||
public void setServiceBranding(String serviceBranding) { |
||||
this.serviceBranding = serviceBranding; |
||||
} |
||||
|
||||
public String getTrainCategory() { |
||||
return trainCategory; |
||||
} |
||||
|
||||
public void setTrainCategory(String trainCategory) { |
||||
this.trainCategory = trainCategory; |
||||
} |
||||
|
||||
public String getBusinessSector() { |
||||
return businessSector; |
||||
} |
||||
|
||||
public void setBusinessSector(String businessSector) { |
||||
this.businessSector = businessSector; |
||||
} |
||||
|
||||
public int getSpeed() { |
||||
return speed; |
||||
} |
||||
|
||||
public void setSpeed(int speed) { |
||||
this.speed = speed; |
||||
} |
||||
|
||||
public String getReservation() { |
||||
return reservation; |
||||
} |
||||
|
||||
public void setReservation(String reservation) { |
||||
this.reservation = reservation; |
||||
} |
||||
|
||||
public String getCatering() { |
||||
return catering; |
||||
} |
||||
|
||||
public void setCatering(String catering) { |
||||
this.catering = catering; |
||||
} |
||||
|
||||
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 getSignalId() { |
||||
return signalId; |
||||
} |
||||
|
||||
public void setSignalId(String signalId) { |
||||
this.signalId = signalId; |
||||
} |
||||
|
||||
public String getHeadcode() { |
||||
return headcode; |
||||
} |
||||
|
||||
public void setHeadcode(String headcode) { |
||||
this.headcode = headcode; |
||||
} |
||||
|
||||
public String getOperatingCharacteristic() { |
||||
return operatingCharacteristic; |
||||
} |
||||
|
||||
public void setOperatingCharacteristic(String operatingCharacteristic) { |
||||
this.operatingCharacteristic = operatingCharacteristic; |
||||
} |
||||
|
||||
public String getSleeper() { |
||||
return sleeper; |
||||
} |
||||
|
||||
public void setSleeper(String sleeper) { |
||||
this.sleeper = sleeper; |
||||
} |
||||
|
||||
public String getTrainServiceCode() { |
||||
return trainServiceCode; |
||||
} |
||||
|
||||
public void setTrainServiceCode(String trainServiceCode) { |
||||
this.trainServiceCode = trainServiceCode; |
||||
} |
||||
|
||||
public String getTrainClass() { |
||||
return trainClass; |
||||
} |
||||
|
||||
public void setTrainClass(String trainClass) { |
||||
this.trainClass = trainClass; |
||||
} |
||||
|
||||
public List<TrainScheduleLocation> getScheduleLocations() { |
||||
return scheduleLocations; |
||||
} |
||||
|
||||
public static TrainScheduleSector parseJSON(String json){ |
||||
return parseJSON(new JSONObject(json)); |
||||
} |
||||
|
||||
public static TrainScheduleSector parseJSON(JSONObject object){ |
||||
TrainScheduleSector tss = new TrainScheduleSector(); |
||||
tss.trainCategory = object.optString("CIF_train_category"); |
||||
tss.signalId = object.optString("signalling_id"); |
||||
tss.headcode = object.optString("CIF_headcode"); |
||||
tss.trainServiceCode = object.optString("CIF_train_service_code"); |
||||
tss.businessSector = object.optString("CIF_business_sector"); |
||||
tss.powerType = object.optString("CIF_power_type"); |
||||
tss.timingLoad = object.optString("CIF_timing_load"); |
||||
tss.speed = JSONUtil.parseInt(object.optString("CIF_speed")); |
||||
tss.operatingCharacteristic = object.optString("CIF_operating_characteristics"); |
||||
tss.trainClass = object.optString("CIF_train_class"); |
||||
tss.sleeper = object.optString("CIF_sleepers"); |
||||
tss.reservation = object.optString("COF_reservations"); |
||||
tss.catering = object.optString("CIF_catering_code"); |
||||
tss.serviceBranding = object.optString("CIF_service_branding"); |
||||
JSONArray locations = object.getJSONArray("schedule_location"); |
||||
for(int i=0;i<locations.length();i++){ |
||||
JSONObject location = locations.getJSONObject(i); |
||||
TrainScheduleLocation tsl = TrainScheduleLocation.parseJSON(location, i+1); |
||||
tsl.setRecordSector(tss); |
||||
|
||||
tss.scheduleLocations.add(tsl); |
||||
} |
||||
return tss; |
||||
} |
||||
} |
||||
@ -0,0 +1,39 @@
|
||||
package org.leolo.nrdatad.util; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Date; |
||||
|
||||
public class DateUtil { |
||||
|
||||
private static Logger log = LogManager.getLogger(); |
||||
|
||||
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd"; |
||||
|
||||
public static Date parseDate(String date){ |
||||
return parseDate(date, DEFAULT_DATE_FORMAT, true); |
||||
} |
||||
|
||||
public static Date parseDate(String date, boolean suppressException){ |
||||
return parseDate(date, DEFAULT_DATE_FORMAT, suppressException); |
||||
} |
||||
|
||||
public static Date parseDate(String data, String dateFormat){ |
||||
return parseDate(data, dateFormat, true); |
||||
} |
||||
public static Date parseDate(String data, String dateFormat, boolean suppressException){ |
||||
try{ |
||||
return new SimpleDateFormat(dateFormat).parse(data); |
||||
} catch (ParseException e) { |
||||
log.atWarn().withThrowable(e).log("Unable to parse date"); |
||||
if(suppressException){ |
||||
return null; |
||||
} |
||||
throw new RuntimeException(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,76 @@
|
||||
package org.leolo.nrdatad.util; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.leolo.nrdatad.ConfigurationManager; |
||||
import org.leolo.nrdatad.Constants; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.InputStreamReader; |
||||
import java.net.URISyntaxException; |
||||
import java.net.URL; |
||||
import java.net.URLConnection; |
||||
import java.util.Base64; |
||||
import java.util.zip.GZIPInputStream; |
||||
|
||||
public class HttpUtil { |
||||
|
||||
Logger log = LogManager.getLogger(); |
||||
|
||||
public static String sendHttpRequest(URL url, String userName, String password) throws IOException { |
||||
URLConnection conn = url.openConnection(); |
||||
String userpwd = userName+":"+password; |
||||
conn.addRequestProperty("Authorization", "Basic "+ Base64.getEncoder().encodeToString(userpwd.getBytes())); |
||||
conn.connect(); |
||||
StringBuilder sb = new StringBuilder(); |
||||
try(BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()))){ |
||||
while(true){ |
||||
String line = br.readLine(); |
||||
if(line == null) break; |
||||
sb.append(line).append("\n"); |
||||
} |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
public static String sendHttpRequest(String url, String userName, String password) throws IOException, URISyntaxException { |
||||
return sendHttpRequest(new URL(url), userName, password); |
||||
} |
||||
public static String sendHttpRequestForGZipFile(URL url, String userName, String password) throws IOException { |
||||
URLConnection conn = url.openConnection(); |
||||
String userpwd = userName+":"+password; |
||||
conn.addRequestProperty("Authorization", "Basic "+ Base64.getEncoder().encodeToString(userpwd.getBytes())); |
||||
conn.connect(); |
||||
StringBuilder sb = new StringBuilder(); |
||||
try( |
||||
GZIPInputStream gis = new GZIPInputStream(conn.getInputStream()); |
||||
BufferedReader br = new BufferedReader(new InputStreamReader(gis)) |
||||
){ |
||||
while(true){ |
||||
String line = br.readLine(); |
||||
if(line == null) break; |
||||
sb.append(line).append("\n"); |
||||
} |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
public static InputStream getHttpGZipStream(URL url, String userName, String password) throws IOException, URISyntaxException { |
||||
URLConnection conn = url.openConnection(); |
||||
String userpwd = userName+":"+password; |
||||
conn.addRequestProperty("Authorization", "Basic "+ Base64.getEncoder().encodeToString(userpwd.getBytes())); |
||||
conn.connect(); |
||||
return new GZIPInputStream(conn.getInputStream()); |
||||
} |
||||
|
||||
public static InputStream getHttpGZipStream(String url, String userName, String password) throws IOException, URISyntaxException { |
||||
return getHttpGZipStream(new URL(url), userName, password); |
||||
} |
||||
|
||||
public static String sendHttpRequestForGZipFile(String url, String userName, String password) throws IOException, URISyntaxException { |
||||
return sendHttpRequestForGZipFile(new URL(url), userName, password); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,32 @@
|
||||
package org.leolo.nrdatad.util; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
public class JSONUtil { |
||||
|
||||
static Logger log = LogManager.getLogger(); |
||||
|
||||
public static int parseInt(String val){ |
||||
//Throw exception for empty string, or just a plus sign to maintenance backward
|
||||
//compatibility with previous version.
|
||||
if(val.length()==0 || "+".equals(val)){ |
||||
throw new NumberFormatException(); |
||||
} |
||||
if (val.startsWith("+")) { |
||||
return _parseInt(val.substring(1)); |
||||
} |
||||
return _parseInt(val); |
||||
} |
||||
|
||||
private static int _parseInt(String val) { |
||||
if(val.length()==0){ |
||||
return 0; |
||||
} |
||||
if (val.startsWith("0")) { |
||||
return _parseInt(val.substring(1)); |
||||
} |
||||
return Integer.parseInt(val); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,25 @@
|
||||
package org.leolo.nrdatad.util; |
||||
|
||||
public class Range<E extends Comparable> { |
||||
|
||||
private E lowerBound; |
||||
private E upperBound; |
||||
|
||||
public Range(E bound1, E bound2){ |
||||
if(bound1.compareTo(bound2)==-1){ |
||||
lowerBound = bound1; |
||||
upperBound = bound2; |
||||
}else{ |
||||
lowerBound = bound2; |
||||
upperBound = bound1; |
||||
} |
||||
} |
||||
|
||||
public E getLowerBound() { |
||||
return lowerBound; |
||||
} |
||||
|
||||
public E getUpperBound() { |
||||
return upperBound; |
||||
} |
||||
} |
||||
@ -0,0 +1,32 @@
|
||||
package org.leolo.nrdatad.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(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,58 @@
|
||||
package org.leolo.nrdatad.util; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
import java.util.Date; |
||||
|
||||
public class TimeUtil { |
||||
public static final long ONE_SECOND = 1_000; |
||||
public static final long ONE_MINUTE = 60_000; |
||||
public static final long ONE_HOUR = 3_600_000; |
||||
public static final long ONE_DAY = 86_400_000; |
||||
|
||||
private static Logger log = LogManager.getLogger(); |
||||
|
||||
public static long extractTime(Date date){ |
||||
return date.getTime()%ONE_DAY; |
||||
} |
||||
|
||||
public static long parseTime(String time){ |
||||
return parseTime(time, 0); |
||||
} |
||||
|
||||
|
||||
public static long parseTime(String time, int dayOffSet){ |
||||
time = time.strip().toUpperCase(); |
||||
long result; |
||||
//This given string can be 1, 2, 4 or 5 characters long
|
||||
int strLen = time.length(); |
||||
if (strLen == 0 ) { |
||||
result = 0; |
||||
} else if (strLen==1||strLen==2) { |
||||
if("H".equals(time)) { |
||||
result = 30 * ONE_SECOND; |
||||
} else if(time.endsWith("H")){ |
||||
result = Integer.parseInt(time.substring(0, 1))*ONE_MINUTE + 30*ONE_SECOND; |
||||
}else{ |
||||
result = Integer.parseInt(time)*ONE_MINUTE; |
||||
} |
||||
} else if (strLen==4||strLen==5) { |
||||
if(time.endsWith("H")){ |
||||
result = Integer.parseInt(time.substring(0, 2))*ONE_HOUR + |
||||
Integer.parseInt(time.substring(2, 4))*ONE_MINUTE + |
||||
30*ONE_SECOND; |
||||
}else{ |
||||
result = Integer.parseInt(time.substring(0, 2))*ONE_HOUR + |
||||
Integer.parseInt(time.substring(2, 4))*ONE_MINUTE; |
||||
} |
||||
} else { |
||||
log.atWarn().log("String \"{}\" is not a legal value.", time); |
||||
throw new RuntimeException(time+" is Illegal value for time"); |
||||
} |
||||
|
||||
result += dayOffSet*ONE_DAY; |
||||
return result; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,11 @@
|
||||
package org.leolo.nrdatad.util; |
||||
|
||||
import java.util.UUID; |
||||
|
||||
public class UUIDUtil { |
||||
|
||||
public static UUID getNextUUID(){ |
||||
return null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<Configuration status="warn"> |
||||
<Appenders> |
||||
<Console name="Console" target="SYSTEM_OUT"> |
||||
<PatternLayout |
||||
pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> |
||||
</Console> |
||||
|
||||
</Appenders> |
||||
<Loggers> |
||||
<Root level="debug"> |
||||
<AppenderRef ref="Console" /> |
||||
</Root> |
||||
<Logger name="org.leolo.nrdd"> |
||||
<AppenderRef ref="Console" /> |
||||
</Logger> |
||||
</Loggers> |
||||
</Configuration> |
||||
@ -0,0 +1,92 @@
|
||||
package org.leolo.nrdatad; |
||||
|
||||
import org.apache.logging.log4j.LogBuilder; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.junit.*; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.IOException; |
||||
import java.io.PrintWriter; |
||||
import java.nio.file.Files; |
||||
import java.util.Random; |
||||
import static org.junit.Assert.*; |
||||
|
||||
public class ConfigurationTest { |
||||
|
||||
public static final char[] randomChars = "1234567890qwertyuiopasdfghjklzxcvbnm".toCharArray(); |
||||
private static Logger log = LogManager.getLogger(); |
||||
|
||||
private static String fileName; |
||||
|
||||
@Before public void setUpClass(){ |
||||
int round = 0; |
||||
while(true) { |
||||
fileName = "test-"+getRandomFileName()+".tmp"; |
||||
log.always().log("File name is {}", fileName); |
||||
if(!new File(fileName).exists()){ |
||||
break; |
||||
} |
||||
if(++round>48){ |
||||
assertTrue("Cannot get a file name", false); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private static String getRandomFileName(){ |
||||
StringBuilder sb = new StringBuilder(); |
||||
Random r = new Random(); |
||||
for(int i=0;i<16;i++){ |
||||
sb.append(randomChars[r.nextInt(randomChars.length)]); |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
@Test public void basicLoad() throws Exception{ |
||||
assertEquals("Dirty configs", 0, ConfigurationManager.getInstance().size()); |
||||
//Step 1: Create a simple one
|
||||
try(PrintWriter out = new PrintWriter(new File(fileName))){ |
||||
out.println("key1=value1"); |
||||
out.println("key2=value2"); |
||||
out.println("key3=value3"); |
||||
out.println("key4=value4"); |
||||
out.println("#key5=value5"); |
||||
}catch(IOException e){ |
||||
log.always().withThrowable(e).log("Unable to test"); |
||||
assert false; |
||||
} |
||||
ConfigurationManager.getInstance().loadConfiguration(fileName); |
||||
assertEquals("Config key count mismatch", 4, ConfigurationManager.getInstance().size()); |
||||
assertEquals("Config key count mismatch", "value1", ConfigurationManager.getInstance().getProperty("key1")); |
||||
assertEquals("Config key count mismatch", "value3", ConfigurationManager.getInstance().getProperty("key3")); |
||||
assertEquals("Config key count mismatch", "value4", ConfigurationManager.getInstance().getProperty("key4")); |
||||
assertEquals("Config key count mismatch", "value2", ConfigurationManager.getInstance().getProperty("key2")); |
||||
|
||||
assertEquals("Config key count mismatch", null, ConfigurationManager.getInstance().getProperty("key5")); |
||||
} |
||||
|
||||
@Test public void notExistFile(){ |
||||
assertEquals("Dirty configs", 0, ConfigurationManager.getInstance().size()); |
||||
try { |
||||
ConfigurationManager.getInstance().loadConfiguration(fileName); |
||||
}catch(IOException e){ |
||||
return; |
||||
} |
||||
assertFalse("Exception not thrown", true); |
||||
} |
||||
|
||||
@After public void cleanUpEach(){ |
||||
try { |
||||
Files.deleteIfExists(new File(fileName).toPath()); |
||||
log.atInfo().log("Removed file {}", fileName); |
||||
} catch (IOException e) { |
||||
log.always().withThrowable(e).log("Unable to remove file"); |
||||
} |
||||
ConfigurationManager.getInstance().clear(); |
||||
} |
||||
|
||||
@AfterClass public static void cleanup(){ |
||||
new File(fileName).deleteOnExit(); |
||||
} |
||||
} |
||||
@ -0,0 +1,270 @@
|
||||
package org.leolo.nrdatad; |
||||
import org.json.JSONObject; |
||||
import org.junit.Test; |
||||
import org.leolo.nrdatad.model.Corpus; |
||||
import org.leolo.nrdatad.model.Smart; |
||||
import org.leolo.nrdatad.model.SmartEvent; |
||||
import org.leolo.nrdatad.model.SmartStepType; |
||||
|
||||
import static org.junit.Assert.*; |
||||
public class ReferenceDataParserTest { |
||||
|
||||
@Test |
||||
public void testCorpusNormalCase1(){ |
||||
String json = "{\"NLC\":\"535500\",\"STANOX\":\"87701\",\"TIPLOC\":\"ECROYDN\",\"3ALPHA\":\"ECR\",\"UIC\":\"53550\",\"NLCDESC\":\"EAST CROYDON\",\"NLCDESC16\":\"\"}"; |
||||
Corpus corpus = Corpus.parseJSON(json); |
||||
assertEquals("535500", corpus.getNlcCode()); |
||||
assertEquals("87701", corpus.getStanoxCode()); |
||||
assertEquals("ECROYDN", corpus.getTiplocCode()); |
||||
assertEquals("ECR", corpus.getCrsCode()); |
||||
assertEquals("53550", corpus.getUicCode()); |
||||
assertEquals("EAST CROYDON", corpus.getLongDescription()); |
||||
} |
||||
|
||||
@Test |
||||
public void testCorpusNormalCase2(){ |
||||
String json = "{\"NLC\":\"535500\",\"STANOX\":\"87701\",\"TIPLOC\":\"ECROYDN\",\"3ALPHA\":\"ECR\",\"UIC\":\"53550\",\"NLCDESC\":\"EAST CROYDON\",\"NLCDESC16\":\"\"}"; |
||||
Corpus corpus = Corpus.parseJSON(new JSONObject(json)); |
||||
assertEquals("535500", corpus.getNlcCode()); |
||||
assertEquals("87701", corpus.getStanoxCode()); |
||||
assertEquals("ECROYDN", corpus.getTiplocCode()); |
||||
assertEquals("ECR", corpus.getCrsCode()); |
||||
assertEquals("53550", corpus.getUicCode()); |
||||
assertEquals("EAST CROYDON", corpus.getLongDescription()); |
||||
} |
||||
|
||||
@Test |
||||
public void testSmartNormalCase1(){ |
||||
String json = "{\"STEPTYPE\":\"B\",\"FROMBERTH\":\"7910\",\"TOBERTH\":\"7904\",\"STANOX\":\"01125\",\"EVENT\":\"A\",\"PLATFORM\":\"1\"," + |
||||
"\"TOLINE\":\"\",\"BERTHOFFSET\":\"+59\",\"ROUTE\":\"\",\"FROMLINE\":\"\",\"TD\":\"IH\",\"COMMENT\":\"02/12/2018\",\"STANME\":\"NAIRN\"}"; |
||||
Smart smart = Smart.parseJSON(json); |
||||
assertEquals(SmartStepType.BETWEEN, smart.getStepType()); |
||||
assertEquals("7910", smart.getFromBerth()); |
||||
assertEquals("7904", smart.getToBerth()); |
||||
assertEquals("01125", smart.getStanox()); |
||||
assertEquals(SmartEvent.ARRIVE_UP, smart.getEvent()); |
||||
assertEquals("1", smart.getPlatform()); |
||||
assertEquals("", smart.getToLine()); |
||||
assertEquals(59, smart.getBerthOffset()); |
||||
assertEquals("", smart.getRoute()); |
||||
assertEquals("", smart.getFromLine()); |
||||
assertEquals("IH", smart.getTd()); |
||||
assertEquals("02/12/2018", smart.getComment()); |
||||
assertEquals("NAIRN", smart.getStationName()); |
||||
} |
||||
@Test |
||||
public void testSmartInvalidEnumVal1(){ |
||||
String json = "{\"STEPTYPE\":\"B\",\"FROMBERTH\":\"7910\",\"TOBERTH\":\"7904\",\"STANOX\":\"01125\",\"EVENT\":\"Z\",\"PLATFORM\":\"1\"," + |
||||
"\"TOLINE\":\"\",\"BERTHOFFSET\":\"+59\",\"ROUTE\":\"\",\"FROMLINE\":\"\",\"TD\":\"IH\",\"COMMENT\":\"02/12/2018\",\"STANME\":\"NAIRN\"}"; |
||||
Smart smart = Smart.parseJSON(json); |
||||
assertEquals(SmartStepType.BETWEEN, smart.getStepType()); |
||||
assertEquals("7910", smart.getFromBerth()); |
||||
assertEquals("7904", smart.getToBerth()); |
||||
assertEquals("01125", smart.getStanox()); |
||||
assertNull(smart.getEvent()); |
||||
assertEquals("1", smart.getPlatform()); |
||||
assertEquals("", smart.getToLine()); |
||||
assertEquals(59, smart.getBerthOffset()); |
||||
assertEquals("", smart.getRoute()); |
||||
assertEquals("", smart.getFromLine()); |
||||
assertEquals("IH", smart.getTd()); |
||||
assertEquals("02/12/2018", smart.getComment()); |
||||
assertEquals("NAIRN", smart.getStationName()); |
||||
} |
||||
|
||||
@Test |
||||
public void testSmartNormalCase2(){ |
||||
String json = "{\"STEPTYPE\":\"B\",\"FROMBERTH\":\"7910\",\"TOBERTH\":\"7904\",\"STANOX\":\"01125\",\"EVENT\":\"A\",\"PLATFORM\":\"1\"," + |
||||
"\"TOLINE\":\"\",\"BERTHOFFSET\":\"+59\",\"ROUTE\":\"\",\"FROMLINE\":\"\",\"TD\":\"IH\",\"COMMENT\":\"02/12/2018\",\"STANME\":\"NAIRN\"}"; |
||||
Smart smart = Smart.parseJSON(new JSONObject(json)); |
||||
assertEquals(SmartStepType.BETWEEN, smart.getStepType()); |
||||
assertEquals("7910", smart.getFromBerth()); |
||||
assertEquals("7904", smart.getToBerth()); |
||||
assertEquals("01125", smart.getStanox()); |
||||
assertEquals(SmartEvent.ARRIVE_UP, smart.getEvent()); |
||||
assertEquals("1", smart.getPlatform()); |
||||
assertEquals("", smart.getToLine()); |
||||
assertEquals(59, smart.getBerthOffset()); |
||||
assertEquals("", smart.getRoute()); |
||||
assertEquals("", smart.getFromLine()); |
||||
assertEquals("IH", smart.getTd()); |
||||
assertEquals("02/12/2018", smart.getComment()); |
||||
assertEquals("NAIRN", smart.getStationName()); |
||||
} |
||||
@Test |
||||
public void testSmartInvalidEnumVal2(){ |
||||
String json = "{\"STEPTYPE\":\"B\",\"FROMBERTH\":\"7910\",\"TOBERTH\":\"7904\",\"STANOX\":\"01125\",\"EVENT\":\"Z\",\"PLATFORM\":\"1\"," + |
||||
"\"TOLINE\":\"\",\"BERTHOFFSET\":\"+59\",\"ROUTE\":\"\",\"FROMLINE\":\"\",\"TD\":\"IH\",\"COMMENT\":\"02/12/2018\",\"STANME\":\"NAIRN\"}"; |
||||
Smart smart = Smart.parseJSON(new JSONObject(json)); |
||||
assertEquals(SmartStepType.BETWEEN, smart.getStepType()); |
||||
assertEquals("7910", smart.getFromBerth()); |
||||
assertEquals("7904", smart.getToBerth()); |
||||
assertEquals("01125", smart.getStanox()); |
||||
assertNull(smart.getEvent()); |
||||
assertEquals("1", smart.getPlatform()); |
||||
assertEquals("", smart.getToLine()); |
||||
assertEquals(59, smart.getBerthOffset()); |
||||
assertEquals("", smart.getRoute()); |
||||
assertEquals("", smart.getFromLine()); |
||||
assertEquals("IH", smart.getTd()); |
||||
assertEquals("02/12/2018", smart.getComment()); |
||||
assertEquals("NAIRN", smart.getStationName()); |
||||
} |
||||
|
||||
@Test |
||||
public void testSmartNormalCase3(){ |
||||
String json = "{\"STEPTYPE\":\"B\",\"FROMBERTH\":\"7910\",\"TOBERTH\":\"7904\",\"STANOX\":\"01125\",\"EVENT\":\"A\",\"PLATFORM\":\"1\"," + |
||||
"\"TOLINE\":\"\",\"BERTHOFFSET\":\"-59\",\"ROUTE\":\"\",\"FROMLINE\":\"\",\"TD\":\"IH\",\"COMMENT\":\"02/12/2018\",\"STANME\":\"NAIRN\"}"; |
||||
Smart smart = Smart.parseJSON(json); |
||||
assertEquals(SmartStepType.BETWEEN, smart.getStepType()); |
||||
assertEquals("7910", smart.getFromBerth()); |
||||
assertEquals("7904", smart.getToBerth()); |
||||
assertEquals("01125", smart.getStanox()); |
||||
assertEquals(SmartEvent.ARRIVE_UP, smart.getEvent()); |
||||
assertEquals("1", smart.getPlatform()); |
||||
assertEquals("", smart.getToLine()); |
||||
assertEquals(-59, smart.getBerthOffset()); |
||||
assertEquals("", smart.getRoute()); |
||||
assertEquals("", smart.getFromLine()); |
||||
assertEquals("IH", smart.getTd()); |
||||
assertEquals("02/12/2018", smart.getComment()); |
||||
assertEquals("NAIRN", smart.getStationName()); |
||||
} |
||||
@Test |
||||
public void testSmartInvalidEnumVal3(){ |
||||
String json = "{\"STEPTYPE\":\"B\",\"FROMBERTH\":\"7910\",\"TOBERTH\":\"7904\",\"STANOX\":\"01125\",\"EVENT\":\"Z\",\"PLATFORM\":\"1\"," + |
||||
"\"TOLINE\":\"\",\"BERTHOFFSET\":\"-59\",\"ROUTE\":\"\",\"FROMLINE\":\"\",\"TD\":\"IH\",\"COMMENT\":\"02/12/2018\",\"STANME\":\"NAIRN\"}"; |
||||
Smart smart = Smart.parseJSON(json); |
||||
assertEquals(SmartStepType.BETWEEN, smart.getStepType()); |
||||
assertEquals("7910", smart.getFromBerth()); |
||||
assertEquals("7904", smart.getToBerth()); |
||||
assertEquals("01125", smart.getStanox()); |
||||
assertNull(smart.getEvent()); |
||||
assertEquals("1", smart.getPlatform()); |
||||
assertEquals("", smart.getToLine()); |
||||
assertEquals(-59, smart.getBerthOffset()); |
||||
assertEquals("", smart.getRoute()); |
||||
assertEquals("", smart.getFromLine()); |
||||
assertEquals("IH", smart.getTd()); |
||||
assertEquals("02/12/2018", smart.getComment()); |
||||
assertEquals("NAIRN", smart.getStationName()); |
||||
} |
||||
|
||||
@Test |
||||
public void testSmartNormalCase4(){ |
||||
String json = "{\"STEPTYPE\":\"B\",\"FROMBERTH\":\"7910\",\"TOBERTH\":\"7904\",\"STANOX\":\"01125\",\"EVENT\":\"A\",\"PLATFORM\":\"1\"," + |
||||
"\"TOLINE\":\"\",\"BERTHOFFSET\":\"-59\",\"ROUTE\":\"\",\"FROMLINE\":\"\",\"TD\":\"IH\",\"COMMENT\":\"02/12/2018\",\"STANME\":\"NAIRN\"}"; |
||||
Smart smart = Smart.parseJSON(new JSONObject(json)); |
||||
assertEquals(SmartStepType.BETWEEN, smart.getStepType()); |
||||
assertEquals("7910", smart.getFromBerth()); |
||||
assertEquals("7904", smart.getToBerth()); |
||||
assertEquals("01125", smart.getStanox()); |
||||
assertEquals(SmartEvent.ARRIVE_UP, smart.getEvent()); |
||||
assertEquals("1", smart.getPlatform()); |
||||
assertEquals("", smart.getToLine()); |
||||
assertEquals(-59, smart.getBerthOffset()); |
||||
assertEquals("", smart.getRoute()); |
||||
assertEquals("", smart.getFromLine()); |
||||
assertEquals("IH", smart.getTd()); |
||||
assertEquals("02/12/2018", smart.getComment()); |
||||
assertEquals("NAIRN", smart.getStationName()); |
||||
} |
||||
@Test |
||||
public void testSmartInvalidEnumVal4(){ |
||||
String json = "{\"STEPTYPE\":\"B\",\"FROMBERTH\":\"7910\",\"TOBERTH\":\"7904\",\"STANOX\":\"01125\",\"EVENT\":\"Z\",\"PLATFORM\":\"1\"," + |
||||
"\"TOLINE\":\"\",\"BERTHOFFSET\":\"-59\",\"ROUTE\":\"\",\"FROMLINE\":\"\",\"TD\":\"IH\",\"COMMENT\":\"02/12/2018\",\"STANME\":\"NAIRN\"}"; |
||||
Smart smart = Smart.parseJSON(new JSONObject(json)); |
||||
assertEquals(SmartStepType.BETWEEN, smart.getStepType()); |
||||
assertEquals("7910", smart.getFromBerth()); |
||||
assertEquals("7904", smart.getToBerth()); |
||||
assertEquals("01125", smart.getStanox()); |
||||
assertNull(smart.getEvent()); |
||||
assertEquals("1", smart.getPlatform()); |
||||
assertEquals("", smart.getToLine()); |
||||
assertEquals(-59, smart.getBerthOffset()); |
||||
assertEquals("", smart.getRoute()); |
||||
assertEquals("", smart.getFromLine()); |
||||
assertEquals("IH", smart.getTd()); |
||||
assertEquals("02/12/2018", smart.getComment()); |
||||
assertEquals("NAIRN", smart.getStationName()); |
||||
} |
||||
|
||||
@Test |
||||
public void testSmartNormalCase6(){ |
||||
String json = "{\"STEPTYPE\":\"B\",\"FROMBERTH\":\"7910\",\"TOBERTH\":\"7904\",\"STANOX\":\"01125\",\"EVENT\":\"A\",\"PLATFORM\":\"1\"," + |
||||
"\"TOLINE\":\"\",\"BERTHOFFSET\":\"59\",\"ROUTE\":\"\",\"FROMLINE\":\"\",\"TD\":\"IH\",\"COMMENT\":\"02/12/2018\",\"STANME\":\"NAIRN\"}"; |
||||
Smart smart = Smart.parseJSON(json); |
||||
assertEquals(SmartStepType.BETWEEN, smart.getStepType()); |
||||
assertEquals("7910", smart.getFromBerth()); |
||||
assertEquals("7904", smart.getToBerth()); |
||||
assertEquals("01125", smart.getStanox()); |
||||
assertEquals(SmartEvent.ARRIVE_UP, smart.getEvent()); |
||||
assertEquals("1", smart.getPlatform()); |
||||
assertEquals("", smart.getToLine()); |
||||
assertEquals(59, smart.getBerthOffset()); |
||||
assertEquals("", smart.getRoute()); |
||||
assertEquals("", smart.getFromLine()); |
||||
assertEquals("IH", smart.getTd()); |
||||
assertEquals("02/12/2018", smart.getComment()); |
||||
assertEquals("NAIRN", smart.getStationName()); |
||||
} |
||||
@Test |
||||
public void testSmartInvalidEnumVal6(){ |
||||
String json = "{\"STEPTYPE\":\"B\",\"FROMBERTH\":\"7910\",\"TOBERTH\":\"7904\",\"STANOX\":\"01125\",\"EVENT\":\"Z\",\"PLATFORM\":\"1\"," + |
||||
"\"TOLINE\":\"\",\"BERTHOFFSET\":\"59\",\"ROUTE\":\"\",\"FROMLINE\":\"\",\"TD\":\"IH\",\"COMMENT\":\"02/12/2018\",\"STANME\":\"NAIRN\"}"; |
||||
Smart smart = Smart.parseJSON(json); |
||||
assertEquals(SmartStepType.BETWEEN, smart.getStepType()); |
||||
assertEquals("7910", smart.getFromBerth()); |
||||
assertEquals("7904", smart.getToBerth()); |
||||
assertEquals("01125", smart.getStanox()); |
||||
assertNull(smart.getEvent()); |
||||
assertEquals("1", smart.getPlatform()); |
||||
assertEquals("", smart.getToLine()); |
||||
assertEquals(59, smart.getBerthOffset()); |
||||
assertEquals("", smart.getRoute()); |
||||
assertEquals("", smart.getFromLine()); |
||||
assertEquals("IH", smart.getTd()); |
||||
assertEquals("02/12/2018", smart.getComment()); |
||||
assertEquals("NAIRN", smart.getStationName()); |
||||
} |
||||
|
||||
@Test |
||||
public void testSmartNormalCase5(){ |
||||
String json = "{\"STEPTYPE\":\"B\",\"FROMBERTH\":\"7910\",\"TOBERTH\":\"7904\",\"STANOX\":\"01125\",\"EVENT\":\"A\",\"PLATFORM\":\"1\"," + |
||||
"\"TOLINE\":\"\",\"BERTHOFFSET\":\"59\",\"ROUTE\":\"\",\"FROMLINE\":\"\",\"TD\":\"IH\",\"COMMENT\":\"02/12/2018\",\"STANME\":\"NAIRN\"}"; |
||||
Smart smart = Smart.parseJSON(new JSONObject(json)); |
||||
assertEquals(SmartStepType.BETWEEN, smart.getStepType()); |
||||
assertEquals("7910", smart.getFromBerth()); |
||||
assertEquals("7904", smart.getToBerth()); |
||||
assertEquals("01125", smart.getStanox()); |
||||
assertEquals(SmartEvent.ARRIVE_UP, smart.getEvent()); |
||||
assertEquals("1", smart.getPlatform()); |
||||
assertEquals("", smart.getToLine()); |
||||
assertEquals(59, smart.getBerthOffset()); |
||||
assertEquals("", smart.getRoute()); |
||||
assertEquals("", smart.getFromLine()); |
||||
assertEquals("IH", smart.getTd()); |
||||
assertEquals("02/12/2018", smart.getComment()); |
||||
assertEquals("NAIRN", smart.getStationName()); |
||||
} |
||||
@Test |
||||
public void testSmartInvalidEnumVal5(){ |
||||
String json = "{\"STEPTYPE\":\"B\",\"FROMBERTH\":\"7910\",\"TOBERTH\":\"7904\",\"STANOX\":\"01125\",\"EVENT\":\"Z\",\"PLATFORM\":\"1\"," + |
||||
"\"TOLINE\":\"\",\"BERTHOFFSET\":\"59\",\"ROUTE\":\"\",\"FROMLINE\":\"\",\"TD\":\"IH\",\"COMMENT\":\"02/12/2018\",\"STANME\":\"NAIRN\"}"; |
||||
Smart smart = Smart.parseJSON(new JSONObject(json)); |
||||
assertEquals(SmartStepType.BETWEEN, smart.getStepType()); |
||||
assertEquals("7910", smart.getFromBerth()); |
||||
assertEquals("7904", smart.getToBerth()); |
||||
assertEquals("01125", smart.getStanox()); |
||||
assertNull(smart.getEvent()); |
||||
assertEquals("1", smart.getPlatform()); |
||||
assertEquals("", smart.getToLine()); |
||||
assertEquals(59, smart.getBerthOffset()); |
||||
assertEquals("", smart.getRoute()); |
||||
assertEquals("", smart.getFromLine()); |
||||
assertEquals("IH", smart.getTd()); |
||||
assertEquals("02/12/2018", smart.getComment()); |
||||
assertEquals("NAIRN", smart.getStationName()); |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,31 @@
|
||||
package org.leolo.nrdatad; |
||||
|
||||
import org.junit.Test; |
||||
import org.leolo.nrdatad.model.AssociationCategory; |
||||
import org.leolo.nrdatad.model.ShortTermPlanningIndicator; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
public class ScheduleEnumTest { |
||||
|
||||
@Test |
||||
public void testAssociationCategory(){ |
||||
assertEquals(AssociationCategory.DIVIDE, AssociationCategory.parseCode("VV")); |
||||
assertEquals(AssociationCategory.JOIN, AssociationCategory.parseCode("JJ")); |
||||
assertEquals(AssociationCategory.NEXT, AssociationCategory.parseCode("NP")); |
||||
assertNull(AssociationCategory.parseCode("XX")); |
||||
assertNull(AssociationCategory.parseCode(null)); |
||||
assertNull(AssociationCategory.parseCode("")); |
||||
} |
||||
|
||||
@Test public void testShortTermPlanningIndicator(){ |
||||
assertEquals(ShortTermPlanningIndicator.CANCELLATION, ShortTermPlanningIndicator.parseCode("C")); |
||||
assertEquals(ShortTermPlanningIndicator.NEW, ShortTermPlanningIndicator.parseCode("N")); |
||||
assertEquals(ShortTermPlanningIndicator.PERMANENT, ShortTermPlanningIndicator.parseCode("P")); |
||||
assertEquals(ShortTermPlanningIndicator.OVERLAY, ShortTermPlanningIndicator.parseCode("O")); |
||||
assertNull(ShortTermPlanningIndicator.parseCode("X")); |
||||
assertNull(ShortTermPlanningIndicator.parseCode(null)); |
||||
assertNull(ShortTermPlanningIndicator.parseCode("")); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,29 @@
|
||||
package org.leolo.nrdatad; |
||||
|
||||
import org.junit.Test; |
||||
import org.leolo.nrdatad.model.SmartEvent; |
||||
import org.leolo.nrdatad.model.SmartStepType; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
public class SmartEnumTest { |
||||
|
||||
@Test |
||||
public void testSmartStepType(){ |
||||
assertEquals(SmartStepType.BETWEEN, SmartStepType.parseCode("B")); |
||||
assertEquals(SmartStepType.BETWEEN, SmartStepType.parseCode("b")); |
||||
assertNull(SmartStepType.parseCode("Q")); |
||||
assertNull(SmartStepType.parseCode("X")); |
||||
assertNull(SmartStepType.parseCode("")); |
||||
} |
||||
|
||||
@Test |
||||
public void testSmartEvent(){ |
||||
assertEquals(SmartEvent.ARRIVE_UP, SmartEvent.parseCode("A")); |
||||
assertEquals(SmartEvent.ARRIVE_UP, SmartEvent.parseCode("a")); |
||||
assertNull(SmartEvent.parseCode("Q")); |
||||
assertNull(SmartEvent.parseCode("X")); |
||||
assertNull(SmartEvent.parseCode("")); |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,51 @@
|
||||
package org.leolo.nrdatad.db.test; |
||||
|
||||
import org.leolo.nrdatad.db.*; |
||||
import org.leolo.nrdatad.db.MetadataDao; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.SQLException; |
||||
|
||||
public class DatabaseManager implements org.leolo.nrdatad.db.DatabaseManager { |
||||
|
||||
public void initPool() { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public boolean checkConnection() { |
||||
return true; |
||||
} |
||||
|
||||
@Override |
||||
public Connection getConnection() throws SQLException { |
||||
throw new RuntimeException("Function not supported by stub"); |
||||
} |
||||
|
||||
@Override |
||||
public SmartDao getSmartDao() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public TiplocDao getTiplocDao() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public TrainAssociationDao getTrainAssociationDao() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public MetadataDao getMetadataDao() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public CorpusDao getCORPUSDao() { |
||||
return null; |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,40 @@
|
||||
package org.leolo.nrdatad.db.test; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.leolo.nrdatad.db.DatabaseManager; |
||||
|
||||
import java.sql.SQLException; |
||||
import java.util.HashMap; |
||||
import java.util.Set; |
||||
import java.util.function.BiConsumer; |
||||
|
||||
public class MetadataDao extends org.leolo.nrdatad.db.MetadataDao { |
||||
|
||||
private HashMap<String, String> dataMap = new HashMap<>(); |
||||
|
||||
public MetadataDao(DatabaseManager manager) { |
||||
super(manager); |
||||
} |
||||
|
||||
@Override |
||||
public String getMetadata(String key, String defaultValue) throws SQLException { |
||||
if(dataMap.containsKey(key)) |
||||
return dataMap.get(key); |
||||
return defaultValue; |
||||
} |
||||
|
||||
@Override |
||||
public void updateMetadata(String key, @NotNull String value) throws SQLException { |
||||
dataMap.put(key, value); |
||||
} |
||||
|
||||
@Override |
||||
public Set<String> getKeys() throws SQLException { |
||||
return dataMap.keySet(); |
||||
} |
||||
|
||||
@Override |
||||
public void forEach(BiConsumer<String, String> action) throws SQLException { |
||||
dataMap.forEach(action); |
||||
} |
||||
} |
||||
@ -0,0 +1,105 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
public class ScheduleAssociationTest { |
||||
|
||||
@Test public void basicCase1() throws ParseException { |
||||
String json = "{\"diagram_type\":\"T\",\"assoc_end_date\":\"2022-12-05T00:00:00Z\",\"assoc_location_suffix\":null," + |
||||
"\"assoc_days\":\"1000000\",\"assoc_train_uid\":\"L77547\",\"transaction_type\":\"Create\"," + |
||||
"\"date_indicator\":\"S\",\"base_location_suffix\":null,\"main_train_uid\":\"L77935\"," + |
||||
"\"CIF_stp_indicator\":\"P\",\"assoc_start_date\":\"2022-05-16T00:00:00Z\"," + |
||||
"\"location\":\"KNGX\",\"category\":\"NP\"}"; |
||||
ScheduleAssociation sa = ScheduleAssociation.parseJSON(json); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); |
||||
assertEquals(sdf.parse("20221205"), sa.getEndDate()); |
||||
assertEquals("", sa.getAssocLocationSuffix()); |
||||
assertEquals("1000000", sa.getAssoDays()); |
||||
assertEquals("L77547", sa.getAssoUid()); |
||||
assertEquals(0, sa.getAssociationDate()); |
||||
assertEquals("", sa.getBaseLocationSuffix()); |
||||
assertEquals("L77935", sa.getMainUid()); |
||||
assertEquals(ShortTermPlanningIndicator.PERMANENT, sa.getStpIndicator()); |
||||
assertEquals(sdf.parse("20220516"), sa.getStartDate()); |
||||
assertEquals("KNGX", sa.getAssociationLocation()); |
||||
assertEquals(AssociationCategory.NEXT, sa.getAssociationCategory()); |
||||
assertEquals("L77935L77547KNGXPFE4P", sa.getAuid()); |
||||
assertEquals(790828983, sa.hashCode()); |
||||
} |
||||
|
||||
@Test public void vstpAssoc1() throws ParseException { |
||||
String json = "{\"diagram_type\":\"T\",\"assoc_end_date\":\"2022-12-05T00:00:00Z\",\"assoc_location_suffix\":null," + |
||||
"\"assoc_days\":\"1000000\",\"assoc_train_uid\":\" 77547\",\"transaction_type\":\"Create\"," + |
||||
"\"date_indicator\":\"S\",\"base_location_suffix\":null,\"main_train_uid\":\" 77935\"," + |
||||
"\"CIF_stp_indicator\":\"P\",\"assoc_start_date\":\"2022-05-16T00:00:00Z\"," + |
||||
"\"location\":\"KNGX\",\"category\":\"NP\"}"; |
||||
ScheduleAssociation sa = ScheduleAssociation.parseJSON(json); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); |
||||
assertEquals(sdf.parse("20221205"), sa.getEndDate()); |
||||
assertEquals("", sa.getAssocLocationSuffix()); |
||||
assertEquals("1000000", sa.getAssoDays()); |
||||
assertEquals("77547", sa.getAssoUid()); |
||||
assertEquals(0, sa.getAssociationDate()); |
||||
assertEquals("", sa.getBaseLocationSuffix()); |
||||
assertEquals("77935", sa.getMainUid()); |
||||
assertEquals(ShortTermPlanningIndicator.PERMANENT, sa.getStpIndicator()); |
||||
assertEquals(sdf.parse("20220516"), sa.getStartDate()); |
||||
assertEquals("KNGX", sa.getAssociationLocation()); |
||||
assertEquals(AssociationCategory.NEXT, sa.getAssociationCategory()); |
||||
assertEquals("7793577547KNGXPFE4P", sa.getAuid()); |
||||
assertEquals(-1968067017, sa.hashCode()); |
||||
} |
||||
|
||||
|
||||
@Test public void basicCase2() throws ParseException { |
||||
String json = "{\"diagram_type\":\"T\",\"assoc_end_date\":\"2022-12-05T00:00:00Z\"," + |
||||
"\"assoc_days\":\"1000000\",\"assoc_train_uid\":\"L77547\",\"transaction_type\":\"Create\"," + |
||||
"\"date_indicator\":\"S\",\"main_train_uid\":\"L77935\"," + |
||||
"\"CIF_stp_indicator\":\"P\",\"assoc_start_date\":\"2022-05-16T00:00:00Z\"," + |
||||
"\"location\":\"KNGX\",\"category\":\"NP\"}"; |
||||
ScheduleAssociation sa = ScheduleAssociation.parseJSON(json); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); |
||||
assertEquals(sdf.parse("20221205"), sa.getEndDate()); |
||||
assertEquals("", sa.getAssocLocationSuffix()); |
||||
assertEquals("1000000", sa.getAssoDays()); |
||||
assertEquals("L77547", sa.getAssoUid()); |
||||
assertEquals(0, sa.getAssociationDate()); |
||||
assertEquals("", sa.getBaseLocationSuffix()); |
||||
assertEquals("L77935", sa.getMainUid()); |
||||
assertEquals(ShortTermPlanningIndicator.PERMANENT, sa.getStpIndicator()); |
||||
assertEquals(sdf.parse("20220516"), sa.getStartDate()); |
||||
assertEquals("KNGX", sa.getAssociationLocation()); |
||||
assertEquals(AssociationCategory.NEXT, sa.getAssociationCategory()); |
||||
assertEquals("L77935L77547KNGXPFE4P", sa.getAuid()); |
||||
assertEquals(790828983, sa.hashCode()); |
||||
} |
||||
|
||||
@Test public void vstpAssoc2() throws ParseException { |
||||
String json = "{\"diagram_type\":\"T\",\"assoc_end_date\":\"2022-12-05T00:00:00Z\"," + |
||||
"\"assoc_days\":\"1000000\",\"assoc_train_uid\":\" 77547\",\"transaction_type\":\"Create\"," + |
||||
"\"date_indicator\":\"S\",\"main_train_uid\":\" 77935\"," + |
||||
"\"CIF_stp_indicator\":\"P\",\"assoc_start_date\":\"2022-05-16T00:00:00Z\"," + |
||||
"\"location\":\"KNGX\",\"category\":\"NP\"}"; |
||||
ScheduleAssociation sa = ScheduleAssociation.parseJSON(json); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); |
||||
assertEquals(sdf.parse("20221205"), sa.getEndDate()); |
||||
assertEquals("", sa.getAssocLocationSuffix()); |
||||
assertEquals("1000000", sa.getAssoDays()); |
||||
assertEquals("77547", sa.getAssoUid()); |
||||
assertEquals(0, sa.getAssociationDate()); |
||||
assertEquals("", sa.getBaseLocationSuffix()); |
||||
assertEquals("77935", sa.getMainUid()); |
||||
assertEquals(ShortTermPlanningIndicator.PERMANENT, sa.getStpIndicator()); |
||||
assertEquals(sdf.parse("20220516"), sa.getStartDate()); |
||||
assertEquals("KNGX", sa.getAssociationLocation()); |
||||
assertEquals(AssociationCategory.NEXT, sa.getAssociationCategory()); |
||||
assertEquals("7793577547KNGXPFE4P", sa.getAuid()); |
||||
assertEquals(-1968067017, sa.hashCode()); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,30 @@
|
||||
package org.leolo.nrdatad.model; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
public class TiplocTest { |
||||
@Test public void basicTest(){ |
||||
String json = "{\"tps_description\":\"ABERDEEN\",\"crs_code\":\"ABD\",\"description\":\"ABERDEEN\"," + |
||||
"\"stanox\":\"02071\",\"tiploc_code\":\"ABRDEEN\",\"transaction_type\":\"Create\",\"nalco\":\"897600\"}"; |
||||
Tiploc tiploc = Tiploc.parseJSON(json); |
||||
assertEquals("ABERDEEN", tiploc.getTpsDescription()); |
||||
assertEquals("ABD", tiploc.getCrsCode()); |
||||
assertEquals("ABERDEEN", tiploc.getDescription()); |
||||
assertEquals("02071", tiploc.getStanox()); |
||||
assertEquals("ABRDEEN", tiploc.getTiplocCode()); |
||||
assertEquals("897600", tiploc.getNalco()); |
||||
} |
||||
@Test public void basicTest2(){ |
||||
String json = "{\"tps_description\":\"ABERDEEN\",\"description\":\"ABERDEEN\"," + |
||||
"\"stanox\":\"02071\",\"tiploc_code\":\"ABRDEEN\",\"transaction_type\":\"Create\",\"nalco\":\"897600\"}"; |
||||
Tiploc tiploc = Tiploc.parseJSON(json); |
||||
assertEquals("ABERDEEN", tiploc.getTpsDescription()); |
||||
assertEquals("", tiploc.getCrsCode()); |
||||
assertEquals("ABERDEEN", tiploc.getDescription()); |
||||
assertEquals("02071", tiploc.getStanox()); |
||||
assertEquals("ABRDEEN", tiploc.getTiplocCode()); |
||||
assertEquals("897600", tiploc.getNalco()); |
||||
} |
||||
} |
||||
@ -0,0 +1,208 @@
|
||||
package org.leolo.nrdatad.model; |
||||
import org.junit.Test; |
||||
import org.leolo.nrdatad.util.TestUtil; |
||||
import org.leolo.nrdatad.util.TimeUtil; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.InputStreamReader; |
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
|
||||
import static org.junit.Assert.*; |
||||
public class TrainScheduleTest { |
||||
|
||||
@Test public void testSchedule1() throws IOException, ParseException { |
||||
String json = TestUtil.openResourceFileAsString("org/leolo/nrdatad/test/V56331_N.json"); |
||||
TrainSchedule ts = TrainSchedule.parseJSON(json); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); |
||||
//Schedule Info
|
||||
assertEquals("V56331", ts.getTrainUid()); |
||||
assertEquals("V56331M3M4N", ts.getSUID()); |
||||
assertEquals("AW", ts.getAtocCode()); |
||||
assertEquals(ShortTermPlanningIndicator.NEW, ts.getShortTermPlanningIndicator()); |
||||
assertEquals(sdf.parse("20230104"), ts.getStartDate()); |
||||
assertEquals(sdf.parse("20230105"), ts.getEndDate()); |
||||
assertEquals("0011000", ts.getRunsOn()); |
||||
assertEquals("",ts.getRunsOnBankHoliday()); |
||||
//Sector Info
|
||||
TrainScheduleSector tss = ts.getSector(); |
||||
assertEquals("", tss.getServiceBranding()); |
||||
assertEquals("OO", tss.getTrainCategory()); |
||||
assertEquals("??", tss.getBusinessSector()); |
||||
assertEquals(75, tss.getSpeed()); |
||||
assertEquals("", tss.getReservation()); |
||||
assertEquals("", tss.getCatering()); |
||||
assertEquals("DMU", tss.getPowerType()); |
||||
assertEquals("S", tss.getTimingLoad()); |
||||
assertEquals("2F60", tss.getSignalId()); |
||||
assertEquals("", tss.getHeadcode()); |
||||
assertEquals("", tss.getOperatingCharacteristic()); |
||||
assertEquals("", tss.getSleeper()); |
||||
assertEquals("25441000", tss.getTrainServiceCode()); |
||||
assertEquals("S", tss.getTrainClass()); |
||||
//Check each location
|
||||
//1 - PTYPRID
|
||||
TrainScheduleLocation tsl = tss.getScheduleLocations().get(0); |
||||
assertEquals(0, tsl.getPathingAllowance()); |
||||
assertEquals(TrainScheduleLocationRecordIdentity.ORIGINATE, tsl.getRecordIdentity()); |
||||
assertEquals(0, tsl.getEngineeringAllowance()); |
||||
assertEquals("U", tsl.getLine()); |
||||
assertEquals("", tsl.getPath()); |
||||
assertEquals(TrainScheduleLocation.UNKNOWN_RECORD_SEQUENCE, tsl.getTiplocInstance()); |
||||
assertEquals(tss, tsl.getRecordSector()); |
||||
assertEquals(1, tsl.getRecordSequence()); |
||||
assertEquals("1", tsl.getPlatform()); |
||||
assertEquals(TimeUtil.parseTime("1654"), tsl.getWttDeparture()); |
||||
assertEquals(TimeUtil.parseTime("1654"), tsl.getPublicDeparture()); |
||||
assertEquals(0, tsl.getWttArrival()); |
||||
assertEquals(0, tsl.getPublicArrival()); |
||||
assertEquals(0, tsl.getWttPass()); |
||||
//2 - TREFRST
|
||||
tsl = tss.getScheduleLocations().get(1); |
||||
assertEquals(180_000, tsl.getPathingAllowance()); |
||||
assertEquals(TrainScheduleLocationRecordIdentity.INTERMEDIATE, tsl.getRecordIdentity()); |
||||
assertEquals(60_000, tsl.getEngineeringAllowance()); |
||||
assertEquals("UL", tsl.getLine()); |
||||
assertEquals("UP", tsl.getPath()); |
||||
assertEquals(TrainScheduleLocation.UNKNOWN_RECORD_SEQUENCE, tsl.getTiplocInstance()); |
||||
assertEquals(tss, tsl.getRecordSector()); |
||||
assertEquals(2, tsl.getRecordSequence()); |
||||
assertEquals("A", tsl.getPlatform()); |
||||
assertEquals(TimeUtil.parseTime("1657H"), tsl.getWttDeparture()); |
||||
assertEquals(TimeUtil.parseTime("1657"), tsl.getPublicDeparture()); |
||||
assertEquals(TimeUtil.parseTime("1656H"), tsl.getWttArrival()); |
||||
assertEquals(TimeUtil.parseTime("1656"), tsl.getPublicArrival()); |
||||
assertEquals(0, tsl.getWttPass()); |
||||
//8 - CVLESBY
|
||||
tsl = tss.getScheduleLocations().get(7); |
||||
assertEquals(0, tsl.getPathingAllowance()); |
||||
assertEquals(TrainScheduleLocationRecordIdentity.INTERMEDIATE, tsl.getRecordIdentity()); |
||||
assertEquals(0, tsl.getEngineeringAllowance()); |
||||
assertEquals("", tsl.getLine()); |
||||
assertEquals("", tsl.getPath()); |
||||
assertEquals(TrainScheduleLocation.UNKNOWN_RECORD_SEQUENCE, tsl.getTiplocInstance()); |
||||
assertEquals(tss, tsl.getRecordSector()); |
||||
assertEquals(8, tsl.getRecordSequence()); |
||||
assertEquals("", tsl.getPlatform()); |
||||
assertEquals(0, tsl.getWttDeparture()); |
||||
assertEquals(0, tsl.getPublicDeparture()); |
||||
assertEquals(0, tsl.getWttArrival()); |
||||
assertEquals(0, tsl.getPublicArrival()); |
||||
assertEquals(TimeUtil.parseTime("1723"), tsl.getWttPass()); |
||||
//9 - CRDFCEN
|
||||
tsl = tss.getScheduleLocations().get(8); |
||||
assertEquals(0, tsl.getPathingAllowance()); |
||||
assertEquals(TrainScheduleLocationRecordIdentity.TERMINATE, tsl.getRecordIdentity()); |
||||
assertEquals(0, tsl.getEngineeringAllowance()); |
||||
assertEquals("", tsl.getLine()); |
||||
assertEquals("", tsl.getPath()); |
||||
assertEquals(TrainScheduleLocation.UNKNOWN_RECORD_SEQUENCE, tsl.getTiplocInstance()); |
||||
assertEquals(tss, tsl.getRecordSector()); |
||||
assertEquals(9, tsl.getRecordSequence()); |
||||
assertEquals("7", tsl.getPlatform()); |
||||
assertEquals(0, tsl.getWttDeparture()); |
||||
assertEquals(0, tsl.getPublicDeparture()); |
||||
assertEquals(TimeUtil.parseTime("1724"), tsl.getWttArrival()); |
||||
assertEquals(TimeUtil.parseTime("1725"), tsl.getPublicArrival()); |
||||
assertEquals(0, tsl.getWttPass()); |
||||
} |
||||
|
||||
@Test public void testSchedule2() throws IOException, ParseException { |
||||
String json = TestUtil.openResourceFileAsString("org/leolo/nrdatad/test/V56332_N.json"); |
||||
TrainSchedule ts = TrainSchedule.parseJSON(json); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); |
||||
//Schedule Info
|
||||
assertEquals("V56332", ts.getTrainUid()); |
||||
assertEquals("V56332M3M4N", ts.getSUID()); |
||||
assertEquals("AW", ts.getAtocCode()); |
||||
assertEquals(ShortTermPlanningIndicator.NEW, ts.getShortTermPlanningIndicator()); |
||||
assertEquals(sdf.parse("20230104"), ts.getStartDate()); |
||||
assertEquals(sdf.parse("20230105"), ts.getEndDate()); |
||||
assertEquals("0011000", ts.getRunsOn()); |
||||
assertEquals("",ts.getRunsOnBankHoliday()); |
||||
//Sector Info
|
||||
TrainScheduleSector tss = ts.getSector(); |
||||
assertEquals("", tss.getServiceBranding()); |
||||
assertEquals("OO", tss.getTrainCategory()); |
||||
assertEquals("??", tss.getBusinessSector()); |
||||
assertEquals(75, tss.getSpeed()); |
||||
assertEquals("", tss.getReservation()); |
||||
assertEquals("", tss.getCatering()); |
||||
assertEquals("DMU", tss.getPowerType()); |
||||
assertEquals("S", tss.getTimingLoad()); |
||||
assertEquals("2F60", tss.getSignalId()); |
||||
assertEquals("", tss.getHeadcode()); |
||||
assertEquals("", tss.getOperatingCharacteristic()); |
||||
assertEquals("", tss.getSleeper()); |
||||
assertEquals("25441000", tss.getTrainServiceCode()); |
||||
assertEquals("S", tss.getTrainClass()); |
||||
//Check each location
|
||||
//1 - PTYPRID
|
||||
TrainScheduleLocation tsl = tss.getScheduleLocations().get(0); |
||||
assertEquals(0, tsl.getPathingAllowance()); |
||||
assertEquals(TrainScheduleLocationRecordIdentity.ORIGINATE, tsl.getRecordIdentity()); |
||||
assertEquals(0, tsl.getEngineeringAllowance()); |
||||
assertEquals("U", tsl.getLine()); |
||||
assertEquals("", tsl.getPath()); |
||||
assertEquals(TrainScheduleLocation.UNKNOWN_RECORD_SEQUENCE, tsl.getTiplocInstance()); |
||||
assertEquals(tss, tsl.getRecordSector()); |
||||
assertEquals(1, tsl.getRecordSequence()); |
||||
assertEquals("1", tsl.getPlatform()); |
||||
assertEquals(TimeUtil.parseTime("1654"), tsl.getWttDeparture()); |
||||
assertEquals(TimeUtil.parseTime("1654"), tsl.getPublicDeparture()); |
||||
assertEquals(0, tsl.getWttArrival()); |
||||
assertEquals(0, tsl.getPublicArrival()); |
||||
assertEquals(0, tsl.getWttPass()); |
||||
//2 - TREFRST
|
||||
tsl = tss.getScheduleLocations().get(1); |
||||
assertEquals(180_000, tsl.getPathingAllowance()); |
||||
assertEquals(TrainScheduleLocationRecordIdentity.INTERMEDIATE, tsl.getRecordIdentity()); |
||||
assertEquals(60_000, tsl.getEngineeringAllowance()); |
||||
assertEquals("UL", tsl.getLine()); |
||||
assertEquals("UP", tsl.getPath()); |
||||
assertEquals(TrainScheduleLocation.UNKNOWN_RECORD_SEQUENCE, tsl.getTiplocInstance()); |
||||
assertEquals(tss, tsl.getRecordSector()); |
||||
assertEquals(2, tsl.getRecordSequence()); |
||||
assertEquals("A", tsl.getPlatform()); |
||||
assertEquals(TimeUtil.parseTime("1657H"), tsl.getWttDeparture()); |
||||
assertEquals(TimeUtil.parseTime("1657"), tsl.getPublicDeparture()); |
||||
assertEquals(TimeUtil.parseTime("1656H"), tsl.getWttArrival()); |
||||
assertEquals(TimeUtil.parseTime("1656"), tsl.getPublicArrival()); |
||||
assertEquals(0, tsl.getWttPass()); |
||||
//8 - CVLESBY
|
||||
tsl = tss.getScheduleLocations().get(7); |
||||
assertEquals(0, tsl.getPathingAllowance()); |
||||
assertEquals(TrainScheduleLocationRecordIdentity.INTERMEDIATE, tsl.getRecordIdentity()); |
||||
assertEquals(0, tsl.getEngineeringAllowance()); |
||||
assertEquals("", tsl.getLine()); |
||||
assertEquals("", tsl.getPath()); |
||||
assertEquals(TrainScheduleLocation.UNKNOWN_RECORD_SEQUENCE, tsl.getTiplocInstance()); |
||||
assertEquals(tss, tsl.getRecordSector()); |
||||
assertEquals(8, tsl.getRecordSequence()); |
||||
assertEquals("", tsl.getPlatform()); |
||||
assertEquals(0, tsl.getWttDeparture()); |
||||
assertEquals(0, tsl.getPublicDeparture()); |
||||
assertEquals(0, tsl.getWttArrival()); |
||||
assertEquals(0, tsl.getPublicArrival()); |
||||
assertEquals(TimeUtil.parseTime("1723"), tsl.getWttPass()); |
||||
//9 - CRDFCEN
|
||||
tsl = tss.getScheduleLocations().get(8); |
||||
assertEquals(0, tsl.getPathingAllowance()); |
||||
assertEquals(TrainScheduleLocationRecordIdentity.TERMINATE, tsl.getRecordIdentity()); |
||||
assertEquals(0, tsl.getEngineeringAllowance()); |
||||
assertEquals("", tsl.getLine()); |
||||
assertEquals("", tsl.getPath()); |
||||
assertEquals(TrainScheduleLocation.UNKNOWN_RECORD_SEQUENCE, tsl.getTiplocInstance()); |
||||
assertEquals(tss, tsl.getRecordSector()); |
||||
assertEquals(9, tsl.getRecordSequence()); |
||||
assertEquals("7", tsl.getPlatform()); |
||||
assertEquals(0, tsl.getWttDeparture()); |
||||
assertEquals(0, tsl.getPublicDeparture()); |
||||
assertEquals(TimeUtil.parseTime("1724"), tsl.getWttArrival()); |
||||
assertEquals(TimeUtil.parseTime("1725"), tsl.getPublicArrival()); |
||||
assertEquals(0, tsl.getWttPass()); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,41 @@
|
||||
package org.leolo.nrdatad.util; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import java.util.Calendar; |
||||
import java.util.Date; |
||||
import java.util.GregorianCalendar; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
public class DateUtilTest { |
||||
|
||||
@Test public void testDate1(){ |
||||
// Second day of January 2022
|
||||
Date d1 = DateUtil.parseDate("2022-01-02"); |
||||
Calendar c = GregorianCalendar.getInstance(); |
||||
c.setTime(d1); |
||||
assertEquals(2022, c.get(Calendar.YEAR)); |
||||
assertEquals(Calendar.JANUARY, c.get(Calendar.MONTH)); |
||||
assertEquals(2, c.get(Calendar.DAY_OF_MONTH)); |
||||
} |
||||
|
||||
@Test public void testDate2(){ |
||||
// Second day of January 2022
|
||||
Date d1 = DateUtil.parseDate("2022-01-02", "yyyy-dd-MM"); |
||||
Calendar c = GregorianCalendar.getInstance(); |
||||
c.setTime(d1); |
||||
assertEquals(2022, c.get(Calendar.YEAR)); |
||||
assertEquals(Calendar.FEBRUARY, c.get(Calendar.MONTH)); |
||||
assertEquals(1, c.get(Calendar.DAY_OF_MONTH)); |
||||
} |
||||
|
||||
@Test public void testDateInvalidSuppressed(){ |
||||
assertNull(DateUtil.parseDate("This is not a date")); |
||||
} |
||||
|
||||
@Test(expected = RuntimeException.class) public void testDateException(){ |
||||
DateUtil.parseDate("This is not a date", false); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,48 @@
|
||||
package org.leolo.nrdatad.util; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
public class JSONUtilTest { |
||||
|
||||
@Test public void testJSONUtilParseIntNormal(){ |
||||
assertEquals(10, JSONUtil.parseInt("10")); |
||||
assertEquals(0, JSONUtil.parseInt("0")); |
||||
assertEquals(10, JSONUtil.parseInt("+10")); |
||||
assertEquals(-10, JSONUtil.parseInt("-10")); |
||||
} |
||||
|
||||
@Test public void testZeroPrefix(){ |
||||
assertEquals(75, JSONUtil.parseInt("075")); |
||||
assertEquals(5, JSONUtil.parseInt("005")); |
||||
assertEquals(75, JSONUtil.parseInt("+075")); |
||||
assertEquals(5, JSONUtil.parseInt("+005")); |
||||
assertEquals(-75, JSONUtil.parseInt("-075")); |
||||
assertEquals(-5, JSONUtil.parseInt("-005")); |
||||
} |
||||
|
||||
@Test public void testAllZero(){ |
||||
assertEquals(0, JSONUtil.parseInt("00000000")); |
||||
} |
||||
|
||||
@Test(expected = NumberFormatException.class) public void testJSONUtilParseIntError1(){ |
||||
JSONUtil.parseInt("abcd"); |
||||
} |
||||
@Test(expected = NumberFormatException.class) public void testJSONUtilParseIntError2(){ |
||||
JSONUtil.parseInt(""); |
||||
} |
||||
@Test(expected = NullPointerException.class) public void testJSONUtilParseIntError3(){ |
||||
JSONUtil.parseInt(null); |
||||
} |
||||
@Test(expected = NumberFormatException.class) public void testJSONUtilParseIntError4(){ |
||||
JSONUtil.parseInt("+"); |
||||
} |
||||
@Test(expected = NumberFormatException.class) public void testJSONUtilParseIntError5(){ |
||||
JSONUtil.parseInt("+abcd"); |
||||
} |
||||
@Test(expected = NumberFormatException.class) public void testJSONUtilParseIntError6(){ |
||||
JSONUtil.parseInt("+2200000000"); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,20 @@
|
||||
package org.leolo.nrdatad.util; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import static org.junit.Assert.*; |
||||
public class RangeTest { |
||||
|
||||
@Test |
||||
public void basicInteger1(){ |
||||
Range<Integer> range = new Range<>(1,2); |
||||
assertEquals(1, range.getLowerBound().intValue()); |
||||
assertEquals(2, range.getUpperBound().intValue()); |
||||
range = new Range<>(2,1); |
||||
assertEquals(1, range.getLowerBound().intValue()); |
||||
assertEquals(2, range.getUpperBound().intValue()); |
||||
range = new Range<>(2,2); |
||||
assertEquals(2, range.getLowerBound().intValue()); |
||||
assertEquals(2, range.getUpperBound().intValue()); |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@
|
||||
package org.leolo.nrdatad.util; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
public class TUIDDateFormatTest { |
||||
|
||||
@Test |
||||
public void basicConvert() throws ParseException { |
||||
assertEquals("M0", convert("2022-01-01")); |
||||
assertEquals("MX", convert("2022-01-31")); |
||||
assertEquals("M0", convert("2023-01-01")); |
||||
assertEquals("MX", convert("2023-01-31")); |
||||
|
||||
assertEquals("P0", convert("2022-05-01")); |
||||
assertEquals("PX", convert("2022-05-31")); |
||||
assertEquals("P0", convert("2023-05-01")); |
||||
assertEquals("PX", convert("2023-05-31")); |
||||
|
||||
assertEquals("E0", convert("2022-12-01")); |
||||
assertEquals("EX", convert("2022-12-31")); |
||||
assertEquals("E0", convert("2023-12-01")); |
||||
assertEquals("EX", convert("2023-12-31")); |
||||
|
||||
} |
||||
|
||||
private String convert(String date) throws ParseException { |
||||
return new TUIDDateFormat().format(new SimpleDateFormat("yyyy-MM-dd").parse(date)); |
||||
} |
||||
} |
||||
@ -0,0 +1,31 @@
|
||||
package org.leolo.nrdatad.util; |
||||
|
||||
import java.io.*; |
||||
|
||||
public class TestUtil { |
||||
|
||||
public static BufferedReader openResourceFileAsBufferedReader(String fileName) throws IOException { |
||||
ClassLoader classloader = Thread.currentThread().getContextClassLoader(); |
||||
InputStream is = classloader.getResourceAsStream(fileName); |
||||
if(is==null){ |
||||
throw new FileNotFoundException("Resource file "+fileName+" cannot be found"); |
||||
}else{ |
||||
return new BufferedReader(new InputStreamReader(is)); |
||||
} |
||||
} |
||||
|
||||
public static String openResourceFileAsString(String fileName) throws IOException { |
||||
ClassLoader classloader = Thread.currentThread().getContextClassLoader(); |
||||
InputStream is = classloader.getResourceAsStream(fileName); |
||||
if(is==null){ |
||||
throw new FileNotFoundException("Resource file "+fileName+" cannot be found"); |
||||
} |
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||
is.transferTo(baos); |
||||
String result = new String(baos.toByteArray()); |
||||
baos.close(); |
||||
is.close(); |
||||
return result; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,75 @@
|
||||
package org.leolo.nrdatad.util; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
public class TimeUtilTest { |
||||
|
||||
@Test public void testAllowance(){ |
||||
assertEquals(60000, TimeUtil.parseTime("1")); |
||||
assertEquals(0, TimeUtil.parseTime("")); |
||||
assertEquals(0, TimeUtil.parseTime(" ")); |
||||
assertEquals(0, TimeUtil.parseTime(" ")); |
||||
assertEquals(60000, TimeUtil.parseTime("1 ")); |
||||
assertEquals(90000, TimeUtil.parseTime("1H")); |
||||
assertEquals(30000, TimeUtil.parseTime("H")); |
||||
assertEquals(30000, TimeUtil.parseTime("H ")); |
||||
assertEquals(30000, TimeUtil.parseTime(" H")); |
||||
assertEquals(600000, TimeUtil.parseTime("10")); |
||||
assertEquals(900000, TimeUtil.parseTime("15")); |
||||
assertEquals(1200000, TimeUtil.parseTime("20")); |
||||
} |
||||
|
||||
@Test public void testWTTTime(){ |
||||
assertEquals(3_660_000, TimeUtil.parseTime("0101 ")); |
||||
assertEquals(3_690_000, TimeUtil.parseTime("0101H")); |
||||
assertEquals(36_000_000, TimeUtil.parseTime("1000 ")); |
||||
assertEquals(37_800_000, TimeUtil.parseTime("1030 ")); |
||||
assertEquals(36_030_000, TimeUtil.parseTime("1000H")); |
||||
assertEquals(37_830_000, TimeUtil.parseTime("1030H")); |
||||
assertEquals(72_000_000, TimeUtil.parseTime("2000 ")); |
||||
assertEquals(73_800_000, TimeUtil.parseTime("2030 ")); |
||||
assertEquals(72_030_000, TimeUtil.parseTime("2000H")); |
||||
assertEquals(73_830_000, TimeUtil.parseTime("2030H")); |
||||
assertEquals(3_660_000, TimeUtil.parseTime("0101 ", 0)); |
||||
assertEquals(3_690_000, TimeUtil.parseTime("0101H", 0)); |
||||
assertEquals(36_000_000, TimeUtil.parseTime("1000 ", 0)); |
||||
assertEquals(37_800_000, TimeUtil.parseTime("1030 ", 0)); |
||||
assertEquals(36_030_000, TimeUtil.parseTime("1000H", 0)); |
||||
assertEquals(37_830_000, TimeUtil.parseTime("1030H", 0)); |
||||
assertEquals(72_000_000, TimeUtil.parseTime("2000 ", 0)); |
||||
assertEquals(73_800_000, TimeUtil.parseTime("2030 ", 0)); |
||||
assertEquals(72_030_000, TimeUtil.parseTime("2000H", 0)); |
||||
assertEquals(73_830_000, TimeUtil.parseTime("2030H", 0)); |
||||
// 86_400_000
|
||||
assertEquals( 90_060_000, TimeUtil.parseTime("0101 ", 1)); |
||||
assertEquals( 90_090_000, TimeUtil.parseTime("0101H", 1)); |
||||
assertEquals(122_400_000, TimeUtil.parseTime("1000 ", 1)); |
||||
assertEquals(124_200_000, TimeUtil.parseTime("1030 ", 1)); |
||||
assertEquals(122_430_000, TimeUtil.parseTime("1000H", 1)); |
||||
assertEquals(124_230_000, TimeUtil.parseTime("1030H", 1)); |
||||
assertEquals(158_400_000, TimeUtil.parseTime("2000 ", 1)); |
||||
assertEquals(160_200_000, TimeUtil.parseTime("2030 ", 1)); |
||||
assertEquals(158_430_000, TimeUtil.parseTime("2000H", 1)); |
||||
assertEquals(160_230_000, TimeUtil.parseTime("2030H", 1)); |
||||
} |
||||
|
||||
@Test public void testGBTTTime(){ |
||||
assertEquals(3_660_000, TimeUtil.parseTime("0101")); |
||||
assertEquals(36_000_000, TimeUtil.parseTime("1000")); |
||||
assertEquals(37_800_000, TimeUtil.parseTime("1030")); |
||||
assertEquals(72_000_000, TimeUtil.parseTime("2000")); |
||||
assertEquals(73_800_000, TimeUtil.parseTime("2030")); |
||||
assertEquals(3_660_000, TimeUtil.parseTime("0101", 0)); |
||||
assertEquals(36_000_000, TimeUtil.parseTime("1000", 0)); |
||||
assertEquals(37_800_000, TimeUtil.parseTime("1030", 0)); |
||||
assertEquals(72_000_000, TimeUtil.parseTime("2000", 0)); |
||||
assertEquals(73_800_000, TimeUtil.parseTime("2030", 0)); |
||||
assertEquals( 90_060_000, TimeUtil.parseTime("0101", 1)); |
||||
assertEquals(122_400_000, TimeUtil.parseTime("1000", 1)); |
||||
assertEquals(124_200_000, TimeUtil.parseTime("1030", 1)); |
||||
assertEquals(158_400_000, TimeUtil.parseTime("2000", 1)); |
||||
assertEquals(160_200_000, TimeUtil.parseTime("2030", 1)); |
||||
} |
||||
} |
||||
@ -0,0 +1,178 @@
|
||||
{ |
||||
"CIF_bank_holiday_running": null, |
||||
"train_status": "1", |
||||
"CIF_train_uid": "V56331", |
||||
"schedule_days_runs": "0011000", |
||||
"CIF_stp_indicator": "N", |
||||
"applicable_timetable": "Y", |
||||
"atoc_code": "AW", |
||||
"schedule_start_date": "2023-01-04", |
||||
"new_schedule_segment": { |
||||
"uic_code": "", |
||||
"traction_class": "" |
||||
}, |
||||
"transaction_type": "Create", |
||||
"schedule_end_date": "2023-01-05", |
||||
"schedule_segment": { |
||||
"CIF_service_branding": "", |
||||
"CIF_train_category": "OO", |
||||
"CIF_business_sector": "??", |
||||
"CIF_connection_indicator": null, |
||||
"CIF_speed": "075", |
||||
"CIF_reservations": null, |
||||
"CIF_catering_code": null, |
||||
"CIF_power_type": "DMU", |
||||
"CIF_course_indicator": 1, |
||||
"CIF_timing_load": "S", |
||||
"signalling_id": "2F60", |
||||
"CIF_headcode": "", |
||||
"CIF_operating_characteristics": null, |
||||
"schedule_location": [ |
||||
{ |
||||
"pathing_allowance": null, |
||||
"record_identity": "LO", |
||||
"engineering_allowance": null, |
||||
"line": "U", |
||||
"public_departure": "1654", |
||||
"tiploc_code": "PTYPRID", |
||||
"tiploc_instance": null, |
||||
"departure": "1654", |
||||
"performance_allowance": null, |
||||
"location_type": "LO", |
||||
"platform": "1" |
||||
}, |
||||
{ |
||||
"engineering_allowance": "1", |
||||
"arrival": "1656H", |
||||
"pass": null, |
||||
"line": "UL", |
||||
"public_arrival": "1656", |
||||
"performance_allowance": "2", |
||||
"location_type": "LI", |
||||
"platform": "A", |
||||
"pathing_allowance": "3", |
||||
"record_identity": "LI", |
||||
"path": "UP", |
||||
"public_departure": "1657", |
||||
"tiploc_code": "TREFRST", |
||||
"tiploc_instance": null, |
||||
"departure": "1657H" |
||||
}, |
||||
{ |
||||
"engineering_allowance": null, |
||||
"arrival": "1703", |
||||
"pass": null, |
||||
"line": null, |
||||
"public_arrival": "1704", |
||||
"performance_allowance": null, |
||||
"location_type": "LI", |
||||
"platform": null, |
||||
"pathing_allowance": null, |
||||
"record_identity": "LI", |
||||
"path": null, |
||||
"public_departure": "1704", |
||||
"tiploc_code": "TAFFSWL", |
||||
"tiploc_instance": null, |
||||
"departure": "1704" |
||||
}, |
||||
{ |
||||
"engineering_allowance": null, |
||||
"arrival": "1707", |
||||
"pass": null, |
||||
"line": null, |
||||
"public_arrival": "1708", |
||||
"performance_allowance": null, |
||||
"location_type": "LI", |
||||
"platform": "1", |
||||
"pathing_allowance": null, |
||||
"record_identity": "LI", |
||||
"path": null, |
||||
"public_departure": "1708", |
||||
"tiploc_code": "RADYR", |
||||
"tiploc_instance": null, |
||||
"departure": "1708" |
||||
}, |
||||
{ |
||||
"engineering_allowance": null, |
||||
"arrival": "1710", |
||||
"pass": null, |
||||
"line": null, |
||||
"public_arrival": "1710", |
||||
"performance_allowance": null, |
||||
"location_type": "LI", |
||||
"platform": null, |
||||
"pathing_allowance": null, |
||||
"record_identity": "LI", |
||||
"path": null, |
||||
"public_departure": "1711", |
||||
"tiploc_code": "LLANDAF", |
||||
"tiploc_instance": null, |
||||
"departure": "1711" |
||||
}, |
||||
{ |
||||
"engineering_allowance": "1", |
||||
"arrival": "1714H", |
||||
"pass": null, |
||||
"line": null, |
||||
"public_arrival": "1715", |
||||
"performance_allowance": null, |
||||
"location_type": "LI", |
||||
"platform": null, |
||||
"pathing_allowance": "H", |
||||
"record_identity": "LI", |
||||
"path": null, |
||||
"public_departure": "1715", |
||||
"tiploc_code": "CATHAYS", |
||||
"tiploc_instance": null, |
||||
"departure": "1715H" |
||||
}, |
||||
{ |
||||
"engineering_allowance": null, |
||||
"arrival": "1719", |
||||
"pass": null, |
||||
"line": null, |
||||
"public_arrival": "1720", |
||||
"performance_allowance": null, |
||||
"location_type": "LI", |
||||
"platform": "3", |
||||
"pathing_allowance": null, |
||||
"record_identity": "LI", |
||||
"path": null, |
||||
"public_departure": "1721", |
||||
"tiploc_code": "CARDFQS", |
||||
"tiploc_instance": null, |
||||
"departure": "1721" |
||||
}, |
||||
{ |
||||
"engineering_allowance": null, |
||||
"arrival": null, |
||||
"pass": "1723", |
||||
"line": null, |
||||
"public_arrival": null, |
||||
"performance_allowance": null, |
||||
"location_type": "LI", |
||||
"platform": null, |
||||
"pathing_allowance": null, |
||||
"record_identity": "LI", |
||||
"path": null, |
||||
"public_departure": null, |
||||
"tiploc_code": "CVLESBY", |
||||
"tiploc_instance": null, |
||||
"departure": null |
||||
}, |
||||
{ |
||||
"record_identity": "LT", |
||||
"path": null, |
||||
"arrival": "1724", |
||||
"public_arrival": "1725", |
||||
"tiploc_code": "CRDFCEN", |
||||
"tiploc_instance": null, |
||||
"location_type": "LT", |
||||
"platform": "7" |
||||
} |
||||
], |
||||
"CIF_sleepers": null, |
||||
"CIF_train_service_code": "25441000", |
||||
"CIF_train_class": "S" |
||||
} |
||||
} |
||||
@ -0,0 +1,113 @@
|
||||
{ |
||||
"train_status": "1", |
||||
"CIF_train_uid": "V56332", |
||||
"schedule_days_runs": "0011000", |
||||
"CIF_stp_indicator": "N", |
||||
"applicable_timetable": "Y", |
||||
"atoc_code": "AW", |
||||
"schedule_start_date": "2023-01-04", |
||||
"new_schedule_segment": { |
||||
}, |
||||
"transaction_type": "Create", |
||||
"schedule_end_date": "2023-01-05", |
||||
"schedule_segment": { |
||||
"CIF_train_category": "OO", |
||||
"CIF_business_sector": "??", |
||||
"CIF_speed": "075", |
||||
"CIF_power_type": "DMU", |
||||
"CIF_course_indicator": 1, |
||||
"CIF_timing_load": "S", |
||||
"signalling_id": "2F60", |
||||
"schedule_location": [ |
||||
{ |
||||
"record_identity": "LO", |
||||
"line": "U", |
||||
"public_departure": "1654", |
||||
"tiploc_code": "PTYPRID", |
||||
"departure": "1654", |
||||
"location_type": "LO", |
||||
"platform": "1" |
||||
}, |
||||
{ |
||||
"engineering_allowance": "1", |
||||
"arrival": "1656H", |
||||
"line": "UL", |
||||
"public_arrival": "1656", |
||||
"performance_allowance": "2", |
||||
"location_type": "LI", |
||||
"platform": "A", |
||||
"pathing_allowance": "3", |
||||
"record_identity": "LI", |
||||
"path": "UP", |
||||
"public_departure": "1657", |
||||
"tiploc_code": "TREFRST", |
||||
"departure": "1657H" |
||||
}, |
||||
{ |
||||
"arrival": "1703", |
||||
"public_arrival": "1704", |
||||
"location_type": "LI", |
||||
"record_identity": "LI", |
||||
"public_departure": "1704", |
||||
"tiploc_code": "TAFFSWL", |
||||
"departure": "1704" |
||||
}, |
||||
{ |
||||
"arrival": "1707", |
||||
"public_arrival": "1708", |
||||
"location_type": "LI", |
||||
"platform": "1", |
||||
"record_identity": "LI", |
||||
"public_departure": "1708", |
||||
"tiploc_code": "RADYR", |
||||
"departure": "1708" |
||||
}, |
||||
{ |
||||
"arrival": "1710", |
||||
"public_arrival": "1710", |
||||
"location_type": "LI", |
||||
"record_identity": "LI", |
||||
"public_departure": "1711", |
||||
"tiploc_code": "LLANDAF", |
||||
"departure": "1711" |
||||
}, |
||||
{ |
||||
"engineering_allowance": "1", |
||||
"arrival": "1714H", |
||||
"public_arrival": "1715", |
||||
"location_type": "LI", |
||||
"pathing_allowance": "H", |
||||
"record_identity": "LI", |
||||
"public_departure": "1715", |
||||
"tiploc_code": "CATHAYS", |
||||
"departure": "1715H" |
||||
}, |
||||
{ |
||||
"arrival": "1719", |
||||
"public_arrival": "1720", |
||||
"location_type": "LI", |
||||
"platform": "3", |
||||
"record_identity": "LI", |
||||
"public_departure": "1721", |
||||
"tiploc_code": "CARDFQS", |
||||
"departure": "1721" |
||||
}, |
||||
{ |
||||
"pass": "1723", |
||||
"location_type": "LI", |
||||
"record_identity": "LI", |
||||
"tiploc_code": "CVLESBY" |
||||
}, |
||||
{ |
||||
"record_identity": "LT", |
||||
"arrival": "1724", |
||||
"public_arrival": "1725", |
||||
"tiploc_code": "CRDFCEN", |
||||
"location_type": "LT", |
||||
"platform": "7" |
||||
} |
||||
], |
||||
"CIF_train_service_code": "25441000", |
||||
"CIF_train_class": "S" |
||||
} |
||||
} |
||||
Loading…
Reference in new issue