diff --git a/AndroidManifest.xml b/AndroidManifest.xml
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2,8 +2,6 @@
-
-
@@ -14,13 +12,19 @@
+ android:name=".BustoApp"
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:networkSecurityConfig="@xml/networks_security_config"
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:theme="@style/AppTheme.NoActionBar">
+
+
+
+ android:name=".ActivityMap"
+ android:label="@string/title_activity_map"
+ android:parentActivityName=".ActivityMain"
+ android:theme="@style/MapTheme">
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".ActivityMain"/>
-
+ android:label="@string/app_name"
+ android:screenOrientation="portrait">
-
-
+
@@ -132,4 +134,4 @@
-
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
--- a/build.gradle
+++ b/build.gradle
@@ -6,11 +6,9 @@
}
- dependencies {
-
- classpath 'com.android.tools.build:gradle:4.1.3'
- }
ext {
+ //multidex
+ multidex_version = "2.0.1"
//libraries versions
fragment_version = "1.3.6"
activity_version = "1.2.4"
@@ -21,8 +19,17 @@
acra_version = "5.7.0"
lifecycle_version = "2.3.1"
arch_version = "2.1.0"
+ room_version = "2.3.0"
+ //kotlin
+ kotlin_version = '1.5.0'
+ coroutines_version = "1.5.0"
}
+ dependencies {
+
+ classpath 'com.android.tools.build:gradle:4.1.3'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
}
allprojects {
repositories {
@@ -34,6 +41,8 @@
}
apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 29
@@ -41,11 +50,12 @@
defaultConfig {
applicationId "it.reyboz.bustorino"
- minSdkVersion 14
+ minSdkVersion 15
targetSdkVersion 29
versionCode 35
versionName "1.15.4"
vectorDrawables.useSupportLibrary = true
+ multiDexEnabled true
}
compileOptions {
@@ -91,8 +101,8 @@
implementation "androidx.preference:preference:$preference_version"
implementation "androidx.work:work-runtime:$work_version"
-
- implementation "com.google.android.material:material:1.3.0"
+ implementation "com.google.android.material:material:1.4.0"
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'org.jsoup:jsoup:1.13.1'
@@ -113,5 +123,18 @@
// Lifecycles only (without ViewModel or LiveData)
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
+ // Room components
+ implementation "androidx.room:room-ktx:$room_version"
+ kapt "androidx.room:room-compiler:$room_version"
+ androidTestImplementation "androidx.room:room-testing:$room_version"
+ //multidex - we need this to build the app
+ implementation "androidx.multidex:multidex:$multidex_version"
}
}
+
+dependencies {
+
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
+ api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
+}
\ No newline at end of file
diff --git a/res/layout/activity_experiments.xml b/res/layout/activity_experiments.xml
new file mode 100644
--- /dev/null
+++ b/res/layout/activity_experiments.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/menu/extra_menu_items.xml b/res/menu/principal_menu.xml
rename from res/menu/extra_menu_items.xml
rename to res/menu/principal_menu.xml
--- a/res/menu/extra_menu_items.xml
+++ b/res/menu/principal_menu.xml
@@ -21,4 +21,9 @@
android:orderInCategory="8"
android:title="@string/action_licence"
app:showAsAction="never" />
+
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -157,7 +157,8 @@
storageThe application has crashed because you encountered a bug.
\nIf you want, you can help the developers by sending the crash report via email.
- \nNote that no sensitive data is contained in the report, just small bits of info on your phone and app configuration/state.
+ \nNote that no sensitive data is contained in the report, just small bits of info on your phone and app
+ configuration/state.
The application crashed and the crash report is in the attachments. Please
describe what you were doing before the crash: \n
@@ -171,4 +172,6 @@
Buy us a coffeeMapSearch by stop
+
+
diff --git a/res/values/theme.xml b/res/values/theme.xml
--- a/res/values/theme.xml
+++ b/res/values/theme.xml
@@ -21,4 +21,6 @@
+
+
\ No newline at end of file
diff --git a/res/xml/networks_security_config.xml b/res/xml/networks_security_config.xml
--- a/res/xml/networks_security_config.xml
+++ b/res/xml/networks_security_config.xml
@@ -3,6 +3,6 @@
5t.torino.itgtt.to.it
-
+ comune.torino.it
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/ActivityExperiments.java b/src/it/reyboz/bustorino/ActivityExperiments.java
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/ActivityExperiments.java
@@ -0,0 +1,141 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.Toast;
+import androidx.appcompat.app.AppCompatActivity;
+import android.os.Bundle;
+import it.reyboz.bustorino.backend.Fetcher;
+import it.reyboz.bustorino.backend.gtfs.GtfsDataParser;
+import it.reyboz.bustorino.backend.networkTools;
+import it.reyboz.bustorino.backend.utils;
+import it.reyboz.bustorino.middleware.GeneralActivity;
+
+import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+
+public class ActivityExperiments extends GeneralActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_experiments);
+ Button deleteButton = findViewById(R.id.deleteButton);
+ if(deleteButton!=null)
+ deleteButton.setOnClickListener(view -> {
+ File saveFile = new File(getFilesDir(), "gtfs_data.zip");
+ if(!saveFile.isDirectory() && saveFile.exists()){
+ //delete the file
+ if(saveFile.delete())
+ Toast.makeText(this, "Gtfs zip deleted", Toast.LENGTH_SHORT).show();
+ else
+ Toast.makeText(this, "Cannot delete gtfs zip", Toast.LENGTH_SHORT).show();
+ } else
+ Toast.makeText(this, "Gtfs data zip not present", Toast.LENGTH_SHORT).show();
+ });
+ }
+
+ public void runExp(View v){
+
+ final Context appContext = v.getContext().getApplicationContext();
+
+ Runnable run = new Runnable() {
+ @Override
+ public void run() {
+ final String DEBUG_TAG = "ExperimentsGTFS";
+ AtomicReference res = new AtomicReference<>();
+ //List files = GtfsDataParser.readFilesList(res);
+ Date updateDate = GtfsDataParser.getLastGTFSUpdateDate(res);
+ Log.w(
+ "ExperimentGTFS", "Last update date is " + updateDate//utils.joinList(files, "\n")
+ );
+ //Toast.makeText(v.getContext(), "Gtfs data already downloaded", Toast.LENGTH_SHORT).show();
+
+ File saveFile = new File(getFilesDir(), "gtfs_data.zip");
+ if (!saveFile.isDirectory() && saveFile.exists()) {
+ Log.w(DEBUG_TAG, "Zip exists: " + saveFile);
+ try (FileInputStream fileStream = new FileInputStream(saveFile)) {
+ ZipInputStream stream = new ZipInputStream(fileStream);
+ // now iterate through each item in the stream. The get next
+ // entry call will return a ZipEntry for each file in the
+ // stream
+ ZipEntry entry;
+ String line;
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+ while ((entry = stream.getNextEntry()) != null) {
+ String s = String.format(Locale.ENGLISH, "Entry: %s len %d added",
+ entry.getName(),
+ entry.getSize()
+ );
+ //Toast.makeText(v.getContext(), "File: " + entry.getName(), Toast.LENGTH_SHORT).show();
+ Log.d(DEBUG_TAG, s);
+ //read data in table
+ final String tableName = entry.getName().split("\\.")[0].trim();
+ GtfsDataParser.readCSVWithColumns(reader, tableName, v.getContext().getApplicationContext());
+
+
+ // Once we get the entry from the stream, the stream is
+ // positioned read to read the raw data, and we keep
+ // reading until read returns 0 or less.
+ //result.add(entry.getName());
+ }
+ stream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ //saveFile.delete();
+ } else
+ try {
+ //Toast.makeText(v.getContext(), "Downloading gtfs data", Toast.LENGTH_SHORT).show();
+
+ networkTools.saveFileInCache(saveFile, new URL(GtfsDataParser.GTFS_ADDRESS));
+ Log.w(DEBUG_TAG, "File saved");
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+
+ }
+ };
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+ //Looper looper = new Looper(true);
+ //Handler handler = new Handler();
+ //handler.post(run);
+ executorService.execute(run);
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/ActivityPrincipal.java b/src/it/reyboz/bustorino/ActivityPrincipal.java
--- a/src/it/reyboz/bustorino/ActivityPrincipal.java
+++ b/src/it/reyboz/bustorino/ActivityPrincipal.java
@@ -1,3 +1,20 @@
+/*
+ BusTO - Arrival times for Turin public transport.
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino;
import android.Manifest;
@@ -23,6 +40,7 @@
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
+import androidx.preference.PreferenceManager;
import androidx.work.BackoffPolicy;
import androidx.work.Constraints;
import androidx.work.ExistingPeriodicWorkPolicy;
@@ -165,22 +183,11 @@
requestArrivalsForStopID(busStopID);
}
//Try (hopefully) database update
- PeriodicWorkRequest wr = new PeriodicWorkRequest.Builder(DBUpdateWorker.class, 1, TimeUnit.DAYS)
- .setBackoffCriteria(BackoffPolicy.LINEAR, 30, TimeUnit.MINUTES)
- .setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED)
- .build())
- .build();
- final WorkManager workManager = WorkManager.getInstance(this);
-
- final int version = theShPr.getInt(DatabaseUpdate.DB_VERSION_KEY, -10);
- if (version >= 0)
- workManager.enqueueUniquePeriodicWork(DBUpdateWorker.DEBUG_TAG,
- ExistingPeriodicWorkPolicy.KEEP, wr);
- else workManager.enqueueUniquePeriodicWork(DBUpdateWorker.DEBUG_TAG,
- ExistingPeriodicWorkPolicy.REPLACE, wr);
+ DatabaseUpdate.requestDBUpdateWithWork(this, false);
/*
- Set database update
+ Watch for database update
*/
+ final WorkManager workManager = WorkManager.getInstance(this);
workManager.getWorkInfosForUniqueWorkLiveData(DBUpdateWorker.DEBUG_TAG)
.observe(this, workInfoList -> {
// If there are no matching work info, do nothing
@@ -300,7 +307,11 @@
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.extra_menu_items, menu);
+ getMenuInflater().inflate(R.menu.principal_menu, menu);
+ MenuItem experimentsMenuItem = menu.findItem(R.id.action_experiments);
+ SharedPreferences shPr = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+ boolean exper_On = shPr.getBoolean(getString(R.string.pref_key_experimental), false);
+ experimentsMenuItem.setVisible(exper_On);
return super.onCreateOptionsMenu(menu);
}
@@ -569,6 +580,8 @@
case R.id.action_licence:
openIceweasel("https://www.gnu.org/licenses/gpl-3.0.html", activityContext);
return true;
+ case R.id.action_experiments:
+ startActivity(new Intent(ActivityPrincipal.this, ActivityExperiments.class));
default:
}
return false;
diff --git a/src/it/reyboz/bustorino/BustoApp.java b/src/it/reyboz/bustorino/BustoApp.java
--- a/src/it/reyboz/bustorino/BustoApp.java
+++ b/src/it/reyboz/bustorino/BustoApp.java
@@ -1,8 +1,25 @@
+/*
+ BusTO - Arrival times for Turin public transport.
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino;
-import android.app.Application;
import android.content.Context;
+import androidx.multidex.MultiDexApplication;
import org.acra.ACRA;
import org.acra.BuildConfig;
import org.acra.ReportField;
@@ -14,7 +31,7 @@
import static org.acra.ReportField.*;
-public class BustoApp extends Application {
+public class BustoApp extends MultiDexApplication {
private static final ReportField[] REPORT_FIELDS = {REPORT_ID, APP_VERSION_CODE, APP_VERSION_NAME,
PACKAGE_NAME, PHONE_MODEL, BRAND, PRODUCT, ANDROID_VERSION, BUILD_CONFIG, CUSTOM_DATA,
IS_SILENT, STACK_TRACE, INITIAL_CONFIGURATION, CRASH_CONFIGURATION, DISPLAY, USER_COMMENT,
diff --git a/src/it/reyboz/bustorino/backend/Fetcher.java b/src/it/reyboz/bustorino/backend/Fetcher.java
--- a/src/it/reyboz/bustorino/backend/Fetcher.java
+++ b/src/it/reyboz/bustorino/backend/Fetcher.java
@@ -31,6 +31,7 @@
* QUERY_TOO_SHORT: input more characters and retry.
*/
enum Result {
- OK, CLIENT_OFFLINE, SERVER_ERROR, SETUP_ERROR,PARSER_ERROR, EMPTY_RESULT_SET, QUERY_TOO_SHORT,SERVER_ERROR_404
+ OK, CLIENT_OFFLINE, SERVER_ERROR, SETUP_ERROR,PARSER_ERROR, EMPTY_RESULT_SET, QUERY_TOO_SHORT, SERVER_ERROR_404,
+ CONNECTION_ERROR
}
}
diff --git a/src/it/reyboz/bustorino/backend/gtfs/GtfsDataParser.java b/src/it/reyboz/bustorino/backend/gtfs/GtfsDataParser.java
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/backend/gtfs/GtfsDataParser.java
@@ -0,0 +1,256 @@
+package it.reyboz.bustorino.backend.gtfs;
+
+import android.content.Context;
+import android.util.Log;
+import androidx.annotation.NonNull;
+import it.reyboz.bustorino.backend.Fetcher;
+import it.reyboz.bustorino.backend.networkTools;
+import it.reyboz.bustorino.data.gtfs.CsvTableInserter;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+abstract public class GtfsDataParser {
+ public static final String GTFS_ADDRESS="https://www.gtt.to.it/open_data/gtt_gtfs.zip";
+ public static final String GTFS_PAGE_ADDRESS="http://aperto.comune.torino.it/dataset/feed-gtfs-trasporti-gtt";
+
+ private static final String DEBUG_TAG = "BusTO-GTFSDataParser";
+
+ private static final Pattern quotePattern = Pattern.compile("^\\s*\"((?:[^\"]|(?:\"\"))*?)\"\\s*,");
+
+ /**
+ * First trial for a function to download the zip
+ * @param res Fetcher.result
+ * @return the list of files inside the ziè
+ */
+ public static ArrayList readFilesList(AtomicReference res){
+
+ HttpURLConnection urlConnection;
+ InputStream in;
+ ArrayList result = new ArrayList<>();
+ try {
+ final URL gtfsUrl = new URL(GTFS_ADDRESS);
+ urlConnection = (HttpURLConnection) gtfsUrl.openConnection();
+ } catch(IOException e) {
+ //e.printStackTrace();
+ res.set(Fetcher.Result.SERVER_ERROR); // even when offline, urlConnection works fine. WHY.
+ return null;
+ }
+ urlConnection.setConnectTimeout(4000);
+ urlConnection.setReadTimeout(50*1000);
+
+ try {
+ in = urlConnection.getInputStream();
+ } catch (Exception e) {
+ try {
+ if(urlConnection.getResponseCode()==404)
+ res.set(Fetcher.Result.SERVER_ERROR_404);
+ } catch (IOException e2) {
+ e2.printStackTrace();
+ }
+ return null;
+
+ }
+ try (ZipInputStream stream = new ZipInputStream(in)) {
+
+ // now iterate through each item in the stream. The get next
+ // entry call will return a ZipEntry for each file in the
+ // stream
+ ZipEntry entry;
+ while ((entry = stream.getNextEntry()) != null) {
+ String s = String.format(Locale.ENGLISH, "Entry: %s len %d added",
+ entry.getName(),
+ entry.getSize()
+ );
+ System.out.println(s);
+
+ // Once we get the entry from the stream, the stream is
+ // positioned read to read the raw data, and we keep
+ // reading until read returns 0 or less.
+ result.add(entry.getName());
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ // we must always close the zip file.
+ return result;
+ }
+
+ public static Date getLastGTFSUpdateDate(AtomicReference res) {
+ URL theURL;
+ final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ENGLISH);
+ //final Date baseDate = dateFormat.parse("1970-00-00T00:00:00+0000");
+ final Date nullDate = new Date(0);
+ try{
+ theURL = new URL(GTFS_PAGE_ADDRESS);
+ } catch (IOException ex){
+ Log.e(DEBUG_TAG, "Fixed URL is null, this is a real issue");
+ return nullDate;
+ }
+ res.set(Fetcher.Result.OK);
+ final String fullPageDOM = networkTools.getDOM(theURL, res);
+ if(fullPageDOM== null){
+ //Something wrong happend
+ Log.e(DEBUG_TAG, "Cannot get URL");
+ return nullDate;
+ }
+ res.set(Fetcher.Result.OK);
+ Document doc = Jsoup.parse(fullPageDOM);
+
+ Elements sections = doc.select("section.additional-info");
+ Date finalDate = new Date(0);
+ for (Element sec: sections){
+ Element head = sec.select("h3").first();
+ String headTitle = head.text();
+ if(!headTitle.trim().toLowerCase(Locale.ITALIAN).equals("informazioni supplementari"))
+ continue;
+
+ for (Element row: sec.select("tr")){
+ if(!row.selectFirst("th").text().trim()
+ .toLowerCase(Locale.ITALIAN).equals("ultimo aggiornamento"))
+ continue;
+
+ Attributes spanAttributes = row.selectFirst("td > span").attributes();
+ String dateAsString = spanAttributes.get("data-datetime");
+ try {
+ finalDate = dateFormat.parse(dateAsString);
+ return finalDate;
+ }catch (ParseException ex){
+ Log.e(DEBUG_TAG, "Wrong date for the last update of GTFS Data: "+dateAsString);
+ res.set(Fetcher.Result.PARSER_ERROR);
+ ex.printStackTrace();
+ }
+ break;
+ }
+ }
+ res.set(Fetcher.Result.PARSER_ERROR);
+ return finalDate;
+
+ }
+
+ public static void readCSVWithColumns(BufferedReader reader, String tableName, Context con) throws IOException {
+
+ //String[] elements;
+ List lineElements;
+
+ String line;
+
+ final String header = reader.readLine();
+ if (header == null){
+ throw new IOException();
+ }
+
+ //elements = header.split("\n")[0].split(",");
+ //System.out.println(Arrays.toString(elements));
+
+ lineElements = readCsvLine(header);
+
+
+ final HashMap columnMap = new HashMap<>();
+
+ final CsvTableInserter inserter = new CsvTableInserter(tableName,con);
+
+ for (int i=0; i< lineElements.size(); i++){
+ //columnMap.put(i, fixStringIfItHasQuotes(elements[i].trim()) );
+ columnMap.put(i, lineElements.get(i).trim() );
+
+ }
+ Log.d(DEBUG_TAG, "Columns for the file: "+columnMap);
+ boolean first = true;
+ while((line = reader.readLine())!=null){
+ //there is a line of data
+ //elements = line.split("\n")[0].split(",");
+ if(first) Log.d(DEBUG_TAG, "Element line: "+line);
+ lineElements = readCsvLine(line);
+
+ final Map rowsMap = getColumnsAsString(lineElements.toArray(new String[0]), columnMap);
+ if (first){
+ Log.d(DEBUG_TAG, " in map:"+rowsMap);
+ first=false;
+ }
+ inserter.addElement(rowsMap);
+ }
+
+ //commit data
+ inserter.insertDataInDatabase();
+ }
+ @NonNull
+ private static Map getColumnsAsString(@NonNull String[] lineElements, Map colsIndices)
+ {
+ final HashMap theMap = new HashMap<>();
+ for(int l=0; l1){
+ //if(elements.length<3) throw new IllegalArgumentException("Malformed string");
+ return elements[1];
+ } else if(elements.length > 0)
+ return elements[0];
+ else
+ return item;
+ }
+ //https://stackoverflow.com/questions/7800494/parse-csv-with-double-quote-in-some-cases#7800519
+ public static List readCsvLine(String line) throws IllegalArgumentException
+ {
+
+ List list = new ArrayList();
+ line += ",";
+
+ for (int x = 0; x < line.length(); x++)
+ {
+ String s = line.substring(x);
+ if (s.trim().startsWith("\""))
+ {
+ Matcher m = quotePattern.matcher(s);
+ if (!m.find()) {
+ Log.e(DEBUG_TAG, "Cannot find pattern, "+s+" , line: "+line);
+ throw new IllegalArgumentException("CSV is malformed");
+ }
+ list.add(m.group(1).replace("\"\"", "\""));
+ x += m.end() - 1;
+ }
+ else
+ {
+ int y = s.indexOf(",");
+ if (y == -1)
+ throw new IllegalArgumentException("CSV is malformed");
+ list.add(s.substring(0, y));
+ x += y;
+ }
+ }
+ return list;
+ }
+}
diff --git a/src/it/reyboz/bustorino/backend/networkTools.java b/src/it/reyboz/bustorino/backend/networkTools.java
--- a/src/it/reyboz/bustorino/backend/networkTools.java
+++ b/src/it/reyboz/bustorino/backend/networkTools.java
@@ -18,22 +18,20 @@
package it.reyboz.bustorino.backend;
+import android.content.Context;
import androidx.annotation.Nullable;
import android.util.Log;
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicReference;
public abstract class networkTools {
- static String getDOM(final URL url, final AtomicReference res) {
+ public static String getDOM(final URL url, final AtomicReference res) {
//Log.d("asyncwget", "Catching URL in background: " + uri[0]);
HttpURLConnection urlConnection;
StringBuilder result = null;
@@ -70,6 +68,52 @@
res.set(Fetcher.Result.PARSER_ERROR); // will be set to "OK" later, this is a safety net in case StringBuilder returns null, the website returns an HTTP 204 or something like that.
return result.toString();
}
+
+ public static Fetcher.Result saveFileInCache(File outputFile, URL url) {
+ HttpURLConnection urlConnection;
+ try {
+ urlConnection = (HttpURLConnection) url.openConnection();
+ } catch (IOException e) {
+ //e.printStackTrace();
+ return Fetcher.Result.CONNECTION_ERROR;
+ }
+ urlConnection.setConnectTimeout(4000);
+ urlConnection.setReadTimeout(50 * 1000);
+
+ Log.d("BusTO net Tools", "Download file "+url);
+ try (InputStream inputStream = urlConnection.getInputStream()) {
+ //File outputFile = new File(con.getFilesDir(), fileName);
+ //BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
+ FileOutputStream outputStream = new FileOutputStream(outputFile);
+ byte buffer[] = new byte[16384];
+ boolean inProgress = true;
+ while(inProgress){
+ int numread = inputStream.read(buffer);
+ inProgress = (numread > 0);
+ if(inProgress) outputStream.write(buffer, 0, numread);
+ }
+ outputStream.close();
+ //while (bufferedInputStream.available())
+ } catch (IOException e) {
+ e.printStackTrace();
+ try {
+ final Fetcher.Result res;
+ if(urlConnection.getResponseCode()==404)
+ res= Fetcher.Result.SERVER_ERROR_404;
+ else if(urlConnection.getResponseCode()!=200)
+ res= Fetcher.Result.SERVER_ERROR;
+ else res= Fetcher.Result.PARSER_ERROR;
+ urlConnection.disconnect();
+ return res;
+ } catch (IOException ioException) {
+ ioException.printStackTrace();
+ urlConnection.disconnect();
+ return Fetcher.Result.PARSER_ERROR;
+ }
+ }
+ urlConnection.disconnect();
+ return Fetcher.Result.OK;
+ }
@Nullable
static String queryURL(URL url, AtomicReference res){
return queryURL(url,res,null);
diff --git a/src/it/reyboz/bustorino/backend/utils.java b/src/it/reyboz/bustorino/backend/utils.java
--- a/src/it/reyboz/bustorino/backend/utils.java
+++ b/src/it/reyboz/bustorino/backend/utils.java
@@ -8,10 +8,12 @@
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
+import androidx.annotation.Nullable;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
+import java.util.List;
public abstract class utils {
private static final double EarthRadius = 6371e3;
@@ -153,4 +155,17 @@
return "Trace too Short.";
}
*/
+ public static String joinList(@Nullable List dat, String separator){
+ StringBuilder sb = new StringBuilder();
+ if(dat==null || dat.size()==0)
+ return "";
+ else if(dat.size()==1)
+ return dat.get(0);
+ sb.append(dat.get(0));
+ for (int i=1; i.
+ */
+package it.reyboz.bustorino.data;
+
+public class AppRepository {
+
+
+}
diff --git a/src/it/reyboz/bustorino/data/DBUpdateWorker.java b/src/it/reyboz/bustorino/data/DBUpdateWorker.java
--- a/src/it/reyboz/bustorino/data/DBUpdateWorker.java
+++ b/src/it/reyboz/bustorino/data/DBUpdateWorker.java
@@ -1,3 +1,20 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.data;
import android.annotation.SuppressLint;
diff --git a/src/it/reyboz/bustorino/data/DatabaseUpdate.java b/src/it/reyboz/bustorino/data/DatabaseUpdate.java
--- a/src/it/reyboz/bustorino/data/DatabaseUpdate.java
+++ b/src/it/reyboz/bustorino/data/DatabaseUpdate.java
@@ -1,3 +1,20 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.data;
import android.content.ContentValues;
@@ -5,6 +22,8 @@
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
+import androidx.core.content.ContextCompat;
+import androidx.work.*;
import it.reyboz.bustorino.R;
import it.reyboz.bustorino.backend.Fetcher;
import it.reyboz.bustorino.backend.FiveTAPIFetcher;
@@ -14,6 +33,7 @@
import org.json.JSONObject;
import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static android.content.Context.MODE_PRIVATE;
@@ -155,4 +175,25 @@
editor.putBoolean(con.getString(R.string.databaseUpdatingPref),value);
return editor.commit();
}
+
+ /**
+ * Request update using workmanager framework
+ * @param con the context to use
+ * @param forced if you want to force the request to go now
+ */
+ public static void requestDBUpdateWithWork(Context con, boolean forced){
+ final SharedPreferences theShPr = PreferencesHolder.getMainSharedPreferences(con);
+ final WorkManager workManager = WorkManager.getInstance(con);
+ PeriodicWorkRequest wr = new PeriodicWorkRequest.Builder(DBUpdateWorker.class, 1, TimeUnit.DAYS)
+ .setBackoffCriteria(BackoffPolicy.LINEAR, 30, TimeUnit.MINUTES)
+ .setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED)
+ .build())
+ .build();
+ final int version = theShPr.getInt(DatabaseUpdate.DB_VERSION_KEY, -10);
+ if (version >= 0 && !forced)
+ workManager.enqueueUniquePeriodicWork(DBUpdateWorker.DEBUG_TAG,
+ ExistingPeriodicWorkPolicy.KEEP, wr);
+ else workManager.enqueueUniquePeriodicWork(DBUpdateWorker.DEBUG_TAG,
+ ExistingPeriodicWorkPolicy.REPLACE, wr);
+ }
}
diff --git a/src/it/reyboz/bustorino/data/FavoritesLiveData.java b/src/it/reyboz/bustorino/data/FavoritesLiveData.java
--- a/src/it/reyboz/bustorino/data/FavoritesLiveData.java
+++ b/src/it/reyboz/bustorino/data/FavoritesLiveData.java
@@ -1,3 +1,20 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.data;
diff --git a/src/it/reyboz/bustorino/data/GTTInfoInject.java b/src/it/reyboz/bustorino/data/GTTInfoInject.java
--- a/src/it/reyboz/bustorino/data/GTTInfoInject.java
+++ b/src/it/reyboz/bustorino/data/GTTInfoInject.java
@@ -1,3 +1,20 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.data;
import java.util.Locale;
diff --git a/src/it/reyboz/bustorino/data/NextGenDB.java b/src/it/reyboz/bustorino/data/NextGenDB.java
--- a/src/it/reyboz/bustorino/data/NextGenDB.java
+++ b/src/it/reyboz/bustorino/data/NextGenDB.java
@@ -123,7 +123,7 @@
db.execSQL(SQL_CREATE_BRANCH_TABLE);
db.execSQL(SQL_CREATE_CONNECTIONS_TABLE);
- DatabaseUpdateService.startDBUpdate(appContext,0,true);
+ DatabaseUpdate.requestDBUpdateWithWork(appContext, true);
}
}
diff --git a/src/it/reyboz/bustorino/data/PreferencesHolder.java b/src/it/reyboz/bustorino/data/PreferencesHolder.java
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/PreferencesHolder.java
@@ -0,0 +1,34 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import it.reyboz.bustorino.R;
+
+import static android.content.Context.MODE_PRIVATE;
+
+/**
+ * Static class for commonly used SharedPreference operations
+ */
+public abstract class PreferencesHolder {
+
+ public static SharedPreferences getMainSharedPreferences(Context context){
+ return context.getSharedPreferences(context.getString(R.string.mainSharedPreferences), MODE_PRIVATE);
+ }
+}
diff --git a/src/it/reyboz/bustorino/data/gtfs/Converters.kt b/src/it/reyboz/bustorino/data/gtfs/Converters.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/gtfs/Converters.kt
@@ -0,0 +1,103 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data.gtfs
+
+import androidx.room.TypeConverter
+import java.text.SimpleDateFormat
+import java.util.*
+
+/**
+ * Class to convert values for objects into
+ * the needed columns
+ *
+ * handled automatically by Room with TypeConverter
+ */
+class Converters {
+
+
+ @TypeConverter
+ fun fromString(value: String?): Date? {
+ return dateFromFmtString(value)
+ }
+
+ @TypeConverter
+ fun dateToString(date: Date?): String? {
+ return date?.let { stringFormat.format(it)}
+ }
+
+ @TypeConverter
+ fun exceptionToInt(type: GtfsServiceDate.ExceptionType?): Int? {
+ return type?.value
+ }
+ @TypeConverter
+ fun fromInt(value: Int?): GtfsServiceDate.ExceptionType? {
+ return value?.let { GtfsServiceDate.ExceptionType.getByValue(it) }
+ }
+
+ companion object{
+ const val DATE_FMT_STRING = "yyyyMMdd"
+ val stringFormat = SimpleDateFormat(DATE_FMT_STRING, Locale.US)
+
+ fun fromStringNum(string: String?): Boolean?{
+ string?.let { if (it.trim() == "1")
+ return true
+ else if(it.trim() == "0")
+ return false
+ else throw Exception("Cannot convert $string to numeric value") }
+ return null
+
+ }
+ fun fromStringNum(string: String?, defaultVal: Boolean): Boolean{
+ string?.let { if (it.trim() == "1")
+ return true
+ else if(it.trim() == "0")
+ return false
+ else return defaultVal }
+ return defaultVal
+
+ }
+ fun dateFromFmtString(value: String?): Date?{
+ return value?.let {
+
+ stringFormat.parse(it)
+ }
+ }
+
+ fun wheelchairFromString(string: String?): GtfsStop.WheelchairAccess?{
+ string?.let { if (it.trim() == "1")
+ return GtfsStop.WheelchairAccess.SOMETIMES
+ else if(it.trim() == "0")
+ return GtfsStop.WheelchairAccess.UNKNOWN
+ else if(it.trim() == "2")
+ return GtfsStop.WheelchairAccess.IMPOSSIBLE
+ else //throw Exception("Cannot convert $string to wheelchair access") }
+ return GtfsStop.WheelchairAccess.UNKNOWN
+
+ }
+ return null
+ }
+ @TypeConverter
+ fun wheelchairToInt(access:GtfsStop.WheelchairAccess): Int{
+ return access.value;
+ }
+ @TypeConverter
+ fun wheelchairFromInt(value: Int): GtfsStop.WheelchairAccess{
+ return GtfsStop.WheelchairAccess.getByValue(value)?: GtfsStop.WheelchairAccess.UNKNOWN
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/data/gtfs/CsvTableInserter.kt b/src/it/reyboz/bustorino/data/gtfs/CsvTableInserter.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/gtfs/CsvTableInserter.kt
@@ -0,0 +1,82 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data.gtfs
+
+import android.content.Context
+import android.util.Log
+import java.util.ArrayList
+
+class CsvTableInserter(
+ val tableName: String, context: Context
+) {
+ private val database: GtfsDatabase = GtfsDatabase.getGtfsDatabase(context)
+ private val dao: StaticGtfsDao = database.gtfsDao()
+
+ private val elementsList: MutableList< in GtfsTable> = mutableListOf()
+
+ fun addElement(csvLineElements: Map) {
+
+ when(tableName){
+ "stops" ->
+ elementsList.add(GtfsStop(csvLineElements))
+ "routes" ->
+ elementsList.add(GtfsRoute(csvLineElements))
+ "calendar" ->
+ elementsList.add(GtfsService(csvLineElements))
+ "calendar_dates" ->
+ elementsList.add(GtfsServiceDate(csvLineElements))
+ "trips" ->
+ elementsList.add(GtfsTrip(csvLineElements))
+ "shapes" ->
+ elementsList.add(GtfsShape(csvLineElements))
+ "stop_times" ->
+ elementsList.add(GtfsStopTime(csvLineElements))
+
+
+ }
+ if(elementsList.size >= MAX_ELEMENTS){
+ //have to insert
+ Log.d(DEBUG_TAG, "Inserting first batch of elements now, list size: "+elementsList.size)
+ if (tableName == "routes")
+ dao.insertRoutes(elementsList.filterIsInstance())
+ else
+ insertDataInDatabase()
+
+ elementsList.clear()
+
+ }
+ }
+ fun insertDataInDatabase(){
+ when(tableName){
+ "stops" -> dao.updateStops(elementsList.filterIsInstance())
+ "routes" -> dao.clearAndInsertRoutes(elementsList.filterIsInstance())
+ "calendar" -> dao.insertServices(elementsList.filterIsInstance())
+ "calendar_dates" -> dao.insertDates(elementsList.filterIsInstance())
+ "trips" -> dao.insertTrips(elementsList.filterIsInstance())
+ "stop_times"-> dao.insertStopTimes(elementsList.filterIsInstance())
+ "shapes" -> dao.insertShapes(elementsList.filterIsInstance())
+
+ }
+ }
+
+ companion object{
+ val MAX_ELEMENTS = 5000
+
+ val DEBUG_TAG="BusTO - TableInserter"
+ }
+}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/data/gtfs/GtfsDatabase.kt b/src/it/reyboz/bustorino/data/gtfs/GtfsDatabase.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/gtfs/GtfsDatabase.kt
@@ -0,0 +1,57 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data.gtfs
+
+import android.content.Context
+import androidx.room.*
+
+@Database(
+ entities = [
+ GtfsServiceDate::class,
+ GtfsStop::class,
+ GtfsService::class,
+ GtfsRoute::class,
+ GtfsStopTime::class,
+ GtfsTrip::class,
+ GtfsShape::class],
+ version = GtfsDatabase.VERSION,
+ exportSchema = false,
+)
+@TypeConverters(Converters::class)
+public abstract class GtfsDatabase : RoomDatabase() {
+
+ abstract fun gtfsDao() : StaticGtfsDao
+
+ companion object{
+ @Volatile
+ private var INSTANCE: GtfsDatabase? =null
+
+ fun getGtfsDatabase(context: Context): GtfsDatabase{
+ return INSTANCE ?: synchronized(this){
+ val instance = Room.databaseBuilder(context.applicationContext,
+ GtfsDatabase::class.java,
+ "gtfs_database").build()
+ INSTANCE = instance
+ instance
+ }
+ }
+
+ const val VERSION = 1
+ const val FOREIGNKEY_ONDELETE = ForeignKey.NO_ACTION
+ }
+}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/data/gtfs/GtfsRoute.kt b/src/it/reyboz/bustorino/data/gtfs/GtfsRoute.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/gtfs/GtfsRoute.kt
@@ -0,0 +1,79 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data.gtfs
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName=GtfsRoute.DB_TABLE)
+data class GtfsRoute(
+ @PrimaryKey @ColumnInfo(name = COL_ROUTE_ID)
+ val ID: String,
+ @ColumnInfo(name = "agency_id")
+ val agencyID: String,
+ @ColumnInfo(name = "route_short_name")
+ val shortName: String,
+ @ColumnInfo(name = "route_long_name")
+ val longName: String,
+ @ColumnInfo(name = "route_desc")
+ val description: String,
+ @ColumnInfo(name ="route_type")
+ val type: String,
+ //@ColumnInfo(name ="route_url")
+ //val url: String,
+ @ColumnInfo(name ="route_color")
+ val color: String,
+ @ColumnInfo(name ="route_text_color")
+ val textColor: String,
+ @ColumnInfo(name = COL_SORT_ORDER)
+ val sortOrder: Int
+): GtfsTable {
+
+ constructor(valuesByColumn: Map) : this(
+ valuesByColumn[COL_ROUTE_ID]!!,
+ valuesByColumn["agency_id"]!!,
+ valuesByColumn["route_short_name"]!!,
+ valuesByColumn["route_long_name"]!!,
+ valuesByColumn["route_desc"]!!,
+ valuesByColumn["route_type"]!!,
+ valuesByColumn["route_color"]!!,
+ valuesByColumn["route_text_color"]!!,
+ valuesByColumn[COL_SORT_ORDER]?.toInt()!!
+ )
+ companion object {
+ const val DB_TABLE: String="routes_table"
+ const val COL_SORT_ORDER: String="route_sort_order"
+ const val COL_ROUTE_ID = "route_id"
+
+ val COLUMNS = arrayOf(COL_ROUTE_ID,
+ "agency_id",
+ "route_short_name",
+ "route_long_name",
+ "route_desc",
+ "route_type",
+ "route_color",
+ "route_text_color",
+ COL_SORT_ORDER
+ )
+ }
+
+ override fun getColumns(): Array {
+ return COLUMNS
+ }
+}
diff --git a/src/it/reyboz/bustorino/data/gtfs/GtfsService.kt b/src/it/reyboz/bustorino/data/gtfs/GtfsService.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/gtfs/GtfsService.kt
@@ -0,0 +1,94 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data.gtfs
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.util.Date
+
+@Entity(tableName = GtfsService.DB_TABLE)
+data class GtfsService(
+ @PrimaryKey
+ @ColumnInfo(name = COL_SERVICE_ID)
+ val serviceID: String,
+ @ColumnInfo(name = COL_MONDAY)
+ val onMonday: Boolean,
+ @ColumnInfo(name = COL_TUESDAY)
+ val onTuesday: Boolean,
+ @ColumnInfo(name = COL_WEDNESDAY)
+ val onWednesday: Boolean,
+ @ColumnInfo(name = COL_THURSDAY)
+ val onThursday: Boolean,
+ @ColumnInfo(name = COL_FRIDAY)
+ val onFriday: Boolean,
+ @ColumnInfo(name = COL_SATURDAY)
+ val onSaturday: Boolean,
+ @ColumnInfo(name = COL_SUNDAY)
+ val onSunday: Boolean,
+ @ColumnInfo(name = COL_START_DATE)
+ val startDate: Date,
+ @ColumnInfo(name = COL_END_DATE)
+ val endDate: Date,
+): GtfsTable {
+
+ constructor(valuesByColumn: Map) : this(
+ valuesByColumn[COL_SERVICE_ID]!!,
+ Converters.fromStringNum(valuesByColumn[COL_MONDAY])!!,
+ Converters.fromStringNum(valuesByColumn[COL_TUESDAY])!!,
+ Converters.fromStringNum(valuesByColumn[COL_WEDNESDAY])!!,
+ Converters.fromStringNum(valuesByColumn[COL_THURSDAY])!!,
+ Converters.fromStringNum(valuesByColumn[COL_FRIDAY])!!,
+ Converters.fromStringNum(valuesByColumn[COL_SATURDAY])!!,
+ Converters.fromStringNum(valuesByColumn[COL_SUNDAY])!!,
+ Converters.dateFromFmtString(valuesByColumn[COL_START_DATE])!!,
+ Converters.dateFromFmtString(valuesByColumn[COL_END_DATE])!!
+ )
+ companion object{
+ const val DB_TABLE="gtfs_calendar"
+ const val COL_SERVICE_ID="service_id"
+ const val COL_MONDAY="monday"
+ const val COL_TUESDAY="tuesday"
+ const val COL_WEDNESDAY="wednesday"
+ const val COL_THURSDAY="thursday"
+ const val COL_FRIDAY="friday"
+ const val COL_SATURDAY="saturday"
+ const val COL_SUNDAY="sunday"
+ const val COL_START_DATE="start_date"
+
+ const val COL_END_DATE="end_date"
+
+ val COLUMNS = arrayOf(
+ COL_SERVICE_ID,
+ COL_MONDAY,
+ COL_TUESDAY,
+ COL_WEDNESDAY,
+ COL_THURSDAY,
+ COL_FRIDAY,
+ COL_SATURDAY,
+ COL_SUNDAY,
+ COL_START_DATE
+ )
+ }
+
+
+
+ override fun getColumns(): Array {
+ return COLUMNS
+ }
+}
diff --git a/src/it/reyboz/bustorino/data/gtfs/GtfsServiceDate.kt b/src/it/reyboz/bustorino/data/gtfs/GtfsServiceDate.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/gtfs/GtfsServiceDate.kt
@@ -0,0 +1,72 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data.gtfs
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.ForeignKey
+import java.util.Date
+
+
+@Entity(
+ tableName = GtfsServiceDate.DB_TABLE,
+ primaryKeys = [GtfsServiceDate.COL_SERVICE_ID, GtfsServiceDate.COL_DATE],
+ foreignKeys = [ForeignKey(entity = GtfsService::class,
+ parentColumns = [GtfsService.COL_SERVICE_ID],
+ childColumns = [GtfsServiceDate.COL_SERVICE_ID],
+ onDelete = GtfsDatabase.FOREIGNKEY_ONDELETE)]
+)
+data class GtfsServiceDate(
+ @ColumnInfo(name= COL_SERVICE_ID)
+ val serviceID: String,
+ @ColumnInfo(name=COL_DATE)
+ val date: Date,
+ @ColumnInfo(name=COL_EXCEPTION)
+ val exceptionType: ExceptionType,
+): GtfsTable {
+ companion object{
+ const val DB_TABLE="gtfs_calendar_dates"
+ const val COL_SERVICE_ID="service_id"
+ const val COL_DATE="date"
+ const val COL_EXCEPTION="exception_type"
+
+ val COLUMNS = arrayOf(COL_SERVICE_ID, COL_DATE, COL_SERVICE_ID)
+
+ val converter = Converters()
+
+ }
+ constructor(valuesByColumn: Map) : this(
+ valuesByColumn[COL_SERVICE_ID]!!,
+ converter.fromString(valuesByColumn[COL_DATE])!!,
+ valuesByColumn[COL_EXCEPTION]?.let { ExceptionType.getByValue(it.toInt()) }!!
+ )
+ enum class ExceptionType(val value: Int){
+ ADDED(1),
+ REMOVED(2);
+
+ companion object {
+ private val VALUES = values()
+ fun getByValue(value: Int) = VALUES.firstOrNull { it.value == value }
+ }
+ }
+
+ override fun getColumns(): Array {
+ return COLUMNS
+ }
+}
+
diff --git a/src/it/reyboz/bustorino/data/gtfs/GtfsShape.kt b/src/it/reyboz/bustorino/data/gtfs/GtfsShape.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/gtfs/GtfsShape.kt
@@ -0,0 +1,61 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data.gtfs
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+
+@Entity(tableName = GtfsShape.DB_TABLE,
+primaryKeys = [GtfsShape.COL_SHAPE_ID, GtfsShape.COL_POINT_SEQ])
+data class GtfsShape(
+ @ColumnInfo(name = COL_SHAPE_ID)
+ val shapeID: String,
+ @ColumnInfo(name = COL_POINT_LAT)
+ val pointLat: Double,
+ @ColumnInfo(name = COL_POINT_LON)
+ val pointLon: Double,
+ @ColumnInfo(name = COL_POINT_SEQ)
+ val pointSequence: Int,
+): GtfsTable {
+
+ constructor(valuesByColumn: Map) : this(
+ valuesByColumn[COL_SHAPE_ID]!!,
+ valuesByColumn[COL_POINT_LAT]?.toDoubleOrNull()!!,
+ valuesByColumn[COL_POINT_LON]?.toDoubleOrNull()!!,
+ valuesByColumn[COL_POINT_SEQ]?.toIntOrNull()!!
+ )
+
+ companion object{
+ const val DB_TABLE="gtfs_shapes"
+ const val COL_SHAPE_ID = "shape_id"
+ const val COL_POINT_LAT="shape_pt_lat"
+ const val COL_POINT_LON="shape_pt_lon"
+ const val COL_POINT_SEQ="shape_pt_sequence"
+
+ val COLUMNS= arrayOf(
+ COL_SHAPE_ID,
+ COL_POINT_LAT,
+ COL_POINT_LON,
+ COL_POINT_SEQ
+ )
+ }
+
+ override fun getColumns(): Array {
+ return COLUMNS
+ }
+}
diff --git a/src/it/reyboz/bustorino/data/gtfs/GtfsStop.kt b/src/it/reyboz/bustorino/data/gtfs/GtfsStop.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/gtfs/GtfsStop.kt
@@ -0,0 +1,90 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data.gtfs
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = GtfsStop.DB_TABLE)
+data class GtfsStop(
+ @PrimaryKey
+ @ColumnInfo(name= COL_STOP_ID)
+ val internalID: Int,
+ @ColumnInfo(name= COL_STOP_CODE)
+ val gttStopID: String,
+ @ColumnInfo(name= COL_STOP_NAME)
+ val stopName: String,
+ @ColumnInfo(name= COL_GTT_PLACE)
+ val gttPlaceName: String,
+ @ColumnInfo(name= COL_LATITUDE)
+ val latitude: Double,
+ @ColumnInfo(name= COL_LONGITUDE)
+ val longitude: Double,
+ //@ColumnInfo(name="zone_id")
+ //val zoneID: Int,
+ @ColumnInfo(name= COL_WHEELCHAIR)
+ val wheelchair: WheelchairAccess,
+): GtfsTable {
+
+ constructor(valuesByColumn: Map) : this(
+ valuesByColumn[COL_STOP_ID]?.toIntOrNull()!!,
+ valuesByColumn[COL_STOP_CODE]!!,
+ valuesByColumn[COL_STOP_NAME]!!,
+ valuesByColumn[COL_GTT_PLACE]!!,
+ valuesByColumn[COL_LATITUDE]?.toDoubleOrNull()!!,
+ valuesByColumn[COL_LONGITUDE]?.toDoubleOrNull()!!,
+ //valuesByColumn["zone_id"]?.toIntOrNull()!!,
+ Converters.wheelchairFromString(valuesByColumn[COL_WHEELCHAIR])!!
+ )
+ companion object{
+ const val DB_TABLE="stops_gtfs"
+ const val COL_STOP_CODE="stop_code"
+ const val COL_STOP_ID = "stop_id"
+ const val COL_GTT_PLACE="stop_desc"
+ const val COL_STOP_NAME="stop_name"
+ const val COL_LATITUDE="stop_lat"
+ const val COL_LONGITUDE="stop_lon"
+ const val COL_WHEELCHAIR="wheelchair_boarding"
+ val COLUMNS = arrayOf(
+ COL_STOP_CODE,
+ COL_STOP_ID,
+ COL_GTT_PLACE,
+ COL_STOP_NAME,
+ COL_LATITUDE,
+ COL_LONGITUDE,
+ //"zone_id",
+ COL_WHEELCHAIR
+ )
+ }
+
+ override fun getColumns(): Array {
+ return COLUMNS
+ }
+
+ enum class WheelchairAccess(val value: Int){
+ UNKNOWN(0),
+ SOMETIMES(1),
+ IMPOSSIBLE(2);
+
+ companion object {
+ private val VALUES = values()
+ fun getByValue(value: Int) = VALUES.firstOrNull { it.value == value }
+ }
+ }
+}
diff --git a/src/it/reyboz/bustorino/data/gtfs/GtfsStopTime.kt b/src/it/reyboz/bustorino/data/gtfs/GtfsStopTime.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/gtfs/GtfsStopTime.kt
@@ -0,0 +1,78 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data.gtfs
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.ForeignKey
+import androidx.room.Index
+
+@Entity(tableName = GtfsStopTime.DB_TABLE,
+ primaryKeys = [GtfsStopTime.COL_TRIP_ID, GtfsStopTime.COL_STOP_ID],
+ foreignKeys = [
+ ForeignKey(entity = GtfsStop::class,
+ parentColumns = [GtfsStop.COL_STOP_ID],
+ childColumns = [GtfsStopTime.COL_STOP_ID],
+ onDelete = GtfsDatabase.FOREIGNKEY_ONDELETE),
+ ForeignKey(entity = GtfsTrip::class,
+ parentColumns = [GtfsTrip.COL_TRIP_ID],
+ childColumns = [GtfsStopTime.COL_TRIP_ID],
+ onDelete = GtfsDatabase.FOREIGNKEY_ONDELETE),
+ ],
+ indices = [Index(GtfsStopTime.COL_STOP_ID)]
+)
+data class GtfsStopTime(
+ @ColumnInfo(name= COL_TRIP_ID)
+ val tripID: String,
+ @ColumnInfo(name= COL_ARRIVAL_TIME)
+ val arrivalTime: String,
+ @ColumnInfo(name= COL_DEPARTURE_TIME)
+ val departureTime:String,
+ @ColumnInfo(name= COL_STOP_ID)
+ val stopID: Int,
+ @ColumnInfo(name= COL_STOP_SEQUENCE)
+ val stopSequence: Int,
+): GtfsTable {
+ constructor(valuesByColumn: Map) : this(
+ valuesByColumn[COL_TRIP_ID]!!,
+ valuesByColumn[COL_ARRIVAL_TIME]!!,
+ valuesByColumn[COL_DEPARTURE_TIME]!!,
+ valuesByColumn[COL_STOP_ID]?.toIntOrNull()!!,
+ valuesByColumn[COL_STOP_SEQUENCE]?.toIntOrNull()!!
+ )
+ companion object{
+ const val DB_TABLE="gtfs_stop_times"
+ const val COL_TRIP_ID="trip_id"
+ const val COL_ARRIVAL_TIME="arrival_time"
+ const val COL_DEPARTURE_TIME="departure_time"
+ const val COL_STOP_ID="stop_id"
+ const val COL_STOP_SEQUENCE="stop_sequence"
+
+ val COLUMNS = arrayOf(
+ COL_TRIP_ID,
+ COL_ARRIVAL_TIME,
+ COL_DEPARTURE_TIME,
+ COL_STOP_ID,
+ COL_STOP_SEQUENCE
+ )
+ }
+
+ override fun getColumns(): Array {
+ return COLUMNS
+ }
+}
diff --git a/src/it/reyboz/bustorino/data/gtfs/GtfsTable.java b/src/it/reyboz/bustorino/data/gtfs/GtfsTable.java
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/gtfs/GtfsTable.java
@@ -0,0 +1,24 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data.gtfs;
+
+public interface GtfsTable {
+
+ String[] getColumns();
+
+}
diff --git a/src/it/reyboz/bustorino/data/gtfs/GtfsTrip.kt b/src/it/reyboz/bustorino/data/gtfs/GtfsTrip.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/gtfs/GtfsTrip.kt
@@ -0,0 +1,107 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data.gtfs
+
+import androidx.room.*
+
+@Entity(tableName = GtfsTrip.DB_TABLE,
+ foreignKeys=[
+ ForeignKey(entity = GtfsRoute::class,
+ parentColumns = [GtfsRoute.COL_ROUTE_ID],
+ childColumns = [GtfsTrip.COL_ROUTE_ID],
+ onDelete = GtfsDatabase.FOREIGNKEY_ONDELETE),
+ // The service_id: ID referencing calendar.service_id or calendar_dates.service_id
+ /*
+ ForeignKey(entity = GtfsService::class,
+ parentColumns = [GtfsService.COL_SERVICE_ID],
+ childColumns = [GtfsTrips.COL_SERVICE_ID],
+ onDelete = GtfsDatabase.FOREIGNKEY_ONDELETE),
+ */
+ ],
+ indices = [Index(GtfsTrip.COL_ROUTE_ID)]
+)
+data class GtfsTrip(
+ @ColumnInfo(name = COL_ROUTE_ID )
+ val routeID: String,
+ @ColumnInfo(name = COL_SERVICE_ID)
+ val serviceID: String,
+ @PrimaryKey
+ @ColumnInfo(name = COL_TRIP_ID)
+ val tripID: String,
+ @ColumnInfo(name = COL_HEADSIGN)
+ val tripHeadsign: String,
+ @ColumnInfo(name = COL_DIRECTION_ID)
+ val directionID: Int,
+ @ColumnInfo(name = COL_BLOCK_ID)
+ val blockID: String,
+ @ColumnInfo(name = COL_SHAPE_ID)
+ val shapeID: String,
+ @ColumnInfo(name = COL_WHEELCHAIR)
+ val isWheelchairAccess: Boolean,
+ @ColumnInfo(name = COL_LIMITED_R)
+ val isLimitedRoute: Boolean,
+
+): GtfsTable {
+
+ constructor(valuesByColumn: Map) : this(
+ valuesByColumn[COL_ROUTE_ID]!!,
+ valuesByColumn[COL_SERVICE_ID]!!,
+ valuesByColumn[COL_TRIP_ID]!!,
+ valuesByColumn[COL_HEADSIGN]!!,
+ valuesByColumn[COL_DIRECTION_ID]?.toIntOrNull()?: 0,
+ valuesByColumn[COL_BLOCK_ID]!!,
+ valuesByColumn[COL_SHAPE_ID]!!,
+ Converters.fromStringNum(valuesByColumn[COL_WHEELCHAIR], false),
+ Converters.fromStringNum(valuesByColumn[COL_LIMITED_R], false)
+ )
+
+ companion object{
+ const val DB_TABLE="gtfs_trips"
+ const val COL_ROUTE_ID="route_id"
+ const val COL_SERVICE_ID="service_id"
+ const val COL_TRIP_ID = "trip_id"
+ const val COL_HEADSIGN="trip_headsign"
+ //const val COL_SHORT_NAME="trip_short_name",
+ const val COL_DIRECTION_ID="direction_id"
+ const val COL_BLOCK_ID="block_id"
+ const val COL_SHAPE_ID = "shape_id"
+ const val COL_WHEELCHAIR="wheelchair_accessible"
+ const val COL_LIMITED_R="limited_route"
+
+ val COLUMNS= arrayOf(
+ COL_ROUTE_ID,
+ COL_SERVICE_ID,
+ COL_TRIP_ID,
+ COL_HEADSIGN,
+ COL_DIRECTION_ID,
+ COL_BLOCK_ID,
+ COL_SHAPE_ID,
+ COL_WHEELCHAIR,
+ COL_LIMITED_R
+ )
+ /*
+ open fun fromContentValues(values: ContentValues) {
+ val tripItem = GtfsTrips();
+ }
+ */
+ }
+
+ override fun getColumns(): Array {
+ return COLUMNS
+ }
+}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/data/gtfs/StaticGtfsDao.kt b/src/it/reyboz/bustorino/data/gtfs/StaticGtfsDao.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/data/gtfs/StaticGtfsDao.kt
@@ -0,0 +1,77 @@
+/*
+ BusTO - Data components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.data.gtfs
+
+import androidx.lifecycle.LiveData
+import androidx.room.*
+
+@Dao
+interface StaticGtfsDao {
+ @Query("SELECT * FROM "+GtfsRoute.DB_TABLE+" ORDER BY "+GtfsRoute.COL_SORT_ORDER)
+ fun getAllRoutes() : LiveData>
+
+ @Query("SELECT * FROM "+GtfsStop.DB_TABLE+" WHERE "+GtfsStop.COL_STOP_CODE+" LIKE :queryID")
+ fun getStopByStopID(queryID: String): LiveData>
+
+ @Query("SELECT * FROM "+GtfsShape.DB_TABLE+
+ " WHERE "+GtfsShape.COL_SHAPE_ID+" LIKE :shapeID"+
+ " ORDER BY "+GtfsShape.COL_POINT_SEQ+ " ASC"
+ )
+ fun getShapeByID(shapeID: String) : LiveData>
+
+ @Transaction
+ fun clearAndInsertRoutes(routes: List){
+ deleteAllRoutes()
+ insertRoutes(routes)
+ }
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insertRoutes(users: List)
+ @Insert
+ fun insertStops(stops: List)
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insertCalendarServices(services: List)
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insertShapes(shapes: List)
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insertDates(dates: List)
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insertServices(services: List)
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insertTrips(trips: List)
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insertStopTimes(stopTimes: List)
+
+ @Query("DELETE FROM "+GtfsRoute.DB_TABLE)
+ fun deleteAllRoutes()
+ @Query("DELETE FROM "+GtfsStop.DB_TABLE)
+ fun deleteAllStops()
+ @Update(onConflict = OnConflictStrategy.REPLACE)
+ fun updateShapes(shapes: List) : Int
+
+ @Transaction
+ fun updateStops(stops: List){
+ deleteAllStops()
+ insertStops(stops)
+ }
+}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/fragments/FavoritesFragment.java b/src/it/reyboz/bustorino/fragments/FavoritesFragment.java
--- a/src/it/reyboz/bustorino/fragments/FavoritesFragment.java
+++ b/src/it/reyboz/bustorino/fragments/FavoritesFragment.java
@@ -1,3 +1,20 @@
+/*
+ BusTO - Fragments components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.fragments;
import android.app.AlertDialog;
diff --git a/src/it/reyboz/bustorino/fragments/MapFragment.java b/src/it/reyboz/bustorino/fragments/MapFragment.java
--- a/src/it/reyboz/bustorino/fragments/MapFragment.java
+++ b/src/it/reyboz/bustorino/fragments/MapFragment.java
@@ -1,3 +1,21 @@
+/*
+ BusTO - Fragments components
+ Copyright (C) 2020 Andrea Ugo
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.fragments;
import android.Manifest;
diff --git a/src/it/reyboz/bustorino/fragments/NearbyStopsFragment.java b/src/it/reyboz/bustorino/fragments/NearbyStopsFragment.java
--- a/src/it/reyboz/bustorino/fragments/NearbyStopsFragment.java
+++ b/src/it/reyboz/bustorino/fragments/NearbyStopsFragment.java
@@ -328,15 +328,16 @@
@Override
- public void onLoadFinished(@NonNull Loader loader, Cursor data) {
+ public void onLoadFinished(@NonNull Loader loader, Cursor cursor) {
if (0 > MAX_DISTANCE) throw new AssertionError();
//Cursor might be null
- Log.d(DEBUG_TAG, "Num stops found: "+data.getCount()+", Current distance: "+distance);
- if(data==null){
+ if(cursor==null){
Log.e(DEBUG_TAG,"Null cursor, something really wrong happened");
return;
}
- if(!isDBUpdating() && (data.getCount()0) {
- ArrayList stopList = createStopListFromCursor(data);
+ if(cursor.getCount()>0) {
+ ArrayList stopList = createStopListFromCursor(cursor);
double minDistance = Double.POSITIVE_INFINITY;
for(Stop s: stopList){
minDistance = Math.min(minDistance, s.getDistanceFromLocation(lastReceivedLocation));
diff --git a/src/it/reyboz/bustorino/fragments/SettingsFragment.java b/src/it/reyboz/bustorino/fragments/SettingsFragment.java
--- a/src/it/reyboz/bustorino/fragments/SettingsFragment.java
+++ b/src/it/reyboz/bustorino/fragments/SettingsFragment.java
@@ -1,3 +1,20 @@
+/*
+ BusTO - Fragments components
+ Copyright (C) 2020 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.fragments;
import android.content.Context;
diff --git a/src/it/reyboz/bustorino/map/CustomInfoWindow.java b/src/it/reyboz/bustorino/map/CustomInfoWindow.java
--- a/src/it/reyboz/bustorino/map/CustomInfoWindow.java
+++ b/src/it/reyboz/bustorino/map/CustomInfoWindow.java
@@ -1,3 +1,21 @@
+/*
+ BusTO - Map components
+ Copyright (C) 2020 Andrea Ugo
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.map;
import android.annotation.SuppressLint;
diff --git a/src/it/reyboz/bustorino/map/LocationOverlay.java b/src/it/reyboz/bustorino/map/LocationOverlay.java
--- a/src/it/reyboz/bustorino/map/LocationOverlay.java
+++ b/src/it/reyboz/bustorino/map/LocationOverlay.java
@@ -1,5 +1,5 @@
/*
- BusTO (middleware)
+ BusTO - Map components
Copyright (C) 2021 Fabio Mazza
This program is free software: you can redistribute it and/or modify
diff --git a/src/it/reyboz/bustorino/middleware/GeneralActivity.java b/src/it/reyboz/bustorino/middleware/GeneralActivity.java
--- a/src/it/reyboz/bustorino/middleware/GeneralActivity.java
+++ b/src/it/reyboz/bustorino/middleware/GeneralActivity.java
@@ -25,6 +25,7 @@
import it.reyboz.bustorino.R;
import it.reyboz.bustorino.backend.utils;
+import it.reyboz.bustorino.data.PreferencesHolder;
/**
* Activity class that contains all the generally useful methods
@@ -58,7 +59,7 @@
}
protected SharedPreferences getMainSharedPreferences(){
- return getSharedPreferences(getString(R.string.mainSharedPreferences),MODE_PRIVATE);
+ return PreferencesHolder.getMainSharedPreferences(this);
}
public void hideKeyboard() {
View view = getCurrentFocus();