Page MenuHomeGitPull.it

D240.1785978467.diff
No OneTemporary

Authored By
Unknown
Size
62 KB
Referenced Files
None
Subscribers
None

D240.1785978467.diff

diff --git a/app/assets/schemas/it.reyboz.bustorino.data.gtfs.GtfsDatabase/4.json b/app/assets/schemas/it.reyboz.bustorino.data.gtfs.GtfsDatabase/4.json
new file mode 100644
--- /dev/null
+++ b/app/assets/schemas/it.reyboz.bustorino.data.gtfs.GtfsDatabase/4.json
@@ -0,0 +1,950 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 4,
+ "identityHash": "329d27f1f2a9415ef1a8f87957b99e64",
+ "entities": [
+ {
+ "tableName": "gtfs_feeds",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`feed_id` TEXT NOT NULL, PRIMARY KEY(`feed_id`))",
+ "fields": [
+ {
+ "fieldPath": "gtfsId",
+ "columnName": "feed_id",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "feed_id"
+ ]
+ }
+ },
+ {
+ "tableName": "gtfs_agencies",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`gtfs_id` TEXT NOT NULL, `ag_name` TEXT NOT NULL, `ag_url` TEXT NOT NULL, `fare_url` TEXT, `phone` TEXT, `feed_id` TEXT, PRIMARY KEY(`gtfs_id`))",
+ "fields": [
+ {
+ "fieldPath": "gtfsId",
+ "columnName": "gtfs_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "ag_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "url",
+ "columnName": "ag_url",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "fareUrl",
+ "columnName": "fare_url",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "phone",
+ "columnName": "phone",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "feed.gtfsId",
+ "columnName": "feed_id",
+ "affinity": "TEXT"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "gtfs_id"
+ ]
+ }
+ },
+ {
+ "tableName": "gtfs_calendar_dates",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`service_id` TEXT NOT NULL, `date` TEXT NOT NULL, `exception_type` INTEGER NOT NULL, PRIMARY KEY(`service_id`, `date`), FOREIGN KEY(`service_id`) REFERENCES `gtfs_calendar`(`service_id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "serviceID",
+ "columnName": "service_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "exceptionType",
+ "columnName": "exception_type",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "service_id",
+ "date"
+ ]
+ },
+ "foreignKeys": [
+ {
+ "table": "gtfs_calendar",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "service_id"
+ ],
+ "referencedColumns": [
+ "service_id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "stops_gtfs",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`stop_id` INTEGER NOT NULL, `stop_code` TEXT NOT NULL, `stop_name` TEXT NOT NULL, `stop_desc` TEXT NOT NULL, `stop_lat` REAL NOT NULL, `stop_lon` REAL NOT NULL, `wheelchair_boarding` TEXT NOT NULL, PRIMARY KEY(`stop_id`))",
+ "fields": [
+ {
+ "fieldPath": "internalID",
+ "columnName": "stop_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "gttStopID",
+ "columnName": "stop_code",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "stopName",
+ "columnName": "stop_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "gttPlaceName",
+ "columnName": "stop_desc",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "latitude",
+ "columnName": "stop_lat",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "longitude",
+ "columnName": "stop_lon",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "wheelchair",
+ "columnName": "wheelchair_boarding",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "stop_id"
+ ]
+ }
+ },
+ {
+ "tableName": "gtfs_calendar",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`service_id` TEXT NOT NULL, `monday` INTEGER NOT NULL, `tuesday` INTEGER NOT NULL, `wednesday` INTEGER NOT NULL, `thursday` INTEGER NOT NULL, `friday` INTEGER NOT NULL, `saturday` INTEGER NOT NULL, `sunday` INTEGER NOT NULL, `start_date` TEXT NOT NULL, `end_date` TEXT NOT NULL, PRIMARY KEY(`service_id`))",
+ "fields": [
+ {
+ "fieldPath": "serviceID",
+ "columnName": "service_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "onMonday",
+ "columnName": "monday",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "onTuesday",
+ "columnName": "tuesday",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "onWednesday",
+ "columnName": "wednesday",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "onThursday",
+ "columnName": "thursday",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "onFriday",
+ "columnName": "friday",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "onSaturday",
+ "columnName": "saturday",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "onSunday",
+ "columnName": "sunday",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "startDate",
+ "columnName": "start_date",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "endDate",
+ "columnName": "end_date",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "service_id"
+ ]
+ }
+ },
+ {
+ "tableName": "routes_table",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`route_id` TEXT NOT NULL, `agency_id` TEXT NOT NULL, `route_short_name` TEXT NOT NULL, `route_long_name` TEXT NOT NULL, `route_desc` TEXT NOT NULL, `route_mode` TEXT NOT NULL, `route_color` TEXT NOT NULL, `route_text_color` TEXT NOT NULL, PRIMARY KEY(`route_id`))",
+ "fields": [
+ {
+ "fieldPath": "gtfsId",
+ "columnName": "route_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "agencyID",
+ "columnName": "agency_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "shortName",
+ "columnName": "route_short_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "longName",
+ "columnName": "route_long_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "description",
+ "columnName": "route_desc",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mode",
+ "columnName": "route_mode",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "color",
+ "columnName": "route_color",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "textColor",
+ "columnName": "route_text_color",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "route_id"
+ ]
+ }
+ },
+ {
+ "tableName": "gtfs_stop_times",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`trip_id` TEXT NOT NULL, `arrival_time` TEXT NOT NULL, `departure_time` TEXT NOT NULL, `stop_id` INTEGER NOT NULL, `stop_sequence` INTEGER NOT NULL, PRIMARY KEY(`trip_id`, `stop_id`), FOREIGN KEY(`stop_id`) REFERENCES `stops_gtfs`(`stop_id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`trip_id`) REFERENCES `gtfs_trips`(`trip_id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "tripID",
+ "columnName": "trip_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "arrivalTime",
+ "columnName": "arrival_time",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "departureTime",
+ "columnName": "departure_time",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "stopID",
+ "columnName": "stop_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "stopSequence",
+ "columnName": "stop_sequence",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "trip_id",
+ "stop_id"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_gtfs_stop_times_stop_id",
+ "unique": false,
+ "columnNames": [
+ "stop_id"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_gtfs_stop_times_stop_id` ON `${TABLE_NAME}` (`stop_id`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "stops_gtfs",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "stop_id"
+ ],
+ "referencedColumns": [
+ "stop_id"
+ ]
+ },
+ {
+ "table": "gtfs_trips",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "trip_id"
+ ],
+ "referencedColumns": [
+ "trip_id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "gtfs_trips",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`route_id` TEXT NOT NULL, `service_id` TEXT NOT NULL, `trip_id` TEXT NOT NULL, `trip_headsign` TEXT NOT NULL, `direction_id` INTEGER NOT NULL, `block_id` TEXT NOT NULL, `shape_id` TEXT NOT NULL, `wheelchair_accessible` TEXT NOT NULL, `limited_route` INTEGER NOT NULL, `pattern_code` TEXT NOT NULL DEFAULT '', `semantic_hash` TEXT, PRIMARY KEY(`trip_id`), FOREIGN KEY(`route_id`) REFERENCES `routes_table`(`route_id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "routeID",
+ "columnName": "route_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "serviceID",
+ "columnName": "service_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "tripID",
+ "columnName": "trip_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "tripHeadsign",
+ "columnName": "trip_headsign",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "directionID",
+ "columnName": "direction_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "blockID",
+ "columnName": "block_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "shapeID",
+ "columnName": "shape_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isWheelchairAccess",
+ "columnName": "wheelchair_accessible",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isLimitedRoute",
+ "columnName": "limited_route",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "patternId",
+ "columnName": "pattern_code",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "''"
+ },
+ {
+ "fieldPath": "semanticHash",
+ "columnName": "semantic_hash",
+ "affinity": "TEXT"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "trip_id"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_gtfs_trips_route_id",
+ "unique": false,
+ "columnNames": [
+ "route_id"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_gtfs_trips_route_id` ON `${TABLE_NAME}` (`route_id`)"
+ },
+ {
+ "name": "index_gtfs_trips_trip_id",
+ "unique": false,
+ "columnNames": [
+ "trip_id"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_gtfs_trips_trip_id` ON `${TABLE_NAME}` (`trip_id`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "routes_table",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "route_id"
+ ],
+ "referencedColumns": [
+ "route_id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "gtfs_shapes",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`shape_id` TEXT NOT NULL, `shape_pt_lat` REAL NOT NULL, `shape_pt_lon` REAL NOT NULL, `shape_pt_sequence` INTEGER NOT NULL, PRIMARY KEY(`shape_id`, `shape_pt_sequence`))",
+ "fields": [
+ {
+ "fieldPath": "shapeID",
+ "columnName": "shape_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "pointLat",
+ "columnName": "shape_pt_lat",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "pointLon",
+ "columnName": "shape_pt_lon",
+ "affinity": "REAL",
+ "notNull": true
+ },
+ {
+ "fieldPath": "pointSequence",
+ "columnName": "shape_pt_sequence",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "shape_id",
+ "shape_pt_sequence"
+ ]
+ }
+ },
+ {
+ "tableName": "mato_patterns",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pattern_name` TEXT NOT NULL, `pattern_code` TEXT NOT NULL, `pattern_hash` TEXT NOT NULL, `pattern_direction_id` INTEGER NOT NULL, `pattern_route_id` TEXT NOT NULL, `pattern_headsign` TEXT, `pattern_polyline` TEXT NOT NULL, `pattern_polylength` INTEGER NOT NULL, PRIMARY KEY(`pattern_code`), FOREIGN KEY(`pattern_route_id`) REFERENCES `routes_table`(`route_id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "name",
+ "columnName": "pattern_name",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "code",
+ "columnName": "pattern_code",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "semanticHash",
+ "columnName": "pattern_hash",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "directionId",
+ "columnName": "pattern_direction_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "routeGtfsId",
+ "columnName": "pattern_route_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "headsign",
+ "columnName": "pattern_headsign",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "patternGeometryPoly",
+ "columnName": "pattern_polyline",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "patternGeometryLength",
+ "columnName": "pattern_polylength",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "pattern_code"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_mato_patterns_pattern_code",
+ "unique": false,
+ "columnNames": [
+ "pattern_code"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_mato_patterns_pattern_code` ON `${TABLE_NAME}` (`pattern_code`)"
+ },
+ {
+ "name": "index_mato_patterns_pattern_route_id",
+ "unique": false,
+ "columnNames": [
+ "pattern_route_id"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_mato_patterns_pattern_route_id` ON `${TABLE_NAME}` (`pattern_route_id`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "routes_table",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "pattern_route_id"
+ ],
+ "referencedColumns": [
+ "route_id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "patterns_stops",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pattern_gtfs_id` TEXT NOT NULL, `stop_gtfs_id` TEXT NOT NULL, `stop_order` INTEGER NOT NULL, PRIMARY KEY(`pattern_gtfs_id`, `stop_gtfs_id`, `stop_order`), FOREIGN KEY(`pattern_gtfs_id`) REFERENCES `mato_patterns`(`pattern_code`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "patternId",
+ "columnName": "pattern_gtfs_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "stopGtfsId",
+ "columnName": "stop_gtfs_id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "order",
+ "columnName": "stop_order",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "pattern_gtfs_id",
+ "stop_gtfs_id",
+ "stop_order"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_patterns_stops_pattern_gtfs_id",
+ "unique": false,
+ "columnNames": [
+ "pattern_gtfs_id"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_patterns_stops_pattern_gtfs_id` ON `${TABLE_NAME}` (`pattern_gtfs_id`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "mato_patterns",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "pattern_gtfs_id"
+ ],
+ "referencedColumns": [
+ "pattern_code"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "gtfsrt_alerts",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `cause` INTEGER NOT NULL, `effect` INTEGER NOT NULL, `fetchedAt` INTEGER NOT NULL, `userSeen` INTEGER NOT NULL, PRIMARY KEY(`id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "cause",
+ "columnName": "cause",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "effect",
+ "columnName": "effect",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "fetchedAt",
+ "columnName": "fetchedAt",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userSeen",
+ "columnName": "userSeen",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ }
+ },
+ {
+ "tableName": "gtfsrt_alert_translations",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`hash` TEXT NOT NULL, `alertId` TEXT NOT NULL, `field` TEXT NOT NULL, `language` TEXT, `text` TEXT NOT NULL, PRIMARY KEY(`hash`), FOREIGN KEY(`alertId`) REFERENCES `gtfsrt_alerts`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "hash",
+ "columnName": "hash",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "alertId",
+ "columnName": "alertId",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "field",
+ "columnName": "field",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "language",
+ "columnName": "language",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "text",
+ "columnName": "text",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "hash"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_gtfsrt_alert_translations_alertId",
+ "unique": false,
+ "columnNames": [
+ "alertId"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_gtfsrt_alert_translations_alertId` ON `${TABLE_NAME}` (`alertId`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "gtfsrt_alerts",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "alertId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "alerts_active_periods",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`hash` TEXT NOT NULL, `alertId` TEXT NOT NULL, `start` INTEGER, `end` INTEGER, PRIMARY KEY(`hash`), FOREIGN KEY(`alertId`) REFERENCES `gtfsrt_alerts`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "hash",
+ "columnName": "hash",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "alertId",
+ "columnName": "alertId",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "start",
+ "columnName": "start",
+ "affinity": "INTEGER"
+ },
+ {
+ "fieldPath": "end",
+ "columnName": "end",
+ "affinity": "INTEGER"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "hash"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_alerts_active_periods_alertId",
+ "unique": false,
+ "columnNames": [
+ "alertId"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_alerts_active_periods_alertId` ON `${TABLE_NAME}` (`alertId`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "gtfsrt_alerts",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "alertId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "alerts_informed_entities",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`internalId` TEXT NOT NULL, `alertId` TEXT NOT NULL, `routeId` TEXT, `routeType` INTEGER, `stopId` TEXT, `tripId` TEXT, `tripRouteId` TEXT, `directionId` INTEGER, PRIMARY KEY(`internalId`), FOREIGN KEY(`alertId`) REFERENCES `gtfsrt_alerts`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "internalId",
+ "columnName": "internalId",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "alertId",
+ "columnName": "alertId",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "routeId",
+ "columnName": "routeId",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "routeType",
+ "columnName": "routeType",
+ "affinity": "INTEGER"
+ },
+ {
+ "fieldPath": "stopId",
+ "columnName": "stopId",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "tripId",
+ "columnName": "tripId",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "tripRouteId",
+ "columnName": "tripRouteId",
+ "affinity": "TEXT"
+ },
+ {
+ "fieldPath": "directionId",
+ "columnName": "directionId",
+ "affinity": "INTEGER"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "internalId"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_alerts_informed_entities_alertId",
+ "unique": false,
+ "columnNames": [
+ "alertId"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_alerts_informed_entities_alertId` ON `${TABLE_NAME}` (`alertId`)"
+ },
+ {
+ "name": "index_alerts_informed_entities_routeId",
+ "unique": false,
+ "columnNames": [
+ "routeId"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_alerts_informed_entities_routeId` ON `${TABLE_NAME}` (`routeId`)"
+ },
+ {
+ "name": "index_alerts_informed_entities_stopId",
+ "unique": false,
+ "columnNames": [
+ "stopId"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_alerts_informed_entities_stopId` ON `${TABLE_NAME}` (`stopId`)"
+ },
+ {
+ "name": "index_alerts_informed_entities_tripId",
+ "unique": false,
+ "columnNames": [
+ "tripId"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_alerts_informed_entities_tripId` ON `${TABLE_NAME}` (`tripId`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "gtfsrt_alerts",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "alertId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ }
+ ],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '329d27f1f2a9415ef1a8f87957b99e64')"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/FragmentHelper.java b/app/src/main/java/it/reyboz/bustorino/fragments/FragmentHelper.java
--- a/app/src/main/java/it/reyboz/bustorino/fragments/FragmentHelper.java
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/FragmentHelper.java
@@ -29,10 +29,7 @@
import android.widget.Toast;
import it.reyboz.bustorino.R;
-import it.reyboz.bustorino.backend.Fetcher;
-import it.reyboz.bustorino.backend.Palina;
-import it.reyboz.bustorino.backend.Stop;
-import it.reyboz.bustorino.backend.utils;
+import it.reyboz.bustorino.backend.*;
import it.reyboz.bustorino.middleware.*;
import java.lang.ref.WeakReference;
@@ -52,7 +49,7 @@
private final Context context;
public static final int NO_FRAME = -3;
private static final String DEBUG_TAG = "BusTO FragmHelper";
- private WeakReference<AsyncTask> lastTaskRef;
+ private final StopSearcher stopSearcher;
private boolean shouldHaltAllActivities=false;
@@ -66,6 +63,7 @@
this.primaryFrameLayout = primaryFrameLayout;
this.secondaryFrameLayout = secondaryFrameLayout;
this.context = context.getApplicationContext();
+ stopSearcher = new StopSearcher(this);
}
/**
@@ -81,9 +79,6 @@
this.lastSuccessfullySearchedBusStop = stop;
}
- public void setLastTaskRef(AsyncTask task) {
- this.lastTaskRef = new WeakReference<>(task);
- }
/**
* Called when you need to create a fragment for a specified Palina
@@ -199,12 +194,19 @@
this.shouldHaltAllActivities = shouldI;
}
- public void stopLastRequestIfNeeded(boolean interruptIfRunning){
- if(lastTaskRef == null) return;
+ public void stopLastRequestIfNeeded(){
+ /*if(lastTaskRef == null) return;
AsyncTask task = lastTaskRef.get();
if(task!=null){
task.cancel(interruptIfRunning);
}
+
+ */
+ stopSearcher.cancelLastRequest();
+ }
+ public void requestStopSearch(String query){
+ stopSearcher.cancelLastRequest();
+ stopSearcher.runRequest(query, new StopsFinderByName[]{new GTTStopsFetcher(), new FiveTStopsFetcher()}); // run with the default fetchers
}
/**
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/MainScreenFragment.java b/app/src/main/java/it/reyboz/bustorino/fragments/MainScreenFragment.java
--- a/app/src/main/java/it/reyboz/bustorino/fragments/MainScreenFragment.java
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/MainScreenFragment.java
@@ -59,8 +59,6 @@
import it.reyboz.bustorino.R;
import it.reyboz.bustorino.backend.*;
import it.reyboz.bustorino.data.PreferencesHolder;
-import it.reyboz.bustorino.middleware.AsyncArrivalsSearcher;
-import it.reyboz.bustorino.middleware.AsyncStopsSearcher;
import it.reyboz.bustorino.middleware.BarcodeScanContract;
import it.reyboz.bustorino.middleware.BarcodeScanOptions;
import it.reyboz.bustorino.middleware.BarcodeScanUtils;
@@ -109,31 +107,25 @@
//private ImageButton addToFavorites;
//// HIDDEN BUT IMPORTANT ELEMENTS ////
private FragmentManager childFragMan;
- Handler mainHandler;
- private final Runnable refreshStop = new Runnable() {
- public void run() {
- if(getContext() == null) return;
-
- if (childFragMan.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) {
- ArrivalsFragment fragment = (ArrivalsFragment) childFragMan.findFragmentById(R.id.resultFrame);
- if (fragment == null){
- //we create a new fragment, which is WRONG
- Log.e("BusTO-RefreshStop", "Asking for refresh when there is no fragment");
- // AsyncDataDownload(fragmentHelper, arrivalsFetchers,getContext()).execute();
- } else{
- //String stopName = fragment.getStopID();
-
- //new AsyncArrivalsSearcher(fragmentHelper, fragment.getCurrentFetchersAsArray(), getContext()).execute(stopName);
- fragment.requestArrivalsForTheFragment();
- }
- } else { //we create a new fragment, which is WRONG
- List<ArrivalsFetcher> fetcherList = utils.getDefaultArrivalsFetchers(getContext());
- ArrivalsFetcher[] arrivalsFetchers = new ArrivalsFetcher[fetcherList.size()];
- arrivalsFetchers = fetcherList.toArray(arrivalsFetchers);
- new AsyncArrivalsSearcher(fragmentHelper, arrivalsFetchers, getContext()).execute();
+
+ private void refreshStop() {
+ if(getContext() == null){
+ Log.w(DEBUG_TAG,"Asked to refresh stop but context is null");
+ return;
+ }
+ if (childFragMan.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) {
+ ArrivalsFragment fragment = (ArrivalsFragment) childFragMan.findFragmentById(R.id.resultFrame);
+ if (fragment == null){
+ //we create a new fragment, which is WRONG
+ Log.e("BusTO-RefreshStop", "Asking for refresh when there is no fragment");
+ } else{
+ //String stopName = fragment.getStopID();
+ fragment.requestArrivalsForTheFragment();
}
+ } else { //we create a new fragment, which is WRONG
+ Log.w(DEBUG_TAG, "Asked to refresh stop when there is no fragment");
}
- };
+ }
//
private final ActivityResultLauncher<BarcodeScanOptions> barcodeLauncher = registerForActivityResult(new BarcodeScanContract(),
result -> {
@@ -203,58 +195,6 @@
});
- //private final LocationCriteria cr = new LocationCriteria(2000, 10000);
- //Location
- /*private AppLocationManager.LocationRequester requester = new AppLocationManager.LocationRequester() {
- @Override
- public void onLocationChanged(Location loc) {
-
- }
-
- @Override
- public void onLocationStatusChanged(int status) {
-
- if(status == AppLocationManager.LOCATION_GPS_AVAILABLE && !isNearbyFragmentShown() && checkLocationPermission()){
- //request Stops
- //pendingNearbyStopsRequest = false;
- if (getContext()!= null && !isNearbyFragmentShown())
- //mainHandler.post(new NearbyStopsRequester(getContext(), cr));
- showNearbyFragmentIfPossible();
- }
- }
-
- @Override
- public long getLastUpdateTimeMillis() {
- return 50;
- }
-
- @Override
- public LocationCriteria getLocationCriteria() {
- return cr;
- }
-
- @Override
- public void onLocationProviderAvailable() {
- //Log.w(DEBUG_TAG, "pendingNearbyStopRequest: "+pendingNearbyStopsRequest);
- if(!isNearbyFragmentShown() && getContext()!=null){
- // we should have the location permission
- if(!checkLocationPermission())
- Log.e(DEBUG_TAG, "Asking to show nearbystopfragment when " +
- "we have no location permission");
- pendingNearbyStopsFragmentRequest = true;
- //mainHandler.post(new NearbyStopsRequester(getContext(), cr));
- showNearbyFragmentIfPossible();
- }
- }
-
- @Override
- public void onLocationDisabled() {
-
- }
- };
-
- */
-
//// ACTIVITY ATTACHED (LISTENER ///
private CommonFragmentListener mListener;
@@ -315,7 +255,7 @@
});
swipeRefreshLayout
- .setOnRefreshListener(() -> mainHandler.post(refreshStop));
+ .setOnRefreshListener(this::refreshStop);
swipeRefreshLayout.setColorSchemeResources(R.color.blue_500, R.color.orange_500);
coordLayout = root.findViewById(R.id.coord_layout);
@@ -405,7 +345,7 @@
if(getContext()==null) return; //we are not attached
//Fragment fr = getChildFragmentManager().findFragmentById(R.id.resultFrame);
- fragmentHelper.stopLastRequestIfNeeded(true);
+ fragmentHelper.stopLastRequestIfNeeded();
toggleSpinner(false);
}
@@ -415,7 +355,6 @@
super.onAttach(context);
Log.d(DEBUG_TAG, "OnAttach called, setupOnAttach: "+ setupOnStart);
- mainHandler = new Handler();
if (context instanceof CommonFragmentListener) {
mListener = (CommonFragmentListener) context;
} else {
@@ -531,9 +470,9 @@
public void onPause() {
//mainHandler = null;
//locationManager.removeLocationRequestFor(requester);
- super.onPause();
fragmentHelper.setBlockAllActivities(true);
- fragmentHelper.stopLastRequestIfNeeded(true);
+ fragmentHelper.stopLastRequestIfNeeded();
+ super.onPause();
}
@@ -564,10 +503,10 @@
* @param v View clicked
*/
public void onSearchClick(View v) {
- final StopsFinderByName[] stopsFinderByNames = new StopsFinderByName[]{new GTTStopsFetcher(), new FiveTStopsFetcher()};
+ //final StopsFinderByName[] stopsFinderByNames = new StopsFinderByName[]{new GTTStopsFetcher(), new FiveTStopsFetcher()};
if (searchMode == SEARCH_BY_ID) {
String busStopID = busStopSearchByIDEditText.getText().toString();
- fragmentHelper.stopLastRequestIfNeeded(true);
+ fragmentHelper.stopLastRequestIfNeeded();
requestArrivalsForStopID(busStopID);
} else { // searchMode == SEARCH_BY_NAME
String query = busStopSearchByNameEditText.getText().toString();
@@ -579,8 +518,7 @@
Toast.makeText(getContext(), R.string.query_too_short, Toast.LENGTH_SHORT).show();
}
else {
- fragmentHelper.stopLastRequestIfNeeded(true);
- new AsyncStopsSearcher(fragmentHelper, stopsFinderByNames).execute(query);
+ fragmentHelper.requestStopSearch(query);
}
}
}
@@ -831,72 +769,5 @@
pendingNearbyStopsFragmentRequest = false;
}
}
- /////////// LOCATION METHODS //////////
-
- /*
- private void startStopRequest(String provider) {
- Log.d(DEBUG_TAG, "Provider " + provider + " got enabled");
- if (locmgr != null && mainHandler != null && pendingNearbyStopsRequest && locmgr.getProvider(provider).meetsCriteria(cr)) {
-
- }
- }
-
- */
- /*
-
- * Run location requests separately and asynchronously
-
- class NearbyStopsRequester implements Runnable {
- Context appContext;
- Criteria cr;
-
- public NearbyStopsRequester(Context appContext, Criteria criteria) {
- this.appContext = appContext.getApplicationContext();
- this.cr = criteria;
- }
-
- @Override
- public void run() {
- if(isNearbyFragmentShown()) {
- //nothing to do
- Log.w(DEBUG_TAG, "launched nearby fragment request but we already are showing");
- return;
- }
-
- final boolean isOldVersion = Build.VERSION.SDK_INT < Build.VERSION_CODES.M;
- final boolean noPermission = ActivityCompat.checkSelfPermission(appContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
- ActivityCompat.checkSelfPermission(appContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED;
-
- //if we don't have the permission, we have to ask for it, if we haven't
- // asked too many times before
- if (noPermission) {
- if (!isOldVersion) {
- pendingNearbyStopsRequest = true;
- //Permissions.assertLocationPermissions(appContext,getActivity());
- requestPermissionLauncher.launch(LOCATION_PERMISSIONS);
- Log.w(DEBUG_TAG, "Cannot get position: Asking permission, noPositionFromSys: " + noPermission);
- return;
- } else {
- Toast.makeText(appContext, "Asked for permission position too many times", Toast.LENGTH_LONG).show();
- }
- } else setOption(LOCATION_PERMISSION_GIVEN, true);
-
- AppLocationManager appLocationManager = AppLocationManager.getInstance(appContext);
- final boolean haveProviders = appLocationManager.anyLocationProviderMatchesCriteria(cr);
- if (haveProviders
- && fragmentHelper.getLastSuccessfullySearchedBusStop() == null
- && !fragMan.isDestroyed()) {
- //Go ahead with the request
- Log.d("mainActivity", "Recreating stop fragment");
- showNearbyStopsFragment();
- pendingNearbyStopsRequest = false;
- } else if(!haveProviders){
- Log.e(DEBUG_TAG, "NO PROVIDERS FOR POSITION");
- }
-
- }
- }
-
- */
}
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/middleware/AsyncArrivalsSearcher.java b/app/src/main/java/it/reyboz/bustorino/middleware/AsyncArrivalsSearcher.java
deleted file mode 100644
--- a/app/src/main/java/it/reyboz/bustorino/middleware/AsyncArrivalsSearcher.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- BusTO (middleware)
- Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
- */
-package it.reyboz.bustorino.middleware;
-
-import android.annotation.SuppressLint;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.SQLException;
-import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
-import android.os.AsyncTask;
-
-import androidx.annotation.NonNull;
-
-import android.util.Log;
-
-import it.reyboz.bustorino.backend.*;
-import it.reyboz.bustorino.backend.mato.MatoAPIFetcher;
-import it.reyboz.bustorino.data.AppDataProvider;
-import it.reyboz.bustorino.data.NextGenDB;
-import it.reyboz.bustorino.fragments.FragmentHelper;
-import it.reyboz.bustorino.data.NextGenDB.Contract.*;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.Calendar;
-
-/**
- * This should be used to download data, but not to display it
- */
-public class AsyncArrivalsSearcher extends AsyncTask<String, Fetcher.Result,Palina>{
-
- private static final String TAG = "BusTO-DataDownload";
- private static final String DEBUG_TAG = TAG;
- private boolean failedAll = false;
-
- private final AtomicReference<Fetcher.Result> finalResultRef;
- private String query;
- WeakReference<FragmentHelper> helperRef;
- private final ArrayList<Thread> otherActivities = new ArrayList<>();
- private final ArrivalsFetcher[] theFetchers;
- @SuppressLint("StaticFieldLeak")
- private final Context context;
- private final boolean replaceFragment;
-
-
- public AsyncArrivalsSearcher(FragmentHelper fh, @NonNull ArrivalsFetcher[] fetchers, Context context) {
- helperRef = new WeakReference<>(fh);
- fh.setLastTaskRef(this);
- finalResultRef = new AtomicReference<>();
- this.context = context.getApplicationContext();
- this.replaceFragment = true;
-
- theFetchers = fetchers;
- if (theFetchers.length < 1){
- throw new IllegalArgumentException("You have to put at least one Fetcher, idiot!");
- }
-
- }
-
- @Override
- protected Palina doInBackground(String... params) {
- RecursionHelper<ArrivalsFetcher> r = new RecursionHelper<>(theFetchers);
- Palina resultPalina = null;
- FragmentHelper fh = helperRef.get();
- ArrayList<Fetcher.Result> results = new ArrayList<>(theFetchers.length);
- //If the FragmentHelper is null, that means the activity doesn't exist anymore
- StringBuilder sb = new StringBuilder();
- for (ArrivalsFetcher f: theFetchers){
- sb.append("");
- sb.append(f.getClass().getSimpleName());
- sb.append("; ");
- }
- Log.d(DEBUG_TAG, "Using fetchers: "+sb.toString());
- if (fh == null){
- return null;
- }
-
- //Log.d(TAG,"refresh layout reference is: "+fh.isRefreshLayoutReferenceTrue());
- while(r.valid()) {
- if(this.isCancelled()) {
- return null;
- }
- //get the data from the fetcher
- ArrivalsFetcher f = r.getAndMoveForward();
- AtomicReference<Fetcher.Result> resRef = new AtomicReference<>();
- if (f instanceof ArrivalsFetcherContext){
- ((ArrivalsFetcherContext)f).setContext(context);
- }
- Log.d(TAG,"Using the ArrivalsFetcher: "+f.getClass());
-
- Stop lastSearchedBusStop = fh.getLastSuccessfullySearchedBusStop();
- Palina p;
- String stopID;
- if(params.length>0)
- stopID=params[0]; //(it's a Palina)
- else if(lastSearchedBusStop!=null)
- stopID = lastSearchedBusStop.ID; //(it's a Palina)
- else {
- publishProgress(Fetcher.Result.QUERY_TOO_SHORT);
- return null;
- }
- //Skip the FiveTAPIFetcher for the Metro Stops because it shows incomprehensible arrival times
- try {
- if (f instanceof FiveTAPIFetcher && Integer.parseInt(stopID) >= 8200)
- continue;
- } catch (NumberFormatException ex){
- Log.e(DEBUG_TAG, "The stop number is not a valid integer, expect failures");
- }
- p= f.ReadArrivalTimesAll(stopID,resRef);
-
-
- //if (res.get()!= Fetcher.Result.OK)
- Log.d(DEBUG_TAG, "Arrivals fetcher: "+f+"\n\tProgress: "+resRef.get());
-
- if(f instanceof FiveTAPIFetcher){
- AtomicReference<Fetcher.Result> gres = new AtomicReference<>();
- List<Route> branches = ((FiveTAPIFetcher) f).getDirectionsForStop(stopID,gres);
- Log.d(DEBUG_TAG, "FiveTArrivals fetcher: "+f+"\n\tDetails req: "+gres.get());
- if(gres.get() == Fetcher.Result.OK){
- p.addInfoFromRoutes(branches);
- Thread t = new Thread(new BranchInserter(branches, context));
- t.start();
- otherActivities.add(t);
- } else{
- resRef.set(Fetcher.Result.NOT_FOUND);
- }
- //put updated values into Database
- }
-
- if(lastSearchedBusStop != null && resRef.get()== Fetcher.Result.OK) {
- // check that we don't have the same stop
- if(lastSearchedBusStop.ID.equals(p.ID)) {
- // searched and it's the same
- String sn = lastSearchedBusStop.getStopDisplayName();
- if(sn != null) {
- // "merge" Stop over Palina and we're good to go
- p.mergeNameFrom(lastSearchedBusStop);
- }
- }
- }
- p.mergeDuplicateRoutes(0);
- if (resRef.get() == Fetcher.Result.OK && p.getTotalNumberOfPassages() == 0 ) {
- resRef.set(Fetcher.Result.EMPTY_RESULT_SET);
- Log.d(DEBUG_TAG, "Setting empty results");
- }
- publishProgress(resRef.get());
- //TODO: find a way to avoid overloading the user with toasts
- if (resultPalina == null && f instanceof MatoAPIFetcher && p.queryAllRoutes().size() > 0){
- resultPalina = p;
- }
- //find if it went well
- results.add(resRef.get());
- if(resRef.get()== Fetcher.Result.OK) {
- //wait for other threads to finish
- for(Thread t: otherActivities){
- try {
- t.join();
- } catch (InterruptedException e) {
- //do nothing
- }
- }
- return p;
- }
-
- finalResultRef.set(resRef.get());
- }
- /*
- boolean emptyResults = true;
- for (Fetcher.Result re: results){
- if (!re.equals(Fetcher.Result.EMPTY_RESULT_SET)) {
- emptyResults = false;
- break;
- }
- }
-
- */
- //at this point, we are sure that the result has been negative
- failedAll=true;
-
-
- return resultPalina;
- }
-
- @Override
- protected void onProgressUpdate(Fetcher.Result... values) {
- FragmentHelper fh = helperRef.get();
- if (fh!=null)
- for (Fetcher.Result r : values){
- //TODO: make Toast
- fh.showErrorMessage(r, SearchRequestType.ARRIVALS);
- }
- else {
- Log.w(TAG,"We had to show some progress but activity was destroyed");
- }
- }
-
- @Override
- protected void onPostExecute(Palina p) {
- FragmentHelper fh = helperRef.get();
-
- if(p == null || fh == null){
- //everything went bad
- if(fh!=null) fh.toggleSpinner(false);
- cancel(true);
- //TODO: send message here
- return;
- }
-
- if(isCancelled()) return;
-
-
- fh.createOrUpdateStopFragment( p, replaceFragment);
- }
-
- @Override
- protected void onCancelled() {
- FragmentHelper fh = helperRef.get();
- if (fh!=null) fh.toggleSpinner(false);
- }
-
- @Override
- protected void onPreExecute() {
- FragmentHelper fh = helperRef.get();
- if (fh!=null) fh.toggleSpinner(true);
- }
-
-
- public static class BranchInserter implements Runnable{
- private final List<Route> routesToInsert;
-
- private final Context context;
- //private final NextGenDB nextGenDB;
-
- public BranchInserter(List<Route> routesToInsert,@NonNull Context con) {
- this.routesToInsert = routesToInsert;
- this.context = con.getApplicationContext();
- //nextGenDB = new NextGenDB(context);
- }
-
- @Override
- public void run() {
- NextGenDB.insertBranchesIntoDB(context, routesToInsert);
- }
- }
-}
diff --git a/app/src/main/java/it/reyboz/bustorino/middleware/AsyncStopsSearcher.java b/app/src/main/java/it/reyboz/bustorino/middleware/AsyncStopsSearcher.java
deleted file mode 100644
--- a/app/src/main/java/it/reyboz/bustorino/middleware/AsyncStopsSearcher.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- BusTO (middleware)
- 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 <http://www.gnu.org/licenses/>.
- */
-package it.reyboz.bustorino.middleware;
-
-import android.os.AsyncTask;
-import android.util.Log;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
-import it.reyboz.bustorino.backend.Fetcher;
-import it.reyboz.bustorino.backend.Stop;
-import it.reyboz.bustorino.backend.StopsFinderByName;
-import it.reyboz.bustorino.fragments.FragmentHelper;
-
-public class AsyncStopsSearcher extends AsyncTask<String, Fetcher.Result, List<Stop>> {
-
- private static final String TAG = "BusTO-StopsSearcher";
- private static final String DEBUG_TAG = TAG;
- private final StopsFinderByName[] fetchers;
- private final AtomicReference<Fetcher.Result> res;
-
- private WeakReference<FragmentHelper> helperWR;
-
- private String theQuery;
-
- public AsyncStopsSearcher(FragmentHelper fh, StopsFinderByName[] fetchers) {
- this.fetchers = fetchers;
- if (fetchers.length < 1){
- throw new IllegalArgumentException("You have to put at least one Fetcher, idiot!");
- }
-
- this.res = new AtomicReference<>();
- this.helperWR = new WeakReference<>(fh);
- fh.setLastTaskRef(this);
-
- }
-
- @Override
- protected List<Stop> doInBackground(String... strings) {
- RecursionHelper<StopsFinderByName> r = new RecursionHelper<>(fetchers);
- if (helperWR.get()==null || strings.length == 0)
- return null;
- Log.d(DEBUG_TAG,"Running with query "+strings[0]);
-
- ArrayList<Fetcher.Result> results = new ArrayList<>();
- List<Stop> resultsList;
- while (r.valid()){
- if (this.isCancelled()) return null;
-
- final StopsFinderByName finder = r.getAndMoveForward();
- theQuery = strings[0].trim();
- resultsList = finder.FindByName(theQuery, res);
- Log.d(DEBUG_TAG, "Result: "+res.get()+", "+resultsList.size()+" stops");
-
- if (res.get()== Fetcher.Result.OK){
- return resultsList;
- }
- results.add(res.get());
- }
- boolean emptyResults = true;
- for (Fetcher.Result re: results){
- if (!re.equals(Fetcher.Result.EMPTY_RESULT_SET)) {
- emptyResults = false;
- break;
- }
- }
- if(emptyResults){
- publishProgress(Fetcher.Result.EMPTY_RESULT_SET);
- }
- return new ArrayList<>();
- }
-
- @Override
- protected void onProgressUpdate(Fetcher.Result... values) {
- FragmentHelper fh = helperWR.get();
- if (fh!=null)
- for (Fetcher.Result r : values){
- fh.showErrorMessage(r, SearchRequestType.STOPS);
- }
- else {
- Log.w(TAG,"We had to show some progress but activity was destroyed");
- }
- }
- @Override
- protected void onCancelled() {
- FragmentHelper fh = helperWR.get();
- if (fh!=null) fh.toggleSpinner(false);
- }
-
- @Override
- protected void onPreExecute() {
- FragmentHelper fh = helperWR.get();
- if (fh!=null) fh.toggleSpinner(true);
- }
-
- @Override
- protected void onPostExecute(List<Stop> stops) {
- final FragmentHelper fh = helperWR.get();
-
- if (stops==null || stops.size() == 0 || fh==null || theQuery==null) {
- if (fh!=null) fh.toggleSpinner(false);
- cancel(true);
- return;
- }
- if(isCancelled()){
- fh.toggleSpinner(false);
- return;
- }
- fh.createStopListFragment(stops, theQuery, true);
-
-
- }
-}
diff --git a/app/src/main/java/it/reyboz/bustorino/middleware/StopSearcher.kt b/app/src/main/java/it/reyboz/bustorino/middleware/StopSearcher.kt
new file mode 100644
--- /dev/null
+++ b/app/src/main/java/it/reyboz/bustorino/middleware/StopSearcher.kt
@@ -0,0 +1,133 @@
+package it.reyboz.bustorino.middleware
+
+import android.content.Context
+import android.util.Log
+import it.reyboz.bustorino.backend.Fetcher
+import it.reyboz.bustorino.backend.FiveTStopsFetcher
+import it.reyboz.bustorino.backend.GTTStopsFetcher
+import it.reyboz.bustorino.backend.Stop
+import it.reyboz.bustorino.backend.StopsFinderByName
+import it.reyboz.bustorino.fragments.FragmentHelper
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.cancelAndJoin
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import java.lang.ref.WeakReference
+import java.util.concurrent.atomic.AtomicReference
+import kotlin.coroutines.cancellation.CancellationException
+
+class StopSearcher(
+ fragmentHelper: FragmentHelper,
+) {
+
+ private val helperRef = WeakReference(fragmentHelper)
+ private val resultRef = AtomicReference<Fetcher.Result>(Fetcher.Result.PARSER_ERROR)
+
+ private val finders = arrayOf(GTTStopsFetcher(), FiveTStopsFetcher())
+ private var lastJob : Job? = null
+
+ private suspend fun getData(query: String, r: RecursionHelper<StopsFinderByName>): List<Stop>? {
+ if (helperRef.get() == null) return null
+ if(query.isEmpty()) {
+ resultRef.set(Fetcher.Result.QUERY_TOO_SHORT)
+ return null
+ }
+ resultRef.set(Fetcher.Result.OK)
+ Log.d(DEBUG_TAG, "Running with query " + query)
+
+ //val results = ArrayList<Fetcher.Result>()
+ //var resultsList: List<Stop?>
+ val queryOk = query.trim { it <= ' ' }
+ while (r.valid()) {
+
+ val finder = r.getAndMoveForward()
+ val resultsList = finder.FindByName(queryOk, resultRef)
+ Log.d(DEBUG_TAG, "Result: " + resultRef.get() + ", " + resultsList.size + " stops")
+
+ if (resultRef.get() == Fetcher.Result.OK) {
+ return resultsList
+ }
+ //results.add(resultRef.get())
+ }
+ /*var emptyResults = true
+ for (re in results) {
+ if (re != Fetcher.Result.EMPTY_RESULT_SET) {
+ emptyResults = false
+ break
+ }
+ }
+ if (emptyResults) {
+ showResultAsync(Fetcher.Result.EMPTY_RESULT_SET)
+ }
+
+ */
+ return listOf<Stop>()
+ }
+
+
+ private fun showError(result: Fetcher.Result) {
+ val helper = helperRef.get() ?: return
+ helper.showErrorMessage(result, SearchRequestType.STOPS)
+ }
+
+ fun runRequest(query: String, fetchers: Array<StopsFinderByName>?) {
+ //start spinner
+
+ helperRef.get()?.toggleSpinner(true)
+ lastJob = CoroutineScope(Dispatchers.IO).launch{
+ try {
+ val r = RecursionHelper<StopsFinderByName>(fetchers ?: finders)
+ val stopList = getData(query, r)
+ if(stopList == null) {
+ withContext(Dispatchers.Main) {
+ showError(resultRef.get())
+ }
+ }
+ else if(stopList.isEmpty()) {
+ withContext(Dispatchers.Main) {
+ showError(Fetcher.Result.EMPTY_RESULT_SET)
+ }
+ } else{
+ //list of stops, non-null and not empty
+ withContext(Dispatchers.Main) {
+ showResult(stopList, query)
+ }
+ }
+
+ }catch (e: CancellationException) {
+ Log.d(DEBUG_TAG, "Request cancelled")
+ /*withContext(Dispatchers.Main) {
+ helperRef.get()?.toggleSpinner(false)
+ }
+
+ */
+ }
+ withContext(Dispatchers.Main) {
+ helperRef.get()?.toggleSpinner(false)
+ }
+
+ }
+ }
+ fun runRequest(query: String) {
+ runRequest(query, null)
+ }
+
+ fun cancelLastRequest() {
+ lastJob?.let{
+ if(!it.isCompleted)
+ it.cancel()
+ }
+ }
+ fun showResult(stops:List<Stop>, query: String) {
+ val helper = helperRef.get() ?: return
+ helper.createStopListFragment(stops,query, true)
+ }
+
+
+ companion object {
+ const val DEBUG_TAG = "BusTO-StopSearcher"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -346,7 +346,7 @@
<string name="location_permission_not_granted">Location permission has not been granted</string>
<string name="no_permission_dialog_title">Missing permission</string>
<!-- If more permissions are needed, adapt this string to make if "fillable" -->
- <string name="no_permission_dialog_text_location">To use this functionality, the application needs access to the location, which can not only be granted in the system settings.</string>
+ <string name="no_permission_dialog_text_location">To use this functionality, the application needs access to the location, which now can only be granted in the system settings.</string>
<string name="no_permission_dialog_open">Open settings</string>
<string name="close_tutorial">OK, close the tutorial</string>

File Metadata

Mime Type
text/plain
Expires
Thu, Aug 6, 03:07 (3 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2037905
Default Alt Text
D240.1785978467.diff (62 KB)

Event Timeline