Skip to content

feat: add basic support for location_groups #85

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/main/java/com/mecatran/gtfsvtor/dao/AppendableDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import com.mecatran.gtfsvtor.model.GtfsFeedInfo;
import com.mecatran.gtfsvtor.model.GtfsFrequency;
import com.mecatran.gtfsvtor.model.GtfsLevel;
import com.mecatran.gtfsvtor.model.GtfsLocationGroup;
import com.mecatran.gtfsvtor.model.GtfsLocationGroupStop;
import com.mecatran.gtfsvtor.model.GtfsPathway;
import com.mecatran.gtfsvtor.model.GtfsRoute;
import com.mecatran.gtfsvtor.model.GtfsShapePoint;
Expand Down Expand Up @@ -90,5 +92,10 @@ public void addAttribution(GtfsAttribution attribution,

public void addStopArea(GtfsStopArea stopArea, SourceContext sourceContext);

public void addLocationGroup(GtfsLocationGroup locationGroup,
SourceContext sourceContext);

public void addLocationGroupStop(GtfsLocationGroupStop locationGroupStop, SourceContext sourceContext);

public void close();
}
8 changes: 8 additions & 0 deletions src/main/java/com/mecatran/gtfsvtor/dao/ReadOnlyDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import com.mecatran.gtfsvtor.model.GtfsLegGroup;
import com.mecatran.gtfsvtor.model.GtfsLevel;
import com.mecatran.gtfsvtor.model.GtfsNetwork;
import com.mecatran.gtfsvtor.model.GtfsLocationGroup;
import com.mecatran.gtfsvtor.model.GtfsLocationGroupStop;
import com.mecatran.gtfsvtor.model.GtfsObject;
import com.mecatran.gtfsvtor.model.GtfsPathway;
import com.mecatran.gtfsvtor.model.GtfsRoute;
Expand Down Expand Up @@ -56,6 +58,12 @@ public interface ReadOnlyDao {

public GtfsStop getStop(GtfsStop.Id stopId);

public Stream<GtfsLocationGroup> getLocationGroups();

public GtfsLocationGroup getLocationGroup(GtfsLocationGroup.Id locationGroupId);

public Stream<GtfsLocationGroupStop> getLocationGroupStops(GtfsLocationGroup.Id locationGroupId) ;

public boolean hasZoneId(GtfsZone.Id zoneId);

public Stream<GtfsCalendar> getCalendars();
Expand Down
50 changes: 48 additions & 2 deletions src/main/java/com/mecatran/gtfsvtor/dao/inmemory/InMemoryDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
import com.mecatran.gtfsvtor.model.GtfsLegGroup;
import com.mecatran.gtfsvtor.model.GtfsLevel;
import com.mecatran.gtfsvtor.model.GtfsNetwork;
import com.mecatran.gtfsvtor.model.GtfsLocationGroup;
import com.mecatran.gtfsvtor.model.GtfsLocationGroupStop;
import com.mecatran.gtfsvtor.model.GtfsObject;
import com.mecatran.gtfsvtor.model.GtfsObjectWithSourceRef;
import com.mecatran.gtfsvtor.model.GtfsPathway;
Expand Down Expand Up @@ -75,16 +77,20 @@ public class InMemoryDao implements IndexedReadOnlyDao, AppendableDao {
private Map<GtfsRoute.Id, GtfsRoute> routes = new HashMap<>();
private Set<GtfsNetwork.Id> networkIds = new HashSet<>();
private Map<GtfsStop.Id, GtfsStop> stops = new HashMap<>();
private Map<GtfsLocationGroup.Id, GtfsLocationGroup> locationGroups = new HashMap<>();
private Set<GtfsZone.Id> zoneIds = new HashSet<>();
private Map<GtfsCalendar.Id, GtfsCalendar> calendars = new HashMap<>();
private Map<GtfsTrip.Id, GtfsTrip> trips = new HashMap<>();
private GtfsIdIndexer.GtfsStopIdIndexer stopIdIndexer = new GtfsIdIndexer.GtfsStopIdIndexer();
private GtfsIdIndexer.GtfsLocationGroupIdIndexer locationGroupIdIndexer = new GtfsIdIndexer.GtfsLocationGroupIdIndexer();
private StopTimesDao stopTimesDao;
private ShapePointsDao shapePointsDao;
private ListMultimap<GtfsTrip.Id, GtfsFrequency> frequencies = ArrayListMultimap
.create();
private Multimap<GtfsCalendar.Id, GtfsCalendarDate> calendarDates = ArrayListMultimap
.create();
private Multimap<GtfsLocationGroup.Id, GtfsLocationGroupStop> locationGroupStops = ArrayListMultimap
.create();
private Map<GtfsTransfer.Id, GtfsTransfer> transfers = new HashMap<>();
private Map<GtfsPathway.Id, GtfsPathway> pathways = new HashMap<>();
private Map<GtfsFareAttribute.Id, GtfsFareAttribute> fareAttributes = new HashMap<>();
Expand Down Expand Up @@ -132,14 +138,14 @@ public InMemoryDao(StopTimesDaoMode stopTimesDaoMode,
switch (stopTimesDaoMode) {
case AUTO:
stopTimesDao = new AutoSwitchStopTimesDao(
maxShapePointsInterleaving, stopIdIndexer);
maxShapePointsInterleaving, stopIdIndexer, locationGroupIdIndexer);
break;
case PACKED:
stopTimesDao = new PackingStopTimesDao(maxShapePointsInterleaving,
stopIdIndexer);
break;
case UNSORTED:
stopTimesDao = new PackingUnsortedStopTimesDao(stopIdIndexer);
stopTimesDao = new PackingUnsortedStopTimesDao(stopIdIndexer, locationGroupIdIndexer);
break;
}
switch (shapePointsDaoMode) {
Expand Down Expand Up @@ -204,6 +210,20 @@ public GtfsStop getStop(GtfsStop.Id stopId) {
return stops.get(stopId);
}

@Override
public Stream<GtfsLocationGroup> getLocationGroups() {
return locationGroups.values().stream();
}

public GtfsLocationGroup getLocationGroup(GtfsLocationGroup.Id locationGroupId) {
return locationGroups.get(locationGroupId);
}

@Override
public Stream<GtfsLocationGroupStop> getLocationGroupStops(GtfsLocationGroup.Id locationGroupId) {
return locationGroupStops.get(locationGroupId).stream();
}

@Override
public boolean hasZoneId(GtfsZone.Id zoneId) {
return zoneIds.contains(zoneId);
Expand Down Expand Up @@ -627,6 +647,32 @@ public void addStop(GtfsStop stop, SourceContext sourceContext) {
}
}

public void addLocationGroup(GtfsLocationGroup locationGroup, SourceContext sourceContext) {
if (locationGroup.getId() == null) {
sourceContext.getReportSink()
.report(new MissingObjectIdError(
sourceContext.getSourceRef(), "location_group_id"),
sourceContext.getSourceInfo());
return;
}
GtfsLocationGroup existingLocationGroup = getLocationGroup(locationGroup.getId());
if (existingLocationGroup != null) {
sourceContext.getReportSink()
.report(new DuplicatedObjectIdError(
existingLocationGroup.getSourceRef(),
sourceContext.getSourceRef(), locationGroup.getId(),
"location_group_id"), null, sourceContext.getSourceInfo());
return;
}
locationGroups.put(locationGroup.getId(), locationGroup);
}

@Override
public void addLocationGroupStop(GtfsLocationGroupStop locationGroupStop, SourceContext sourceContext) {
// TODO check for existance and not null
locationGroupStops.put(locationGroupStop.getLocationGroupId(), locationGroupStop);
}

@Override
public void addCalendar(GtfsCalendar calendar,
SourceContext sourceContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.mecatran.gtfsvtor.model.GtfsId;
import com.mecatran.gtfsvtor.model.GtfsLocationGroup;
import com.mecatran.gtfsvtor.model.GtfsObject;
import com.mecatran.gtfsvtor.model.GtfsStop;

Expand All @@ -21,6 +22,10 @@ public static class GtfsStopIdIndexer
extends GtfsIdIndexer<String, GtfsStop, GtfsStop.Id> {
};

public static class GtfsLocationGroupIdIndexer
extends GtfsIdIndexer<String, GtfsLocationGroup, GtfsLocationGroup.Id> {
};

/**
* Insert the value if not present, return the associated index
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@
public class AutoSwitchStopTimesDao implements StopTimesDao {

private GtfsIdIndexer.GtfsStopIdIndexer stopIdIndexer;
private GtfsIdIndexer.GtfsLocationGroupIdIndexer locationGroupIdIndexer;
private PackingStopTimesDao pstDao;
private PackingUnsortedStopTimesDao pustDao;
private StopTimesDao currentDao;
private boolean verbose = false;

public AutoSwitchStopTimesDao(int maxInterleaving,
GtfsIdIndexer.GtfsStopIdIndexer stopIdIndexer) {
GtfsIdIndexer.GtfsStopIdIndexer stopIdIndexer,
GtfsIdIndexer.GtfsLocationGroupIdIndexer locationGroupIdIndexer) {
this.stopIdIndexer = stopIdIndexer;
this.locationGroupIdIndexer = locationGroupIdIndexer;
pstDao = new PackingStopTimesDao(maxInterleaving, stopIdIndexer)
.withInterleavingOverflowCallback(this::handleOverflow);
pustDao = null;
Expand Down Expand Up @@ -70,7 +73,7 @@ private boolean handleOverflow(int n) {
"Interleaving stop times overflow detected. Switching to relevant DAO implementation to better handle this.\nThis will increase memory consumption, though.");
pstDao.withVerbose(false);
pstDao.close();
pustDao = new PackingUnsortedStopTimesDao(stopIdIndexer)
pustDao = new PackingUnsortedStopTimesDao(stopIdIndexer, locationGroupIdIndexer)
.withVerbose(verbose);
// Copy over
pstDao.getStopTimes().forEach(pustDao::addStopTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.List;

import com.mecatran.gtfsvtor.model.GtfsDropoffType;
import com.mecatran.gtfsvtor.model.GtfsLocationGroup;
import com.mecatran.gtfsvtor.model.GtfsLogicalTime;
import com.mecatran.gtfsvtor.model.GtfsPickupType;
import com.mecatran.gtfsvtor.model.GtfsStop;
Expand All @@ -30,8 +31,12 @@ public interface Context {

public int indexStopId(GtfsStop.Id stopId);

public int indexLocationGroupId(GtfsLocationGroup.Id locationGroupId);

public GtfsStop.Id getStopIdIndex(int stopIdIndex);

public GtfsLocationGroup.Id getLocationGroupIdIndex(int locationGroupIdIndex);

public PackedUnsortedTimePattern intern(
PackedUnsortedTimePattern tData);

Expand Down Expand Up @@ -65,10 +70,14 @@ public PackedUnsortedStopPattern intern(
private static final int NULL_TIMEPOINT = 0x3;

// sdata
// 32 bits -> stop ID index (could be lower)
private static final long STOPIDX_MASK = 0x00000000FFFFFFFFL;
private static final int STOPIDX_SHIFT = 0;
private static final int NULL_STOPIDX = 0xFFFFFFFF;
// 1 bit -> is Flex
private static final long ISFLEX_MASK = 0x0000000000000001L;
private static final int ISFLEX_SHIFT = 0;
private static final int ISFLEX_FLAG = 1;
// 31 bits -> stop ID index (could be lower)
private static final long STOPIDX_MASK = 0x00000000FFFFFFFEL;
private static final int STOPIDX_SHIFT = 1;
private static final int NULL_STOPIDX = 0xFFFFFFFE;
// 32 bits -> stop seq
private static final long STOPSEQ_MASK = 0xFFFFFFFF00000000L;
private static final int STOPSEQ_SHIFT = 32;
Expand All @@ -85,14 +94,26 @@ public PackedUnsortedStopTimes() {

public void addStopTime(Context context, GtfsStopTime stopTime) {
long tdata = 0L;
GtfsLogicalTime arrTime = stopTime.getArrivalTime();
tdata = setData(tdata, ARRTIME_MASK, ARRTIME_SHIFT, arrTime == null
? NULL_TIME
: arrTime.getSecondSinceMidnight() + TIME_SHIFT - baseTime);
GtfsLogicalTime depTime = stopTime.getDepartureTime();
tdata = setData(tdata, DEPTIME_MASK, DEPTIME_SHIFT, depTime == null
? NULL_TIME
: depTime.getSecondSinceMidnight() + TIME_SHIFT - baseTime);
boolean isFlex = stopTime.getLocationGroupId() != null;
if (isFlex) {
GtfsLogicalTime startWindow = stopTime.getStartPickupDropOffWindow();
tdata = setData(tdata, ARRTIME_MASK, ARRTIME_SHIFT, startWindow == null
? NULL_TIME
: startWindow.getSecondSinceMidnight() + TIME_SHIFT - baseTime);
GtfsLogicalTime endWindow = stopTime.getEndPickupDropOffWindow();
tdata = setData(tdata, DEPTIME_MASK, DEPTIME_SHIFT, endWindow == null
? NULL_TIME
: endWindow.getSecondSinceMidnight() + TIME_SHIFT - baseTime);
} else {
GtfsLogicalTime arrTime = stopTime.getArrivalTime();
tdata = setData(tdata, ARRTIME_MASK, ARRTIME_SHIFT, arrTime == null
? NULL_TIME
: arrTime.getSecondSinceMidnight() + TIME_SHIFT - baseTime);
GtfsLogicalTime depTime = stopTime.getDepartureTime();
tdata = setData(tdata, DEPTIME_MASK, DEPTIME_SHIFT, depTime == null
? NULL_TIME
: depTime.getSecondSinceMidnight() + TIME_SHIFT - baseTime);
}
GtfsDropoffType dropoff = stopTime.getDropoffType().orElse(null);
tdata = setData(tdata, DROPOFF_MASK, DROPOFF_SHIFT,
dropoff == null ? NULL_DROPOFF : dropoff.getValue());
Expand All @@ -105,9 +126,16 @@ public void addStopTime(Context context, GtfsStopTime stopTime) {
timeData.addTData(tdata);

long sdata = 0L;
int stopIndex = stopTime.getStopId() == null ? NULL_STOPIDX
: context.indexStopId(stopTime.getStopId());
sdata = setData(sdata, STOPIDX_MASK, STOPIDX_SHIFT, stopIndex);
if (isFlex) {
sdata = setData(sdata, ISFLEX_MASK, ISFLEX_SHIFT, ISFLEX_FLAG);
int locationGroupIndex = stopTime.getLocationGroupId() == null ? NULL_STOPIDX
: context.indexLocationGroupId(stopTime.getLocationGroupId());
sdata = setData(sdata, STOPIDX_MASK, STOPIDX_SHIFT, locationGroupIndex);
} else {
int stopIndex = stopTime.getStopId() == null ? NULL_STOPIDX
: context.indexStopId(stopTime.getStopId());
sdata = setData(sdata, STOPIDX_MASK, STOPIDX_SHIFT, stopIndex);
}
sdata = setData(sdata, STOPSEQ_MASK, STOPSEQ_SHIFT,
stopTime.getStopSequence().getSequence());
Double shapeDistTraveled = stopTime.getShapeDistTraveled();
Expand Down Expand Up @@ -157,15 +185,47 @@ public List<GtfsStopTime> getStopTimes(GtfsTrip.Id tripId,
GtfsStopTime.Builder builder = new SimpleGtfsStopTime.Builder();
builder.withTripId(tripId);

long sdata = stopData.getSData(i);
boolean isFlex = getData(sdata, ISFLEX_MASK, ISFLEX_SHIFT) == ISFLEX_FLAG;

if (isFlex) {
int locationGroupIndex = getData(sdata, STOPIDX_MASK, STOPIDX_SHIFT);
if (locationGroupIndex != NULL_STOPIDX) {
builder.withLocationGroupId(context.getLocationGroupIdIndex(locationGroupIndex));
}
} else {
int stopIndex = getData(sdata, STOPIDX_MASK, STOPIDX_SHIFT);
if (stopIndex != NULL_STOPIDX) {
builder.withStopId(context.getStopIdIndex(stopIndex));
}
}

int stopseq = getData(sdata, STOPSEQ_MASK, STOPSEQ_SHIFT);
builder.withStopSequence(
GtfsTripStopSequence.fromSequence(stopseq));
builder.withShapeDistTraveled(stopData.getShapeDist(i));
builder.withStopHeadsign(stopData.getHeadsign(i));

long tdata = timeData.getTData(i);
int arr = getData(tdata, ARRTIME_MASK, ARRTIME_SHIFT);
if (arr != NULL_TIME)
builder.withArrivalTime(
GtfsLogicalTime.getTime(arr - TIME_SHIFT + baseTime));
int dep = getData(tdata, DEPTIME_MASK, DEPTIME_SHIFT);
if (dep != NULL_TIME)
builder.withDepartureTime(
GtfsLogicalTime.getTime(dep - TIME_SHIFT + baseTime));
if (isFlex) {
int startWindow = getData(tdata, ARRTIME_MASK, ARRTIME_SHIFT);
if (startWindow != NULL_TIME)
builder.withStartPickupDropOffWindow(
GtfsLogicalTime.getTime(startWindow - TIME_SHIFT + baseTime));
int endWindow = getData(tdata, DEPTIME_MASK, DEPTIME_SHIFT);
if (endWindow != NULL_TIME)
builder.withEndPickupDropOffWindow(
GtfsLogicalTime.getTime(endWindow - TIME_SHIFT + baseTime));
} else {
int arr = getData(tdata, ARRTIME_MASK, ARRTIME_SHIFT);
if (arr != NULL_TIME)
builder.withArrivalTime(
GtfsLogicalTime.getTime(arr - TIME_SHIFT + baseTime));
int dep = getData(tdata, DEPTIME_MASK, DEPTIME_SHIFT);
if (dep != NULL_TIME)
builder.withDepartureTime(
GtfsLogicalTime.getTime(dep - TIME_SHIFT + baseTime));
}
int dropoff = getData(tdata, DROPOFF_MASK, DROPOFF_SHIFT);
if (dropoff != NULL_DROPOFF)
builder.withDropoffType(GtfsDropoffType.fromValue(dropoff));
Expand All @@ -176,16 +236,6 @@ public List<GtfsStopTime> getStopTimes(GtfsTrip.Id tripId,
if (timepoint != NULL_TIMEPOINT)
builder.withTimepoint(GtfsTimepoint.fromValue(timepoint));

long sdata = stopData.getSData(i);
int stopIndex = getData(sdata, STOPIDX_MASK, STOPIDX_SHIFT);
if (stopIndex != NULL_STOPIDX) {
builder.withStopId(context.getStopIdIndex(stopIndex));
}
int stopseq = getData(sdata, STOPSEQ_MASK, STOPSEQ_SHIFT);
builder.withStopSequence(
GtfsTripStopSequence.fromSequence(stopseq));
builder.withShapeDistTraveled(stopData.getShapeDist(i));
builder.withStopHeadsign(stopData.getHeadsign(i));

ret.add(builder.build());
}
Expand Down
Loading