From 92d2fcd8c55d02a631d43be3da4cfe184dba9f93 Mon Sep 17 00:00:00 2001 From: Brian Ferris Date: Tue, 16 Jan 2024 10:43:37 -0800 Subject: [PATCH] Column-based data representation. --- .../gtfsvalidator/cli/Arguments.java | 6 + core/build.gradle | 2 + .../columns/ColumnStoreBase.java | 96 ++++++ .../columns/GtfsColumnAssignments.java | 7 + .../GtfsColumnBasedCollectionFactory.java | 253 +++++++++++++++ .../columns/GtfsColumnBasedEntity.java | 24 ++ .../columns/GtfsColumnBasedEntityBuilder.java | 27 ++ .../gtfsvalidator/columns/GtfsColumns.java | 33 ++ .../gtfsvalidator/parsing/RowParser.java | 49 +++ .../gtfsvalidator/table/AnyTableLoader.java | 80 ++++- .../table/GtfsColumnDescriptor.java | 25 ++ .../table/GtfsEnumDescriptor.java | 15 + .../gtfsvalidator/table/GtfsFeedLoader.java | 3 + .../gtfsvalidator/table/GtfsSetter.java | 10 + .../table/GtfsTableDescriptor.java | 8 +- .../columns/ColumnStoreBaseTest.java | 154 +++++++++ .../GtfsColumnBasedCollectionFactoryTest.java | 96 ++++++ .../gtfsvalidator/parsing/RowParserTest.java | 60 +--- .../table/AnyTableLoaderTest.java | 46 +-- .../table/GtfsFeedContainerTest.java | 5 +- .../table/GtfsFeedLoaderTest.java | 16 +- .../testgtfs/GtfsTestEntity.java | 155 ---------- .../testgtfs/GtfsTestMultiFileValidator.java | 7 +- .../testgtfs/GtfsTestSingleFileValidator.java | 8 +- .../testgtfs/GtfsTestTableContainer.java | 78 ----- .../testgtfs/GtfsTestTableContainer2.java | 79 ----- .../testgtfs/GtfsTestTableDescriptor.java | 114 ------- .../testgtfs/GtfsTestTableDescriptor2.java | 115 ------- .../DefaultValidatorProviderTest.java | 15 +- .../validator/ValidatorLoaderTest.java | 12 +- core/testing/build.gradle | 13 + .../testgtfs/GtfsTestEntity2Schema.java | 19 ++ .../testgtfs/GtfsTestEntitySchema.java | 18 ++ extensions/build.gradle | 22 ++ .../GoogleTicketingAgencySchema.java | 13 + .../GoogleTicketingDeepLinksSchema.java | 18 ++ .../ticketing/GoogleTicketingRouteSchema.java | 13 + .../GoogleTicketingStopTimeSchema.java | 8 + .../GoogleTicketingStopTimeValidator.java | 43 +++ .../ticketing/GoogleTicketingTripSchema.java | 10 + .../ticketing/GoogleTicketingTypeEnum.java | 7 + .../runner/ValidationRunner.java | 5 + .../runner/ValidationRunnerConfig.java | 7 +- .../report/model/FeedMetadataTest.java | 2 +- .../gtfsvalidator/util/CalendarUtilTest.java | 9 +- .../gtfsvalidator/util/StopUtilTest.java | 4 +- .../util/TripCalendarUtilTest.java | 8 +- .../util/shape/ShapePointsTest.java | 2 +- .../util/shape/StopPointsTest.java | 8 +- .../util/shape/StopToShapeMatcherTest.java | 6 +- .../AgencyConsistencyValidatorTest.java | 2 +- .../AttributionWithoutRoleValidatorTest.java | 15 +- .../validator/BikeAllowanceValidatorTest.java | 8 +- ...WithOverlappingStopTimesValidatorTest.java | 4 +- .../validator/DateTripsValidatorTest.java | 2 +- .../DuplicateFareMediaValidatorTest.java | 12 +- .../DuplicateRouteNameValidatorTest.java | 2 +- .../ExpiredCalendarValidatorTest.java | 36 +-- .../FareAttributeAgencyIdValidatorTest.java | 26 +- .../validator/FareMediaNameValidatorTest.java | 8 +- ...ferRuleDurationLimitTypeValidatorTest.java | 9 +- ...ransferRuleTransferCountValidatorTest.java | 14 +- .../validator/FeedContactValidatorTest.java | 2 +- .../FeedExpirationDateValidatorTest.java | 2 +- .../FeedServiceDateValidatorTest.java | 2 +- .../GtfsFrequencyEndRangeValidatorTest.java | 10 +- .../GtfsShapeLatLonValidatorTest.java | 8 +- ...sTripServiceIdForeignKeyValidatorTest.java | 4 +- .../LocationHasStopTimesValidatorTest.java | 4 +- ...LocationTypeSingleEntityValidatorTest.java | 13 +- ...atchingFeedAndAgencyLangValidatorTest.java | 4 +- ...gCalendarAndCalendarDateValidatorTest.java | 2 +- .../MissingLevelIdValidatorTest.java | 4 +- .../MissingTripEdgeValidatorTest.java | 4 +- .../NetworkIdConsistencyValidatorTest.java | 6 +- .../OverlappingFrequencyValidatorTest.java | 2 +- .../validator/ParentStationValidatorTest.java | 14 +- ...thwayDanglingGenericNodeValidatorTest.java | 6 +- .../PathwayEndpointTypeValidatorTest.java | 6 +- .../validator/PathwayLoopValidatorTest.java | 7 +- ...PathwayReachableLocationValidatorTest.java | 6 +- .../validator/RouteAgencyIdValidatorTest.java | 26 +- .../RouteColorContrastValidatorTest.java | 2 +- .../validator/RouteNameValidatorTest.java | 2 +- .../ShapeIncreasingDistanceValidatorTest.java | 2 +- .../ShapeToStopMatchingValidatorTest.java | 10 +- .../validator/ShapeUsageValidatorTest.java | 4 +- .../validator/StopNameValidatorTest.java | 18 +- .../StopRequiredLocationValidatorTest.java | 28 +- ...eArrivalAndDepartureTimeValidatorTest.java | 2 +- ...opTimeIncreasingDistanceValidatorTest.java | 2 +- .../StopTimeTravelSpeedValidatorTest.java | 8 +- .../validator/StopZoneIdValidatorTest.java | 44 +-- .../TimeframeOverlapValidatorTest.java | 22 +- ...frameServiceIdForeignKeyValidatorTest.java | 8 +- ...TimeframeStartAndEndTimeValidatorTest.java | 10 +- .../validator/TimepointTimeValidatorTest.java | 16 +- .../validator/TransferDirectionTest.java | 20 +- ...nsfersInSeatTransferTypeValidatorTest.java | 106 ++----- .../TransfersStopTypeValidatorTest.java | 20 +- .../TransfersTripReferenceValidatorTest.java | 34 +- ...slationFieldAndReferenceValidatorTest.java | 32 +- .../TripAndShapeDistanceValidatorTest.java | 8 +- .../validator/TripUsabilityValidatorTest.java | 4 +- .../validator/TripUsageValidatorTest.java | 4 +- .../UrlConsistencyValidatorTest.java | 6 +- .../annotation/ColumnStoreTypes.java | 12 + .../gtfsvalidator/annotation/GtfsTable.java | 3 + .../table/GtfsEntityBuilder.java | 3 + processor/README.md | 4 + processor/columns/build.gradle | 33 ++ .../columns/ColumnStoreGenerator.java | 256 +++++++++++++++ .../processor/columns/ColumnsProcessor.java | 70 +++++ .../gtfsvalidator/processor/Analyser.java | 46 ++- .../ColumnBasedEntityBuilderGenerator.java | 175 +++++++++++ ...BasedEntityColumnAssignmentsGenerator.java | 65 ++++ ...umnBasedEntityImplementationGenerator.java | 292 ++++++++++++++++++ .../CurrencyAmountValidatorGenerator.java | 5 +- .../processor/EndRangeValidatorGenerator.java | 8 +- .../processor/EntityGenerator.java | 250 +++++++++++++++ .../EntityImplementationGenerator.java | 64 +--- .../processor/EnumGenerator.java | 3 +- .../ForeignKeyValidatorGenerator.java | 3 +- .../processor/GtfsAnnotationProcessor.java | 21 +- .../processor/GtfsEntityClasses.java | 42 ++- .../processor/GtfsEnumDescriptor.java | 9 + .../processor/GtfsFieldDescriptor.java | 21 +- .../processor/GtfsFileDescriptor.java | 4 + .../processor/LatLonValidatorGenerator.java | 8 +- .../MixedCaseValidatorGenerator.java | 5 +- .../processor/TableContainerGenerator.java | 45 ++- .../TableContainerIndexGenerator.java | 98 ++++-- .../processor/TableDescriptorGenerator.java | 158 ++++------ .../processor/EnumGeneratorTest.java | 7 +- .../processor/tests/EnumSizesSchema.java | 3 - .../processor/tests/ManyTypesSchema.java | 33 ++ .../tests/CurrencyAmountSchemaTest.java | 1 - .../processor/tests/EnumSizesSchemaTest.java | 28 +- .../IdAndSequencePrimaryKeySchemaTest.java | 3 - .../processor/tests/ManyFieldsSchemaTest.java | 3 +- .../tests/ManyTypesColumnBasedTest.java | 130 ++++++++ .../processor/tests/MixedCaseSchemaTest.java | 2 - ...MultiColumnLocalePrimaryKeySchemaTest.java | 2 - .../MultiColumnPrimaryKeySchemaTest.java | 3 - ...ortedTranslationsPrimaryKeySchemaTest.java | 2 - ...RecommendedColumnAnnotationSchemaTest.java | 1 - .../tests/RequiredAnnotationSchemaTest.java | 1 - .../RequiredColumnAnnotationSchemaTest.java | 1 - .../SingleColumnPrimaryKeySchemaTest.java | 2 - settings.gradle | 5 + 150 files changed, 3112 insertions(+), 1333 deletions(-) create mode 100644 core/src/main/java/org/mobilitydata/gtfsvalidator/columns/ColumnStoreBase.java create mode 100644 core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnAssignments.java create mode 100644 core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedCollectionFactory.java create mode 100644 core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedEntity.java create mode 100644 core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedEntityBuilder.java create mode 100644 core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumns.java create mode 100644 core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsEnumDescriptor.java create mode 100644 core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsSetter.java create mode 100644 core/src/test/java/org/mobilitydata/gtfsvalidator/columns/ColumnStoreBaseTest.java create mode 100644 core/src/test/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedCollectionFactoryTest.java delete mode 100644 core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestEntity.java delete mode 100644 core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableContainer.java delete mode 100644 core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableContainer2.java delete mode 100644 core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableDescriptor.java delete mode 100644 core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableDescriptor2.java create mode 100644 core/testing/build.gradle create mode 100644 core/testing/src/main/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestEntity2Schema.java create mode 100644 core/testing/src/main/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestEntitySchema.java create mode 100644 extensions/build.gradle create mode 100644 extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingAgencySchema.java create mode 100644 extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingDeepLinksSchema.java create mode 100644 extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingRouteSchema.java create mode 100644 extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingStopTimeSchema.java create mode 100644 extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingStopTimeValidator.java create mode 100644 extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingTripSchema.java create mode 100644 extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingTypeEnum.java create mode 100644 model/src/main/java/org/mobilitydata/gtfsvalidator/annotation/ColumnStoreTypes.java create mode 100644 processor/README.md create mode 100644 processor/columns/build.gradle create mode 100644 processor/columns/src/main/java/org/mobilitydata/gtfsvalidator/processor/columns/ColumnStoreGenerator.java create mode 100644 processor/columns/src/main/java/org/mobilitydata/gtfsvalidator/processor/columns/ColumnsProcessor.java create mode 100644 processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ColumnBasedEntityBuilderGenerator.java create mode 100644 processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ColumnBasedEntityColumnAssignmentsGenerator.java create mode 100644 processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ColumnBasedEntityImplementationGenerator.java create mode 100644 processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EntityGenerator.java create mode 100644 processor/tests/src/main/java/org/mobilitydata/gtfsvalidator/processor/tests/ManyTypesSchema.java create mode 100644 processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/ManyTypesColumnBasedTest.java diff --git a/cli/src/main/java/org/mobilitydata/gtfsvalidator/cli/Arguments.java b/cli/src/main/java/org/mobilitydata/gtfsvalidator/cli/Arguments.java index 77a135a0cd..846ab689f8 100644 --- a/cli/src/main/java/org/mobilitydata/gtfsvalidator/cli/Arguments.java +++ b/cli/src/main/java/org/mobilitydata/gtfsvalidator/cli/Arguments.java @@ -110,6 +110,11 @@ public class Arguments { description = "Skips check for new validator version") private boolean skipValidatorUpdate = false; + @Parameter( + names = {"-cbs", "--column_based_storage"}, + description = "Use column-based storage") + private boolean useColumnBasedStorage = false; + ValidationRunnerConfig toConfig() throws URISyntaxException { ValidationRunnerConfig.Builder builder = ValidationRunnerConfig.builder(); if (input != null) { @@ -141,6 +146,7 @@ ValidationRunnerConfig toConfig() throws URISyntaxException { builder.setNumThreads(numThreads); builder.setPrettyJson(pretty); builder.setSkipValidatorUpdate(skipValidatorUpdate); + builder.setUseColumnBasedStorage(useColumnBasedStorage); return builder.build(); } diff --git a/core/build.gradle b/core/build.gradle index cccd38adc9..b8026d5284 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -27,6 +27,7 @@ plugins { dependencies { implementation project(':model') annotationProcessor project(':processor:notices') + annotationProcessor project(':processor:columns') annotationProcessor 'com.google.auto.value:auto-value:1.7.4' compileOnly 'com.google.auto.value:auto-value-annotations:1.7.4' implementation 'org.apache.commons:commons-compress:1.20' @@ -42,6 +43,7 @@ dependencies { implementation 'com.googlecode.libphonenumber:libphonenumber:8.12.13' implementation 'com.google.flogger:flogger:0.6' implementation 'io.github.classgraph:classgraph:4.8.146' + testImplementation project(':core:testing') testImplementation 'com.google.flogger:flogger-system-backend:0.6' testImplementation group: 'junit', name: 'junit', version: '4.13' testImplementation "com.google.truth:truth:1.0.1" diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/ColumnStoreBase.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/ColumnStoreBase.java new file mode 100644 index 0000000000..2511f6b0df --- /dev/null +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/ColumnStoreBase.java @@ -0,0 +1,96 @@ +package org.mobilitydata.gtfsvalidator.columns; + +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.List; + +/** + * Base classes for column store implementation classes, as produced from {@link + * org.mobilitydata.gtfsvalidator.annotation.ColumnStoreTypes} annotations. + */ +public class ColumnStoreBase { + static int reserveColumn(List valuesByColumnIndex, Class type, int initialCapacity) { + T[] values = (T[]) Array.newInstance(type, initialCapacity); + valuesByColumnIndex.add(values); + return valuesByColumnIndex.size() - 1; + } + + static void reservePrimitivePresence( + List primitivePresenceByColumnIndex, int columnIndex, int initialCapacity) { + int highOrderIndex = columnIndex / 8; + if (highOrderIndex >= primitivePresenceByColumnIndex.size()) { + primitivePresenceByColumnIndex.add(new byte[initialCapacity]); + } + } + + static boolean hasPrimitive( + List primitivePresenceByColumnIndex, int columnIndex, int row) { + if (columnIndex == -1) { + return false; + } + int highOrderIndex = columnIndex / 8; + int lowOrderIndex = columnIndex % 8; + byte[] values = primitivePresenceByColumnIndex.get(highOrderIndex); + return (values[row] & (1 << lowOrderIndex)) != 0; + } + + static boolean hasValue(List valuesByColumnIndex, int columnIndex, int row) { + if (columnIndex == -1) { + return false; + } + T[] values = valuesByColumnIndex.get(columnIndex); + return row < values.length && values[row] != null; + } + + static T getValue(List valuesByColumnIndex, int columnIndex, int row, T defaultValue) { + if (columnIndex == -1) { + return defaultValue; + } + T[] values = valuesByColumnIndex.get(columnIndex); + if (row >= values.length) { + return defaultValue; + } + T value = values[row]; + return value != null ? value : defaultValue; + } + + static void setPrimitivePresence( + List primitivePresenceByColumnIndex, int columnIndex, int row) { + int highOrderIndex = columnIndex / 8; + int lowOrderIndex = columnIndex % 8; + byte[] presenceValues = primitivePresenceByColumnIndex.get(highOrderIndex); + if (presenceValues.length <= row) { + int newSize = calculateNewCapacity(presenceValues.length, row + 1); + presenceValues = Arrays.copyOf(presenceValues, newSize); + primitivePresenceByColumnIndex.set(highOrderIndex, presenceValues); + } + presenceValues[row] |= (1 << lowOrderIndex); + } + + static void setValue(List valuesByColumnIndex, int columnIndex, int row, T value) { + T[] values = valuesByColumnIndex.get(columnIndex); + if (values.length <= row) { + int newSize = calculateNewCapacity(values.length, row + 1); + values = Arrays.copyOf(values, newSize); + valuesByColumnIndex.set(columnIndex, values); + } + values[row] = value; + } + + static int calculateNewCapacity(int currentSize, int minSize) { + int newSize = currentSize; + while (newSize < minSize) { + newSize <<= 1; + } + return newSize; + } + + static void trimToSize(List valuesByColumnIndex, int size) { + for (int i = 0; i < valuesByColumnIndex.size(); ++i) { + T[] values = valuesByColumnIndex.get(i); + if (values.length > size) { + valuesByColumnIndex.set(i, Arrays.copyOf(values, size)); + } + } + } +} diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnAssignments.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnAssignments.java new file mode 100644 index 0000000000..b4e163124a --- /dev/null +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnAssignments.java @@ -0,0 +1,7 @@ +package org.mobilitydata.gtfsvalidator.columns; + +/** + * Marker interface for generate ColumnAssignment classes, which track the mapping from GTFS fields + * to column indices within a {@link GtfsColumnStore}. + */ +public interface GtfsColumnAssignments {} diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedCollectionFactory.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedCollectionFactory.java new file mode 100644 index 0000000000..e92cafcdd4 --- /dev/null +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedCollectionFactory.java @@ -0,0 +1,253 @@ +package org.mobilitydata.gtfsvalidator.columns; + +import com.google.common.base.Preconditions; +import java.util.AbstractList; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * A factory for producing various collection classes that are designed to hold {@link + * GtfsColumnBasedEntity} entries in a memory efficient way. + * + *

The main idea is that instead of holding an entity reference directly, we just store the + * entity's row index in the column store instead and only construct the entity facade when needed. + */ +public class GtfsColumnBasedCollectionFactory { + + /** + * Factory method for constructing an entity facade. + * + * @param + */ + public interface EntityFactory { + T create(GtfsColumnStore store, GtfsColumnAssignments assignments, int rowIndex); + } + + private final GtfsColumnStore store; + private final GtfsColumnAssignments assignments; + private final EntityFactory entityFactory; + + public GtfsColumnBasedCollectionFactory( + GtfsColumnStore store, GtfsColumnAssignments assignments, EntityFactory entityFactory) { + this.store = store; + this.assignments = assignments; + this.entityFactory = entityFactory; + } + + /** + * If the specified collection is associated with a collection factory, the collection factory + * instance will be returned. + */ + public static Optional getForList(List c) { + if (c instanceof HasFactory) { + return Optional.of(((HasFactory) c).getFactory()); + } + return Optional.empty(); + } + + /** + * Ensures that a given entity is associated with the column store and assignments of this + * collection factory. Trying to use an entity with a different store or column assignments would + * cause errors. + */ + private void checkOwnership(T entity) { + Preconditions.checkArgument(this.store == entity.store, "store mismatch"); + Preconditions.checkArgument( + this.assignments == entity.getAssignments(), "assignments mismatch"); + } + + /** + * Returns a List designed to contain all entities in the column store. Entities must be added + * sequentially in order. This is more memory efficient than {@link #createSomeEntitiesList()}. + */ + public List createAllEntitiesList() { + return new AllEntitiesListImpl(); + } + + private class AllEntitiesListImpl extends AbstractList implements HasFactory { + + private int size = 0; + + @Override + public boolean add(T t) { + checkOwnership(t); + Preconditions.checkArgument(t.rowIndex == size); + size++; + return true; + } + + @Override + public T get(int index) { + return entityFactory.create(store, assignments, index); + } + + @Override + public int size() { + return size; + } + + @Override + public GtfsColumnBasedCollectionFactory getFactory() { + return GtfsColumnBasedCollectionFactory.this; + } + } + + /** + * Returns a List designed to contain some subset of entities in the column store, in arbitrary + * order. This is less memory efficient than {@link #createAllEntitiesList()}. + */ + public List createSomeEntitiesList() { + return new SomeEntitiesListImpl(); + } + + private class SomeEntitiesListImpl extends AbstractList implements HasFactory { + + private int[] indices = new int[10]; + + private int size = 0; + + @Override + public boolean add(T t) { + checkOwnership(t); + + size++; + + if (indices.length < size) { + int newCapacity = indices.length; + while (newCapacity < size) { + newCapacity <<= 1; + } + this.indices = Arrays.copyOf(this.indices, newCapacity); + } + + this.indices[size - 1] = t.rowIndex; + + return true; + } + + @Override + public T get(int index) { + return entityFactory.create(store, assignments, indices[index]); + } + + @Override + public T set(int index, T element) { + checkOwnership(element); + int existingRowIndex = this.indices[index]; + this.indices[index] = element.rowIndex; + return entityFactory.create(store, assignments, existingRowIndex); + } + + @Override + public int size() { + return size; + } + + @Override + public GtfsColumnBasedCollectionFactory getFactory() { + return GtfsColumnBasedCollectionFactory.this; + } + } + + /** Returns a Map designed to store entities as values. */ + public Map createSomeEntitiesMap() { + return new MapImpl<>(); + } + + private class MapImpl extends AbstractMap { + private final Map indicesByKey = new HashMap<>(); + + private final EntrySetAdapter entrySetAdapter = new EntrySetAdapter(); + + @Override + public boolean containsKey(Object key) { + return indicesByKey.containsKey(key); + } + + @Override + public T get(Object key) { + Integer index = indicesByKey.get(key); + if (index == null) { + return null; + } + return entityFactory.create(store, assignments, index); + } + + @Override + public T put(K key, T value) { + checkOwnership(value); + Integer existingIndex = indicesByKey.put(key, value.rowIndex); + if (existingIndex == null) { + return null; + } + return entityFactory.create(store, assignments, existingIndex); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public T remove(Object key) { + throw new UnsupportedOperationException(); + } + + @Override + public Set> entrySet() { + return entrySetAdapter; + } + + private class EntrySetAdapter extends AbstractSet> { + + @Override + public Iterator> iterator() { + Iterator> iterator = indicesByKey.entrySet().iterator(); + return new Iterator<>() { + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Entry next() { + Entry entry = iterator.next(); + return new Map.Entry() { + + @Override + public K getKey() { + return entry.getKey(); + } + + @Override + public T getValue() { + return entityFactory.create(store, assignments, entry.getValue()); + } + + @Override + public T setValue(T value) { + throw new UnsupportedOperationException(); + } + }; + } + }; + } + + @Override + public int size() { + return indicesByKey.size(); + } + } + } + + private interface HasFactory { + GtfsColumnBasedCollectionFactory getFactory(); + } +} diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedEntity.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedEntity.java new file mode 100644 index 0000000000..4b88a511b2 --- /dev/null +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedEntity.java @@ -0,0 +1,24 @@ +package org.mobilitydata.gtfsvalidator.columns; + +import org.mobilitydata.gtfsvalidator.table.GtfsEntity; + +/** + * A GtfsEntity whose field values are not stored directly in the entity class, but instead stored + * in an underlying {@link GtfsColumnStore}. + */ +public abstract class GtfsColumnBasedEntity implements GtfsEntity { + protected final GtfsColumnStore store; + + /** + * The 0-based row index (not the same as a CSV row number) indicating the row of the entity in + * the column store. + */ + protected final int rowIndex; + + protected GtfsColumnBasedEntity(GtfsColumnStore store, int rowIndex) { + this.store = store; + this.rowIndex = rowIndex; + } + + protected abstract GtfsColumnAssignments getAssignments(); +} diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedEntityBuilder.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedEntityBuilder.java new file mode 100644 index 0000000000..00228c615e --- /dev/null +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedEntityBuilder.java @@ -0,0 +1,27 @@ +package org.mobilitydata.gtfsvalidator.columns; + +import org.mobilitydata.gtfsvalidator.table.GtfsEntityBuilder; + +public abstract class GtfsColumnBasedEntityBuilder + implements GtfsEntityBuilder { + + protected final GtfsColumnStore store; + + protected int rowIndex = -1; + + public GtfsColumnBasedEntityBuilder(GtfsColumnStore store) { + this.store = store; + } + + protected abstract GtfsColumnAssignments getAssignments(); + + public abstract GtfsColumnBasedCollectionFactory getCollectionFactory(); + + @Override + public void clear() { + this.rowIndex++; + } + + @Override + public void close() {} +} diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumns.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumns.java new file mode 100644 index 0000000000..5f0bcbf726 --- /dev/null +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumns.java @@ -0,0 +1,33 @@ +package org.mobilitydata.gtfsvalidator.columns; + +import java.math.BigDecimal; +import java.time.ZoneId; +import java.util.Currency; +import java.util.Locale; +import org.mobilitydata.gtfsvalidator.annotation.ColumnStoreTypes; +import org.mobilitydata.gtfsvalidator.type.GtfsColor; +import org.mobilitydata.gtfsvalidator.type.GtfsDate; +import org.mobilitydata.gtfsvalidator.type.GtfsTime; + +/** + * This marker interface is used to generate the {@link GtfsColumnStore} implementation. + * + *

While we could maintain {@link GtfsColumnStore} by hand, the set of code to support each type + * specified in {@link ColumnStoreTypes} is very repetitive. It was easier to generate the class + * instead, which allows for easier refactoring and adding new types in the future. + */ +@ColumnStoreTypes({ + byte.class, + short.class, + int.class, + double.class, + String.class, + BigDecimal.class, + Currency.class, + GtfsColor.class, + GtfsDate.class, + GtfsTime.class, + Locale.class, + ZoneId.class +}) +public interface GtfsColumns {} diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/parsing/RowParser.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/parsing/RowParser.java index e29f7b53c5..fb281e979b 100644 --- a/core/src/main/java/org/mobilitydata/gtfsvalidator/parsing/RowParser.java +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/parsing/RowParser.java @@ -42,6 +42,7 @@ import org.mobilitydata.gtfsvalidator.notice.ValidationNotice; import org.mobilitydata.gtfsvalidator.table.GtfsColumnDescriptor; import org.mobilitydata.gtfsvalidator.table.GtfsEnum; +import org.mobilitydata.gtfsvalidator.table.GtfsEnumDescriptor; import org.mobilitydata.gtfsvalidator.type.GtfsColor; import org.mobilitydata.gtfsvalidator.type.GtfsDate; import org.mobilitydata.gtfsvalidator.type.GtfsTime; @@ -125,6 +126,54 @@ public boolean checkRowLength() { return true; } + @Nullable + public Object parseValue(int columnIndex, GtfsColumnDescriptor columnDescriptor) { + switch (columnDescriptor.fieldType()) { + case COLOR: + return asColor(columnIndex, columnDescriptor); + case CURRENCY_CODE: + return asCurrencyCode(columnIndex, columnDescriptor); + case DATE: + return asDate(columnIndex, columnDescriptor); + case DECIMAL: + return asDecimal(columnIndex, columnDescriptor); + case EMAIL: + return asEmail(columnIndex, columnDescriptor); + case ENUM: + { + GtfsEnumDescriptor enumDescriptor = columnDescriptor.enumDescriptor().get(); + return asEnum( + columnIndex, + columnDescriptor, + enumDescriptor.creator(), + enumDescriptor.defaultValue()); + } + case FLOAT: + return asFloat(columnIndex, columnDescriptor); + case ID: + return asId(columnIndex, columnDescriptor); + case INTEGER: + return asInteger(columnIndex, columnDescriptor); + case LANGUAGE_CODE: + return asLanguageCode(columnIndex, columnDescriptor); + case LATITUDE: + return asLatitude(columnIndex, columnDescriptor); + case LONGITUDE: + return asLongitude(columnIndex, columnDescriptor); + case PHONE_NUMBER: + return asPhoneNumber(columnIndex, columnDescriptor); + case TEXT: + return asText(columnIndex, columnDescriptor); + case TIME: + return asTime(columnIndex, columnDescriptor); + case TIMEZONE: + return asTimezone(columnIndex, columnDescriptor); + case URL: + return asUrl(columnIndex, columnDescriptor); + } + throw new IllegalArgumentException("Unhandled field type: " + columnDescriptor.fieldType()); + } + @Nullable public String asString(int columnIndex, GtfsColumnDescriptor columnDescriptor) { String s = row.asString(columnIndex); diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/table/AnyTableLoader.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/table/AnyTableLoader.java index 3765bf22cb..906e317007 100644 --- a/core/src/main/java/org/mobilitydata/gtfsvalidator/table/AnyTableLoader.java +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/table/AnyTableLoader.java @@ -1,7 +1,6 @@ package org.mobilitydata.gtfsvalidator.table; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.common.flogger.FluentLogger; import com.univocity.parsers.common.TextParsingException; import com.univocity.parsers.csv.CsvParserSettings; @@ -12,6 +11,9 @@ import java.util.Optional; import java.util.stream.Collectors; import javax.annotation.Nullable; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnBasedCollectionFactory; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnBasedEntityBuilder; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnStore; import org.mobilitydata.gtfsvalidator.notice.CsvParsingFailedNotice; import org.mobilitydata.gtfsvalidator.notice.EmptyFileNotice; import org.mobilitydata.gtfsvalidator.notice.MissingRecommendedFileNotice; @@ -36,6 +38,12 @@ public final class AnyTableLoader { private static final List> singleEntityValidatorsWithParsingErrors = new ArrayList<>(); + private static boolean useColumnBasedStorage = false; + + public static void setUseColumnBasedStorage(boolean enabled) { + useColumnBasedStorage = enabled; + } + public List> getValidatorsWithParsingErrors() { return Collections.unmodifiableList(singleFileValidatorsWithParsingErrors); } @@ -79,24 +87,24 @@ public static GtfsTableContainer load( GtfsTableContainer.TableStatus.INVALID_HEADERS); } final int nColumns = columnDescriptors.size(); - final ImmutableMap fieldLoadersMap = tableDescriptor.getFieldLoaders(); final int[] columnIndices = new int[nColumns]; - final GtfsFieldLoader[] fieldLoaders = new GtfsFieldLoader[nColumns]; final FieldCache[] fieldCaches = new FieldCache[nColumns]; for (int i = 0; i < nColumns; ++i) { GtfsColumnDescriptor columnDescriptor = columnDescriptors.get(i); String columnName = columnDescriptor.columnName(); columnIndices[i] = header.getColumnIndex(columnName); - fieldLoaders[i] = fieldLoadersMap.get(columnName); if (columnDescriptor.isCached()) { // FieldCache is a generic type. However, info about generics is eliminated at runtime. fieldCaches[i] = new FieldCache(); } } - final GtfsEntityBuilder builder = tableDescriptor.createEntityBuilder(); + + Dependencies deps = constructDependencies(tableDescriptor); + GtfsEntityBuilder builder = deps.entityBuilder; + List entities = deps.entities; + final RowParser rowParser = new RowParser(gtfsFilename, header, validatorProvider.getFieldValidator()); - final List entities = new ArrayList<>(); boolean hasUnparsableRows = false; final List> singleEntityValidators = validatorProvider.createSingleEntityValidators( @@ -117,8 +125,13 @@ public static GtfsTableContainer load( builder.clear(); builder.setCsvRowNumber(rowParser.getRowNumber()); for (int i = 0; i < nColumns; ++i) { - fieldLoaders[i].load( - rowParser, columnIndices[i], columnDescriptors.get(i), fieldCaches[i], builder); + parseRowAndColumn( + rowParser, + columnIndices[i], + tableDescriptor, + columnDescriptors.get(i), + fieldCaches[i], + builder); } } if (rowNotices.hasValidationErrors()) { @@ -143,6 +156,7 @@ public static GtfsTableContainer load( return tableDescriptor.createContainerForInvalidStatus( GtfsTableContainer.TableStatus.UNPARSABLE_ROWS); } + builder.close(); GtfsTableContainer table = tableDescriptor.createContainerForHeaderAndEntities(header, entities, noticeContainer); ValidatorUtil.invokeSingleFileValidators( @@ -152,6 +166,27 @@ public static GtfsTableContainer load( return table; } + private static class Dependencies { + GtfsEntityBuilder entityBuilder; + List entities; + } + + private static Dependencies constructDependencies(GtfsTableDescriptor tableDescriptor) { + Dependencies deps = new Dependencies(); + if (useColumnBasedStorage) { + GtfsColumnStore columnStore = new GtfsColumnStore(); + GtfsColumnBasedEntityBuilder entityBuilder = + tableDescriptor.createColumnBasedEntityBuilder(columnStore); + GtfsColumnBasedCollectionFactory collectionFactory = entityBuilder.getCollectionFactory(); + deps.entityBuilder = entityBuilder; + deps.entities = collectionFactory.createAllEntitiesList(); + } else { + deps.entityBuilder = tableDescriptor.createEntityBuilder(); + deps.entities = new ArrayList<>(); + } + return deps; + } + private static NoticeContainer validateHeaders( ValidatorProvider validatorProvider, String gtfsFilename, @@ -217,4 +252,33 @@ public static GtfsTableContainer loadMissingFile( noticeContainer); return table; } + + private static void parseRowAndColumn( + RowParser rowParser, + int columnIndex, + GtfsTableDescriptor tableDescriptor, + GtfsColumnDescriptor columnDescriptor, + FieldCache fieldCache, + GtfsEntityBuilder builder) { + Object value = rowParser.parseValue(columnIndex, columnDescriptor); + // If the column isn't present in the input CSV, we don't do anything with the (likely null) + // parsed value. + if (columnIndex == -1 || value == null) { + return; + } + value = addToCacheIfPresent(value, fieldCache); + GtfsSetter setter = + (GtfsSetter) + (useColumnBasedStorage + ? columnDescriptor.columnBasedEntityBuilderSetter() + : columnDescriptor.entityBuilderSetter()); + setter.setValue(builder, value); + } + + protected static V addToCacheIfPresent(V value, @Nullable FieldCache fieldCache) { + if (fieldCache == null) { + return value; + } + return fieldCache.addIfAbsent(value); + } } diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsColumnDescriptor.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsColumnDescriptor.java index 0546e479d1..a173f7b5dd 100644 --- a/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsColumnDescriptor.java +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsColumnDescriptor.java @@ -3,6 +3,7 @@ import com.google.auto.value.AutoValue; import java.util.Optional; import org.mobilitydata.gtfsvalidator.annotation.FieldLevelEnum; +import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; import org.mobilitydata.gtfsvalidator.parsing.RowParser; @AutoValue @@ -15,6 +16,16 @@ public abstract class GtfsColumnDescriptor { public abstract FieldLevelEnum fieldLevel(); + public abstract Class javaType(); + + public abstract FieldTypeEnum fieldType(); + + public abstract Optional enumDescriptor(); + + public abstract GtfsSetter entityBuilderSetter(); + + public abstract GtfsSetter columnBasedEntityBuilderSetter(); + public abstract Optional numberBounds(); public abstract boolean isCached(); @@ -29,6 +40,8 @@ public static GtfsColumnDescriptor.Builder builder() { return new AutoValue_GtfsColumnDescriptor.Builder(); } + public abstract Builder toBuilder(); + @AutoValue.Builder public abstract static class Builder { public abstract Builder setColumnName(String value); @@ -39,6 +52,18 @@ public abstract static class Builder { public abstract Builder setFieldLevel(FieldLevelEnum value); + public abstract Builder setJavaType(Class javaType); + + public abstract Builder setFieldType(FieldTypeEnum fieldType); + + public abstract Builder setEnumDescriptor(GtfsEnumDescriptor enumDescriptor); + + public abstract Builder setEntityBuilderSetter( + GtfsSetter setterMethod); + + public abstract Builder setColumnBasedEntityBuilderSetter( + GtfsSetter setterMethod); + public abstract Builder setNumberBounds(Optional value); public abstract Builder setNumberBounds(RowParser.NumberBounds value); diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsEnumDescriptor.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsEnumDescriptor.java new file mode 100644 index 0000000000..7bc7132370 --- /dev/null +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsEnumDescriptor.java @@ -0,0 +1,15 @@ +package org.mobilitydata.gtfsvalidator.table; + +import com.google.auto.value.AutoValue; +import org.mobilitydata.gtfsvalidator.parsing.RowParser.EnumCreator; + +@AutoValue +public abstract class GtfsEnumDescriptor { + public abstract EnumCreator creator(); + + public abstract GtfsEnum defaultValue(); + + public static GtfsEnumDescriptor create(EnumCreator creator, GtfsEnum defaultValue) { + return new AutoValue_GtfsEnumDescriptor(creator, defaultValue); + } +} diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsFeedLoader.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsFeedLoader.java index 1edb051184..fd2d19f40d 100644 --- a/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsFeedLoader.java +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsFeedLoader.java @@ -49,6 +49,8 @@ public class GtfsFeedLoader { private final HashMap> tableDescriptors = new HashMap<>(); private int numThreads = 1; + private boolean useColumnBasedEntities = true; + /** * The set of validators that were skipped during validation because their file dependencies had * parse errors plus validators that are optional. @@ -148,6 +150,7 @@ public GtfsFeedContainer loadAndValidate( addThreadExecutionError(e, noticeContainer); } } + GtfsFeedContainer feed = new GtfsFeedContainer(tableContainers); List> validatorCallables = new ArrayList<>(); // Validators with parser-error dependencies will not be returned here, but instead added to diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsSetter.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsSetter.java new file mode 100644 index 0000000000..7fa90f9512 --- /dev/null +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsSetter.java @@ -0,0 +1,10 @@ +package org.mobilitydata.gtfsvalidator.table; + +@FunctionalInterface +public interface GtfsSetter { + K setValue(K builder, V value); + + static GtfsSetter, V> noopSetter() { + return (builder, value) -> builder; + } +} diff --git a/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsTableDescriptor.java b/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsTableDescriptor.java index 01f3b773db..5336d15e5a 100644 --- a/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsTableDescriptor.java +++ b/core/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsTableDescriptor.java @@ -1,9 +1,10 @@ package org.mobilitydata.gtfsvalidator.table; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import java.util.List; import java.util.Optional; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnBasedEntityBuilder; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnStore; import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; import org.mobilitydata.gtfsvalidator.parsing.CsvHeader; @@ -20,12 +21,13 @@ public abstract GtfsTableContainer createContainerForHeaderAndEntities( public abstract GtfsEntityBuilder createEntityBuilder(); + public abstract GtfsColumnBasedEntityBuilder createColumnBasedEntityBuilder( + GtfsColumnStore store); + public abstract Class getEntityClass(); public abstract String gtfsFilename(); - public abstract ImmutableMap getFieldLoaders(); - public abstract boolean isRecommended(); public boolean isRequired() { diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/columns/ColumnStoreBaseTest.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/columns/ColumnStoreBaseTest.java new file mode 100644 index 0000000000..ec4fa14d39 --- /dev/null +++ b/core/src/test/java/org/mobilitydata/gtfsvalidator/columns/ColumnStoreBaseTest.java @@ -0,0 +1,154 @@ +package org.mobilitydata.gtfsvalidator.columns; + +import static com.google.common.truth.Truth.assertThat; +import static org.mobilitydata.gtfsvalidator.columns.ColumnStoreBase.hasPrimitive; +import static org.mobilitydata.gtfsvalidator.columns.ColumnStoreBase.reserveColumn; +import static org.mobilitydata.gtfsvalidator.columns.ColumnStoreBase.reservePrimitivePresence; + +import java.util.ArrayList; +import java.util.List; +import org.junit.Test; + +public class ColumnStoreBaseTest { + + @Test + public void testReserveColumn() { + List values = new ArrayList<>(); + values.add(new String[2]); + + int columnIndex = reserveColumn(values, String.class, 3); + + assertThat(columnIndex).isEqualTo(1); + assertThat(values).hasSize(2); + assertThat(values.get(1)).asList().containsExactly(null, null, null); + } + + @Test + public void testReservePrimitivePresence_newColumn() { + List presence = new ArrayList<>(); + + reservePrimitivePresence(presence, 0, 3); + + assertThat(presence).hasSize(1); + assertThat(presence.get(0)).asList().containsExactly(b(0), b(0), b(0)); + } + + @Test + public void testReservePrimitivePresence_existingColumn() { + List presence = new ArrayList<>(); + presence.add(new byte[2]); + + // None of these should trigger a new column, since they fit within the existing 8 bits of + // a byte. + reservePrimitivePresence(presence, 0, 3); + reservePrimitivePresence(presence, 3, 3); + reservePrimitivePresence(presence, 7, 3); + + assertThat(presence).hasSize(1); + assertThat(presence.get(0)).asList().containsExactly(b(0), b(0)); + } + + @Test + public void testReservePrimitivePresence_extendColumns() { + List presence = new ArrayList<>(); + presence.add(new byte[2]); + + reservePrimitivePresence(presence, 8, 3); + + assertThat(presence).hasSize(2); + assertThat(presence.get(0)).asList().containsExactly(b(0), b(0)); + assertThat(presence.get(1)).asList().containsExactly(b(0), b(0), b(0)); + } + + @Test + public void testHasPrimitive() { + List presence = new ArrayList<>(); + presence.add(new byte[] {b(0b00001010), b(0b01010000)}); + presence.add(new byte[] {b(0b00000101), b(0b10100000)}); + + assertThat(hasPrimitive(presence, 0, 0)).isFalse(); + assertThat(hasPrimitive(presence, 1, 0)).isTrue(); + assertThat(hasPrimitive(presence, 2, 0)).isFalse(); + assertThat(hasPrimitive(presence, 3, 0)).isTrue(); + assertThat(hasPrimitive(presence, 4, 0)).isFalse(); + assertThat(hasPrimitive(presence, 7, 0)).isFalse(); + assertThat(hasPrimitive(presence, 8, 0)).isTrue(); + assertThat(hasPrimitive(presence, 9, 0)).isFalse(); + assertThat(hasPrimitive(presence, 10, 0)).isTrue(); + assertThat(hasPrimitive(presence, 11, 0)).isFalse(); + + assertThat(hasPrimitive(presence, 0, 1)).isFalse(); + assertThat(hasPrimitive(presence, 3, 1)).isFalse(); + assertThat(hasPrimitive(presence, 4, 1)).isTrue(); + assertThat(hasPrimitive(presence, 5, 1)).isFalse(); + assertThat(hasPrimitive(presence, 6, 1)).isTrue(); + assertThat(hasPrimitive(presence, 7, 1)).isFalse(); + assertThat(hasPrimitive(presence, 8, 1)).isFalse(); + assertThat(hasPrimitive(presence, 12, 1)).isFalse(); + assertThat(hasPrimitive(presence, 13, 1)).isTrue(); + assertThat(hasPrimitive(presence, 14, 1)).isFalse(); + assertThat(hasPrimitive(presence, 15, 1)).isTrue(); + } + + @Test + public void testSetPrimitivePresence_existingCapacity() { + List presence = new ArrayList<>(); + presence.add(new byte[2]); + presence.add(new byte[2]); + ColumnStoreBase.setPrimitivePresence(presence, 0, 0); + ColumnStoreBase.setPrimitivePresence(presence, 2, 0); + ColumnStoreBase.setPrimitivePresence(presence, 1, 1); + ColumnStoreBase.setPrimitivePresence(presence, 10, 1); + ColumnStoreBase.setPrimitivePresence(presence, 11, 0); + + assertThat(presence.get(0)).asList().containsExactly(b(0b00000101), b(0b00000010)); + assertThat(presence.get(1)).asList().containsExactly(b(0b00001000), b(0b00000100)); + } + + @Test + public void testSetPrimitivePresence_extendCapacity() { + List presence = new ArrayList<>(); + presence.add(new byte[2]); + + ColumnStoreBase.setPrimitivePresence(presence, 1, 0); + ColumnStoreBase.setPrimitivePresence(presence, 2, 1); + ColumnStoreBase.setPrimitivePresence(presence, 5, 2); + ColumnStoreBase.setPrimitivePresence(presence, 6, 3); + + assertThat(presence.get(0)) + .asList() + .containsExactly(b(0b00000010), b(0b00000100), b(0b00100000), b(0b01000000)); + } + + @Test + public void testSetValue_withinCapacity() { + List values = new ArrayList<>(); + values.add(new String[2]); + values.add(new String[2]); + + ColumnStoreBase.setValue(values, 0, 1, "a"); + + assertThat(values.get(0)).asList().containsExactly(null, "a"); + assertThat(values.get(1)).asList().containsExactly(null, null); + + ColumnStoreBase.setValue(values, 1, 0, "b"); + + assertThat(values.get(0)).asList().containsExactly(null, "a"); + assertThat(values.get(1)).asList().containsExactly("b", null); + } + + @Test + public void testSetValue_extendCapacity() { + List values = new ArrayList<>(); + values.add(new String[2]); + + ColumnStoreBase.setValue(values, 0, 0, "a"); + ColumnStoreBase.setValue(values, 0, 2, "c"); + + assertThat(values.get(0)).asList().containsExactly("a", null, "c", null); + } + + private static byte b(int v) { + return (byte) v; + } +} diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedCollectionFactoryTest.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedCollectionFactoryTest.java new file mode 100644 index 0000000000..242a7ea1e2 --- /dev/null +++ b/core/src/test/java/org/mobilitydata/gtfsvalidator/columns/GtfsColumnBasedCollectionFactoryTest.java @@ -0,0 +1,96 @@ +package org.mobilitydata.gtfsvalidator.columns; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + +import java.util.List; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntityColumnBased; + +public class GtfsColumnBasedCollectionFactoryTest { + + private GtfsColumnStore store; + + private GtfsTestEntityColumnBased.Builder builder; + + private GtfsColumnAssignments assignments; + + private GtfsColumnBasedCollectionFactory factory; + + @Before + public void before() { + store = new GtfsColumnStore(); + builder = new GtfsTestEntityColumnBased.Builder(store); + assignments = ((GtfsColumnBasedEntityBuilder) builder).getAssignments(); + factory = + new GtfsColumnBasedCollectionFactory<>( + store, assignments, GtfsTestEntityColumnBased::create); + } + + @Test + public void testAllEntitiesList() { + List entities = factory.createAllEntitiesList(); + + builder.clear(); + entities.add(builder.setCsvRowNumber(1).setId("a").setCode("xyz").build()); + builder.clear(); + entities.add(builder.setCsvRowNumber(3).setId("b").setCode("efg").build()); + + assertThat(entities).hasSize(2); + + assertThat(entities.get(0)).isEqualTo(GtfsTestEntityColumnBased.create(store, assignments, 0)); + assertThat(entities.get(1)).isEqualTo(GtfsTestEntityColumnBased.create(store, assignments, 1)); + + assertThrows(UnsupportedOperationException.class, () -> entities.clear()); + } + + @Test + public void testSomeEntitiesList() { + builder.clear(); + GtfsTestEntityColumnBased a = builder.setCsvRowNumber(1).setId("a").build(); + builder.clear(); + GtfsTestEntityColumnBased b = builder.setCsvRowNumber(3).setId("b").build(); + builder.clear(); + GtfsTestEntityColumnBased c = builder.setCsvRowNumber(4).setId("c").build(); + + List entities = factory.createSomeEntitiesList(); + entities.add(c); + entities.add(a); + + assertThat(entities).hasSize(2); + + assertThat(entities.get(0)).isEqualTo(GtfsTestEntityColumnBased.create(store, assignments, 2)); + assertThat(entities.get(1)).isEqualTo(GtfsTestEntityColumnBased.create(store, assignments, 0)); + + GtfsTestEntityColumnBased existing = entities.set(0, b); + assertThat(existing).isEqualTo(GtfsTestEntityColumnBased.create(store, assignments, 2)); + assertThat(entities.get(0)).isEqualTo(GtfsTestEntityColumnBased.create(store, assignments, 1)); + + assertThrows(UnsupportedOperationException.class, () -> entities.clear()); + } + + @Test + public void testSomeEntitiesMap() { + builder.clear(); + GtfsTestEntityColumnBased a = builder.setCsvRowNumber(1).setId("a").build(); + builder.clear(); + GtfsTestEntityColumnBased b = builder.setCsvRowNumber(3).setId("b").build(); + builder.clear(); + GtfsTestEntityColumnBased c = builder.setCsvRowNumber(4).setId("c").build(); + + Map entities = factory.createSomeEntitiesMap(); + entities.put("a", a); + entities.put("c", c); + + assertThat(entities).hasSize(2); + + assertThat(entities.get("a")) + .isEqualTo(GtfsTestEntityColumnBased.create(store, assignments, 0)); + assertThat(entities.get("c")) + .isEqualTo(GtfsTestEntityColumnBased.create(store, assignments, 2)); + + assertThrows(UnsupportedOperationException.class, () -> entities.clear()); + } +} diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/parsing/RowParserTest.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/parsing/RowParserTest.java index 260f3da2e2..fe4638039e 100644 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/parsing/RowParserTest.java +++ b/core/src/test/java/org/mobilitydata/gtfsvalidator/parsing/RowParserTest.java @@ -21,15 +21,16 @@ import java.time.LocalDate; import java.time.ZoneId; import java.util.Arrays; -import java.util.Optional; import java.util.function.Function; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mobilitydata.gtfsvalidator.annotation.FieldLevelEnum; +import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; import org.mobilitydata.gtfsvalidator.input.CountryCode; import org.mobilitydata.gtfsvalidator.notice.*; import org.mobilitydata.gtfsvalidator.table.GtfsColumnDescriptor; +import org.mobilitydata.gtfsvalidator.table.GtfsSetter; import org.mobilitydata.gtfsvalidator.type.GtfsColor; import org.mobilitydata.gtfsvalidator.type.GtfsDate; import org.mobilitydata.gtfsvalidator.type.GtfsTime; @@ -45,42 +46,18 @@ public class RowParserTest { private static GtfsFieldValidator FIELD_VALIDATOR = new DefaultFieldValidator(TEST_COUNTRY_CODE); private static GtfsColumnDescriptor GTFS_COLUMN_DESCRIPTOR = - new GtfsColumnDescriptor() { - @Override - public String columnName() { - return "column name"; - } - - @Override - public boolean headerRequired() { - return false; - } - - @Override - public boolean headerRecommended() { - return false; - } - - @Override - public FieldLevelEnum fieldLevel() { - return FieldLevelEnum.REQUIRED; - } - - @Override - public Optional numberBounds() { - return Optional.empty(); - } - - @Override - public boolean isCached() { - return false; - } - - @Override - public boolean isMixedCase() { - return false; - } - }; + GtfsColumnDescriptor.builder() + .setColumnName("column name") + .setHeaderRequired(false) + .setHeaderRecommended(false) + .setFieldLevel(FieldLevelEnum.REQUIRED) + .setJavaType(String.class) + .setFieldType(FieldTypeEnum.TEXT) + .setEntityBuilderSetter(GtfsSetter.noopSetter()) + .setColumnBasedEntityBuilderSetter(GtfsSetter.noopSetter()) + .setIsCached(false) + .setIsMixedCase(false) + .build(); private static RowParser createParser(String cellValue) { NoticeContainer noticeContainer = new NoticeContainer(); @@ -143,14 +120,7 @@ public void asString_required_valid() { public void asString_recommended_missing() { RowParser parser = createParser(null); GtfsColumnDescriptor tempColumnDescriptor = - GtfsColumnDescriptor.builder() - .setColumnName("column name") - .setHeaderRequired(false) - .setHeaderRecommended(false) - .setFieldLevel(FieldLevelEnum.RECOMMENDED) - .setIsMixedCase(false) - .setIsCached(false) - .build(); + GTFS_COLUMN_DESCRIPTOR.toBuilder().setFieldLevel(FieldLevelEnum.RECOMMENDED).build(); assertThat(parser.asString(0, tempColumnDescriptor)).isEqualTo(null); MissingRecommendedFieldNotice notice = diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/table/AnyTableLoaderTest.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/table/AnyTableLoaderTest.java index 6c6da42f6e..81655bc6a0 100644 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/table/AnyTableLoaderTest.java +++ b/core/src/test/java/org/mobilitydata/gtfsvalidator/table/AnyTableLoaderTest.java @@ -13,12 +13,10 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.mobilitydata.gtfsvalidator.annotation.FieldLevelEnum; import org.mobilitydata.gtfsvalidator.notice.*; import org.mobilitydata.gtfsvalidator.parsing.CsvHeader; -import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntity; +import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntityTableDescriptor; import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestSingleFileValidator; -import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestTableDescriptor; import org.mobilitydata.gtfsvalidator.validator.FileValidator; import org.mobilitydata.gtfsvalidator.validator.GtfsFieldValidator; import org.mobilitydata.gtfsvalidator.validator.TableHeaderValidator; @@ -108,24 +106,18 @@ public void validate( @Test public void invalidRowLengthNotice() { - var testTableDescriptor = spy(new GtfsTestTableDescriptor()); - when(testTableDescriptor.createContainerForInvalidStatus( - GtfsTableContainer.TableStatus.UNPARSABLE_ROWS)) - .thenReturn(mockContainer); + var testTableDescriptor = new GtfsTestEntityTableDescriptor(); when(validatorProvider.getTableHeaderValidator()).thenReturn(mock(TableHeaderValidator.class)); InputStream inputStream = toInputStream("id,code\n" + "s1\n"); - var loadedContainer = - AnyTableLoader.load(testTableDescriptor, validatorProvider, inputStream, loaderNotices); - + AnyTableLoader.load(testTableDescriptor, validatorProvider, inputStream, loaderNotices); assertThat(loaderNotices.getValidationNotices()) .containsExactly(new InvalidRowLengthNotice("filename.txt", 2, 1, 2)); - assertThat(loadedContainer).isEqualTo(mockContainer); } @Test public void parsableTableRows() { - var testTableDescriptor = new GtfsTestTableDescriptor(); + var testTableDescriptor = new GtfsTestEntityTableDescriptor(); when(validatorProvider.getTableHeaderValidator()).thenReturn(mock(TableHeaderValidator.class)); when(validatorProvider.getFieldValidator()).thenReturn(mock(GtfsFieldValidator.class)); GtfsTestSingleFileValidator validator = mock(GtfsTestSingleFileValidator.class); @@ -145,38 +137,16 @@ public void parsableTableRows() { @Test public void missingRequiredField() { - var testTableDescriptor = spy(new GtfsTestTableDescriptor()); - when(testTableDescriptor.getColumns()) - .thenReturn( - ImmutableList.of( - GtfsColumnDescriptor.builder() - .setColumnName(GtfsTestEntity.ID_FIELD_NAME) - .setHeaderRequired(true) - .setHeaderRecommended(false) - .setFieldLevel(FieldLevelEnum.REQUIRED) - .setIsMixedCase(false) - .setIsCached(false) - .build(), - GtfsColumnDescriptor.builder() - .setColumnName(GtfsTestEntity.CODE_FIELD_NAME) - .setHeaderRequired(false) - .setHeaderRecommended(false) - .setFieldLevel(FieldLevelEnum.REQUIRED) - .setIsMixedCase(false) - .setIsCached(false) - .build())); - when(testTableDescriptor.createContainerForInvalidStatus( - GtfsTableContainer.TableStatus.UNPARSABLE_ROWS)) - .thenReturn(mockContainer); + // The `id` field is required for GtfsTestEntity + var testTableDescriptor = new GtfsTestEntityTableDescriptor(); when(validatorProvider.getTableHeaderValidator()).thenReturn(mock(TableHeaderValidator.class)); when(validatorProvider.getFieldValidator()).thenReturn(mock(GtfsFieldValidator.class)); - InputStream inputStream = toInputStream("id,code\n" + "s1,\n"); + InputStream inputStream = toInputStream("id,code\n" + ",some code\n"); var loadedContainer = AnyTableLoader.load(testTableDescriptor, validatorProvider, inputStream, loaderNotices); assertThat(loaderNotices.getValidationNotices()) - .contains(new MissingRequiredFieldNotice("filename.txt", 2, "code")); - assertThat(loadedContainer).isEqualTo(mockContainer); + .contains(new MissingRequiredFieldNotice("filename.txt", 2, "id")); } } diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/table/GtfsFeedContainerTest.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/table/GtfsFeedContainerTest.java index 21735bac2b..dbfa787644 100644 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/table/GtfsFeedContainerTest.java +++ b/core/src/test/java/org/mobilitydata/gtfsvalidator/table/GtfsFeedContainerTest.java @@ -21,13 +21,14 @@ import com.google.common.collect.ImmutableList; import org.junit.Test; import org.mobilitydata.gtfsvalidator.table.GtfsTableContainer.TableStatus; -import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestTableContainer; +import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntityTableContainer; public class GtfsFeedContainerTest { @Test public void getTableForFilename() { - GtfsTestTableContainer table = new GtfsTestTableContainer(TableStatus.EMPTY_FILE); + GtfsTestEntityTableContainer table = + GtfsTestEntityTableContainer.forStatus(TableStatus.EMPTY_FILE); GtfsFeedContainer feedContainer = new GtfsFeedContainer(ImmutableList.of(table)); assertThat(feedContainer.getTableForFilename("filename.txt")).hasValue(table); diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/table/GtfsFeedLoaderTest.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/table/GtfsFeedLoaderTest.java index d70d125efd..4d13dabf3a 100644 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/table/GtfsFeedLoaderTest.java +++ b/core/src/test/java/org/mobilitydata/gtfsvalidator/table/GtfsFeedLoaderTest.java @@ -12,10 +12,10 @@ import org.mobilitydata.gtfsvalidator.input.GtfsInput; import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntity; +import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntityTableContainer; +import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntityTableDescriptor; import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntityValidator; import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestSingleFileValidator; -import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestTableContainer; -import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestTableDescriptor; import org.mobilitydata.gtfsvalidator.testgtfs.WholeFeedValidator; import org.mobilitydata.gtfsvalidator.testing.MockGtfs; import org.mobilitydata.gtfsvalidator.validator.DefaultValidatorProvider; @@ -48,10 +48,12 @@ public void testEndToEnd() throws Exception { TestUtils.contextForTest(), ValidatorLoader.createForClasses(VALIDATOR_CLASSES)); NoticeContainer notices = new NoticeContainer(); - GtfsFeedLoader loader = new GtfsFeedLoader(ImmutableList.of(GtfsTestTableDescriptor.class)); + GtfsFeedLoader loader = + new GtfsFeedLoader(ImmutableList.of(GtfsTestEntityTableDescriptor.class)); GtfsFeedContainer feedContainer = loader.loadAndValidate(input, provider, notices); - GtfsTestTableContainer container = feedContainer.getTable(GtfsTestTableContainer.class); + GtfsTestEntityTableContainer container = + feedContainer.getTable(GtfsTestEntityTableContainer.class); assertThat(container.getEntities()).hasSize(1); GtfsTestEntity entity = container.getEntities().get(0); @@ -70,10 +72,12 @@ public void testInvalidDataInTable() throws Exception { TestUtils.contextForTest(), ValidatorLoader.createForClasses(VALIDATOR_CLASSES)); NoticeContainer notices = new NoticeContainer(); - GtfsFeedLoader loader = new GtfsFeedLoader(ImmutableList.of(GtfsTestTableDescriptor.class)); + GtfsFeedLoader loader = + new GtfsFeedLoader(ImmutableList.of(GtfsTestEntityTableDescriptor.class)); GtfsFeedContainer feedContainer = loader.loadAndValidate(input, provider, notices); - GtfsTestTableContainer container = feedContainer.getTable(GtfsTestTableContainer.class); + GtfsTestEntityTableContainer container = + feedContainer.getTable(GtfsTestEntityTableContainer.class); assertThat(container.getEntities()).isEmpty(); assertThat(loader.getMultiFileValidatorsWithParsingErrors()) diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestEntity.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestEntity.java deleted file mode 100644 index 2e0fab653e..0000000000 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestEntity.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.mobilitydata.gtfsvalidator.testgtfs; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.mobilitydata.gtfsvalidator.table.GtfsEntity; -import org.mobilitydata.gtfsvalidator.table.GtfsEntityBuilder; - -public class GtfsTestEntity implements GtfsEntity { - public static final String FILENAME = "filename.txt"; - - public static final String ID_FIELD_NAME = "id"; - - public static final String CODE_FIELD_NAME = "code"; - - public static final String DEFAULT_ID = ""; - - public static final String DEFAULT_CODE = ""; - - private int csvRowNumber; - - private String id; - - private String code; - - private short bitField0_; - - /** Use {@link Builder} class to construct an object. */ - private GtfsTestEntity() {} - - @Override - public int csvRowNumber() { - return csvRowNumber; - } - - @Nonnull - public String id() { - return id; - } - - public boolean hasId() { - return (bitField0_ & 0x1) != 0; - } - - public String code() { - return code; - } - - public boolean hasCode() { - return (bitField0_ & 0x2) != 0; - } - - public static final class Builder implements GtfsEntityBuilder { - private int csvRowNumber; - - private String id; - - private String code; - - private short bitField0_; - - public Builder() { - // Initialize all fields to default values. - clear(); - } - - @Override - public int csvRowNumber() { - return csvRowNumber; - } - - @Override - public GtfsTestEntity.Builder setCsvRowNumber(int value) { - csvRowNumber = value; - return this; - } - - @Nonnull - public String id() { - return id; - } - - @Nonnull - public GtfsTestEntity.Builder setId(@Nullable String value) { - if (value == null) { - return clearId(); - } - id = value; - bitField0_ |= 0x1; - return this; - } - - @Nonnull - public GtfsTestEntity.Builder clearId() { - id = DEFAULT_ID; - bitField0_ &= ~0x1; - return this; - } - - @Nonnull - public String code() { - return code; - } - - @Nonnull - public GtfsTestEntity.Builder setCode(@Nullable String value) { - if (value == null) { - return clearCode(); - } - code = value; - bitField0_ |= 0x2; - return this; - } - - @Nonnull - public GtfsTestEntity.Builder clearCode() { - code = DEFAULT_CODE; - bitField0_ &= ~0x2; - return this; - } - - @Override - public GtfsTestEntity build() { - GtfsTestEntity entity = new GtfsTestEntity(); - entity.csvRowNumber = this.csvRowNumber; - entity.bitField0_ = this.bitField0_; - entity.id = this.id; - entity.code = this.code; - return entity; - } - - @Override - public void clear() { - csvRowNumber = 0; - bitField0_ = 0; - id = DEFAULT_ID; - code = DEFAULT_CODE; - } - } -} diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestMultiFileValidator.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestMultiFileValidator.java index 7585b3624f..c63159ecd2 100644 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestMultiFileValidator.java +++ b/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestMultiFileValidator.java @@ -22,11 +22,12 @@ public class GtfsTestMultiFileValidator extends FileValidator { - private final GtfsTestTableContainer table; - private final GtfsTestTableContainer2 unparsableTable; + private final GtfsTestEntityTableContainer table; + private final GtfsTestEntity2TableContainer unparsableTable; @Inject - public GtfsTestMultiFileValidator(GtfsTestTableContainer table, GtfsTestTableContainer2 table2) { + public GtfsTestMultiFileValidator( + GtfsTestEntityTableContainer table, GtfsTestEntity2TableContainer table2) { this.table = table; this.unparsableTable = table2; } diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestSingleFileValidator.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestSingleFileValidator.java index cd3bf2052a..c902ea22dc 100644 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestSingleFileValidator.java +++ b/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestSingleFileValidator.java @@ -24,13 +24,15 @@ public class GtfsTestSingleFileValidator extends FileValidator { - private final GtfsTestTableContainer table; + private final GtfsTestEntityTableContainer table; private final CountryCode countryCode; private final DateForValidation dateForValidation; @Inject public GtfsTestSingleFileValidator( - GtfsTestTableContainer table, CountryCode countryCode, DateForValidation dateForValidation) { + GtfsTestEntityTableContainer table, + CountryCode countryCode, + DateForValidation dateForValidation) { this.table = table; this.countryCode = countryCode; this.dateForValidation = dateForValidation; @@ -39,7 +41,7 @@ public GtfsTestSingleFileValidator( @Override public void validate(NoticeContainer noticeContainer) {} - public GtfsTestTableContainer getStopTable() { + public GtfsTestEntityTableContainer getStopTable() { return table; } diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableContainer.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableContainer.java deleted file mode 100644 index e84ab8041a..0000000000 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableContainer.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.mobilitydata.gtfsvalidator.testgtfs; - -import com.google.common.collect.ImmutableList; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; -import org.mobilitydata.gtfsvalidator.parsing.CsvHeader; -import org.mobilitydata.gtfsvalidator.table.GtfsTableContainer; - -public class GtfsTestTableContainer extends GtfsTableContainer { - private static final ImmutableList KEY_COLUMN_NAMES = - ImmutableList.of(GtfsTestEntity.ID_FIELD_NAME); - - private List entities; - - private GtfsTestTableContainer( - GtfsTestTableDescriptor descriptor, CsvHeader header, List entities) { - super(descriptor, TableStatus.PARSABLE_HEADERS_AND_ROWS, header); - this.entities = entities; - } - - public GtfsTestTableContainer(TableStatus tableStatus) { - super(new GtfsTestTableDescriptor(), tableStatus, CsvHeader.EMPTY); - this.entities = new ArrayList<>(); - } - - @Override - public Class getEntityClass() { - return GtfsTestEntity.class; - } - - @Override - public String gtfsFilename() { - return GtfsTestEntity.FILENAME; - } - - @Override - public List getEntities() { - return entities; - } - - /** Creates a table with given header and entities */ - public static GtfsTestTableContainer forHeaderAndEntities( - GtfsTestTableDescriptor descriptor, - CsvHeader header, - List entities, - NoticeContainer noticeContainer) { - GtfsTestTableContainer table = new GtfsTestTableContainer(descriptor, header, entities); - return table; - } - - @Override - public ImmutableList getKeyColumnNames() { - return KEY_COLUMN_NAMES; - } - - @Override - public Optional byTranslationKey(String recordId, String recordSubId) { - return Optional.empty(); - } -} diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableContainer2.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableContainer2.java deleted file mode 100644 index 962b5bb6e7..0000000000 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableContainer2.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.mobilitydata.gtfsvalidator.testgtfs; - -import com.google.common.collect.ImmutableList; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; -import org.mobilitydata.gtfsvalidator.parsing.CsvHeader; -import org.mobilitydata.gtfsvalidator.table.GtfsTableContainer; - -// We need a second test table class to test multi file validators. -public class GtfsTestTableContainer2 extends GtfsTableContainer { - private static final ImmutableList KEY_COLUMN_NAMES = - ImmutableList.of(GtfsTestEntity.ID_FIELD_NAME); - - private List entities; - - private GtfsTestTableContainer2( - GtfsTestTableDescriptor2 descriptor, CsvHeader header, List entities) { - super(descriptor, TableStatus.PARSABLE_HEADERS_AND_ROWS, header); - this.entities = entities; - } - - public GtfsTestTableContainer2(TableStatus tableStatus) { - super(new GtfsTestTableDescriptor2(), tableStatus, CsvHeader.EMPTY); - this.entities = new ArrayList<>(); - } - - @Override - public Class getEntityClass() { - return GtfsTestEntity.class; - } - - @Override - public String gtfsFilename() { - return GtfsTestEntity.FILENAME + "2"; - } - - @Override - public List getEntities() { - return entities; - } - - /** Creates a table with given header and entities */ - public static GtfsTestTableContainer2 forHeaderAndEntities( - GtfsTestTableDescriptor2 descriptor, - CsvHeader header, - List entities, - NoticeContainer noticeContainer) { - GtfsTestTableContainer2 table = new GtfsTestTableContainer2(descriptor, header, entities); - return table; - } - - @Override - public ImmutableList getKeyColumnNames() { - return KEY_COLUMN_NAMES; - } - - @Override - public Optional byTranslationKey(String recordId, String recordSubId) { - return Optional.empty(); - } -} diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableDescriptor.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableDescriptor.java deleted file mode 100644 index 58dcdae890..0000000000 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableDescriptor.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.mobilitydata.gtfsvalidator.testgtfs; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.util.List; -import java.util.Optional; -import org.mobilitydata.gtfsvalidator.annotation.FieldLevelEnum; -import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; -import org.mobilitydata.gtfsvalidator.parsing.CsvHeader; -import org.mobilitydata.gtfsvalidator.parsing.FieldCache; -import org.mobilitydata.gtfsvalidator.parsing.RowParser; -import org.mobilitydata.gtfsvalidator.table.*; - -public class GtfsTestTableDescriptor extends GtfsTableDescriptor { - @Override - public GtfsTableContainer createContainerForInvalidStatus( - GtfsTableContainer.TableStatus tableStatus) { - return new GtfsTestTableContainer(tableStatus); - } - - @Override - public GtfsTableContainer createContainerForHeaderAndEntities( - CsvHeader header, List entities, NoticeContainer noticeContainer) { - return GtfsTestTableContainer.forHeaderAndEntities(this, header, entities, noticeContainer); - } - - @Override - public GtfsEntityBuilder createEntityBuilder() { - return new GtfsTestEntity.Builder(); - } - - @Override - public Class getEntityClass() { - return GtfsTestEntity.class; - } - - @Override - public ImmutableList getColumns() { - ImmutableList.Builder builder = ImmutableList.builder(); - builder.add( - GtfsColumnDescriptor.builder() - .setColumnName(GtfsTestEntity.ID_FIELD_NAME) - .setHeaderRequired(true) - .setHeaderRecommended(false) - .setFieldLevel(FieldLevelEnum.REQUIRED) - .setIsMixedCase(false) - .setIsCached(false) - .build()); - builder.add( - GtfsColumnDescriptor.builder() - .setColumnName(GtfsTestEntity.CODE_FIELD_NAME) - .setHeaderRequired(false) - .setHeaderRecommended(false) - .setFieldLevel(FieldLevelEnum.OPTIONAL) - .setIsMixedCase(false) - .setIsCached(false) - .build()); - return builder.build(); - } - - @Override - public ImmutableMap getFieldLoaders() { - ImmutableMap.Builder builder = ImmutableMap.builder(); - builder.put( - GtfsTestEntity.ID_FIELD_NAME, - new GtfsFieldLoader() { - @Override - public void load( - RowParser rowParser, - int columnIndex, - GtfsColumnDescriptor columnDescriptor, - FieldCache fieldCache, - GtfsTestEntity.Builder builder) { - builder.setId( - addToCacheIfPresent(rowParser.asId(columnIndex, columnDescriptor), fieldCache)); - } - }); - builder.put( - GtfsTestEntity.CODE_FIELD_NAME, - new GtfsFieldLoader() { - @Override - public void load( - RowParser rowParser, - int columnIndex, - GtfsColumnDescriptor columnDescriptor, - FieldCache fieldCache, - GtfsTestEntity.Builder builder) { - builder.setCode( - addToCacheIfPresent(rowParser.asText(columnIndex, columnDescriptor), fieldCache)); - } - }); - return builder.build(); - } - - @Override - public String gtfsFilename() { - return GtfsTestEntity.FILENAME; - } - - @Override - public boolean isRecommended() { - return false; - } - - @Override - public boolean isRequired() { - return true; - } - - @Override - public Optional maxCharsPerColumn() { - return Optional.empty(); - } -} diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableDescriptor2.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableDescriptor2.java deleted file mode 100644 index c8442428a5..0000000000 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestTableDescriptor2.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.mobilitydata.gtfsvalidator.testgtfs; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.util.List; -import java.util.Optional; -import org.mobilitydata.gtfsvalidator.annotation.FieldLevelEnum; -import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; -import org.mobilitydata.gtfsvalidator.parsing.CsvHeader; -import org.mobilitydata.gtfsvalidator.parsing.FieldCache; -import org.mobilitydata.gtfsvalidator.parsing.RowParser; -import org.mobilitydata.gtfsvalidator.table.*; - -// We need a second test table descriptor to test multi file contaioners -public class GtfsTestTableDescriptor2 extends GtfsTableDescriptor { - @Override - public GtfsTableContainer createContainerForInvalidStatus( - GtfsTableContainer.TableStatus tableStatus) { - return new GtfsTestTableContainer2(tableStatus); - } - - @Override - public GtfsTableContainer createContainerForHeaderAndEntities( - CsvHeader header, List entities, NoticeContainer noticeContainer) { - return GtfsTestTableContainer2.forHeaderAndEntities(this, header, entities, noticeContainer); - } - - @Override - public GtfsEntityBuilder createEntityBuilder() { - return new GtfsTestEntity.Builder(); - } - - @Override - public Class getEntityClass() { - return GtfsTestEntity.class; - } - - @Override - public ImmutableList getColumns() { - ImmutableList.Builder builder = ImmutableList.builder(); - builder.add( - GtfsColumnDescriptor.builder() - .setColumnName(GtfsTestEntity.ID_FIELD_NAME) - .setHeaderRequired(true) - .setHeaderRecommended(false) - .setFieldLevel(FieldLevelEnum.REQUIRED) - .setIsMixedCase(false) - .setIsCached(false) - .build()); - builder.add( - GtfsColumnDescriptor.builder() - .setColumnName(GtfsTestEntity.CODE_FIELD_NAME) - .setHeaderRequired(false) - .setHeaderRecommended(false) - .setFieldLevel(FieldLevelEnum.OPTIONAL) - .setIsMixedCase(false) - .setIsCached(false) - .build()); - return builder.build(); - } - - @Override - public ImmutableMap getFieldLoaders() { - ImmutableMap.Builder builder = ImmutableMap.builder(); - builder.put( - GtfsTestEntity.ID_FIELD_NAME, - new GtfsFieldLoader() { - @Override - public void load( - RowParser rowParser, - int columnIndex, - GtfsColumnDescriptor columnDescriptor, - FieldCache fieldCache, - GtfsTestEntity.Builder builder) { - builder.setId( - addToCacheIfPresent(rowParser.asId(columnIndex, columnDescriptor), fieldCache)); - } - }); - builder.put( - GtfsTestEntity.CODE_FIELD_NAME, - new GtfsFieldLoader() { - @Override - public void load( - RowParser rowParser, - int columnIndex, - GtfsColumnDescriptor columnDescriptor, - FieldCache fieldCache, - GtfsTestEntity.Builder builder) { - builder.setCode( - addToCacheIfPresent(rowParser.asText(columnIndex, columnDescriptor), fieldCache)); - } - }); - return builder.build(); - } - - @Override - public String gtfsFilename() { - return GtfsTestEntity.FILENAME + "2"; - } - - @Override - public boolean isRecommended() { - return false; - } - - @Override - public boolean isRequired() { - return true; - } - - @Override - public Optional maxCharsPerColumn() { - return Optional.empty(); - } -} diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/validator/DefaultValidatorProviderTest.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/validator/DefaultValidatorProviderTest.java index 90d10fa10f..383daae497 100644 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/validator/DefaultValidatorProviderTest.java +++ b/core/src/test/java/org/mobilitydata/gtfsvalidator/validator/DefaultValidatorProviderTest.java @@ -13,11 +13,11 @@ import org.mobilitydata.gtfsvalidator.table.GtfsFeedContainer; import org.mobilitydata.gtfsvalidator.table.GtfsTableContainer.TableStatus; import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntity; +import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntity2TableContainer; +import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntityTableContainer; import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntityValidator; import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestMultiFileValidator; import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestSingleFileValidator; -import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestTableContainer; -import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestTableContainer2; import org.mobilitydata.gtfsvalidator.testgtfs.WholeFeedValidator; @RunWith(JUnit4.class) @@ -34,8 +34,8 @@ public void testCreateValidators() throws ValidatorLoaderException { GtfsTestSingleFileValidator.class, WholeFeedValidator.class))); - GtfsTestTableContainer tableContainer = - new GtfsTestTableContainer(TableStatus.PARSABLE_HEADERS_AND_ROWS); + GtfsTestEntityTableContainer tableContainer = + GtfsTestEntityTableContainer.forStatus(TableStatus.PARSABLE_HEADERS_AND_ROWS); GtfsFeedContainer feedContainer = new GtfsFeedContainer(ImmutableList.of(tableContainer)); List> singleEntityValidatorsWithParsingErrors = new ArrayList<>(); @@ -78,9 +78,10 @@ public void testCreateValidators_skippedValidators() throws ValidatorLoaderExcep // Create 2 tables, one with errors and the other not. // This will let us test the multi-file validator. - GtfsTestTableContainer tableContainer = new GtfsTestTableContainer(TableStatus.UNPARSABLE_ROWS); - GtfsTestTableContainer2 tableContainer2 = - new GtfsTestTableContainer2(TableStatus.PARSABLE_HEADERS_AND_ROWS); + GtfsTestEntityTableContainer tableContainer = + GtfsTestEntityTableContainer.forStatus(TableStatus.UNPARSABLE_ROWS); + GtfsTestEntity2TableContainer tableContainer2 = + GtfsTestEntity2TableContainer.forStatus(TableStatus.PARSABLE_HEADERS_AND_ROWS); GtfsFeedContainer feedContainer = new GtfsFeedContainer(ImmutableList.of(tableContainer, tableContainer2)); diff --git a/core/src/test/java/org/mobilitydata/gtfsvalidator/validator/ValidatorLoaderTest.java b/core/src/test/java/org/mobilitydata/gtfsvalidator/validator/ValidatorLoaderTest.java index c169d29ac3..bc79b5409f 100644 --- a/core/src/test/java/org/mobilitydata/gtfsvalidator/validator/ValidatorLoaderTest.java +++ b/core/src/test/java/org/mobilitydata/gtfsvalidator/validator/ValidatorLoaderTest.java @@ -25,9 +25,9 @@ import org.mobilitydata.gtfsvalidator.input.DateForValidation; import org.mobilitydata.gtfsvalidator.table.GtfsFeedContainer; import org.mobilitydata.gtfsvalidator.table.GtfsTableContainer.TableStatus; +import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntityTableContainer; import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestEntityValidator; import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestSingleFileValidator; -import org.mobilitydata.gtfsvalidator.testgtfs.GtfsTestTableContainer; import org.mobilitydata.gtfsvalidator.testgtfs.WholeFeedValidator; import org.mobilitydata.gtfsvalidator.validator.ValidatorLoader.ValidatorWithDependencyStatus; @@ -56,7 +56,8 @@ public void createValidatorWithContext_injectsContext() @Test public void createSingleFileValidator_injectsTableContainerAndContext() throws ReflectiveOperationException, ValidatorLoaderException { - GtfsTestTableContainer table = new GtfsTestTableContainer(TableStatus.EMPTY_FILE); + GtfsTestEntityTableContainer table = + GtfsTestEntityTableContainer.forStatus(TableStatus.EMPTY_FILE); GtfsTestSingleFileValidator validator = (GtfsTestSingleFileValidator) ValidatorLoader.createSingleFileValidator( @@ -71,8 +72,8 @@ public void createSingleFileValidator_injectsTableContainerAndContext() @Test public void createMultiFileValidator_injectsFeedContainerAndContext() throws ReflectiveOperationException, ValidatorLoaderException { - GtfsTestTableContainer stopTable = - new GtfsTestTableContainer(TableStatus.PARSABLE_HEADERS_AND_ROWS); + GtfsTestEntityTableContainer stopTable = + GtfsTestEntityTableContainer.forStatus(TableStatus.PARSABLE_HEADERS_AND_ROWS); GtfsFeedContainer feedContainer = new GtfsFeedContainer(ImmutableList.of(stopTable)); ValidatorWithDependencyStatus validatorWithStatus = @@ -89,7 +90,8 @@ public void createMultiFileValidator_injectsFeedContainerAndContext() @Test public void createMultiFileValidator_singleContainer_dependenciesHaveErrors() throws ReflectiveOperationException, ValidatorLoaderException { - GtfsTestTableContainer table = new GtfsTestTableContainer(TableStatus.UNPARSABLE_ROWS); + GtfsTestEntityTableContainer table = + GtfsTestEntityTableContainer.forStatus(TableStatus.UNPARSABLE_ROWS); GtfsFeedContainer feedContainer = new GtfsFeedContainer(ImmutableList.of(table)); ValidatorWithDependencyStatus validatorWithStatus = diff --git a/core/testing/build.gradle b/core/testing/build.gradle new file mode 100644 index 0000000000..964dd958f7 --- /dev/null +++ b/core/testing/build.gradle @@ -0,0 +1,13 @@ +plugins { + id 'java' +} + +dependencies { + implementation project(':model') + implementation project(':core') + annotationProcessor project(':processor') + implementation 'com.google.guava:guava:31.0.1-jre' + implementation 'com.google.code.findbugs:jsr305:3.0.2' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' +} diff --git a/core/testing/src/main/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestEntity2Schema.java b/core/testing/src/main/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestEntity2Schema.java new file mode 100644 index 0000000000..7329f6062c --- /dev/null +++ b/core/testing/src/main/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestEntity2Schema.java @@ -0,0 +1,19 @@ +package org.mobilitydata.gtfsvalidator.testgtfs; + +import org.mobilitydata.gtfsvalidator.annotation.FieldType; +import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; +import org.mobilitydata.gtfsvalidator.annotation.GtfsTable; +import org.mobilitydata.gtfsvalidator.annotation.PrimaryKey; +import org.mobilitydata.gtfsvalidator.annotation.Required; +import org.mobilitydata.gtfsvalidator.table.GtfsEntity; + +@GtfsTable("test_entities_two.txt") +public interface GtfsTestEntity2Schema extends GtfsEntity { + @FieldType(FieldTypeEnum.ID) + @PrimaryKey + @Required + String id(); + + @Required + String code(); +} diff --git a/core/testing/src/main/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestEntitySchema.java b/core/testing/src/main/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestEntitySchema.java new file mode 100644 index 0000000000..08ed85b514 --- /dev/null +++ b/core/testing/src/main/java/org/mobilitydata/gtfsvalidator/testgtfs/GtfsTestEntitySchema.java @@ -0,0 +1,18 @@ +package org.mobilitydata.gtfsvalidator.testgtfs; + +import org.mobilitydata.gtfsvalidator.annotation.FieldType; +import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; +import org.mobilitydata.gtfsvalidator.annotation.GtfsTable; +import org.mobilitydata.gtfsvalidator.annotation.PrimaryKey; +import org.mobilitydata.gtfsvalidator.annotation.Required; +import org.mobilitydata.gtfsvalidator.table.GtfsEntity; + +@GtfsTable("filename.txt") +public interface GtfsTestEntitySchema extends GtfsEntity { + @FieldType(FieldTypeEnum.ID) + @PrimaryKey + @Required + String id(); + + String code(); +} diff --git a/extensions/build.gradle b/extensions/build.gradle new file mode 100644 index 0000000000..96d7b85156 --- /dev/null +++ b/extensions/build.gradle @@ -0,0 +1,22 @@ +plugins { + id 'java' +} + +dependencies { + annotationProcessor project(':processor:notices') + annotationProcessor project(':processor') + annotationProcessor 'com.google.auto.value:auto-value:1.7.4' + implementation project(':model') + implementation project(':core') + implementation project(':main') + compileOnly 'com.google.auto.value:auto-value-annotations:1.7.4' + implementation 'javax.inject:javax.inject:1' + implementation 'com.google.guava:guava:31.0.1-jre' + implementation 'com.google.code.findbugs:jsr305:3.0.2' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingAgencySchema.java b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingAgencySchema.java new file mode 100644 index 0000000000..7113db4ea7 --- /dev/null +++ b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingAgencySchema.java @@ -0,0 +1,13 @@ +package org.mobilitydata.gtfsvalidator.extensions.google.ticketing; + +import org.mobilitydata.gtfsvalidator.annotation.FieldType; +import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; +import org.mobilitydata.gtfsvalidator.annotation.ForeignKey; +import org.mobilitydata.gtfsvalidator.annotation.GtfsTable; + +@GtfsTable("agency.txt") +public interface GoogleTicketingAgencySchema { + @FieldType(FieldTypeEnum.ID) + @ForeignKey(table = "ticketing_deep_links.txt", field = "ticketing_deep_link_id") + String ticketingDeepLinkId(); +} diff --git a/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingDeepLinksSchema.java b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingDeepLinksSchema.java new file mode 100644 index 0000000000..17dba04a90 --- /dev/null +++ b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingDeepLinksSchema.java @@ -0,0 +1,18 @@ +package org.mobilitydata.gtfsvalidator.extensions.google.ticketing; + +import org.mobilitydata.gtfsvalidator.annotation.FieldType; +import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; +import org.mobilitydata.gtfsvalidator.annotation.GtfsTable; +import org.mobilitydata.gtfsvalidator.annotation.PrimaryKey; +import org.mobilitydata.gtfsvalidator.annotation.Required; + +@GtfsTable("ticketing_deep_links.txt") +public interface GoogleTicketingDeepLinksSchema { + @FieldType(FieldTypeEnum.ID) + @Required + @PrimaryKey + String ticketingDeepLinkId(); + + @FieldType(FieldTypeEnum.URL) + String webUrl(); +} diff --git a/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingRouteSchema.java b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingRouteSchema.java new file mode 100644 index 0000000000..034e899873 --- /dev/null +++ b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingRouteSchema.java @@ -0,0 +1,13 @@ +package org.mobilitydata.gtfsvalidator.extensions.google.ticketing; + +import org.mobilitydata.gtfsvalidator.annotation.FieldType; +import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; +import org.mobilitydata.gtfsvalidator.annotation.ForeignKey; +import org.mobilitydata.gtfsvalidator.annotation.GtfsTable; + +@GtfsTable("routes.txt") +public interface GoogleTicketingRouteSchema { + @FieldType(FieldTypeEnum.ID) + @ForeignKey(table = "ticketing_deep_links.txt", field = "ticketing_deep_link_id") + String ticketingDeepLinkId(); +} diff --git a/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingStopTimeSchema.java b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingStopTimeSchema.java new file mode 100644 index 0000000000..b612921122 --- /dev/null +++ b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingStopTimeSchema.java @@ -0,0 +1,8 @@ +package org.mobilitydata.gtfsvalidator.extensions.google.ticketing; + +import org.mobilitydata.gtfsvalidator.annotation.GtfsTable; + +@GtfsTable("stop_times.txt") +public interface GoogleTicketingStopTimeSchema { + GoogleTicketingType ticketingType(); +} diff --git a/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingStopTimeValidator.java b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingStopTimeValidator.java new file mode 100644 index 0000000000..46666213f7 --- /dev/null +++ b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingStopTimeValidator.java @@ -0,0 +1,43 @@ +package org.mobilitydata.gtfsvalidator.extensions.google.ticketing; + +import java.util.Collection; +import org.mobilitydata.gtfsvalidator.annotation.GtfsValidationNotice; +import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; +import org.mobilitydata.gtfsvalidator.notice.SeverityLevel; +import org.mobilitydata.gtfsvalidator.notice.ValidationNotice; +import org.mobilitydata.gtfsvalidator.table.GtfsStopTime; +import org.mobilitydata.gtfsvalidator.table.GtfsStopTimeTableContainer; +import org.mobilitydata.gtfsvalidator.validator.FileValidator; + +public class GoogleTicketingStopTimeValidator extends FileValidator { + + private final GtfsStopTimeTableContainer container; + + public GoogleTicketingStopTimeValidator(GtfsStopTimeTableContainer container) { + this.container = container; + } + + @Override + public void validate(NoticeContainer noticeContainer) { + for (Collection stopTimes : container.byStopIdMap().asMap().values()) {} + } + + private static boolean ticketingIsUnavailable(GtfsStopTime stopTime) { + /* + if (!stopTime.hasExtension(GoogleTicketingStopTime.class)) { + return false; + } + GoogleTicketingStopTime ticketingStopTime = + stopTime.getExtension(GoogleTicketingStopTime.class); + return ticketingStopTime.hasTicketingType() + && ticketingStopTime.ticketingType() == GoogleTicketingType.UNAVAILABLE; + */ + return false; + } + + @GtfsValidationNotice(severity = SeverityLevel.ERROR) + private static final class GoogleTicketingStopTimesWithInconsistentTicketingTypeNotice + extends ValidationNotice { + GoogleTicketingStopTimesWithInconsistentTicketingTypeNotice() {} + } +} diff --git a/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingTripSchema.java b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingTripSchema.java new file mode 100644 index 0000000000..4d5ea653cf --- /dev/null +++ b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingTripSchema.java @@ -0,0 +1,10 @@ +package org.mobilitydata.gtfsvalidator.extensions.google.ticketing; + +import org.mobilitydata.gtfsvalidator.annotation.GtfsTable; + +@GtfsTable("trips.txt") +public interface GoogleTicketingTripSchema { + String ticketingTripId(); + + GoogleTicketingType ticketingType(); +} diff --git a/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingTypeEnum.java b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingTypeEnum.java new file mode 100644 index 0000000000..cb38330233 --- /dev/null +++ b/extensions/src/main/java/org/mobilitydata/gtfsvalidator/extensions/google/ticketing/GoogleTicketingTypeEnum.java @@ -0,0 +1,7 @@ +package org.mobilitydata.gtfsvalidator.extensions.google.ticketing; + +import org.mobilitydata.gtfsvalidator.annotation.GtfsEnumValue; + +@GtfsEnumValue(name = "DEFAULT", value = 0) +@GtfsEnumValue(name = "UNAVAILABLE", value = 1) +public interface GoogleTicketingTypeEnum {} diff --git a/main/src/main/java/org/mobilitydata/gtfsvalidator/runner/ValidationRunner.java b/main/src/main/java/org/mobilitydata/gtfsvalidator/runner/ValidationRunner.java index bd2fdbbb20..87a0880932 100644 --- a/main/src/main/java/org/mobilitydata/gtfsvalidator/runner/ValidationRunner.java +++ b/main/src/main/java/org/mobilitydata/gtfsvalidator/runner/ValidationRunner.java @@ -80,6 +80,11 @@ public Status run(ValidationRunnerConfig config) { logger.atInfo().log("A new version of the validator is available!"); } + if (config.useColumnBasedStorage()) { + logger.atInfo().log("Column-based storage enabled"); + AnyTableLoader.setUseColumnBasedStorage(config.useColumnBasedStorage()); + } + ValidatorLoader validatorLoader; try { validatorLoader = diff --git a/main/src/main/java/org/mobilitydata/gtfsvalidator/runner/ValidationRunnerConfig.java b/main/src/main/java/org/mobilitydata/gtfsvalidator/runner/ValidationRunnerConfig.java index 804d6ab165..3086c640c4 100644 --- a/main/src/main/java/org/mobilitydata/gtfsvalidator/runner/ValidationRunnerConfig.java +++ b/main/src/main/java/org/mobilitydata/gtfsvalidator/runner/ValidationRunnerConfig.java @@ -66,6 +66,8 @@ public Path systemErrorsReportPath() { // If true, the validator will not check for a new validator version public abstract boolean skipValidatorUpdate(); + public abstract boolean useColumnBasedStorage(); + public static Builder builder() { // Set reasonable defaults where appropriate. return new AutoValue_ValidationRunnerConfig.Builder() @@ -76,7 +78,8 @@ public static Builder builder() { .setPrettyJson(false) .setCountryCode(CountryCode.forStringOrUnknown(CountryCode.ZZ)) .setDateForValidation(LocalDate.now()) - .setSkipValidatorUpdate(false); + .setSkipValidatorUpdate(false) + .setUseColumnBasedStorage(false); } @AutoValue.Builder @@ -103,6 +106,8 @@ public abstract static class Builder { public abstract Builder setSkipValidatorUpdate(boolean skipValidatorUpdate); + public abstract Builder setUseColumnBasedStorage(boolean useColumnBasedStorage); + public abstract ValidationRunnerConfig build(); } } diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/report/model/FeedMetadataTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/report/model/FeedMetadataTest.java index cdebe4c4f6..2ba3a4855b 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/report/model/FeedMetadataTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/report/model/FeedMetadataTest.java @@ -62,7 +62,7 @@ private void validateSpecFeature( feedLoaderMock.loadAndValidate( gtfsInput, new DefaultValidatorProvider(validationContext, validatorLoader), - new NoticeContainer()); + noticeContainer); FeedMetadata feedMetadata = FeedMetadata.from(feedContainer, gtfsInput.getFilenames()); assertThat(feedMetadata.specFeatures.get(specFeature)).isEqualTo(expectedValue); } diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/util/CalendarUtilTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/util/CalendarUtilTest.java index fb1d2a923b..b0a5f5d739 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/util/CalendarUtilTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/util/CalendarUtilTest.java @@ -19,6 +19,7 @@ import org.mobilitydata.gtfsvalidator.table.GtfsCalendarDate; import org.mobilitydata.gtfsvalidator.table.GtfsCalendarDateExceptionType; import org.mobilitydata.gtfsvalidator.table.GtfsCalendarDateTableContainer; +import org.mobilitydata.gtfsvalidator.table.GtfsCalendarImpl; import org.mobilitydata.gtfsvalidator.table.GtfsCalendarTableContainer; import org.mobilitydata.gtfsvalidator.type.GtfsDate; @@ -26,8 +27,8 @@ public class CalendarUtilTest { public static GtfsCalendar createGtfsCalendar( String serviceId, LocalDate startDate, LocalDate endDate, Set days) { - GtfsCalendar.Builder calendar = - new GtfsCalendar.Builder() + GtfsCalendarImpl.Builder calendar = + GtfsCalendar.builder() .setServiceId(serviceId) .setStartDate(GtfsDate.fromLocalDate(startDate)) .setEndDate(GtfsDate.fromLocalDate(endDate)); @@ -56,7 +57,7 @@ public static GtfsCalendar createGtfsCalendar( } private static GtfsCalendarDate addedCalendarDate(String serviceId, LocalDate date) { - return new GtfsCalendarDate.Builder() + return GtfsCalendarDate.builder() .setServiceId(serviceId) .setDate(GtfsDate.fromLocalDate(date)) .setExceptionType(GtfsCalendarDateExceptionType.SERVICE_ADDED) @@ -64,7 +65,7 @@ private static GtfsCalendarDate addedCalendarDate(String serviceId, LocalDate da } private static GtfsCalendarDate removedCalendarDate(String serviceId, LocalDate date) { - return new GtfsCalendarDate.Builder() + return GtfsCalendarDate.builder() .setServiceId(serviceId) .setDate(GtfsDate.fromLocalDate(date)) .setExceptionType(GtfsCalendarDateExceptionType.SERVICE_REMOVED) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/util/StopUtilTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/util/StopUtilTest.java index 85566f1632..e417afc0b5 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/util/StopUtilTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/util/StopUtilTest.java @@ -46,7 +46,7 @@ private static String numberToStopId(int number) { private static GtfsStop createStop( int id, @Nullable Double stopLat, @Nullable Double stopLon, @Nullable String parentStation) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(id) .setStopId(numberToStopId(id)) .setStopLat(stopLat) @@ -107,7 +107,7 @@ public void getStopOrParentLatLng_noLatLng() { private static GtfsStop createStop( int id, GtfsLocationType locationType, @Nullable String parentStation) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(id) .setStopId(numberToStopId(id)) .setLocationType(locationType) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/util/TripCalendarUtilTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/util/TripCalendarUtilTest.java index d01796ba55..d4e21ef315 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/util/TripCalendarUtilTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/util/TripCalendarUtilTest.java @@ -67,7 +67,7 @@ public void computeServiceCoverage_notEmpty() { LocalDate.of(2021, 2, 28))), GtfsTripTableContainer.forEntities( ImmutableList.of( - new GtfsTrip.Builder() + GtfsTrip.builder() .setCsvRowNumber(2) .setTripId("trip1") .setServiceId("WEEK") @@ -149,12 +149,12 @@ public void countTripsForEachServiceDate_frequencyBased() { ImmutableSortedSet.of(LocalDate.of(2021, 2, 28))), GtfsTripTableContainer.forEntities( ImmutableList.of( - new GtfsTrip.Builder() + GtfsTrip.builder() .setCsvRowNumber(2) .setTripId("trip1") .setServiceId("service1") .build(), - new GtfsTrip.Builder() + GtfsTrip.builder() .setCsvRowNumber(2) .setTripId("trip2") .setServiceId("service2") @@ -162,7 +162,7 @@ public void countTripsForEachServiceDate_frequencyBased() { noticeContainer), GtfsFrequencyTableContainer.forEntities( ImmutableList.of( - new GtfsFrequency.Builder() + GtfsFrequency.builder() .setCsvRowNumber(2) .setTripId("trip2") .setStartTime(GtfsTime.fromString("12:00:00")) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/util/shape/ShapePointsTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/util/shape/ShapePointsTest.java index 44ce46145d..ba970b35b6 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/util/shape/ShapePointsTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/util/shape/ShapePointsTest.java @@ -42,7 +42,7 @@ public class ShapePointsTest { private static GtfsShape createGtfsShape( double latDegrees, double lngDegrees, Double shapeDistTraveled) { - return new GtfsShape.Builder() + return GtfsShape.builder() .setShapePtLat(latDegrees) .setShapePtLon(lngDegrees) .setShapeDistTraveled(shapeDistTraveled) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/util/shape/StopPointsTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/util/shape/StopPointsTest.java index 8420a99277..fdab7b13a5 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/util/shape/StopPointsTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/util/shape/StopPointsTest.java @@ -42,7 +42,7 @@ public class StopPointsTest { private static GtfsStop createStop( String stopId, String stopName, double stopLat, double stopLon) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(stopId.hashCode()) .setStopId(stopId) .setStopName(stopName) @@ -60,9 +60,9 @@ private static ImmutableList createStops() { private static ImmutableList createStopTimes() { return ImmutableList.of( - new GtfsStopTime.Builder().setStopId("zuerichHB").build(), - new GtfsStopTime.Builder().setStopId("selnau").setShapeDistTraveled(10.0).build(), - new GtfsStopTime.Builder().setStopId("giesshuebel").setShapeDistTraveled(20.0).build()); + GtfsStopTime.builder().setStopId("zuerichHB").build(), + GtfsStopTime.builder().setStopId("selnau").setShapeDistTraveled(10.0).build(), + GtfsStopTime.builder().setStopId("giesshuebel").setShapeDistTraveled(20.0).build()); } @Test diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/util/shape/StopToShapeMatcherTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/util/shape/StopToShapeMatcherTest.java index 61db796a42..36c2ed96c4 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/util/shape/StopToShapeMatcherTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/util/shape/StopToShapeMatcherTest.java @@ -48,7 +48,7 @@ public class StopToShapeMatcherTest { private static GtfsShape createGtfsShape( int ptSequence, double latDegrees, double lngDegrees, Double shapeDistTraveled) { - return new GtfsShape.Builder() + return GtfsShape.builder() .setCsvRowNumber(ptSequence + 2) .setShapePtSequence(ptSequence) .setShapePtLat(latDegrees) @@ -77,7 +77,7 @@ private static String numberToStopId(int number) { } private static GtfsStop createStop(int number, double stopLat, double stopLon) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(2 + number) .setStopId(numberToStopId(number)) .setStopName("Stop " + number) @@ -98,7 +98,7 @@ private static List createStopTimes(Double[] shapeDistTraveled) { List stopTimes = new ArrayList<>(shapeDistTraveled.length); for (int i = 0; i < shapeDistTraveled.length; ++i) { stopTimes.add( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(i + 2) .setStopId(numberToStopId(i)) .setStopSequence(i) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/AgencyConsistencyValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/AgencyConsistencyValidatorTest.java index 6b301f36c0..da0dcdeb32 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/AgencyConsistencyValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/AgencyConsistencyValidatorTest.java @@ -49,7 +49,7 @@ public static GtfsAgency createAgency( String agencyUrl, ZoneId agencyTimezone, @Nullable Locale agencyLang) { - return new GtfsAgency.Builder() + return GtfsAgency.builder() .setCsvRowNumber(csvRowNumber) .setAgencyId(agencyId) .setAgencyName(agencyName) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/AttributionWithoutRoleValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/AttributionWithoutRoleValidatorTest.java index 2508e0d92a..6699da1eed 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/AttributionWithoutRoleValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/AttributionWithoutRoleValidatorTest.java @@ -42,10 +42,7 @@ private static List generateNotices(GtfsAttribution attributio public void attributionWithoutRoleShouldGenerateNotice() { assertThat( generateNotices( - new GtfsAttribution.Builder() - .setCsvRowNumber(2) - .setAttributionId("attr-1") - .build())) + GtfsAttribution.builder().setCsvRowNumber(2).setAttributionId("attr-1").build())) .containsExactly(new AttributionWithoutRoleNotice(2, "attr-1")); } @@ -53,7 +50,7 @@ public void attributionWithoutRoleShouldGenerateNotice() { public void attributionWithoutRoleAndNoIdShouldGenerateNotice() { assertThat( generateNotices( - new GtfsAttribution.Builder().setCsvRowNumber(2).setAttributionId("").build())) + GtfsAttribution.builder().setCsvRowNumber(2).setAttributionId("").build())) .containsExactly(new AttributionWithoutRoleNotice(2, "")); } @@ -61,15 +58,15 @@ public void attributionWithoutRoleAndNoIdShouldGenerateNotice() { public void attributionWithRoleShouldNotGenerateNotice() { assertThat( generateNotices( - new GtfsAttribution.Builder().setCsvRowNumber(2).setIsAuthority(ASSIGNED).build())) + GtfsAttribution.builder().setCsvRowNumber(2).setIsAuthority(ASSIGNED).build())) .isEmpty(); assertThat( generateNotices( - new GtfsAttribution.Builder().setCsvRowNumber(2).setIsOperator(ASSIGNED).build())) + GtfsAttribution.builder().setCsvRowNumber(2).setIsOperator(ASSIGNED).build())) .isEmpty(); assertThat( generateNotices( - new GtfsAttribution.Builder().setCsvRowNumber(2).setIsProducer(ASSIGNED).build())) + GtfsAttribution.builder().setCsvRowNumber(2).setIsProducer(ASSIGNED).build())) .isEmpty(); } @@ -77,7 +74,7 @@ public void attributionWithRoleShouldNotGenerateNotice() { public void attributionWithAllRolesShouldNotGenerateNotice() { assertThat( generateNotices( - new GtfsAttribution.Builder() + GtfsAttribution.builder() .setCsvRowNumber(2) .setIsAuthority(ASSIGNED) .setIsOperator(ASSIGNED) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/BikeAllowanceValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/BikeAllowanceValidatorTest.java index 499b756480..1522a23e47 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/BikeAllowanceValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/BikeAllowanceValidatorTest.java @@ -19,7 +19,7 @@ private static List createTripTable( ArrayList trips = new ArrayList<>(); for (int i = 0; i < rows; i++) { trips.add( - new GtfsTrip.Builder() + GtfsTrip.builder() .setCsvRowNumber(i + 1) .setTripId("t" + i) .setServiceId(serviceId) @@ -32,11 +32,7 @@ private static List createTripTable( private static List createRouteTable(String routeId, GtfsRouteType routeType) { return List.of( - new GtfsRoute.Builder() - .setCsvRowNumber(1) - .setRouteId(routeId) - .setRouteType(routeType) - .build()); + GtfsRoute.builder().setCsvRowNumber(1).setRouteId(routeId).setRouteType(routeType).build()); } private static List generateNotices( diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/BlockTripsWithOverlappingStopTimesValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/BlockTripsWithOverlappingStopTimesValidatorTest.java index 269c54d242..c0aa4a699f 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/BlockTripsWithOverlappingStopTimesValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/BlockTripsWithOverlappingStopTimesValidatorTest.java @@ -58,7 +58,7 @@ private static List createCalendarTable() { public static GtfsStopTime createStopTime( int csvRowNumber, String tripId, String time, String stopId, int stopSequence) { - return new GtfsStopTime.Builder() + return GtfsStopTime.builder() .setCsvRowNumber(csvRowNumber) .setTripId(tripId) .setArrivalTime(GtfsTime.fromString(time)) @@ -70,7 +70,7 @@ public static GtfsStopTime createStopTime( public static GtfsTrip createTrip( int csvRowNumber, String tripId, String serviceId, String blockId) { - return new GtfsTrip.Builder() + return GtfsTrip.builder() .setCsvRowNumber(csvRowNumber) .setTripId(tripId) .setServiceId(serviceId) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/DateTripsValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/DateTripsValidatorTest.java index 1a8e367351..6368d79907 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/DateTripsValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/DateTripsValidatorTest.java @@ -107,7 +107,7 @@ private static ArrayList createTripBlock( ArrayList trips = new ArrayList<>(); for (int i = 0; i < tripsPerDay; i++) { trips.add( - new GtfsTrip.Builder() + GtfsTrip.builder() .setCsvRowNumber(i + 1) .setTripId("t" + i) .setServiceId(serviceId) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/DuplicateFareMediaValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/DuplicateFareMediaValidatorTest.java index 261b10a8be..049e8aa0a1 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/DuplicateFareMediaValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/DuplicateFareMediaValidatorTest.java @@ -28,13 +28,13 @@ private static List generateNotices(List media) public void testUniqueEntries() { ImmutableList media = ImmutableList.of( - new GtfsFareMedia.Builder() + GtfsFareMedia.builder() .setCsvRowNumber(1) .setFareMediaId("a") .setFareMediaName("Transit Card") .setFareMediaType(GtfsFareMediaType.TRANSIT_CARD) .build(), - new GtfsFareMedia.Builder() + GtfsFareMedia.builder() .setCsvRowNumber(2) .setFareMediaId("b") .setFareMediaName("Transit App") @@ -48,13 +48,13 @@ public void testUniqueEntries() { public void testDuplicateEntriesTransitCard() { ImmutableList media = ImmutableList.of( - new GtfsFareMedia.Builder() + GtfsFareMedia.builder() .setCsvRowNumber(1) .setFareMediaId("a") .setFareMediaName("Transit Card") .setFareMediaType(GtfsFareMediaType.TRANSIT_CARD) .build(), - new GtfsFareMedia.Builder() + GtfsFareMedia.builder() .setCsvRowNumber(2) .setFareMediaId("b") .setFareMediaName("Transit Card") @@ -69,13 +69,13 @@ public void testDuplicateEntriesTransitCard() { public void testTransitCardsWithDifferentNames() { ImmutableList media = ImmutableList.of( - new GtfsFareMedia.Builder() + GtfsFareMedia.builder() .setCsvRowNumber(1) .setFareMediaId("a") .setFareMediaName("Transit Card A") .setFareMediaType(GtfsFareMediaType.TRANSIT_CARD) .build(), - new GtfsFareMedia.Builder() + GtfsFareMedia.builder() .setCsvRowNumber(2) .setFareMediaId("b") .setFareMediaName("Transit Card B") diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/DuplicateRouteNameValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/DuplicateRouteNameValidatorTest.java index 441b36321c..5d54bb7bb1 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/DuplicateRouteNameValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/DuplicateRouteNameValidatorTest.java @@ -24,7 +24,7 @@ private static GtfsRoute createRoute( @Nullable String shortName, @Nullable String longName, GtfsRouteType routeType) { - return new GtfsRoute.Builder() + return GtfsRoute.builder() .setCsvRowNumber(csvRowNumber) .setRouteId(routeId) .setAgencyId(agencyId) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ExpiredCalendarValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ExpiredCalendarValidatorTest.java index eac18ce095..1209f9ea69 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ExpiredCalendarValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ExpiredCalendarValidatorTest.java @@ -51,7 +51,7 @@ public void calendarEndDateOneDayAgoShouldGenerateNotice() { List calendars = ImmutableList.of( - new GtfsCalendar.Builder() + GtfsCalendar.builder() .setCsvRowNumber(2) .setServiceId("WEEK") .setStartDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(7))) @@ -78,7 +78,7 @@ public void calendarEndDateTodayShouldNotGenerateNotice() { List calendars = ImmutableList.of( - new GtfsCalendar.Builder() + GtfsCalendar.builder() .setCsvRowNumber(2) .setServiceId("WEEK") .setStartDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(7))) @@ -104,7 +104,7 @@ public void calendarEndDateOneDayFromNowShouldNotGenerateNotice() { List calendars = ImmutableList.of( - new GtfsCalendar.Builder() + GtfsCalendar.builder() .setCsvRowNumber(2) .setServiceId("WEEK") .setStartDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(7))) @@ -130,7 +130,7 @@ public void calendarEndDateOneDayAgoButExtendedByAddedCalendarDateTableShouldNot List calendars = ImmutableList.of( - new GtfsCalendar.Builder() + GtfsCalendar.builder() .setCsvRowNumber(2) .setServiceId("WEEK") .setStartDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(7))) @@ -147,7 +147,7 @@ public void calendarEndDateOneDayAgoButExtendedByAddedCalendarDateTableShouldNot var dateTable = GtfsCalendarDateTableContainer.forEntities( ImmutableList.of( - new GtfsCalendarDate.Builder() + GtfsCalendarDate.builder() .setCsvRowNumber(2) .setServiceId("WEEK") .setDate(GtfsDate.fromLocalDate(TEST_NOW)) @@ -165,7 +165,7 @@ public void calendarEndDateTodayButShortenedByRemovedCalendarDateShouldGenerateN List calendars = ImmutableList.of( - new GtfsCalendar.Builder() + GtfsCalendar.builder() .setCsvRowNumber(2) .setServiceId("WEEK") .setStartDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(7))) @@ -182,7 +182,7 @@ public void calendarEndDateTodayButShortenedByRemovedCalendarDateShouldGenerateN var dateTable = GtfsCalendarDateTableContainer.forEntities( ImmutableList.of( - new GtfsCalendarDate.Builder() + GtfsCalendarDate.builder() .setCsvRowNumber(2) .setServiceId("WEEK") .setDate(GtfsDate.fromLocalDate(TEST_NOW)) @@ -201,7 +201,7 @@ public void calendarWithNoDaysShouldNotGenerateNotice() { List calendars = ImmutableList.of( - new GtfsCalendar.Builder() + GtfsCalendar.builder() .setCsvRowNumber(2) .setServiceId("WEEK") .setStartDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(7))) @@ -222,7 +222,7 @@ public void calendarDateWithForeignKeyViolationShouldNotGenerateNotice() { List calendars = ImmutableList.of( - new GtfsCalendar.Builder() + GtfsCalendar.builder() .setCsvRowNumber(2) .setServiceId("SERVICE_ID") .setStartDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(7))) @@ -234,19 +234,19 @@ public void calendarDateWithForeignKeyViolationShouldNotGenerateNotice() { var calendarDateTable = GtfsCalendarDateTableContainer.forEntities( ImmutableList.of( - new GtfsCalendarDate.Builder() + GtfsCalendarDate.builder() .setCsvRowNumber(3) .setServiceId("NOT_SERVICE_ID") .setDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(2))) .setExceptionType(GtfsCalendarDateExceptionType.SERVICE_REMOVED) .build(), - new GtfsCalendarDate.Builder() + GtfsCalendarDate.builder() .setCsvRowNumber(2) .setServiceId("NOT_SERVICE_ID") .setDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(3))) .setExceptionType(GtfsCalendarDateExceptionType.SERVICE_ADDED) .build(), - new GtfsCalendarDate.Builder() + GtfsCalendarDate.builder() .setCsvRowNumber(4) .setServiceId("NOT_SERVICE_ID") .setDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(1))) @@ -269,19 +269,19 @@ public void calendarDateWithAtLeastCalendarDateNotExpiredShouldNotGenerateNotice var calendarDateTable = GtfsCalendarDateTableContainer.forEntities( ImmutableList.of( - new GtfsCalendarDate.Builder() + GtfsCalendarDate.builder() .setCsvRowNumber(3) .setServiceId("SERVICE_ID_1") .setDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(2))) .setExceptionType(GtfsCalendarDateExceptionType.SERVICE_ADDED) .build(), - new GtfsCalendarDate.Builder() + GtfsCalendarDate.builder() .setCsvRowNumber(2) .setServiceId("SERVICE_ID_2") .setDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(3))) .setExceptionType(GtfsCalendarDateExceptionType.SERVICE_ADDED) .build(), - new GtfsCalendarDate.Builder() + GtfsCalendarDate.builder() .setCsvRowNumber(4) .setServiceId("SERVICE_ID_3") .setDate(GtfsDate.fromLocalDate(TEST_NOW.plusDays(1))) @@ -304,19 +304,19 @@ public void calendarDateWithAllCalendarDatesExpiredShouldGenerateNotice() { var calendarDateTable = GtfsCalendarDateTableContainer.forEntities( ImmutableList.of( - new GtfsCalendarDate.Builder() + GtfsCalendarDate.builder() .setCsvRowNumber(3) .setServiceId("SERVICE_ID_3") .setDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(2))) .setExceptionType(GtfsCalendarDateExceptionType.SERVICE_ADDED) .build(), - new GtfsCalendarDate.Builder() + GtfsCalendarDate.builder() .setCsvRowNumber(2) .setServiceId("SERVICE_ID_2") .setDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(3))) .setExceptionType(GtfsCalendarDateExceptionType.SERVICE_ADDED) .build(), - new GtfsCalendarDate.Builder() + GtfsCalendarDate.builder() .setCsvRowNumber(1) .setServiceId("SERVICE_ID_1") .setDate(GtfsDate.fromLocalDate(TEST_NOW.minusDays(1))) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareAttributeAgencyIdValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareAttributeAgencyIdValidatorTest.java index e80aa8fb22..cd9535a757 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareAttributeAgencyIdValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareAttributeAgencyIdValidatorTest.java @@ -21,12 +21,12 @@ public void agencyIdRequiredErrorWhenMoreThanOneAgency() { GtfsAgencyTableContainer agencyTable = GtfsAgencyTableContainer.forEntities( ImmutableList.of( - new GtfsAgency.Builder() + GtfsAgency.builder() .setCsvRowNumber(0) .setAgencyId("agency1") .setAgencyName("Agency 1") .build(), - new GtfsAgency.Builder() + GtfsAgency.builder() .setCsvRowNumber(1) .setAgencyId("agency2") .setAgencyName("Agency 2") @@ -36,12 +36,12 @@ public void agencyIdRequiredErrorWhenMoreThanOneAgency() { GtfsFareAttributeTableContainer fareTable = GtfsFareAttributeTableContainer.forEntities( ImmutableList.of( - new GtfsFareAttribute.Builder() + GtfsFareAttribute.builder() .setCsvRowNumber(0) .setAgencyId("agency1") .setFareId("fare 0") .build(), - new GtfsFareAttribute.Builder() + GtfsFareAttribute.builder() .setCsvRowNumber(1) .setAgencyId(null) .setFareId("fare_1") @@ -61,7 +61,7 @@ public void agencyIdRecommendedWarningWhenOnlyOneAgency() { GtfsAgencyTableContainer agencyTable = GtfsAgencyTableContainer.forEntities( ImmutableList.of( - new GtfsAgency.Builder() + GtfsAgency.builder() .setCsvRowNumber(1) .setAgencyId(null) .setAgencyName("Agency with no ID") @@ -71,7 +71,7 @@ public void agencyIdRecommendedWarningWhenOnlyOneAgency() { GtfsFareAttributeTableContainer fareTable = GtfsFareAttributeTableContainer.forEntities( ImmutableList.of( - new GtfsFareAttribute.Builder() + GtfsFareAttribute.builder() .setCsvRowNumber(0) .setAgencyId(null) .setFareId("fare_0") @@ -91,12 +91,12 @@ public void WhenMoreThanOneAgencyAndAgencyIdsSpecified_noNotice() { GtfsAgencyTableContainer agencyTable = GtfsAgencyTableContainer.forEntities( ImmutableList.of( - new GtfsAgency.Builder() + GtfsAgency.builder() .setCsvRowNumber(0) .setAgencyId("agency1") .setAgencyName("Agency 1") .build(), - new GtfsAgency.Builder() + GtfsAgency.builder() .setCsvRowNumber(1) .setAgencyId("Agency 2") .setAgencyName("Agency 2") @@ -106,12 +106,12 @@ public void WhenMoreThanOneAgencyAndAgencyIdsSpecified_noNotice() { GtfsFareAttributeTableContainer fareTable = GtfsFareAttributeTableContainer.forEntities( ImmutableList.of( - new GtfsFareAttribute.Builder() + GtfsFareAttribute.builder() .setCsvRowNumber(0) .setAgencyId("agency1") .setFareId("fare 0") .build(), - new GtfsFareAttribute.Builder() + GtfsFareAttribute.builder() .setCsvRowNumber(1) .setAgencyId("agency2") .setFareId("fare_1") @@ -128,7 +128,7 @@ public void WhenMoreSingleAgencyAndAgencyIdSpecified_noNotice() { GtfsAgencyTableContainer agencyTable = GtfsAgencyTableContainer.forEntities( ImmutableList.of( - new GtfsAgency.Builder() + GtfsAgency.builder() .setCsvRowNumber(0) .setAgencyId("agency1") .setAgencyName("Agency 1") @@ -138,12 +138,12 @@ public void WhenMoreSingleAgencyAndAgencyIdSpecified_noNotice() { GtfsFareAttributeTableContainer fareTable = GtfsFareAttributeTableContainer.forEntities( ImmutableList.of( - new GtfsFareAttribute.Builder() + GtfsFareAttribute.builder() .setCsvRowNumber(0) .setAgencyId("agency1") .setFareId("fare 0") .build(), - new GtfsFareAttribute.Builder() + GtfsFareAttribute.builder() .setCsvRowNumber(1) .setAgencyId("agency1") .setFareId("fare_1") diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareMediaNameValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareMediaNameValidatorTest.java index 3241868947..b17da632de 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareMediaNameValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareMediaNameValidatorTest.java @@ -19,7 +19,7 @@ public class FareMediaNameValidatorTest { public void testTransitCard() { assertThat( validationNoticesFor( - new GtfsFareMedia.Builder() + GtfsFareMedia.builder() .setCsvRowNumber(2) .setFareMediaName("Go! Pass") .setFareMediaType(GtfsFareMediaType.TRANSIT_CARD) @@ -27,7 +27,7 @@ public void testTransitCard() { .isEmpty(); assertThat( validationNoticesFor( - new GtfsFareMedia.Builder() + GtfsFareMedia.builder() .setCsvRowNumber(2) .setFareMediaType(GtfsFareMediaType.TRANSIT_CARD) .build())) @@ -38,7 +38,7 @@ public void testTransitCard() { public void testPaperTicket() { assertThat( validationNoticesFor( - new GtfsFareMedia.Builder() + GtfsFareMedia.builder() .setCsvRowNumber(2) .setFareMediaName("Some Ticket") .setFareMediaType(GtfsFareMediaType.PAPER_TICKET) @@ -46,7 +46,7 @@ public void testPaperTicket() { .isEmpty(); assertThat( validationNoticesFor( - new GtfsFareMedia.Builder() + GtfsFareMedia.builder() .setCsvRowNumber(2) .setFareMediaType(GtfsFareMediaType.PAPER_TICKET) .build())) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareTransferRuleDurationLimitTypeValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareTransferRuleDurationLimitTypeValidatorTest.java index f5534fe0ac..bbaf60b49f 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareTransferRuleDurationLimitTypeValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareTransferRuleDurationLimitTypeValidatorTest.java @@ -27,10 +27,7 @@ private static List generateNotices(GtfsFareTransferRule rule) public void durationWithoutTypeShouldGenerateNotice() { assertThat( generateNotices( - new GtfsFareTransferRule.Builder() - .setCsvRowNumber(2) - .setDurationLimit(120) - .build())) + GtfsFareTransferRule.builder().setCsvRowNumber(2).setDurationLimit(120).build())) .containsExactly(new FareTransferRuleDurationLimitWithoutTypeNotice(2)); } @@ -38,7 +35,7 @@ public void durationWithoutTypeShouldGenerateNotice() { public void durationLimitTypeWithoutDurationLimitShouldGenerateNotice() { assertThat( generateNotices( - new GtfsFareTransferRule.Builder() + GtfsFareTransferRule.builder() .setCsvRowNumber(2) .setDurationLimitType(GtfsDurationLimitType.ARRIVAL_TO_ARRIVAL) .build())) @@ -49,7 +46,7 @@ public void durationLimitTypeWithoutDurationLimitShouldGenerateNotice() { public void durationWithTypeShouldNotGenerateNotice() { assertThat( generateNotices( - new GtfsFareTransferRule.Builder() + GtfsFareTransferRule.builder() .setCsvRowNumber(2) .setDurationLimit(120) .setDurationLimitType(GtfsDurationLimitType.ARRIVAL_TO_ARRIVAL) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareTransferRuleTransferCountValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareTransferRuleTransferCountValidatorTest.java index d2fe560e12..be9097e33c 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareTransferRuleTransferCountValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FareTransferRuleTransferCountValidatorTest.java @@ -23,7 +23,7 @@ private static List generateNotices(GtfsFareTransferRule rule) public void validTransferCount() { assertThat( generateNotices( - new GtfsFareTransferRule.Builder() + GtfsFareTransferRule.builder() .setCsvRowNumber(2) .setFromLegGroupId("a") .setToLegGroupId("a") @@ -33,7 +33,7 @@ public void validTransferCount() { assertThat( generateNotices( - new GtfsFareTransferRule.Builder() + GtfsFareTransferRule.builder() .setCsvRowNumber(2) .setFromLegGroupId("a") .setToLegGroupId("a") @@ -46,7 +46,7 @@ public void validTransferCount() { public void invalidTransferCount() { assertThat( generateNotices( - new GtfsFareTransferRule.Builder() + GtfsFareTransferRule.builder() .setCsvRowNumber(2) .setFromLegGroupId("a") .setToLegGroupId("a") @@ -59,7 +59,7 @@ public void invalidTransferCount() { public void invalidNegativeTransferCount() { assertThat( generateNotices( - new GtfsFareTransferRule.Builder() + GtfsFareTransferRule.builder() .setCsvRowNumber(2) .setFromLegGroupId("a") .setToLegGroupId("a") @@ -72,7 +72,7 @@ public void invalidNegativeTransferCount() { public void missingRequiredTransferCount() { assertThat( generateNotices( - new GtfsFareTransferRule.Builder() + GtfsFareTransferRule.builder() .setCsvRowNumber(2) .setFromLegGroupId("a") .setToLegGroupId("a") @@ -84,7 +84,7 @@ public void missingRequiredTransferCount() { public void validUnspecifiedTransferCount() { assertThat( generateNotices( - new GtfsFareTransferRule.Builder() + GtfsFareTransferRule.builder() .setCsvRowNumber(2) .setFromLegGroupId("a") .setToLegGroupId("b") @@ -96,7 +96,7 @@ public void validUnspecifiedTransferCount() { public void forbiddenTransferCount() { assertThat( generateNotices( - new GtfsFareTransferRule.Builder() + GtfsFareTransferRule.builder() .setCsvRowNumber(2) .setFromLegGroupId("a") .setToLegGroupId("b") diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FeedContactValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FeedContactValidatorTest.java index 14063fa302..76efd18f43 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FeedContactValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FeedContactValidatorTest.java @@ -20,7 +20,7 @@ public static GtfsFeedInfo createFeedInfo( String feedVersion, String feedContactEmail, String feedContactUrl) { - return new GtfsFeedInfo.Builder() + return GtfsFeedInfo.builder() .setCsvRowNumber(csvRowNumber) .setFeedPublisherName(feedPublisherName) .setFeedPublisherUrl(feedPublisherUrl) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FeedExpirationDateValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FeedExpirationDateValidatorTest.java index 8eaee1f1a4..60532439c5 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FeedExpirationDateValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FeedExpirationDateValidatorTest.java @@ -40,7 +40,7 @@ private List validateFeedInfo(GtfsFeedInfo feedInfo) { } private GtfsFeedInfo createFeedInfo(GtfsDate feedEndDate) { - return new GtfsFeedInfo.Builder() + return GtfsFeedInfo.builder() .setCsvRowNumber(1) .setFeedPublisherName("feed publisher name value") .setFeedPublisherUrl("https://www.mobilitydata.org") diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FeedServiceDateValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FeedServiceDateValidatorTest.java index ee5f08f14d..0b03f565a5 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FeedServiceDateValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/FeedServiceDateValidatorTest.java @@ -26,7 +26,7 @@ public static GtfsFeedInfo createFeedInfo( Locale feedLang, GtfsDate feedStartDate, GtfsDate feedEndDate) { - return new GtfsFeedInfo.Builder() + return GtfsFeedInfo.builder() .setCsvRowNumber(csvRowNumber) .setFeedPublisherName(feedPublisherName) .setFeedPublisherUrl(feedPublisherUrl) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/GtfsFrequencyEndRangeValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/GtfsFrequencyEndRangeValidatorTest.java index c9a1d253c7..f149aca1fc 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/GtfsFrequencyEndRangeValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/GtfsFrequencyEndRangeValidatorTest.java @@ -45,7 +45,7 @@ private static List generateNotices(GtfsFrequency frequency) { public void inOrder_yieldsNoNotice() { assertThat( generateNotices( - new GtfsFrequency.Builder() + GtfsFrequency.builder() .setCsvRowNumber(2) .setStartTime(GtfsTime.fromString("10:00:00")) .setEndTime(GtfsTime.fromString("11:00:00")) @@ -57,7 +57,7 @@ public void inOrder_yieldsNoNotice() { public void outOfOrder_yieldsNotice() { assertThat( generateNotices( - new GtfsFrequency.Builder() + GtfsFrequency.builder() .setCsvRowNumber(2) .setStartTime(GtfsTime.fromString("11:00:00")) .setEndTime(GtfsTime.fromString("10:00:00")) @@ -71,7 +71,7 @@ public void outOfOrder_yieldsNotice() { public void equal_yieldsNotice() { assertThat( generateNotices( - new GtfsFrequency.Builder() + GtfsFrequency.builder() .setCsvRowNumber(2) .setStartTime(GtfsTime.fromString("10:00:00")) .setEndTime(GtfsTime.fromString("10:00:00")) @@ -87,14 +87,14 @@ public void fieldMissing_yieldsNoNotice() { // handles missing fields gracefully anyway. assertThat( generateNotices( - new GtfsFrequency.Builder() + GtfsFrequency.builder() .setCsvRowNumber(2) .setStartTime(GtfsTime.fromString("10:00:00")) .build())) .isEmpty(); assertThat( generateNotices( - new GtfsFrequency.Builder() + GtfsFrequency.builder() .setCsvRowNumber(2) .setEndTime(GtfsTime.fromString("10:00:00")) .build())) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/GtfsShapeLatLonValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/GtfsShapeLatLonValidatorTest.java index d78839af59..d741f70151 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/GtfsShapeLatLonValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/GtfsShapeLatLonValidatorTest.java @@ -43,7 +43,7 @@ private static List generateNotices(GtfsShape shape) { public void validPoint_yieldsNoNotice() { assertThat( generateNotices( - new GtfsShape.Builder() + GtfsShape.builder() .setCsvRowNumber(2) .setShapePtLat(45.0) .setShapePtLon(45.0) @@ -55,7 +55,7 @@ public void validPoint_yieldsNoNotice() { public void origin_yieldsNotice() { assertThat( generateNotices( - new GtfsShape.Builder() + GtfsShape.builder() .setCsvRowNumber(2) .setShapePtLat(0.0) .setShapePtLon(0.1) @@ -68,7 +68,7 @@ public void origin_yieldsNotice() { public void poles_yieldsNotice() { assertThat( generateNotices( - new GtfsShape.Builder() + GtfsShape.builder() .setCsvRowNumber(2) .setShapePtLat(90.0) .setShapePtLon(0.0) @@ -78,7 +78,7 @@ public void poles_yieldsNotice() { assertThat( generateNotices( - new GtfsShape.Builder() + GtfsShape.builder() .setCsvRowNumber(2) .setShapePtLat(-90.0) .setShapePtLon(0.0) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/GtfsTripServiceIdForeignKeyValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/GtfsTripServiceIdForeignKeyValidatorTest.java index 9f31aa6220..8d2ac5023c 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/GtfsTripServiceIdForeignKeyValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/GtfsTripServiceIdForeignKeyValidatorTest.java @@ -53,7 +53,7 @@ private static GtfsTripTableContainer createTripTable( public static GtfsTrip createTrip( int csvRowNumber, String routeId, String serviceId, String tripId, String shapeId) { - return new GtfsTrip.Builder() + return GtfsTrip.builder() .setCsvRowNumber(csvRowNumber) .setRouteId(routeId) .setServiceId(serviceId) @@ -69,7 +69,7 @@ private static GtfsCalendarTableContainer createCalendarTable( public static GtfsCalendarDate createCalendarDate( int csvRowNumber, String serviceId, GtfsDate date, int exceptionType) { - return new GtfsCalendarDate.Builder() + return GtfsCalendarDate.builder() .setCsvRowNumber(csvRowNumber) .setServiceId(serviceId) .setDate(date) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/LocationHasStopTimesValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/LocationHasStopTimesValidatorTest.java index aaa72f13e9..56436e4e01 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/LocationHasStopTimesValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/LocationHasStopTimesValidatorTest.java @@ -50,7 +50,7 @@ private static List generateNotices( } private static GtfsStop createLocation(GtfsLocationType locationType) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(2) .setStopId("location1") .setStopName("Location 1") @@ -59,7 +59,7 @@ private static GtfsStop createLocation(GtfsLocationType locationType) { } private static GtfsStopTime createStopTimeFor(GtfsStop stop) { - return new GtfsStopTime.Builder().setStopId(stop.stopId()).build(); + return GtfsStopTime.builder().setStopId(stop.stopId()).build(); } @Test diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/LocationTypeSingleEntityValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/LocationTypeSingleEntityValidatorTest.java index fed00e15b7..9beed0b3a8 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/LocationTypeSingleEntityValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/LocationTypeSingleEntityValidatorTest.java @@ -26,6 +26,7 @@ import org.mobilitydata.gtfsvalidator.notice.ValidationNotice; import org.mobilitydata.gtfsvalidator.table.GtfsLocationType; import org.mobilitydata.gtfsvalidator.table.GtfsStop; +import org.mobilitydata.gtfsvalidator.table.GtfsStopImpl; import org.mobilitydata.gtfsvalidator.validator.LocationTypeSingleEntityValidator.LocationWithoutParentStationNotice; import org.mobilitydata.gtfsvalidator.validator.LocationTypeSingleEntityValidator.PlatformWithoutParentStationNotice; import org.mobilitydata.gtfsvalidator.validator.LocationTypeSingleEntityValidator.StationWithParentStationNotice; @@ -41,8 +42,8 @@ private List validateStop(GtfsStop stop) { @Test public void stationWithParentStation() { - GtfsStop.Builder builder = - new GtfsStop.Builder() + GtfsStopImpl.Builder builder = + GtfsStop.builder() .setStopId("s0") .setCsvRowNumber(1) .setStopName("Stop 0") @@ -58,8 +59,8 @@ public void stationWithParentStation() { @Test public void platformWithoutParentStation() { // A GTFS stop with platform_code field should have parent_station. - GtfsStop.Builder builder = - new GtfsStop.Builder() + GtfsStopImpl.Builder builder = + GtfsStop.builder() .setStopId("s0") .setCsvRowNumber(1) .setStopName("Stop 0") @@ -84,8 +85,8 @@ public void locationWithoutParentStationNotice() { new GtfsLocationType[] { GtfsLocationType.ENTRANCE, GtfsLocationType.GENERIC_NODE, GtfsLocationType.BOARDING_AREA }) { - GtfsStop.Builder builder = - new GtfsStop.Builder() + GtfsStopImpl.Builder builder = + GtfsStop.builder() .setStopId("s0") .setCsvRowNumber(1) .setStopName("Stop 0") diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MatchingFeedAndAgencyLangValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MatchingFeedAndAgencyLangValidatorTest.java index bfeef3dc7c..d2f71a9c6c 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MatchingFeedAndAgencyLangValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MatchingFeedAndAgencyLangValidatorTest.java @@ -56,7 +56,7 @@ private static List generateNotices( public static GtfsAgency createAgency( int csvRowNumber, String agencyId, @Nullable Locale agencyLang) { - return new GtfsAgency.Builder() + return GtfsAgency.builder() .setAgencyId(agencyId) .setCsvRowNumber(csvRowNumber) .setAgencyLang(agencyLang) @@ -65,7 +65,7 @@ public static GtfsAgency createAgency( } public static GtfsFeedInfo createFeedInfo(int csvRowNumber, @Nullable Locale feedLang) { - return new GtfsFeedInfo.Builder() + return GtfsFeedInfo.builder() .setCsvRowNumber(csvRowNumber) .setFeedPublisherName("feed publisher name") .setFeedPublisherUrl("www.mobilitydata.org") diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MissingCalendarAndCalendarDateValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MissingCalendarAndCalendarDateValidatorTest.java index afb6e585c1..83e9537c34 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MissingCalendarAndCalendarDateValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MissingCalendarAndCalendarDateValidatorTest.java @@ -52,7 +52,7 @@ private static GtfsCalendarTableContainer createCalendarTable( public static GtfsCalendarDate createCalendarDate( int csvRowNumber, String serviceId, GtfsDate date, int exceptionType) { - return new GtfsCalendarDate.Builder() + return GtfsCalendarDate.builder() .setCsvRowNumber(csvRowNumber) .setServiceId(serviceId) .setDate(date) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MissingLevelIdValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MissingLevelIdValidatorTest.java index 55f1e6c5d0..a0a2809c45 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MissingLevelIdValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MissingLevelIdValidatorTest.java @@ -46,7 +46,7 @@ private static List generateNotices( } private static GtfsStop createStop(int csvRowNumber, String levelId) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setStopId(toStopId(csvRowNumber)) .setCsvRowNumber(csvRowNumber) .setLevelId(levelId) @@ -58,7 +58,7 @@ private static String toStopId(int csvRowNumber) { } private static GtfsPathway createPathway(int csvRowNumber, GtfsPathwayMode pathwayMode) { - return new GtfsPathway.Builder() + return GtfsPathway.builder() .setPathwayId(toPathwayId(pathwayMode, csvRowNumber)) .setCsvRowNumber(csvRowNumber) .setFromStopId(toStopId(csvRowNumber - 1)) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MissingTripEdgeValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MissingTripEdgeValidatorTest.java index f913398150..c8a108f445 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MissingTripEdgeValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/MissingTripEdgeValidatorTest.java @@ -36,7 +36,7 @@ public static GtfsStopTime createStopTime( GtfsTime arrivalTime, GtfsTime departureTime, int stopSequence) { - return new GtfsStopTime.Builder() + return GtfsStopTime.builder() .setCsvRowNumber(csvRowNumber) .setTripId(tripId) .setArrivalTime(arrivalTime) @@ -47,7 +47,7 @@ public static GtfsStopTime createStopTime( } public static GtfsTrip createTrip(int csvRowNumber, String tripId) { - return new GtfsTrip.Builder() + return GtfsTrip.builder() .setCsvRowNumber(csvRowNumber) .setRouteId("route id value") .setTripId(tripId) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NetworkIdConsistencyValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NetworkIdConsistencyValidatorTest.java index 0dfe65a6d2..be50403ad6 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NetworkIdConsistencyValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/NetworkIdConsistencyValidatorTest.java @@ -24,7 +24,7 @@ public void setup() { new GtfsRouteTableDescriptor(), new CsvHeader(ImmutableList.of("route_id", "network_id").toArray(new String[0])), ImmutableList.of( - new GtfsRoute.Builder().setRouteId("123").setNetworkId("network1").build()), + GtfsRoute.builder().setRouteId("123").setNetworkId("network1").build()), noticeContainer); routeNetworkTableContainer = new GtfsRouteNetworkTableContainer( @@ -48,7 +48,7 @@ public void validatesConditionalForbiddenFilePresence1() { routeNetworkTableContainer = GtfsRouteNetworkTableContainer.forEntities( ImmutableList.of( - new GtfsRouteNetwork.Builder().setRouteId("123").setNetworkId("network1").build()), + GtfsRouteNetwork.builder().setRouteId("123").setNetworkId("network1").build()), noticeContainer); NetworkIdConsistencyValidator validator = new NetworkIdConsistencyValidator( @@ -68,7 +68,7 @@ public void validatesConditionalForbiddenFilePresence1() { public void validatesConditionalForbiddenFilePresence2() { networkTableContainer = GtfsNetworkTableContainer.forEntities( - ImmutableList.of(new GtfsNetwork.Builder().setNetworkId("network1").build()), + ImmutableList.of(GtfsNetwork.builder().setNetworkId("network1").build()), noticeContainer); NetworkIdConsistencyValidator validator = new NetworkIdConsistencyValidator( diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/OverlappingFrequencyValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/OverlappingFrequencyValidatorTest.java index 3ea1833da8..b8be77b3a8 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/OverlappingFrequencyValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/OverlappingFrequencyValidatorTest.java @@ -19,7 +19,7 @@ public class OverlappingFrequencyValidatorTest { private GtfsFrequency createFrequency( int csvRowNumber, String tripId, String startTime, String endTime, int headwaySecs) { - return new GtfsFrequency.Builder() + return GtfsFrequency.builder() .setCsvRowNumber(csvRowNumber) .setTripId(tripId) .setStartTime(GtfsTime.fromString(startTime)) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ParentStationValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ParentStationValidatorTest.java index 9543d859d8..f58ecff681 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ParentStationValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ParentStationValidatorTest.java @@ -40,14 +40,14 @@ private List validateChildAndParent( new ParentStationValidator( GtfsStopTableContainer.forEntities( ImmutableList.of( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(1) .setStopId("child") .setStopName("Child location") .setLocationType(childType) .setParentStation("parent") .build(), - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(2) .setStopId("parent") .setStopName("Parent location") @@ -63,7 +63,7 @@ private List validateNoParent(GtfsLocationType locationType) { new ParentStationValidator( GtfsStopTableContainer.forEntities( ImmutableList.of( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(1) .setStopId("child") .setLocationType(locationType) @@ -163,20 +163,20 @@ public void unusedStation() { new ParentStationValidator( GtfsStopTableContainer.forEntities( ImmutableList.of( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(1) .setStopId("child") .setStopName("Child location") .setLocationType(GtfsLocationType.STOP) .setParentStation("used_station") .build(), - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(2) .setStopId("unused_station") .setStopName("Unused station") .setLocationType(GtfsLocationType.STATION) .build(), - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(3) .setStopId("used_station") .setStopName("Used station") @@ -194,7 +194,7 @@ public void foreignKeyViolation_handledGracefully() { new ParentStationValidator( GtfsStopTableContainer.forEntities( ImmutableList.of( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(1) .setStopId("child") .setStopName("Child location") diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayDanglingGenericNodeValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayDanglingGenericNodeValidatorTest.java index 623a568053..024c49f56d 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayDanglingGenericNodeValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayDanglingGenericNodeValidatorTest.java @@ -59,7 +59,7 @@ static String rowToPathwayId(int csvRowNumber) { static GtfsPathway createPathway(int fromStopRow, int toStopRow) { int row = fromStopRow * 1000 + toStopRow; - return new GtfsPathway.Builder() + return GtfsPathway.builder() .setCsvRowNumber(row) .setPathwayId(rowToPathwayId(row)) .setFromStopId(rowToStopId(fromStopRow)) @@ -68,7 +68,7 @@ static GtfsPathway createPathway(int fromStopRow, int toStopRow) { } static GtfsStop createLocation(int csvRowNumber, GtfsLocationType locationType) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setStopId(rowToStopId(csvRowNumber)) .setLocationType(locationType.getNumber()) @@ -77,7 +77,7 @@ static GtfsStop createLocation(int csvRowNumber, GtfsLocationType locationType) static GtfsStop createChildLocation( int csvRowNumber, GtfsLocationType locationType, int parentRow) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setStopId(rowToStopId(csvRowNumber)) .setLocationType(locationType.getNumber()) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayEndpointTypeValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayEndpointTypeValidatorTest.java index 832b7f73c3..d13dcbeb03 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayEndpointTypeValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayEndpointTypeValidatorTest.java @@ -60,7 +60,7 @@ static String rowToPathwayId(int csvRowNumber) { static GtfsPathway createPathway(int fromStopRow, int toStopRow) { int row = fromStopRow * 1000 + toStopRow; - return new GtfsPathway.Builder() + return GtfsPathway.builder() .setCsvRowNumber(row) .setPathwayId(rowToPathwayId(row)) .setFromStopId(rowToStopId(fromStopRow)) @@ -69,7 +69,7 @@ static GtfsPathway createPathway(int fromStopRow, int toStopRow) { } static GtfsStop createStop(int csvRowNumber, GtfsLocationType locationType) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setStopId(rowToStopId(csvRowNumber)) .setLocationType(locationType) @@ -77,7 +77,7 @@ static GtfsStop createStop(int csvRowNumber, GtfsLocationType locationType) { } static GtfsStop createBoardingArea(int csvRowNumber, int parentRow) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setStopId(rowToStopId(csvRowNumber)) .setLocationType(BOARDING_AREA) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayLoopValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayLoopValidatorTest.java index 6018f7ded8..2a5d53acd7 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayLoopValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayLoopValidatorTest.java @@ -38,7 +38,7 @@ private static List generateNotices(GtfsPathway pathway) { @Test public void loop_yieldsNotice() { GtfsPathway pathway = - new GtfsPathway.Builder() + GtfsPathway.builder() .setCsvRowNumber(2) .setPathwayId("pw1") .setFromStopId("platform1") @@ -51,7 +51,7 @@ public void loop_yieldsNotice() { public void noLoop_yieldsNoNotice() { assertThat( generateNotices( - new GtfsPathway.Builder() + GtfsPathway.builder() .setCsvRowNumber(2) .setPathwayId("pw1") .setFromStopId("platform1") @@ -63,8 +63,7 @@ public void noLoop_yieldsNoNotice() { @Test public void noEndpoints_yieldsNoNotice() { assertThat( - generateNotices( - new GtfsPathway.Builder().setCsvRowNumber(2).setPathwayId("pw1").build())) + generateNotices(GtfsPathway.builder().setCsvRowNumber(2).setPathwayId("pw1").build())) .isEmpty(); } } diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayReachableLocationValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayReachableLocationValidatorTest.java index 4920a6db42..44d5d9a55b 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayReachableLocationValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/PathwayReachableLocationValidatorTest.java @@ -63,7 +63,7 @@ static String rowToPathwayId(int csvRowNumber) { static GtfsPathway createPathway( int fromStopRow, int toStopRow, GtfsPathwayIsBidirectional isBidirectional) { int pathwayRow = fromStopRow * 1000 + toStopRow; - return new GtfsPathway.Builder() + return GtfsPathway.builder() .setCsvRowNumber(pathwayRow) .setPathwayId(rowToPathwayId(pathwayRow)) .setFromStopId(rowToStopId(fromStopRow)) @@ -73,7 +73,7 @@ static GtfsPathway createPathway( } static GtfsStop createLocation(int csvRowNumber, GtfsLocationType locationType) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setStopId(rowToStopId(csvRowNumber)) .setLocationType(locationType) @@ -83,7 +83,7 @@ static GtfsStop createLocation(int csvRowNumber, GtfsLocationType locationType) static GtfsStop createChildLocation( int csvRowNumber, GtfsLocationType locationType, int parentRow) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setStopId(rowToStopId(csvRowNumber)) .setLocationType(locationType) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/RouteAgencyIdValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/RouteAgencyIdValidatorTest.java index a7c090ad8e..9971fde615 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/RouteAgencyIdValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/RouteAgencyIdValidatorTest.java @@ -18,12 +18,12 @@ public void agencyIdRequiredErrorWhenMoreThanOneAgency() { GtfsAgencyTableContainer agencyTable = GtfsAgencyTableContainer.forEntities( ImmutableList.of( - new GtfsAgency.Builder() + GtfsAgency.builder() .setCsvRowNumber(0) .setAgencyId("Agency 1") .setAgencyName("Agency 1") .build(), - new GtfsAgency.Builder() + GtfsAgency.builder() .setCsvRowNumber(1) .setAgencyId("Agency 2") .setAgencyName("Agency 2") @@ -33,13 +33,13 @@ public void agencyIdRequiredErrorWhenMoreThanOneAgency() { GtfsRouteTableContainer routeTable = GtfsRouteTableContainer.forEntities( ImmutableList.of( - new GtfsRoute.Builder() + GtfsRoute.builder() .setCsvRowNumber(0) .setAgencyId("agency0") .setRouteId("route_0") .setRouteShortName("Route 0") .build(), - new GtfsRoute.Builder() + GtfsRoute.builder() .setCsvRowNumber(1) .setAgencyId(null) .setRouteId("route_1") @@ -60,7 +60,7 @@ public void agencyIdRecommendedWarningWhenOnlyOneAgency() { GtfsAgencyTableContainer agencyTable = GtfsAgencyTableContainer.forEntities( ImmutableList.of( - new GtfsAgency.Builder() + GtfsAgency.builder() .setCsvRowNumber(1) .setAgencyId(null) .setAgencyName("Agency with no ID") @@ -70,7 +70,7 @@ public void agencyIdRecommendedWarningWhenOnlyOneAgency() { GtfsRouteTableContainer routeTable = GtfsRouteTableContainer.forEntities( ImmutableList.of( - new GtfsRoute.Builder() + GtfsRoute.builder() .setCsvRowNumber(0) .setAgencyId(null) .setRouteId("route_0") @@ -91,7 +91,7 @@ public void SingleAgencyAndAgencyIdSpecified_noNotice() { GtfsAgencyTableContainer agencyTable = GtfsAgencyTableContainer.forEntities( ImmutableList.of( - new GtfsAgency.Builder() + GtfsAgency.builder() .setCsvRowNumber(0) .setAgencyId("agency1") .setAgencyName("Agency 1") @@ -101,13 +101,13 @@ public void SingleAgencyAndAgencyIdSpecified_noNotice() { GtfsRouteTableContainer routeTable = GtfsRouteTableContainer.forEntities( ImmutableList.of( - new GtfsRoute.Builder() + GtfsRoute.builder() .setCsvRowNumber(0) .setAgencyId("agency1") .setRouteId("route_0") .setRouteShortName("Route 0") .build(), - new GtfsRoute.Builder() + GtfsRoute.builder() .setCsvRowNumber(1) .setAgencyId("agency1") .setRouteId("route_1") @@ -125,12 +125,12 @@ public void MoreThanOneAgencyAndAgencyIdsSpecified_noNotice() { GtfsAgencyTableContainer agencyTable = GtfsAgencyTableContainer.forEntities( ImmutableList.of( - new GtfsAgency.Builder() + GtfsAgency.builder() .setCsvRowNumber(0) .setAgencyId("agency1") .setAgencyName("Agency 1") .build(), - new GtfsAgency.Builder() + GtfsAgency.builder() .setCsvRowNumber(1) .setAgencyId("agency2") .setAgencyName("Agency 2") @@ -140,13 +140,13 @@ public void MoreThanOneAgencyAndAgencyIdsSpecified_noNotice() { GtfsRouteTableContainer routeTable = GtfsRouteTableContainer.forEntities( ImmutableList.of( - new GtfsRoute.Builder() + GtfsRoute.builder() .setCsvRowNumber(0) .setAgencyId("agency1") .setRouteId("route_0") .setRouteShortName("Route 0") .build(), - new GtfsRoute.Builder() + GtfsRoute.builder() .setCsvRowNumber(1) .setAgencyId("agency2") .setRouteId("route_1") diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/RouteColorContrastValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/RouteColorContrastValidatorTest.java index e673a105df..da94ce451e 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/RouteColorContrastValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/RouteColorContrastValidatorTest.java @@ -39,7 +39,7 @@ public static GtfsRoute createRoute( GtfsColor routeTextColor, int continuousPickup, int continuousDropOff) { - return new GtfsRoute.Builder() + return GtfsRoute.builder() .setCsvRowNumber(csvRowNumber) .setRouteId(routeId) .setAgencyId(agencyId) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/RouteNameValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/RouteNameValidatorTest.java index cd542761fd..6b09d660d5 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/RouteNameValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/RouteNameValidatorTest.java @@ -41,7 +41,7 @@ private List validateRoute(GtfsRoute route) { } private GtfsRoute createRoute(String shortName, String longName, String desc) { - return new GtfsRoute.Builder() + return GtfsRoute.builder() .setRouteId("r1") .setCsvRowNumber(1) .setRouteShortName(shortName) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ShapeIncreasingDistanceValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ShapeIncreasingDistanceValidatorTest.java index 18077e3fd2..dc6e466451 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ShapeIncreasingDistanceValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ShapeIncreasingDistanceValidatorTest.java @@ -37,7 +37,7 @@ public static GtfsShape createShapePoint( double shapePtLon, int shapePtSequence, Double shapeDistTraveled) { - return new GtfsShape.Builder() + return GtfsShape.builder() .setCsvRowNumber(csvRowNumber) .setShapeId(shapeId) .setShapePtLat(shapePtLat) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ShapeToStopMatchingValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ShapeToStopMatchingValidatorTest.java index eac9f8faa1..743108abde 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ShapeToStopMatchingValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ShapeToStopMatchingValidatorTest.java @@ -106,7 +106,7 @@ private static List generateNotices( } private static GtfsTrip createTrip() { - return new GtfsTrip.Builder() + return GtfsTrip.builder() .setCsvRowNumber(2) .setTripId(TEST_TRIP_ID) .setRouteId(TEST_ROUTE_ID) @@ -115,7 +115,7 @@ private static GtfsTrip createTrip() { } private static GtfsRoute createRoute() { - return new GtfsRoute.Builder() + return GtfsRoute.builder() .setCsvRowNumber(2) .setRouteId(TEST_ROUTE_ID) .setRouteType(GtfsRouteType.BUS) @@ -124,7 +124,7 @@ private static GtfsRoute createRoute() { private static GtfsShape createGtfsShape( int ptSequence, double latDegrees, double lngDegrees, Double shapeDistTraveled) { - return new GtfsShape.Builder() + return GtfsShape.builder() .setShapeId(TEST_SHAPE_ID) .setCsvRowNumber(ptSequence + 2) .setShapePtSequence(ptSequence) @@ -153,7 +153,7 @@ private static String numberToStopId(int number) { } private static GtfsStop createStop(int number, double stopLat, double stopLon) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(2 + number) .setStopId(numberToStopId(number)) .setStopName("Stop " + number) @@ -174,7 +174,7 @@ private static List createStopTimes(Double[] shapeDistTraveled) { List stopTimes = new ArrayList<>(shapeDistTraveled.length); for (int i = 0; i < shapeDistTraveled.length; ++i) { stopTimes.add( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(i + 2) .setStopId(numberToStopId(i)) .setTripId(TEST_TRIP_ID) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ShapeUsageValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ShapeUsageValidatorTest.java index d97e90f336..c9f366796e 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ShapeUsageValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/ShapeUsageValidatorTest.java @@ -38,7 +38,7 @@ public static GtfsShape createShapePoint( double shapePtLon, int shapePtSequence, double shapeDistTraveled) { - return new GtfsShape.Builder() + return GtfsShape.builder() .setCsvRowNumber(csvRowNumber) .setShapeId(shapeId) .setShapePtLat(shapePtLat) @@ -50,7 +50,7 @@ public static GtfsShape createShapePoint( public static GtfsTrip createTrip( int csvRowNumber, String routeId, String serviceId, String tripId, String shapeId) { - return new GtfsTrip.Builder() + return GtfsTrip.builder() .setCsvRowNumber(csvRowNumber) .setRouteId(routeId) .setServiceId(serviceId) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopNameValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopNameValidatorTest.java index 1fd1392626..01f9998b13 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopNameValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopNameValidatorTest.java @@ -41,7 +41,7 @@ private static List generateNotices(GtfsStop stop) { public void sameStopNameAndDesc_generatesNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.STOP) @@ -56,7 +56,7 @@ public void sameStopNameAndDesc_generatesNotice() { public void differentStopNameAndDesc_noNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.STOP) @@ -70,7 +70,7 @@ public void differentStopNameAndDesc_noNotice() { public void missingStopNameForStop_generatesNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.STOP) @@ -84,7 +84,7 @@ public void missingStopNameForStop_generatesNotice() { public void missingStopNameForStation_generatesNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.STATION) @@ -99,7 +99,7 @@ public void missingStopNameForStation_generatesNotice() { public void missingStopNameForEntrance_generatesNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.ENTRANCE) @@ -114,7 +114,7 @@ public void missingStopNameForEntrance_generatesNotice() { public void missingStopNameForGenericNode_noNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.GENERIC_NODE) @@ -127,7 +127,7 @@ public void missingStopNameForGenericNode_noNotice() { public void missingStopNameForBoardingArea_noNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.BOARDING_AREA) @@ -140,7 +140,7 @@ public void missingStopNameForBoardingArea_noNotice() { public void missingStopNameForUnrecognizedLocationType_noNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.UNRECOGNIZED) @@ -153,7 +153,7 @@ public void missingStopNameForUnrecognizedLocationType_noNotice() { public void missingStopDesc_noNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.STOP) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopRequiredLocationValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopRequiredLocationValidatorTest.java index 20ad416590..3482dd016c 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopRequiredLocationValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopRequiredLocationValidatorTest.java @@ -22,7 +22,7 @@ private static List generateNotices(GtfsStop stop) { public void missingLatLongForStop_generatesNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.STOP) @@ -34,7 +34,7 @@ public void missingLatLongForStop_generatesNotice() { public void missingLatLongForStation_generatesNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.STATION) @@ -47,7 +47,7 @@ public void missingLatLongForStation_generatesNotice() { public void missingLatLongForEntrance_generatesNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.ENTRANCE) @@ -61,7 +61,7 @@ public void missingLatLongForEntrance_generatesNotice() { public void missingLatLongForGenericNode_generatesNoNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.GENERIC_NODE) @@ -73,7 +73,7 @@ public void missingLatLongForGenericNode_generatesNoNotice() { public void missingLatLongForBoardingArea_generatesNoNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setLocationType(GtfsLocationType.BOARDING_AREA) @@ -86,7 +86,7 @@ public void missingLatLongForBoardingArea_generatesNoNotice() { public void givenLatLongForStop_generatesNoNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setStopLat(25.25) @@ -100,7 +100,7 @@ public void givenLatLongForStop_generatesNoNotice() { public void givenLatLongForStation_generatesNoNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setStopLat(25.25) @@ -114,7 +114,7 @@ public void givenLatLongForStation_generatesNoNotice() { public void givenLatLongForEntrance_generatesNoNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setStopLat(25.25) @@ -129,7 +129,7 @@ public void givenLatLongForEntrance_generatesNoNotice() { public void givenLatButMissingLongForStop_generatesNoNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setStopLat(25.25) @@ -142,7 +142,7 @@ public void givenLatButMissingLongForStop_generatesNoNotice() { public void givenLongButMissingLatForStop_generatesNoNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setStopLon(25.25) @@ -155,7 +155,7 @@ public void givenLongButMissingLatForStop_generatesNoNotice() { public void givenLatButMissingLongForStation_generatesNoNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setStopLat(25.25) @@ -169,7 +169,7 @@ public void givenLatButMissingLongForStation_generatesNoNotice() { public void givenLongButMissingLatForStation_generatesNoNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setStopLon(25.25) @@ -183,7 +183,7 @@ public void givenLongButMissingLatForStation_generatesNoNotice() { public void givenLatButMissingLongForEntrance_generatesNoNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setStopLat(25.25) @@ -197,7 +197,7 @@ public void givenLatButMissingLongForEntrance_generatesNoNotice() { public void givenLongButMissingLatForEntrance_generatesNoNotice() { assertThat( generateNotices( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(4) .setStopId("stop id value") .setStopLon(25.25) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopTimeArrivalAndDepartureTimeValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopTimeArrivalAndDepartureTimeValidatorTest.java index 67442a35b5..294a7e136e 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopTimeArrivalAndDepartureTimeValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopTimeArrivalAndDepartureTimeValidatorTest.java @@ -37,7 +37,7 @@ public static GtfsStopTime createStopTime( GtfsTime departureTime, String stopId, int stopSequence) { - return new GtfsStopTime.Builder() + return GtfsStopTime.builder() .setCsvRowNumber(csvRowNumber) .setTripId(tripId) .setArrivalTime(arrivalTime) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopTimeIncreasingDistanceValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopTimeIncreasingDistanceValidatorTest.java index 86b620bf19..96071ae914 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopTimeIncreasingDistanceValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopTimeIncreasingDistanceValidatorTest.java @@ -30,7 +30,7 @@ public class StopTimeIncreasingDistanceValidatorTest { public static GtfsStopTime createStopTime( int csvRowNumber, String tripId, String stopId, int stopSequence, double shapeDistTraveled) { - return new GtfsStopTime.Builder() + return GtfsStopTime.builder() .setCsvRowNumber(csvRowNumber) .setTripId(tripId) .setStopId(stopId) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopTimeTravelSpeedValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopTimeTravelSpeedValidatorTest.java index 6a9d0888bd..7478a5ade3 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopTimeTravelSpeedValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopTimeTravelSpeedValidatorTest.java @@ -65,7 +65,7 @@ private static List generateNotices( private static final String TEST_TRIP_ID = "trip0"; private static GtfsRoute createRoute(GtfsRouteType routeType) { - return new GtfsRoute.Builder() + return GtfsRoute.builder() .setCsvRowNumber(2) .setRouteId(TEST_ROUTE_ID) .setRouteType(routeType) @@ -73,7 +73,7 @@ private static GtfsRoute createRoute(GtfsRouteType routeType) { } private static GtfsTrip createTrip() { - return new GtfsTrip.Builder() + return GtfsTrip.builder() .setCsvRowNumber(2) .setTripId(TEST_TRIP_ID) .setRouteId(TEST_ROUTE_ID) @@ -84,7 +84,7 @@ private static List createStops(List points) { List stops = new ArrayList<>(points.size()); for (int i = 0; i < points.size(); ++i) { stops.add( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(i + 2) .setStopId("s" + i) .setStopName("Stop " + i) @@ -99,7 +99,7 @@ private static List createStopTimesSameDepartureArrival(List stopTimes = new ArrayList<>(times.size()); for (int i = 0; i < times.size(); ++i) { stopTimes.add( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(i + 2) .setTripId(TEST_TRIP_ID) .setStopId("s" + i) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopZoneIdValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopZoneIdValidatorTest.java index faf7cd24cc..f179161fa4 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopZoneIdValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/StopZoneIdValidatorTest.java @@ -34,7 +34,7 @@ public class StopZoneIdValidatorTest { private static GtfsStop createStop( int csvRowNumber, GtfsLocationType locationType, String zoneId) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setStopId(toLocationId(locationType, csvRowNumber)) .setLocationType(locationType) @@ -54,7 +54,7 @@ private static GtfsStop createStop( */ private static GtfsFareRule createFareRule( int csvRowNumber, boolean route, boolean origin, boolean destination, boolean contains) { - return new GtfsFareRule.Builder() + return GtfsFareRule.builder() .setCsvRowNumber(csvRowNumber) .setFareId(toFareRuleId(csvRowNumber)) .setRouteId(route ? toRouteId(csvRowNumber) : null) @@ -71,7 +71,11 @@ private static GtfsFareRule createFareRule( * @return a `GtfsFareRule` with only fare_rule_id and origin_id defined */ private static GtfsFareRule createFareRuleWithZoneStructure(int csvRowNumber) { - return createFareRule(csvRowNumber, false, true, false, false); + return GtfsFareRule.builder() + .setCsvRowNumber(csvRowNumber) + .setFareId(toFareRuleId(csvRowNumber)) + .setOriginId("origin id") + .build(); } /** @@ -81,7 +85,11 @@ private static GtfsFareRule createFareRuleWithZoneStructure(int csvRowNumber) { * @return a `GtfsFareRule` with only fare_rule_id and route_id defined */ private static GtfsFareRule createFareRuleWithoutZoneStructure(int csvRowNumber) { - return createFareRule(csvRowNumber, true, false, false, false); + return GtfsFareRule.builder() + .setCsvRowNumber(csvRowNumber) + .setFareId(toFareRuleId(csvRowNumber)) + .setRouteId("route id value") + .build(); } /** @@ -208,20 +216,20 @@ private static List generateNoticesFromStopAndFareRules( List stops = ImmutableList.of(stop); List routes = ImmutableList.of( - new GtfsRoute.Builder() + GtfsRoute.builder() .setCsvRowNumber(csvRowNumber) .setRouteId(toRouteId(csvRowNumber)) .build()); List trips = ImmutableList.of( - new GtfsTrip.Builder() + GtfsTrip.builder() .setCsvRowNumber(csvRowNumber) .setTripId(toTripId(csvRowNumber)) .setRouteId(toRouteId(csvRowNumber)) .build()); List stopTimes = ImmutableList.of( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(csvRowNumber) .setStopId(stop.stopId()) .setTripId(toTripId(csvRowNumber)) @@ -233,7 +241,7 @@ private static List generateNoticesFromStopAndFareRules( public void stop_zoneIdNotProvided_routeNotInFareRules_noNotice() { int csvRowNumber = 0; GtfsStop stop = - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setLocationType(GtfsLocationType.STOP) .setZoneId(null) @@ -251,7 +259,7 @@ public void stop_zoneIdNotProvided_routeNotInFareRules_noNotice() { public void stop_zoneIdNotProvided_routeInFareRulesWithoutZoneFields_noNotice() { int csvRowNumber = 0; GtfsStop stop = - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setLocationType(GtfsLocationType.STOP) .setZoneId(null) @@ -265,7 +273,7 @@ public void stop_zoneIdNotProvided_routeInFareRulesWithoutZoneFields_noNotice() public void stop_zoneIdNotProvided_routeInFareRulesWithOriginId_yieldsNotice() { int csvRowNumber = 0; GtfsStop stop = - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setLocationType(GtfsLocationType.STOP) .setZoneId(null) @@ -280,7 +288,7 @@ public void stop_zoneIdNotProvided_routeInFareRulesWithOriginId_yieldsNotice() { public void stop_zoneIdNotProvided_routeInFareRulesWithDestinationId_yieldsNotice() { int csvRowNumber = 0; GtfsStop stop = - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setLocationType(GtfsLocationType.STOP) .setZoneId(null) @@ -295,7 +303,7 @@ public void stop_zoneIdNotProvided_routeInFareRulesWithDestinationId_yieldsNotic public void stop_zoneIdNotProvided_routeInFareRulesWithContainsId_yieldsNotice() { int csvRowNumber = 0; GtfsStop stop = - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setLocationType(GtfsLocationType.STOP) .setZoneId(null) @@ -310,7 +318,7 @@ public void stop_zoneIdNotProvided_routeInFareRulesWithContainsId_yieldsNotice() public void stop_zoneIdNotProvided_routeInFareRulesWithAndWithoutZoneFields_yieldsNotice() { int csvRowNumber = 0; GtfsStop stop = - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setLocationType(GtfsLocationType.STOP) .setZoneId(null) @@ -327,7 +335,7 @@ public void stop_zoneIdNotProvided_routeInFareRulesWithAndWithoutZoneFields_yiel public void stop_zoneIdProvided_noNotice() { int csvRowNumber = 0; GtfsStop stop = - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setLocationType(GtfsLocationType.STOP) .setZoneId(toZoneId(csvRowNumber)) @@ -359,7 +367,7 @@ public void allLocationTypesExceptStop_noNotice() { assertThat( generateNoticesFromStopAndFareRules( csvRowNumber, - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setLocationType(locationType) .setZoneId(null) @@ -369,7 +377,7 @@ public void allLocationTypesExceptStop_noNotice() { assertThat( generateNoticesFromStopAndFareRules( csvRowNumber, - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setLocationType(locationType) .setZoneId(toZoneId(csvRowNumber)) @@ -389,7 +397,7 @@ public void emptyFareRule_allStopLocationTypes_noZoneId_noNotice() { assertThat( generateNoticesFromStopAndFareRules( csvRowNumber, - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setLocationType(gtfsLocationType) .setZoneId(null) @@ -407,7 +415,7 @@ public void emptyFareRule_allStopLocationTypes_zoneId_noNotice() { assertThat( generateNoticesFromStopAndFareRules( csvRowNumber, - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setLocationType(gtfsLocationType) .setZoneId(toStopId(csvRowNumber)) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimeframeOverlapValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimeframeOverlapValidatorTest.java index 600282fae6..a84ce49909 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimeframeOverlapValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimeframeOverlapValidatorTest.java @@ -21,7 +21,7 @@ public class TimeframeOverlapValidatorTest { public void testSingleTimeframe() { assertThat( validate( - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setTimeframeGroupId("PEAK") .setServiceId("WEEKDAY") .setStartTime(GtfsTime.fromString("00:00:00")) @@ -35,14 +35,14 @@ public void testSingleTimeframe() { public void testNoOverlap() { assertThat( validate( - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setTimeframeGroupId("PEAK") .setServiceId("WEEKDAY") .setStartTime(GtfsTime.fromString("08:00:00")) .setEndTime(GtfsTime.fromString("09:00:00")) .setCsvRowNumber(2) .build(), - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setTimeframeGroupId("PEAK") .setServiceId("WEEKDAY") .setStartTime(GtfsTime.fromString("17:00:00")) @@ -56,14 +56,14 @@ public void testNoOverlap() { public void testNoOverlapButAdjacent() { assertThat( validate( - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setTimeframeGroupId("PEAK") .setServiceId("WEEKDAY") .setStartTime(GtfsTime.fromString("08:00:00")) .setEndTime(GtfsTime.fromString("09:00:00")) .setCsvRowNumber(2) .build(), - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setTimeframeGroupId("PEAK") .setServiceId("WEEKDAY") .setStartTime(GtfsTime.fromString("09:00:00")) @@ -77,14 +77,14 @@ public void testNoOverlapButAdjacent() { public void testOverlap() { assertThat( validate( - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setTimeframeGroupId("PEAK") .setServiceId("WEEKDAY") .setStartTime(GtfsTime.fromString("08:00:00")) .setEndTime(GtfsTime.fromString("09:00:00")) .setCsvRowNumber(2) .build(), - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setTimeframeGroupId("PEAK") .setServiceId("WEEKDAY") .setStartTime(GtfsTime.fromString("08:30:00")) @@ -105,14 +105,14 @@ public void testOverlap() { public void testWithDifferentServiceIds() { assertThat( validate( - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setTimeframeGroupId("PEAK") .setServiceId("WEEKDAY") .setStartTime(GtfsTime.fromString("08:00:00")) .setEndTime(GtfsTime.fromString("09:00:00")) .setCsvRowNumber(2) .build(), - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setTimeframeGroupId("PEAK") .setServiceId("WEEKEND") .setStartTime(GtfsTime.fromString("08:00:00")) @@ -126,14 +126,14 @@ public void testWithDifferentServiceIds() { public void testWithDifferentGroupIds() { assertThat( validate( - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setTimeframeGroupId("PEAK") .setServiceId("WEEKDAY") .setStartTime(GtfsTime.fromString("08:00:00")) .setEndTime(GtfsTime.fromString("09:00:00")) .setCsvRowNumber(2) .build(), - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setTimeframeGroupId("NON-PEAK") .setServiceId("WEEKDAY") .setStartTime(GtfsTime.fromString("08:00:00")) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimeframeServiceIdForeignKeyValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimeframeServiceIdForeignKeyValidatorTest.java index 3dd7db616f..6e2b1eae36 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimeframeServiceIdForeignKeyValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimeframeServiceIdForeignKeyValidatorTest.java @@ -42,7 +42,7 @@ public class TimeframeServiceIdForeignKeyValidatorTest { public void timeframeServiceIdInCalendarTableShouldNotGenerateNotice() { assertThat( generateNotices( - ImmutableList.of(new GtfsTimeframe.Builder().setServiceId("WEEK").build()), + ImmutableList.of(GtfsTimeframe.builder().setServiceId("WEEK").build()), ImmutableList.of( CalendarUtilTest.createGtfsCalendar( "WEEK", @@ -62,10 +62,10 @@ public void timeframeServiceIdInCalendarTableShouldNotGenerateNotice() { public void tripServiceIdInCalendarDateTableShouldNotGenerateNotice() { assertThat( generateNotices( - ImmutableList.of(new GtfsTimeframe.Builder().setServiceId("WEEK").build()), + ImmutableList.of(GtfsTimeframe.builder().setServiceId("WEEK").build()), ImmutableList.of(), ImmutableList.of( - new GtfsCalendarDate.Builder() + GtfsCalendarDate.builder() .setCsvRowNumber(2) .setServiceId("WEEK") .setDate(GtfsDate.fromEpochDay(24354)) @@ -79,7 +79,7 @@ public void tripServiceIdNotInDataShouldGenerateNotice() { assertThat( generateNotices( ImmutableList.of( - new GtfsTimeframe.Builder().setServiceId("WEEK").setCsvRowNumber(1).build()), + GtfsTimeframe.builder().setServiceId("WEEK").setCsvRowNumber(1).build()), ImmutableList.of(), ImmutableList.of())) .containsExactly( diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimeframeStartAndEndTimeValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimeframeStartAndEndTimeValidatorTest.java index a3f38f19b0..4d47510b10 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimeframeStartAndEndTimeValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimeframeStartAndEndTimeValidatorTest.java @@ -36,7 +36,7 @@ public class TimeframeStartAndEndTimeValidatorTest { public void testExplicitFullDayInterval() { assertThat( validate( - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setStartTime(GtfsTime.fromString("00:00:00")) .setEndTime(GtfsTime.fromString("24:00:00")) .build())) @@ -45,14 +45,14 @@ public void testExplicitFullDayInterval() { @Test public void testImplicitFullDayInterval() { - assertThat(validate(new GtfsTimeframe.Builder().build())).isEmpty(); + assertThat(validate(GtfsTimeframe.builder().build())).isEmpty(); } @Test public void testBeyondTwentyFourHours() { assertThat( validate( - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setCsvRowNumber(2) .setStartTime(GtfsTime.fromString("00:00:00")) .setEndTime(GtfsTime.fromString("24:00:01")) @@ -66,7 +66,7 @@ public void testBeyondTwentyFourHours() { public void testOnlyStartTimeSpecified() { assertThat( validate( - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setStartTime(GtfsTime.fromString("00:00:00")) .setCsvRowNumber(2) .build())) @@ -77,7 +77,7 @@ public void testOnlyStartTimeSpecified() { public void testOnlyEndTimeSpecified() { assertThat( validate( - new GtfsTimeframe.Builder() + GtfsTimeframe.builder() .setEndTime(GtfsTime.fromString("10:00:00")) .setCsvRowNumber(2) .build())) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimepointTimeValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimepointTimeValidatorTest.java index 8d3c3455fa..58b61c93ed 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimepointTimeValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TimepointTimeValidatorTest.java @@ -101,7 +101,7 @@ private static CsvHeader createHeaderWithTimepointColumn() { public void timepointWithNoTimeShouldGenerateNotices() { List stopTimes = new ArrayList<>(); stopTimes.add( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(1) .setTripId("first trip id") .setArrivalTime(null) @@ -120,7 +120,7 @@ public void timepointWithNoTimeShouldGenerateNotices() { public void timepointWithBothTimesShouldNotGenerateNotice() { List stopTimes = new ArrayList<>(); stopTimes.add( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(1) .setTripId("first trip id") .setArrivalTime(GtfsTime.fromSecondsSinceMidnight(450)) @@ -136,7 +136,7 @@ public void timepointWithBothTimesShouldNotGenerateNotice() { public void timepoint_missingDepartureTimeShouldGenerateNotice() { List stopTimes = new ArrayList<>(); stopTimes.add( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(1) .setTripId("first trip id") .setArrivalTime(GtfsTime.fromSecondsSinceMidnight(450)) @@ -154,7 +154,7 @@ public void timepoint_missingDepartureTimeShouldGenerateNotice() { public void timepoint_missingArrivalTimeShouldGenerateNotice() { List stopTimes = new ArrayList<>(); stopTimes.add( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(1) .setTripId("first trip id") .setArrivalTime(null) @@ -172,7 +172,7 @@ public void timepoint_missingArrivalTimeShouldGenerateNotice() { public void nonTimepoint_noTimeProvided_shouldNotGenerateNotice() { List stopTimes = new ArrayList<>(); stopTimes.add( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(1) .setTripId("first trip id") .setArrivalTime(null) @@ -188,7 +188,7 @@ public void nonTimepoint_noTimeProvided_shouldNotGenerateNotice() { public void nonTimepoint_timesProvided_shouldNotGenerateNotice() { List stopTimes = new ArrayList<>(); stopTimes.add( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(1) .setTripId("first trip id") .setArrivalTime(GtfsTime.fromSecondsSinceMidnight(450)) @@ -206,7 +206,7 @@ public void emptyTimepoint_noTimesProvided_shouldGenerateNotice() { // (even if the timepoint value is included in header) List stopTimes = new ArrayList<>(); stopTimes.add( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(1) .setTripId("first trip id") .setArrivalTime(null) @@ -225,7 +225,7 @@ public void emptyTimepoint_timesProvided_shouldGenerateNotice() { // (even if the timepoint value is included in header) List stopTimes = new ArrayList<>(); stopTimes.add( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(1) .setTripId("first trip id") .setArrivalTime(GtfsTime.fromSecondsSinceMidnight(450)) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransferDirectionTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransferDirectionTest.java index 6f965a11fe..bce86923f3 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransferDirectionTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransferDirectionTest.java @@ -6,7 +6,6 @@ import org.junit.Test; import org.mobilitydata.gtfsvalidator.table.GtfsTransfer; -import org.mobilitydata.gtfsvalidator.table.GtfsTransfer.Builder; public class TransferDirectionTest { @@ -24,7 +23,7 @@ public void testFieldName() { @Test public void testHasMethodsForEmptyTransfer() { - GtfsTransfer emptyTransfer = new Builder().build(); + GtfsTransfer emptyTransfer = GtfsTransfer.builder().build(); assertThat(TRANSFER_FROM.hasStopId(emptyTransfer)).isFalse(); assertThat(TRANSFER_TO.hasStopId(emptyTransfer)).isFalse(); @@ -38,24 +37,21 @@ public void testHasMethodsForEmptyTransfer() { @Test public void testHasMethods() { - assertThat(TRANSFER_FROM.hasStopId(new GtfsTransfer.Builder().setFromStopId("a").build())) - .isTrue(); - assertThat(TRANSFER_TO.hasStopId(new GtfsTransfer.Builder().setToStopId("a").build())).isTrue(); + assertThat(TRANSFER_FROM.hasStopId(GtfsTransfer.builder().setFromStopId("a").build())).isTrue(); + assertThat(TRANSFER_TO.hasStopId(GtfsTransfer.builder().setToStopId("a").build())).isTrue(); - assertThat(TRANSFER_FROM.hasRouteId(new GtfsTransfer.Builder().setFromRouteId("a").build())) - .isTrue(); - assertThat(TRANSFER_TO.hasRouteId(new GtfsTransfer.Builder().setToRouteId("a").build())) + assertThat(TRANSFER_FROM.hasRouteId(GtfsTransfer.builder().setFromRouteId("a").build())) .isTrue(); + assertThat(TRANSFER_TO.hasRouteId(GtfsTransfer.builder().setToRouteId("a").build())).isTrue(); - assertThat(TRANSFER_FROM.hasTripId(new GtfsTransfer.Builder().setFromTripId("a").build())) - .isTrue(); - assertThat(TRANSFER_TO.hasTripId(new GtfsTransfer.Builder().setToTripId("a").build())).isTrue(); + assertThat(TRANSFER_FROM.hasTripId(GtfsTransfer.builder().setFromTripId("a").build())).isTrue(); + assertThat(TRANSFER_TO.hasTripId(GtfsTransfer.builder().setToTripId("a").build())).isTrue(); } @Test public void testIdMethods() { GtfsTransfer transfer = - new Builder() + GtfsTransfer.builder() .setFromStopId("stopA") .setFromRouteId("routeA") .setFromTripId("tripA") diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransfersInSeatTransferTypeValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransfersInSeatTransferTypeValidatorTest.java index fd0611ae1e..dd115efb63 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransfersInSeatTransferTypeValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransfersInSeatTransferTypeValidatorTest.java @@ -11,7 +11,6 @@ import org.mobilitydata.gtfsvalidator.table.GtfsStopTime; import org.mobilitydata.gtfsvalidator.table.GtfsStopTimeTableContainer; import org.mobilitydata.gtfsvalidator.table.GtfsTransfer; -import org.mobilitydata.gtfsvalidator.table.GtfsTransfer.Builder; import org.mobilitydata.gtfsvalidator.table.GtfsTransferTableContainer; import org.mobilitydata.gtfsvalidator.table.GtfsTransferType; import org.mobilitydata.gtfsvalidator.validator.TransfersInSeatTransferTypeValidator.TransferWithSuspiciousMidTripInSeatNotice; @@ -27,43 +26,21 @@ public void testValidInSeatTransfer() { GtfsStopTableContainer stops = GtfsStopTableContainer.forEntities( ImmutableList.of( - new GtfsStop.Builder() - .setStopId("s0") - .setLocationType(GtfsLocationType.STOP) - .build(), - new GtfsStop.Builder() - .setStopId("s1") - .setLocationType(GtfsLocationType.STOP) - .build()), + GtfsStop.builder().setStopId("s0").setLocationType(GtfsLocationType.STOP).build(), + GtfsStop.builder().setStopId("s1").setLocationType(GtfsLocationType.STOP).build()), noticeContainer); GtfsStopTimeTableContainer stopTimes = GtfsStopTimeTableContainer.forEntities( ImmutableList.of( - new GtfsStopTime.Builder() - .setTripId("t0") - .setStopId("s?") - .setStopSequence(0) - .build(), - new GtfsStopTime.Builder() - .setTripId("t0") - .setStopId("s0") - .setStopSequence(1) - .build(), - new GtfsStopTime.Builder() - .setTripId("t1") - .setStopId("s1") - .setStopSequence(0) - .build(), - new GtfsStopTime.Builder() - .setTripId("t1") - .setStopId("s?") - .setStopSequence(1) - .build()), + GtfsStopTime.builder().setTripId("t0").setStopId("s?").setStopSequence(0).build(), + GtfsStopTime.builder().setTripId("t0").setStopId("s0").setStopSequence(1).build(), + GtfsStopTime.builder().setTripId("t1").setStopId("s1").setStopSequence(0).build(), + GtfsStopTime.builder().setTripId("t1").setStopId("s?").setStopSequence(1).build()), noticeContainer); GtfsTransferTableContainer transfers = GtfsTransferTableContainer.forEntities( ImmutableList.of( - new GtfsTransfer.Builder() + GtfsTransfer.builder() .setCsvRowNumber(2) .setFromStopId("s0") .setToStopId("s1") @@ -84,11 +61,8 @@ public void testInvalidInSeatTransferToStation() { GtfsStopTableContainer stops = GtfsStopTableContainer.forEntities( ImmutableList.of( - new GtfsStop.Builder() - .setStopId("s0") - .setLocationType(GtfsLocationType.STOP) - .build(), - new GtfsStop.Builder() + GtfsStop.builder().setStopId("s0").setLocationType(GtfsLocationType.STOP).build(), + GtfsStop.builder() .setStopId("s1") .setLocationType(GtfsLocationType.STATION) .build()), @@ -96,29 +70,13 @@ public void testInvalidInSeatTransferToStation() { GtfsStopTimeTableContainer stopTimes = GtfsStopTimeTableContainer.forEntities( ImmutableList.of( - new GtfsStopTime.Builder() - .setTripId("t0") - .setStopId("s?") - .setStopSequence(0) - .build(), - new GtfsStopTime.Builder() - .setTripId("t0") - .setStopId("s0") - .setStopSequence(1) - .build(), - new GtfsStopTime.Builder() - .setTripId("t1") - .setStopId("s1") - .setStopSequence(0) - .build(), - new GtfsStopTime.Builder() - .setTripId("t1") - .setStopId("s?") - .setStopSequence(1) - .build()), + GtfsStopTime.builder().setTripId("t0").setStopId("s?").setStopSequence(0).build(), + GtfsStopTime.builder().setTripId("t0").setStopId("s0").setStopSequence(1).build(), + GtfsStopTime.builder().setTripId("t1").setStopId("s1").setStopSequence(0).build(), + GtfsStopTime.builder().setTripId("t1").setStopId("s?").setStopSequence(1).build()), noticeContainer); GtfsTransfer transfer = - new Builder() + GtfsTransfer.builder() .setCsvRowNumber(2) .setFromStopId("s0") .setToStopId("s1") @@ -143,41 +101,19 @@ public void testSuspiciousMidTripInSeatTransfer() { GtfsStopTableContainer stops = GtfsStopTableContainer.forEntities( ImmutableList.of( - new GtfsStop.Builder() - .setStopId("s0") - .setLocationType(GtfsLocationType.STOP) - .build(), - new GtfsStop.Builder() - .setStopId("s1") - .setLocationType(GtfsLocationType.STOP) - .build()), + GtfsStop.builder().setStopId("s0").setLocationType(GtfsLocationType.STOP).build(), + GtfsStop.builder().setStopId("s1").setLocationType(GtfsLocationType.STOP).build()), noticeContainer); GtfsStopTimeTableContainer stopTimes = GtfsStopTimeTableContainer.forEntities( ImmutableList.of( - new GtfsStopTime.Builder() - .setTripId("t0") - .setStopId("s0") - .setStopSequence(0) - .build(), - new GtfsStopTime.Builder() - .setTripId("t0") - .setStopId("s?") - .setStopSequence(1) - .build(), - new GtfsStopTime.Builder() - .setTripId("t1") - .setStopId("s?") - .setStopSequence(0) - .build(), - new GtfsStopTime.Builder() - .setTripId("t1") - .setStopId("s1") - .setStopSequence(1) - .build()), + GtfsStopTime.builder().setTripId("t0").setStopId("s0").setStopSequence(0).build(), + GtfsStopTime.builder().setTripId("t0").setStopId("s?").setStopSequence(1).build(), + GtfsStopTime.builder().setTripId("t1").setStopId("s?").setStopSequence(0).build(), + GtfsStopTime.builder().setTripId("t1").setStopId("s1").setStopSequence(1).build()), noticeContainer); GtfsTransfer transfer = - new Builder() + GtfsTransfer.builder() .setCsvRowNumber(2) .setFromStopId("s0") .setToStopId("s1") diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransfersStopTypeValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransfersStopTypeValidatorTest.java index 0add19d140..32d83ddc47 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransfersStopTypeValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransfersStopTypeValidatorTest.java @@ -6,7 +6,7 @@ import org.junit.Test; import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; import org.mobilitydata.gtfsvalidator.table.GtfsLocationType; -import org.mobilitydata.gtfsvalidator.table.GtfsStop.Builder; +import org.mobilitydata.gtfsvalidator.table.GtfsStop; import org.mobilitydata.gtfsvalidator.table.GtfsStopTableContainer; import org.mobilitydata.gtfsvalidator.table.GtfsTransfer; import org.mobilitydata.gtfsvalidator.table.GtfsTransferTableContainer; @@ -23,13 +23,16 @@ public void testStopToStationTransfer() { GtfsStopTableContainer stops = GtfsStopTableContainer.forEntities( ImmutableList.of( - new Builder().setStopId("s0").setLocationType(GtfsLocationType.STOP).build(), - new Builder().setStopId("s1").setLocationType(GtfsLocationType.STATION).build()), + GtfsStop.builder().setStopId("s0").setLocationType(GtfsLocationType.STOP).build(), + GtfsStop.builder() + .setStopId("s1") + .setLocationType(GtfsLocationType.STATION) + .build()), noticeContainer); GtfsTransferTableContainer transfers = GtfsTransferTableContainer.forEntities( ImmutableList.of( - new GtfsTransfer.Builder() + GtfsTransfer.builder() .setFromStopId("s0") .setToStopId("s1") .setTransferType(GtfsTransferType.RECOMMENDED) @@ -47,14 +50,17 @@ public void testEntranceToGenericNodeTransfer() { GtfsStopTableContainer stops = GtfsStopTableContainer.forEntities( ImmutableList.of( - new Builder().setStopId("s0").setLocationType(GtfsLocationType.ENTRANCE).build(), - new Builder() + GtfsStop.builder() + .setStopId("s0") + .setLocationType(GtfsLocationType.ENTRANCE) + .build(), + GtfsStop.builder() .setStopId("s1") .setLocationType(GtfsLocationType.GENERIC_NODE) .build()), noticeContainer); GtfsTransfer transfer = - new GtfsTransfer.Builder() + GtfsTransfer.builder() .setCsvRowNumber(2) .setFromStopId("s0") .setToStopId("s1") diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransfersTripReferenceValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransfersTripReferenceValidatorTest.java index ecb7bf97f6..5036ad1501 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransfersTripReferenceValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TransfersTripReferenceValidatorTest.java @@ -13,7 +13,7 @@ import org.mobilitydata.gtfsvalidator.table.GtfsTransfer; import org.mobilitydata.gtfsvalidator.table.GtfsTransferTableContainer; import org.mobilitydata.gtfsvalidator.table.GtfsTransferType; -import org.mobilitydata.gtfsvalidator.table.GtfsTrip.Builder; +import org.mobilitydata.gtfsvalidator.table.GtfsTrip; import org.mobilitydata.gtfsvalidator.table.GtfsTripTableContainer; import org.mobilitydata.gtfsvalidator.validator.TransfersTripReferenceValidator.TransferWithInvalidTripAndRouteNotice; import org.mobilitydata.gtfsvalidator.validator.TransfersTripReferenceValidator.TransferWithInvalidTripAndStopNotice; @@ -29,15 +29,15 @@ public void testValidTripReferences() { GtfsTripTableContainer trips = GtfsTripTableContainer.forEntities( ImmutableList.of( - new Builder().setTripId("t0").setRouteId("r0").build(), - new Builder().setTripId("t1").setRouteId("r1").build()), + GtfsTrip.builder().setTripId("t0").setRouteId("r0").build(), + GtfsTrip.builder().setTripId("t1").setRouteId("r1").build()), noticeContainer); GtfsStopTableContainer stops = GtfsStopTableContainer.forEntities( ImmutableList.of( - new GtfsStop.Builder().setStopId("s0").build(), - new GtfsStop.Builder().setStopId("s1_stop").setParentStation("s1_station").build(), - new GtfsStop.Builder() + GtfsStop.builder().setStopId("s0").build(), + GtfsStop.builder().setStopId("s1_stop").setParentStation("s1_station").build(), + GtfsStop.builder() .setStopId("s1_station") .setLocationType(GtfsLocationType.STATION) .build()), @@ -45,13 +45,13 @@ public void testValidTripReferences() { GtfsStopTimeTableContainer stopTimes = GtfsStopTimeTableContainer.forEntities( ImmutableList.of( - new GtfsStopTime.Builder().setTripId("t0").setStopId("s0").build(), - new GtfsStopTime.Builder().setTripId("t1").setStopId("s1_stop").build()), + GtfsStopTime.builder().setTripId("t0").setStopId("s0").build(), + GtfsStopTime.builder().setTripId("t1").setStopId("s1_stop").build()), noticeContainer); GtfsTransferTableContainer transfers = GtfsTransferTableContainer.forEntities( ImmutableList.of( - new GtfsTransfer.Builder() + GtfsTransfer.builder() .setCsvRowNumber(2) .setFromStopId("s0") .setFromRouteId("r0") @@ -77,24 +77,24 @@ public void testInvalidTripReferences() { GtfsTripTableContainer trips = GtfsTripTableContainer.forEntities( ImmutableList.of( - new Builder().setTripId("t0").setRouteId("r0").build(), - new Builder().setTripId("t1").setRouteId("r1").build()), + GtfsTrip.builder().setTripId("t0").setRouteId("r0").build(), + GtfsTrip.builder().setTripId("t1").setRouteId("r1").build()), noticeContainer); GtfsStopTableContainer stops = GtfsStopTableContainer.forEntities( ImmutableList.of( - new GtfsStop.Builder().setStopId("s0").build(), - new GtfsStop.Builder().setStopId("s1").build(), - new GtfsStop.Builder().setStopId("s2").build()), + GtfsStop.builder().setStopId("s0").build(), + GtfsStop.builder().setStopId("s1").build(), + GtfsStop.builder().setStopId("s2").build()), noticeContainer); GtfsStopTimeTableContainer stopTimes = GtfsStopTimeTableContainer.forEntities( ImmutableList.of( - new GtfsStopTime.Builder().setTripId("t0").setStopId("s0").build(), - new GtfsStopTime.Builder().setTripId("t1").setStopId("s1").build()), + GtfsStopTime.builder().setTripId("t0").setStopId("s0").build(), + GtfsStopTime.builder().setTripId("t1").setStopId("s1").build()), noticeContainer); GtfsTransfer transfer = - new GtfsTransfer.Builder() + GtfsTransfer.builder() .setCsvRowNumber(2) .setFromStopId("s0") // This is not the expected route id. diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TranslationFieldAndReferenceValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TranslationFieldAndReferenceValidatorTest.java index 5436b3e87e..5a24255364 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TranslationFieldAndReferenceValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TranslationFieldAndReferenceValidatorTest.java @@ -44,11 +44,11 @@ @RunWith(JUnit4.class) public final class TranslationFieldAndReferenceValidatorTest { - private static final GtfsAgency AGENCY = new GtfsAgency.Builder().setAgencyId("agency0").build(); + private static final GtfsAgency AGENCY = GtfsAgency.builder().setAgencyId("agency0").build(); private static final GtfsStopTime STOP_TIME = - new GtfsStopTime.Builder().setTripId("trip0").setStopSequence(0).build(); + GtfsStopTime.builder().setTripId("trip0").setStopSequence(0).build(); private static final GtfsFeedInfo FEED_INFO = - new GtfsFeedInfo.Builder().setFeedLang(Locale.CANADA).build(); + GtfsFeedInfo.builder().setFeedLang(Locale.CANADA).build(); private static final String[] NEW_FORMAT_CSV_HEADERS = new String[] { @@ -83,13 +83,13 @@ private static List generateNotices( @Test public void legacyFormat_yieldsNoNotice() { - GtfsTranslation translation = new GtfsTranslation.Builder().setCsvRowNumber(2).build(); + GtfsTranslation translation = GtfsTranslation.builder().setCsvRowNumber(2).build(); assertThat(generateNotices(CsvHeader.EMPTY, ImmutableList.of(translation))).isEmpty(); } @Test public void missingRequiredStandardFields_yieldsNotice() { - GtfsTranslation translation = new GtfsTranslation.Builder().setCsvRowNumber(2).build(); + GtfsTranslation translation = GtfsTranslation.builder().setCsvRowNumber(2).build(); assertThat( generateNotices(new CsvHeader(NEW_FORMAT_CSV_HEADERS), ImmutableList.of(translation))) .containsExactly( @@ -101,7 +101,7 @@ public void missingRequiredStandardFields_yieldsNotice() { @Test public void wrongTableName_yieldsNotice() { GtfsTranslation translation = - new GtfsTranslation.Builder() + GtfsTranslation.builder() .setCsvRowNumber(2) .setTableName("wrong") .setFieldName("any") @@ -115,7 +115,7 @@ public void wrongTableName_yieldsNotice() { @Test public void fieldValueDefined_yieldsNoNotice() { GtfsTranslation translation = - new GtfsTranslation.Builder() + GtfsTranslation.builder() .setCsvRowNumber(2) .setTableName("agency") .setFieldName("any") @@ -130,7 +130,7 @@ public void fieldValueDefined_yieldsNoNotice() { @Test public void recordIdAndFieldValueDefined_yieldsNotice() { GtfsTranslation translation = - new GtfsTranslation.Builder() + GtfsTranslation.builder() .setCsvRowNumber(2) .setTableName("agency") .setFieldName("any") @@ -146,7 +146,7 @@ public void recordIdAndFieldValueDefined_yieldsNotice() { @Test public void recordSubIdAndFieldValueDefined_yieldsNotice() { GtfsTranslation translation = - new GtfsTranslation.Builder() + GtfsTranslation.builder() .setCsvRowNumber(2) .setTableName("agency") .setFieldName("any") @@ -163,7 +163,7 @@ public void recordSubIdAndFieldValueDefined_yieldsNotice() { @Test public void noRecordIdForStopTable_yieldsNotice() { GtfsTranslation translation = - new GtfsTranslation.Builder() + GtfsTranslation.builder() .setCsvRowNumber(2) .setTableName("agency") .setFieldName("any") @@ -177,7 +177,7 @@ public void noRecordIdForStopTable_yieldsNotice() { @Test public void wrongRecordIdForStopTable_yieldsNotice() { GtfsTranslation translation = - new GtfsTranslation.Builder() + GtfsTranslation.builder() .setCsvRowNumber(2) .setTableName("agency") .setFieldName("any") @@ -192,7 +192,7 @@ public void wrongRecordIdForStopTable_yieldsNotice() { @Test public void feedInfoTranslation_yieldsNoNotice() { GtfsTranslation translation = - new GtfsTranslation.Builder() + GtfsTranslation.builder() .setCsvRowNumber(2) .setTableName("feed_info") .setFieldName("any") @@ -206,7 +206,7 @@ public void feedInfoTranslation_yieldsNoNotice() { @Test public void unexpectedRecordIdForFeedInfo_yieldsNotice() { GtfsTranslation translation = - new GtfsTranslation.Builder() + GtfsTranslation.builder() .setCsvRowNumber(2) .setTableName("feed_info") .setFieldName("any") @@ -221,7 +221,7 @@ public void unexpectedRecordIdForFeedInfo_yieldsNotice() { @Test public void agencyTranslation_yieldsNoNotice() { GtfsTranslation translation = - new GtfsTranslation.Builder() + GtfsTranslation.builder() .setCsvRowNumber(2) .setTableName("agency") .setFieldName("any") @@ -236,7 +236,7 @@ public void agencyTranslation_yieldsNoNotice() { @Test public void stopTimeTranslation_yieldsNoNotice() { GtfsTranslation translation = - new GtfsTranslation.Builder() + GtfsTranslation.builder() .setCsvRowNumber(2) .setTableName("stop_times") .setFieldName("any") @@ -252,7 +252,7 @@ public void stopTimeTranslation_yieldsNoNotice() { @Test public void unparsableIntegerForStopTime_yieldsNotice() { GtfsTranslation translation = - new GtfsTranslation.Builder() + GtfsTranslation.builder() .setCsvRowNumber(2) .setTableName("stop_times") .setFieldName("any") diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TripAndShapeDistanceValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TripAndShapeDistanceValidatorTest.java index 7b8efc84f5..1c419ae3e3 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TripAndShapeDistanceValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TripAndShapeDistanceValidatorTest.java @@ -18,7 +18,7 @@ private static List createTripTable(int rows) { ArrayList trips = new ArrayList<>(); for (int i = 0; i < rows; i++) { trips.add( - new GtfsTrip.Builder() + GtfsTrip.builder() .setCsvRowNumber(i + 1) .setTripId("t" + i) .setServiceId("sr" + i) @@ -34,7 +34,7 @@ private static List createShapeTable( ArrayList shapes = new ArrayList<>(); for (int i = 0; i < rows; i++) { shapes.add( - new GtfsShape.Builder() + GtfsShape.builder() .setCsvRowNumber(i + 1) .setShapeId("s" + i) .setShapePtLat(lonLat) @@ -50,7 +50,7 @@ private static List createStopTimesTable(int rows, double shapeDis ArrayList stopTimes = new ArrayList<>(); for (int i = 0; i < rows; i++) { stopTimes.add( - new GtfsStopTime.Builder() + GtfsStopTime.builder() .setCsvRowNumber(i + 1) .setTripId("t" + i) .setStopSequence(0) @@ -65,7 +65,7 @@ private static List createStopTable(int rows) { ArrayList stops = new ArrayList<>(); for (int i = 0; i < rows; i++) { stops.add( - new GtfsStop.Builder() + GtfsStop.builder() .setCsvRowNumber(i + 1) .setStopId("st" + i) .setStopLat(0.0) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TripUsabilityValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TripUsabilityValidatorTest.java index 5a1b3a9559..41a05ea92b 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TripUsabilityValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TripUsabilityValidatorTest.java @@ -32,7 +32,7 @@ public class TripUsabilityValidatorTest { public static GtfsTrip createTrip( int csvRowNumber, String routeId, String serviceId, String tripId) { - return new GtfsTrip.Builder() + return GtfsTrip.builder() .setCsvRowNumber(csvRowNumber) .setRouteId(routeId) .setServiceId(serviceId) @@ -42,7 +42,7 @@ public static GtfsTrip createTrip( public static GtfsStopTime createStopTime( int csvRowNumber, String tripId, String stopId, int stopSequence) { - return new GtfsStopTime.Builder() + return GtfsStopTime.builder() .setCsvRowNumber(csvRowNumber) .setTripId(tripId) .setStopSequence(stopSequence) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TripUsageValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TripUsageValidatorTest.java index 552832bf88..5155b77017 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TripUsageValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/TripUsageValidatorTest.java @@ -41,7 +41,7 @@ private static GtfsTripTableContainer createTripTable( public static GtfsTrip createTrip( int csvRowNumber, String routeId, String serviceId, String tripId) { - return new GtfsTrip.Builder() + return GtfsTrip.builder() .setCsvRowNumber(csvRowNumber) .setRouteId(routeId) .setServiceId(serviceId) @@ -51,7 +51,7 @@ public static GtfsTrip createTrip( public static GtfsStopTime createStopTime( int csvRowNumber, String tripId, String time, String stopId, int stopSequence) { - return new GtfsStopTime.Builder() + return GtfsStopTime.builder() .setCsvRowNumber(csvRowNumber) .setTripId(tripId) .setArrivalTime(GtfsTime.fromString(time)) diff --git a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/UrlConsistencyValidatorTest.java b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/UrlConsistencyValidatorTest.java index 24e44e5b48..412d0847ec 100644 --- a/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/UrlConsistencyValidatorTest.java +++ b/main/src/test/java/org/mobilitydata/gtfsvalidator/validator/UrlConsistencyValidatorTest.java @@ -53,7 +53,7 @@ private static List generateNotices( } private static GtfsAgency createAgency(int csvRowNumber, String agencyName, String agencyUrl) { - return new GtfsAgency.Builder() + return GtfsAgency.builder() .setCsvRowNumber(csvRowNumber) .setAgencyName(agencyName) .setAgencyUrl(agencyUrl) @@ -63,7 +63,7 @@ private static GtfsAgency createAgency(int csvRowNumber, String agencyName, Stri } private static GtfsRoute createRoute(int csvRowNumber, String agencyId, String routeUrl) { - return new GtfsRoute.Builder() + return GtfsRoute.builder() .setCsvRowNumber(csvRowNumber) .setRouteUrl(routeUrl) .setRouteId(String.format("route id %s", csvRowNumber)) @@ -75,7 +75,7 @@ private static GtfsRoute createRoute(int csvRowNumber, String agencyId, String r } private static GtfsStop createStop(int csvRowNumber, String stopUrl) { - return new GtfsStop.Builder() + return GtfsStop.builder() .setCsvRowNumber(csvRowNumber) .setStopId(String.format("stop id %s", csvRowNumber)) .setStopUrl(stopUrl) diff --git a/model/src/main/java/org/mobilitydata/gtfsvalidator/annotation/ColumnStoreTypes.java b/model/src/main/java/org/mobilitydata/gtfsvalidator/annotation/ColumnStoreTypes.java new file mode 100644 index 0000000000..c6a4b62340 --- /dev/null +++ b/model/src/main/java/org/mobilitydata/gtfsvalidator/annotation/ColumnStoreTypes.java @@ -0,0 +1,12 @@ +package org.mobilitydata.gtfsvalidator.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface ColumnStoreTypes { + Class[] value(); +} diff --git a/model/src/main/java/org/mobilitydata/gtfsvalidator/annotation/GtfsTable.java b/model/src/main/java/org/mobilitydata/gtfsvalidator/annotation/GtfsTable.java index 7618ff84e9..9193153848 100644 --- a/model/src/main/java/org/mobilitydata/gtfsvalidator/annotation/GtfsTable.java +++ b/model/src/main/java/org/mobilitydata/gtfsvalidator/annotation/GtfsTable.java @@ -20,6 +20,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.mobilitydata.gtfsvalidator.table.GtfsEntity; /** * Annotates an interface that defines schema for a single GTFS table, such as "stops.txt". @@ -48,4 +49,6 @@ * for the CSV Parser. */ int maxCharsPerColumn() default 0; + + Class extensionOf() default GtfsEntity.class; } diff --git a/model/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsEntityBuilder.java b/model/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsEntityBuilder.java index 903cab2ce1..40883f709f 100644 --- a/model/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsEntityBuilder.java +++ b/model/src/main/java/org/mobilitydata/gtfsvalidator/table/GtfsEntityBuilder.java @@ -18,4 +18,7 @@ public interface GtfsEntityBuilder { /** Sets row number in a CSV file. Returns self. */ GtfsEntityBuilder setCsvRowNumber(int value); + + /** Called once after no more entities remain to be built. */ + default void close() {} } diff --git a/processor/README.md b/processor/README.md new file mode 100644 index 0000000000..77f2fac2b3 --- /dev/null +++ b/processor/README.md @@ -0,0 +1,4 @@ + +```java +ClassName.get("com.google.auto.value", "AutoValue.Builder"); +``` \ No newline at end of file diff --git a/processor/columns/build.gradle b/processor/columns/build.gradle new file mode 100644 index 0000000000..ca18514fad --- /dev/null +++ b/processor/columns/build.gradle @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Google LLC, MobilityData IO + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id 'java' +} + +sourceCompatibility = JavaVersion.VERSION_11 +compileJava.options.encoding = "UTF-8" + +dependencies { + implementation project(':model') + annotationProcessor 'com.google.auto.service:auto-service:1.0.1' + compileOnly 'com.google.auto.service:auto-service:1.0.1' + implementation 'com.squareup:javapoet:1.13.0' + implementation 'org.apache.commons:commons-lang3:3.0' + implementation 'com.google.guava:guava:31.0.1-jre' + testImplementation group: 'junit', name: 'junit', version: '4.13' + testImplementation 'com.google.truth:truth:1.1.3' +} \ No newline at end of file diff --git a/processor/columns/src/main/java/org/mobilitydata/gtfsvalidator/processor/columns/ColumnStoreGenerator.java b/processor/columns/src/main/java/org/mobilitydata/gtfsvalidator/processor/columns/ColumnStoreGenerator.java new file mode 100644 index 0000000000..fc99afbfbf --- /dev/null +++ b/processor/columns/src/main/java/org/mobilitydata/gtfsvalidator/processor/columns/ColumnStoreGenerator.java @@ -0,0 +1,256 @@ +package org.mobilitydata.gtfsvalidator.processor.columns; + +import com.google.common.base.CaseFormat; +import com.squareup.javapoet.ArrayTypeName; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import com.squareup.javapoet.TypeSpec.Builder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import org.mobilitydata.gtfsvalidator.annotation.ColumnStoreTypes; +import org.mobilitydata.gtfsvalidator.annotation.Generated; + +public class ColumnStoreGenerator { + + private static final String INITIAL_CAPACITY_FIELD = "INITIAL_CAPACITY"; + + private static final String PRIMITIVE_PRESENCE_FIELD = "primitivePresenceByColumnIndex"; + + TypeSpec generate(TypeElement typesElement) { + List columnTypes = getColumnTypeMirrors(typesElement); + + TypeSpec.Builder typeSpec = + TypeSpec.classBuilder(getStoreClassName(typesElement)) + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Generated.class) + .addSuperinterface(typesElement.asType()) + .superclass(ClassName.get("org.mobilitydata.gtfsvalidator.columns", "ColumnStoreBase")); + + generateFields(columnTypes, typeSpec); + + for (ColumnType columnType : columnTypes) { + generateReserveMethod(columnType, typeSpec); + generateHasMethod(columnType, typeSpec); + generateGetMethod(columnType, typeSpec); + generateSetMethod(columnType, typeSpec); + } + + typeSpec.addMethod(generateTrimToSizeMethod(columnTypes)); + + return typeSpec.build(); + } + + private static String getStoreClassName(TypeElement typesElement) { + return typesElement.getSimpleName().toString().replace("Columns", "Column") + "Store"; + } + + private List getColumnTypeMirrors(TypeElement typesElement) { + return typesElement.getAnnotationMirrors().stream() + .filter(am -> am.getAnnotationType().toString().equals(ColumnStoreTypes.class.getName())) + .flatMap(am -> am.getElementValues().entrySet().stream()) + .filter(elem -> elem.getKey().toString().equals("value()")) + .flatMap(elem -> ((List) elem.getValue().getValue()).stream()) + .map(av -> constructColumnType((TypeMirror) av.getValue())) + .collect(Collectors.toList()); + } + + private void generateFields(List columnTypes, Builder typeSpec) { + typeSpec.addField( + FieldSpec.builder( + int.class, + INITIAL_CAPACITY_FIELD, + Modifier.PRIVATE, + Modifier.STATIC, + Modifier.FINAL) + .initializer("10") + .build()); + typeSpec.addField( + FieldSpec.builder( + ParameterizedTypeName.get(List.class, byte[].class), + PRIMITIVE_PRESENCE_FIELD, + Modifier.PRIVATE, + Modifier.FINAL) + .initializer("new $T<>()", ArrayList.class) + .build()); + + for (ColumnType columnType : columnTypes) { + ParameterizedTypeName listOfArraysType = + ParameterizedTypeName.get( + ClassName.get(List.class), ArrayTypeName.of(ClassName.get(columnType.type))); + typeSpec.addField( + FieldSpec.builder( + listOfArraysType, columnType.fieldName, Modifier.PRIVATE, Modifier.FINAL) + .initializer("new $T<>()", ArrayList.class) + .build()); + } + } + + private void generateReserveMethod(ColumnType columnType, TypeSpec.Builder typeSpec) { + CodeBlock.Builder body = CodeBlock.builder(); + if (columnType.type.getKind().isPrimitive()) { + body.addStatement( + "$T[] values = new $T[$L]", + columnType.typeName, + columnType.typeName, + INITIAL_CAPACITY_FIELD) + .addStatement("$L.add(values)", columnType.fieldName) + .addStatement("int col = $L.size() - 1", columnType.fieldName) + .addStatement( + "reservePrimitivePresence($L, col, $L)", + PRIMITIVE_PRESENCE_FIELD, + INITIAL_CAPACITY_FIELD) + .addStatement("return col"); + } else { + body.addStatement( + "return reserveColumn($L, $T.class, $L)", + columnType.fieldName, + columnType.typeName, + INITIAL_CAPACITY_FIELD); + } + typeSpec.addMethod( + MethodSpec.methodBuilder("reserve" + columnType.name + "Column") + .addModifiers(Modifier.PUBLIC) + .returns(int.class) + .addCode(body.build()) + .build()); + } + + private void generateHasMethod(ColumnType columnType, TypeSpec.Builder typeSpec) { + CodeBlock.Builder body = CodeBlock.builder(); + if (columnType.type.getKind().isPrimitive()) { + body.addStatement("return hasPrimitive($L, columnIndex, row)", PRIMITIVE_PRESENCE_FIELD); + } else { + body.addStatement("return hasValue($L, columnIndex, row)", columnType.fieldName); + } + typeSpec.addMethod( + MethodSpec.methodBuilder("has" + columnType.name) + .addModifiers(Modifier.PUBLIC) + .addParameter(int.class, "columnIndex") + .addParameter(int.class, "row") + .returns(boolean.class) + .addCode(body.build()) + .build()); + } + + private void generateGetMethod(ColumnType columnType, TypeSpec.Builder typeSpec) { + CodeBlock.Builder body = CodeBlock.builder(); + if (columnType.type.getKind().isPrimitive()) { + body.addStatement( + "return has$L(columnIndex, row) ? $L.get(columnIndex)[row] : defaultValue", + columnType.name, + columnType.fieldName); + } else { + body.addStatement( + "return getValue($L, columnIndex, row, defaultValue)", columnType.fieldName); + } + typeSpec.addMethod( + MethodSpec.methodBuilder("get" + columnType.name) + .addModifiers(Modifier.PUBLIC) + .addParameter(int.class, "columnIndex") + .addParameter(int.class, "row") + .addParameter(columnType.typeName, "defaultValue") + .returns(columnType.typeName) + .addCode(body.build()) + .build()); + } + + private void generateSetMethod(ColumnType columnType, TypeSpec.Builder typeSpec) { + CodeBlock.Builder body = CodeBlock.builder(); + if (columnType.type.getKind().isPrimitive()) { + body.add(generatePrimitiveSetMethod(columnType)); + } else { + body.addStatement("setValue($L, columnIndex, row, value)", columnType.fieldName); + } + typeSpec.addMethod( + MethodSpec.methodBuilder("set" + columnType.name) + .addModifiers(Modifier.PUBLIC) + .addParameter(int.class, "columnIndex") + .addParameter(int.class, "row") + .addParameter(columnType.typeName, "value") + .addCode(body.build()) + .build()); + } + + private CodeBlock generatePrimitiveSetMethod(ColumnType columnType) { + return CodeBlock.builder() + .addStatement( + "$T[] values = $L.get(columnIndex)", columnType.typeName, columnType.fieldName) + .beginControlFlow("if (values.length <= row)") + .addStatement("int newSize = calculateNewCapacity(values.length, row + 1)") + .addStatement("values = Arrays.copyOf(values, newSize)") + .addStatement("$L.set(columnIndex, values)", columnType.fieldName) + .endControlFlow() + .addStatement("values[row] = value") + .addStatement("setPrimitivePresence($L, columnIndex, row)", PRIMITIVE_PRESENCE_FIELD) + .build(); + } + + private MethodSpec generateTrimToSizeMethod(List columnTypes) { + CodeBlock.Builder code = CodeBlock.builder(); + for (ColumnType columnType : columnTypes) { + if (columnType.type.getKind().isPrimitive()) { + code.beginControlFlow("for (int i=0; i < $L.size(); ++i)", columnType.fieldName) + .addStatement("$T[] values = $L.get(i)", columnType.typeName, columnType.fieldName) + .addStatement( + "$L.set(i, $T.copyOf(values, newSize))", columnType.fieldName, Arrays.class) + .endControlFlow(); + } else { + code.addStatement("trimToSize($L, newSize)", columnType.fieldName); + } + } + return MethodSpec.methodBuilder("trimToSize") + .addModifiers(Modifier.PUBLIC) + .addParameter(int.class, "newSize") + .addCode(code.build()) + .build(); + } + + private static ColumnType constructColumnType(TypeMirror typeMirror) { + String name = getName(typeMirror); + String fieldName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, name) + "sByColumnIndex"; + return new ColumnType(name, fieldName, typeMirror); + } + + private static String getName(TypeMirror columnType) { + switch (columnType.getKind()) { + case BYTE: + return "Byte"; + case SHORT: + return "Short"; + case INT: + return "Int"; + case DOUBLE: + return "Double"; + case DECLARED: + return ((DeclaredType) columnType).asElement().getSimpleName().toString(); + default: + throw new UnsupportedOperationException("Unsupported kind: " + columnType.getKind()); + } + } + + private static class ColumnType { + final String name; + final String fieldName; + final TypeMirror type; + final TypeName typeName; + + ColumnType(String name, String fieldName, TypeMirror type) { + this.name = name; + this.fieldName = fieldName; + this.type = type; + this.typeName = ClassName.get(type); + } + } +} diff --git a/processor/columns/src/main/java/org/mobilitydata/gtfsvalidator/processor/columns/ColumnsProcessor.java b/processor/columns/src/main/java/org/mobilitydata/gtfsvalidator/processor/columns/ColumnsProcessor.java new file mode 100644 index 0000000000..a4182aefd7 --- /dev/null +++ b/processor/columns/src/main/java/org/mobilitydata/gtfsvalidator/processor/columns/ColumnsProcessor.java @@ -0,0 +1,70 @@ +package org.mobilitydata.gtfsvalidator.processor.columns; + +import static javax.lang.model.util.ElementFilter.typesIn; + +import com.google.auto.service.AutoService; +import com.google.common.collect.ImmutableSet; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.TypeSpec; +import java.io.IOException; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; +import org.mobilitydata.gtfsvalidator.annotation.ColumnStoreTypes; +import org.mobilitydata.gtfsvalidator.annotation.GtfsValidationNotice; +import org.mobilitydata.gtfsvalidator.notice.NoticeDocComments; + +/** + * A processor for {@link GtfsValidationNotice}-annotated notices that extracts source-file comments + * from the Java source and stores them as JSON-serialized {@link NoticeDocComments} resources in + * for run-time access later by the validator. + */ +@AutoService(Processor.class) +public class ColumnsProcessor extends AbstractProcessor { + + private ColumnStoreGenerator generator; + + @Override + public Set getSupportedAnnotationTypes() { + return ImmutableSet.of(ColumnStoreTypes.class.getName()); + } + + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + super.init(processingEnv); + generator = new ColumnStoreGenerator(); + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latestSupported(); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (TypeElement element : typesIn(roundEnv.getElementsAnnotatedWith(ColumnStoreTypes.class))) { + PackageElement pkg = processingEnv.getElementUtils().getPackageOf(element); + TypeSpec typeSpec = generator.generate(element); + writeJavaFile(JavaFile.builder(pkg.toString(), typeSpec).build()); + } + return false; + } + + private void writeJavaFile(JavaFile javaFile) { + try { + javaFile.writeTo(processingEnv.getFiler()); + } catch (IOException e) { + processingEnv + .getMessager() + .printMessage( + Diagnostic.Kind.ERROR, + String.format("failed to generate output file: %s", e.getMessage())); + } + } +} diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/Analyser.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/Analyser.java index 0a15d5577b..14c7dd1988 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/Analyser.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/Analyser.java @@ -20,6 +20,8 @@ import static org.mobilitydata.gtfsvalidator.processor.EnumGenerator.createEnumName; import static org.mobilitydata.gtfsvalidator.processor.GtfsEntityClasses.entityImplementationSimpleName; +import com.google.common.collect.ImmutableMap; +import com.squareup.javapoet.TypeName; import java.math.BigDecimal; import java.time.ZoneId; import java.util.Currency; @@ -29,6 +31,7 @@ import javax.lang.model.type.DeclaredType; import javax.lang.model.type.PrimitiveType; import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; import javax.lang.model.util.SimpleTypeVisitor8; import org.mobilitydata.gtfsvalidator.annotation.*; import org.mobilitydata.gtfsvalidator.parsing.RowParser.NumberBounds; @@ -47,7 +50,14 @@ */ public class Analyser { - public GtfsFileDescriptor analyzeGtfsFileType(TypeElement type) { + private final Elements elements; + + public Analyser(Elements elements) { + this.elements = elements; + } + + public GtfsFileDescriptor analyzeGtfsFileType( + TypeElement type, ImmutableMap enumDescriptorsByName) { GtfsFileDescriptor.Builder fileBuilder = GtfsFileDescriptor.builder(); GtfsTable gtfsFileAnnotation = type.getAnnotation(GtfsTable.class); fileBuilder.setFilename(gtfsFileAnnotation.value().toLowerCase()); @@ -57,6 +67,7 @@ public GtfsFileDescriptor analyzeGtfsFileType(TypeElement type) { } fileBuilder.interfacesBuilder().add(type.asType()); fileBuilder.setClassName(entityImplementationSimpleName(type.getSimpleName().toString())); + fileBuilder.setPackageName(elements.getPackageOf(type).getQualifiedName().toString()); fileBuilder.setRecommended(type.getAnnotation(Recommended.class) != null); fileBuilder.setRequired(type.getAnnotation(Required.class) != null); for (ExecutableElement method : methodsIn(type.getEnclosedElements())) { @@ -64,10 +75,20 @@ public GtfsFileDescriptor analyzeGtfsFileType(TypeElement type) { fieldBuilder.setName(method.getSimpleName().toString()); fieldBuilder.setJavaType(method.getReturnType()); FieldType fieldTypeAnnotation = method.getAnnotation(FieldType.class); - fieldBuilder.setType( + FieldTypeEnum fieldType = fieldTypeAnnotation != null ? fieldTypeAnnotation.value() - : javaTypeToGtfsType(method.getReturnType())); + : javaTypeToGtfsType(method.getReturnType()); + fieldBuilder.setType(fieldType); + if (fieldType == FieldTypeEnum.ENUM) { + String enumTypeName = + ((DeclaredType) method.getReturnType()).asElement().getSimpleName().toString(); + GtfsEnumDescriptor enumDescriptor = enumDescriptorsByName.get(enumTypeName); + if (enumDescriptor == null) { + throw new IllegalStateException("Field references unknown enum type: " + enumTypeName); + } + fieldBuilder.setEnumDescriptor(enumDescriptor); + } fieldBuilder.setRecommended(method.getAnnotation(Recommended.class) != null); fieldBuilder.setColumnRequired(method.getAnnotation(RequiredColumn.class) != null); fieldBuilder.setValueRequired(method.getAnnotation(Required.class) != null); @@ -173,15 +194,18 @@ protected FieldTypeEnum defaultAction(TypeMirror e, Void p) { public GtfsEnumDescriptor analyzeGtfsEnumType(TypeElement type) { GtfsEnumDescriptor.Builder enumBuilder = GtfsEnumDescriptor.builder(); enumBuilder.setName(createEnumName(type.getSimpleName().toString())); + enumBuilder.setPackageName(elements.getPackageOf(type).getQualifiedName().toString()); GtfsEnumValues valuesAnnotation = type.getAnnotation(GtfsEnumValues.class); if (valuesAnnotation != null) { // A typical enum has multiple values. for (GtfsEnumValue value : valuesAnnotation.value()) { addEnumValue(value, enumBuilder); } + enumBuilder.setFieldType(getFieldTypeForEnumValues(valuesAnnotation)); } else { // A trivial enum has a single values. addEnumValue(type.getAnnotation(GtfsEnumValue.class), enumBuilder); + enumBuilder.setFieldType(TypeName.BYTE); } return enumBuilder.build(); } @@ -191,4 +215,20 @@ private void addEnumValue(GtfsEnumValue value, GtfsEnumDescriptor.Builder enumBu .valuesBuilder() .add(GtfsEnumValueDescriptor.create(value.name().toUpperCase(), value.value())); } + + private static TypeName getFieldTypeForEnumValues(GtfsEnumValues valuesAnnotation) { + int minValue = 0; + int maxValue = 0; + for (GtfsEnumValue value : valuesAnnotation.value()) { + minValue = Math.min(minValue, value.value()); + maxValue = Math.max(maxValue, value.value()); + } + if (minValue >= Byte.MIN_VALUE && maxValue <= Byte.MAX_VALUE) { + return TypeName.BYTE; + } + if (minValue >= Short.MIN_VALUE && maxValue <= Short.MAX_VALUE) { + return TypeName.SHORT; + } + return TypeName.INT; + } } diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ColumnBasedEntityBuilderGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ColumnBasedEntityBuilderGenerator.java new file mode 100644 index 0000000000..c21b363cba --- /dev/null +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ColumnBasedEntityBuilderGenerator.java @@ -0,0 +1,175 @@ +package org.mobilitydata.gtfsvalidator.processor; + +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import com.squareup.javapoet.TypeSpec.Builder; +import javax.lang.model.element.Modifier; +import javax.lang.model.type.TypeMirror; +import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnAssignments; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnBasedCollectionFactory; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnBasedEntityBuilder; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnStore; + +public class ColumnBasedEntityBuilderGenerator { + + static final String CLASS_NAME = "Builder"; + + private final GtfsFileDescriptor fileDescriptor; + private final GtfsEntityClasses classNames; + private final GtfsFieldDescriptor csvRowNumberField; + + public ColumnBasedEntityBuilderGenerator( + GtfsFileDescriptor fileDescriptor, + GtfsEntityClasses classNames, + TypeMirror primitiveIntType) { + this.fileDescriptor = fileDescriptor; + this.classNames = classNames; + this.csvRowNumberField = + GtfsFieldDescriptor.builder() + .setName("csvRowNumber") + .setType(FieldTypeEnum.INTEGER) + .setJavaType(primitiveIntType) + .build(); + } + + public TypeSpec create() { + TypeSpec.Builder typeBuilder = + TypeSpec.classBuilder(CLASS_NAME) + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .superclass( + ParameterizedTypeName.get( + ClassName.get(GtfsColumnBasedEntityBuilder.class), + ClassName.get("", classNames.columnBasedEntityImplementationSimpleName()))); + + generateFields(typeBuilder); + + typeBuilder.addMethod(generateConstructor()); + typeBuilder.addMethod(generateCsvRowNumberGetter()); + generateSetters(typeBuilder); + typeBuilder.addMethod(generateBuildMethod()); + typeBuilder.addMethod(generateCloseMethod()); + typeBuilder.addMethod(generateAssignmentsMethod()); + typeBuilder.addMethod(generateCollectionFactoryMethod()); + + return typeBuilder.build(); + } + + private void generateFields(Builder typeBuilder) { + typeBuilder.addField( + FieldSpec.builder(ColumnBasedEntityColumnAssignmentsGenerator.TYPE_NAME, "assignments") + .addModifiers(Modifier.PRIVATE, Modifier.FINAL) + .initializer("new $T()", ColumnBasedEntityColumnAssignmentsGenerator.TYPE_NAME) + .build()); + } + + private MethodSpec generateConstructor() { + return MethodSpec.constructorBuilder() + .addModifiers(Modifier.PUBLIC) + .addParameter(ClassName.get(GtfsColumnStore.class), "store") + .addStatement("super(store)") + .build(); + } + + private MethodSpec generateCsvRowNumberGetter() { + return MethodSpec.methodBuilder("csvRowNumber") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .returns(int.class) + .addStatement("return store.getInt(assignments.csvRowNumber(), rowIndex, -1)") + .build(); + } + + private void generateSetters(TypeSpec.Builder typeSpec) { + generateSetter(csvRowNumberField, typeSpec); + for (GtfsFieldDescriptor field : fileDescriptor.fields()) { + generateSetter(field, typeSpec); + } + } + + private static void generateSetter(GtfsFieldDescriptor field, TypeSpec.Builder typeSpec) { + String columnGetterName = ColumnBasedEntityImplementationGenerator.getFieldTypeColumn(field); + + CodeBlock valueExpression = CodeBlock.of("value"); + if (field.type() == FieldTypeEnum.ENUM) { + valueExpression = CodeBlock.of("value.$LValue()", field.enumDescriptor().get().fieldType()); + } + + CodeBlock.Builder code = CodeBlock.builder(); + if (!field.javaType().getKind().isPrimitive()) { + code.beginControlFlow("if (value == null)").addStatement("return this").endControlFlow(); + } + code.beginControlFlow("if (assignments.$L() == -1)", field.name()) + .addStatement( + "assignments.$L(store.reserve$LColumn())", + FieldNameConverter.setterMethodName(field.name()), + columnGetterName) + .endControlFlow() + .addStatement( + "store.set$L(assignments.$L(), rowIndex, $L)", + columnGetterName, + field.name(), + valueExpression); + + TypeName parameterType = + field.type() == FieldTypeEnum.ENUM + ? ClassName.get(Integer.class) + : TypeName.get(field.javaType()); + typeSpec.addMethod( + MethodSpec.methodBuilder(FieldNameConverter.setterMethodName(field.name())) + .addModifiers(Modifier.PUBLIC) + .addParameter(parameterType, "value") + .returns(ClassName.get("", "Builder")) + .addCode(code.build()) + .addStatement("return this") + .build()); + } + + private MethodSpec generateBuildMethod() { + ClassName entityType = + ClassName.get("", classNames.columnBasedEntityImplementationSimpleName()); + return MethodSpec.methodBuilder("build") + .addModifiers(Modifier.PUBLIC) + .returns(entityType) + .addStatement("return new $T(store, assignments, rowIndex)", entityType) + .build(); + } + + private MethodSpec generateCloseMethod() { + return MethodSpec.methodBuilder("close") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .addStatement("store.trimToSize(rowIndex + 1)") + .build(); + } + + private MethodSpec generateAssignmentsMethod() { + return MethodSpec.methodBuilder("getAssignments") + .addModifiers(Modifier.PROTECTED) + .addAnnotation(Override.class) + .returns(GtfsColumnAssignments.class) + .addStatement("return assignments") + .build(); + } + + private MethodSpec generateCollectionFactoryMethod() { + return MethodSpec.methodBuilder("getCollectionFactory") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .returns( + ParameterizedTypeName.get( + ClassName.get(GtfsColumnBasedCollectionFactory.class), + classNames.columnBasedEntityImplementationTypeName())) + .addStatement( + "return new $T<$T>(store, assignments, $T::create)", + GtfsColumnBasedCollectionFactory.class, + classNames.columnBasedEntityImplementationTypeName(), + classNames.columnBasedEntityImplementationTypeName()) + .build(); + } +} diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ColumnBasedEntityColumnAssignmentsGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ColumnBasedEntityColumnAssignmentsGenerator.java new file mode 100644 index 0000000000..2c14342b94 --- /dev/null +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ColumnBasedEntityColumnAssignmentsGenerator.java @@ -0,0 +1,65 @@ +package org.mobilitydata.gtfsvalidator.processor; + +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.TypeSpec; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.lang.model.element.Modifier; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnAssignments; + +public class ColumnBasedEntityColumnAssignmentsGenerator { + + static final String CLASS_NAME = "ColumnAssignments"; + + static final ClassName TYPE_NAME = ClassName.get("", CLASS_NAME); + + private final GtfsFileDescriptor fileDescriptor; + private final GtfsEntityClasses classNames; + + public ColumnBasedEntityColumnAssignmentsGenerator( + GtfsFileDescriptor fileDescriptor, GtfsEntityClasses classNames) { + this.fileDescriptor = fileDescriptor; + this.classNames = classNames; + } + + public TypeSpec create() { + TypeSpec.Builder typeBuilder = + TypeSpec.classBuilder(CLASS_NAME) + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .addSuperinterface(GtfsColumnAssignments.class); + generateColumnIndexFields(typeBuilder); + return typeBuilder.build(); + } + + private void generateColumnIndexFields(TypeSpec.Builder typeBuilder) { + List fieldNames = new ArrayList<>(); + fieldNames.add("csvRowNumber"); + fieldNames.addAll( + fileDescriptor.fields().stream() + .map(GtfsFieldDescriptor::name) + .collect(Collectors.toList())); + for (String fieldName : fieldNames) { + typeBuilder.addField( + FieldSpec.builder(int.class, fieldName, Modifier.PRIVATE).initializer("-1").build()); + } + for (String fieldName : fieldNames) { + typeBuilder.addMethod( + MethodSpec.methodBuilder(fieldName) + .addModifiers(Modifier.PUBLIC) + .returns(int.class) + .addStatement("return $L", fieldName) + .build()); + } + for (String fieldName : fieldNames) { + typeBuilder.addMethod( + MethodSpec.methodBuilder(FieldNameConverter.setterMethodName(fieldName)) + .addModifiers(Modifier.PUBLIC) + .addParameter(int.class, "value") + .addStatement("$L = value", fieldName) + .build()); + } + } +} diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ColumnBasedEntityImplementationGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ColumnBasedEntityImplementationGenerator.java new file mode 100644 index 0000000000..23cc74f7d7 --- /dev/null +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ColumnBasedEntityImplementationGenerator.java @@ -0,0 +1,292 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mobilitydata.gtfsvalidator.processor; + +import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.fieldDefaultName; +import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.getValueMethodName; +import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.getterMethodName; +import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.hasMethodName; + +import com.google.common.base.CaseFormat; +import com.google.common.base.Preconditions; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import java.util.Objects; +import javax.lang.model.element.Modifier; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.ErrorType; +import javax.lang.model.type.PrimitiveType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.SimpleTypeVisitor8; +import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; +import org.mobilitydata.gtfsvalidator.annotation.Generated; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnAssignments; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnBasedEntity; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnStore; + +/** + * Generates a class that represent a single parsed row of a GTFS table. + * + *

E.g., GtfsStop class is generated for "stops.txt". + */ +public class ColumnBasedEntityImplementationGenerator { + + private static final String COLUMN_STORE_FIELD = "store"; + private static final String COLUMN_ASSIGNMENTS_FIELD = "assignments"; + private static final String ROW_INDEX_FIELD = "rowIndex"; + private static final Class ROW_INDEX_TYPE = int.class; + + private final GtfsFileDescriptor fileDescriptor; + private final GtfsEntityClasses classNames; + private final ColumnBasedEntityColumnAssignmentsGenerator assignmentGenerator; + + private final ColumnBasedEntityBuilderGenerator builderGenerator; + + public ColumnBasedEntityImplementationGenerator( + GtfsFileDescriptor fileDescriptor, TypeMirror primitiveIntType) { + this.fileDescriptor = fileDescriptor; + this.classNames = new GtfsEntityClasses(fileDescriptor); + this.assignmentGenerator = + new ColumnBasedEntityColumnAssignmentsGenerator(fileDescriptor, this.classNames); + this.builderGenerator = + new ColumnBasedEntityBuilderGenerator(fileDescriptor, this.classNames, primitiveIntType); + } + + public JavaFile generateGtfsEntityJavaFile() { + return JavaFile.builder(fileDescriptor.packageName(), generateGtfsEntityClass()).build(); + } + + public TypeSpec generateGtfsEntityClass() { + TypeSpec.Builder typeSpec = + TypeSpec.classBuilder(classNames.columnBasedEntityImplementationSimpleName()) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addAnnotation(Generated.class) + .superclass(ClassName.get(GtfsColumnBasedEntity.class)) + .addSuperinterface(classNames.entityTypeName()); + + generateFields(typeSpec); + typeSpec.addMethod(generateConstructor()); + typeSpec.addMethod(generateCreateMethod()); + typeSpec.addMethod(generateCsvRowNumberMethod()); + generateGetters(typeSpec); + generateHasValueMethods(typeSpec); + typeSpec.addMethod(generateAssignmentsMethod()); + typeSpec.addMethod(generateEqualsMethod()); + + typeSpec.addType(assignmentGenerator.create()); + typeSpec.addType(builderGenerator.create()); + + return typeSpec.build(); + } + + private void generateFields(TypeSpec.Builder typeSpec) { + typeSpec.addField( + ColumnBasedEntityColumnAssignmentsGenerator.TYPE_NAME, + COLUMN_ASSIGNMENTS_FIELD, + Modifier.PRIVATE, + Modifier.FINAL); + } + + private MethodSpec generateConstructor() { + return MethodSpec.constructorBuilder() + .addParameter(ClassName.get(GtfsColumnStore.class), COLUMN_STORE_FIELD) + .addParameter( + ColumnBasedEntityColumnAssignmentsGenerator.TYPE_NAME, COLUMN_ASSIGNMENTS_FIELD) + .addParameter(ROW_INDEX_TYPE, ROW_INDEX_FIELD) + .addStatement("super($L, $L)", COLUMN_STORE_FIELD, ROW_INDEX_FIELD) + .addStatement("this.$L = $L", COLUMN_ASSIGNMENTS_FIELD, COLUMN_ASSIGNMENTS_FIELD) + .build(); + } + + private MethodSpec generateCreateMethod() { + return MethodSpec.methodBuilder("create") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .returns(classNames.columnBasedEntityImplementationTypeName()) + .addParameter(ClassName.get(GtfsColumnStore.class), COLUMN_STORE_FIELD) + .addParameter(GtfsColumnAssignments.class, COLUMN_ASSIGNMENTS_FIELD) + .addParameter(ROW_INDEX_TYPE, ROW_INDEX_FIELD) + .addStatement( + "$T.checkState($L instanceof $T)", + Preconditions.class, + COLUMN_ASSIGNMENTS_FIELD, + ColumnBasedEntityColumnAssignmentsGenerator.TYPE_NAME) + .addStatement( + "return new $T($L, ($T) $L, $L)", + classNames.columnBasedEntityImplementationTypeName(), + COLUMN_STORE_FIELD, + ColumnBasedEntityColumnAssignmentsGenerator.TYPE_NAME, + COLUMN_ASSIGNMENTS_FIELD, + ROW_INDEX_FIELD) + .build(); + } + + private MethodSpec generateCsvRowNumberMethod() { + return MethodSpec.methodBuilder(getterMethodName("csvRowNumber")) + .addModifiers(Modifier.PUBLIC) + .returns(int.class) + .addAnnotation(Override.class) + .addStatement( + "return $L.getInt($L.csvRowNumber(), $L, -1)", + COLUMN_STORE_FIELD, + COLUMN_ASSIGNMENTS_FIELD, + ROW_INDEX_FIELD) + .build(); + } + + private void generateGetters(TypeSpec.Builder typeSpec) { + for (GtfsFieldDescriptor field : fileDescriptor.fields()) { + typeSpec.addMethod(generateGetterMethod(field)); + if (field.type() == FieldTypeEnum.ENUM) { + typeSpec.addMethod(generateEnumValueGetterMethod(field)); + } + } + } + + private MethodSpec generateGetterMethod(GtfsFieldDescriptor field) { + CodeBlock valueGetter = generateValueGetterCodeBlock(field); + if (field.type() == FieldTypeEnum.ENUM) { + valueGetter = CodeBlock.of("$L.forNumber($L)", field.javaType(), valueGetter); + } + return MethodSpec.methodBuilder(getterMethodName(field.name())) + .addModifiers(Modifier.PUBLIC) + .returns(TypeName.get(field.javaType())) + .addAnnotation(EntityGenerator.nullabilityAnnotation(field)) + .addAnnotation(Override.class) + .addStatement("return $L", valueGetter) + .build(); + } + + private MethodSpec generateEnumValueGetterMethod(GtfsFieldDescriptor field) { + CodeBlock valueGetter = generateValueGetterCodeBlock(field); + return MethodSpec.methodBuilder(getValueMethodName(field.name())) + .addModifiers(Modifier.PUBLIC) + .returns(TypeName.INT) + .addAnnotation(EntityGenerator.nullabilityAnnotation(field)) + .addAnnotation(Override.class) + .addStatement("return $L", valueGetter) + .build(); + } + + private CodeBlock generateValueGetterCodeBlock(GtfsFieldDescriptor field) { + String columnGetterName = getFieldTypeColumn(field); + return CodeBlock.of( + "$L.get$L($L.$L(), $L, $T.$L)", + COLUMN_STORE_FIELD, + columnGetterName, + COLUMN_ASSIGNMENTS_FIELD, + field.name(), + ROW_INDEX_FIELD, + classNames.entityTypeName(), + fieldDefaultName(field.name())); + } + + private void generateHasValueMethods(TypeSpec.Builder typeSpec) { + for (GtfsFieldDescriptor field : fileDescriptor.fields()) { + String columnGetterName = getFieldTypeColumn(field); + CodeBlock hasCodeBlock = + CodeBlock.of( + "return $L.has$L(assignments.$L(), $L)", + COLUMN_STORE_FIELD, + columnGetterName, + field.name(), + ROW_INDEX_FIELD); + + typeSpec.addMethod( + MethodSpec.methodBuilder(hasMethodName(field.name())) + .addModifiers(Modifier.PUBLIC) + .returns(boolean.class) + .addAnnotation(Override.class) + .addStatement(hasCodeBlock) + .build()); + } + } + + private MethodSpec generateAssignmentsMethod() { + return MethodSpec.methodBuilder("getAssignments") + .addModifiers(Modifier.PROTECTED) + .addAnnotation(Override.class) + .returns(GtfsColumnAssignments.class) + .addStatement("return $L", COLUMN_ASSIGNMENTS_FIELD) + .build(); + } + + private MethodSpec generateEqualsMethod() { + return MethodSpec.methodBuilder("equals") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .addParameter(Object.class, "rhs") + .returns(boolean.class) + .beginControlFlow("if (this == rhs)") + .addStatement("return true") + .endControlFlow() + .beginControlFlow("if (rhs == null || getClass() != rhs.getClass())") + .addStatement("return false") + .endControlFlow() + .addStatement( + "$T entity = ($T) rhs", + classNames.columnBasedEntityImplementationTypeName(), + classNames.columnBasedEntityImplementationTypeName()) + .addCode("return $T.equals(this.store, entity.store)", Objects.class) + .addCode(" && $T.equals(this.assignments, entity.assignments)", Objects.class) + .addStatement(" && this.rowIndex == entity.rowIndex", Objects.class) + .build(); + } + + static String getFieldTypeColumn(GtfsFieldDescriptor field) { + if (field.enumDescriptor().isPresent()) { + return capitalize(field.enumDescriptor().get().fieldType().toString()); + } + if (field.javaType().getKind().isPrimitive()) { + return capitalize(field.javaType().getKind().toString()); + } else if (field.javaType().getKind() == TypeKind.DECLARED) { + return ((DeclaredType) field.javaType()).asElement().getSimpleName().toString(); + } else { + throw new UnsupportedOperationException(); + } + } + + private static String capitalize(String name) { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name); + } + + static class FieldTypeGetterName extends SimpleTypeVisitor8 { + @Override + public String visitPrimitive(PrimitiveType t, Void p) { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, t.getKind().toString()); + } + + @Override + public String visitDeclared(DeclaredType t, Void p) { + return t.asElement().getSimpleName().toString(); + } + + @Override + public String visitError(ErrorType t, Void unused) { + return t.asElement().getSimpleName().toString(); + } + + @Override + protected String defaultAction(TypeMirror e, Void p) { + return "Int"; + } + } +} diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/CurrencyAmountValidatorGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/CurrencyAmountValidatorGenerator.java index 42d60f6927..bcf5026d3d 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/CurrencyAmountValidatorGenerator.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/CurrencyAmountValidatorGenerator.java @@ -58,15 +58,14 @@ private static TypeSpec generateValidator(GtfsFileDescriptor fileDescriptor) { .addAnnotation(GtfsValidator.class) .superclass( ParameterizedTypeName.get( - ClassName.get(SingleEntityValidator.class), - entityClasses.entityImplementationTypeName())); + ClassName.get(SingleEntityValidator.class), entityClasses.entityTypeName())); MethodSpec.Builder validateMethod = MethodSpec.methodBuilder("validate") .addModifiers(Modifier.PUBLIC) .addAnnotation(Override.class) .returns(void.class) - .addParameter(entityClasses.entityImplementationTypeName(), "entity") + .addParameter(entityClasses.entityTypeName(), "entity") .addParameter(NoticeContainer.class, "noticeContainer"); for (GtfsFieldDescriptor amountField : fileDescriptor.fields()) { diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EndRangeValidatorGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EndRangeValidatorGenerator.java index fa86a6fcb4..d2af81b553 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EndRangeValidatorGenerator.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EndRangeValidatorGenerator.java @@ -64,15 +64,14 @@ private static Optional generateValidator(GtfsFileDescriptor fileDescr .addAnnotation(GtfsValidator.class) .superclass( ParameterizedTypeName.get( - ClassName.get(SingleEntityValidator.class), - entityClasses.entityImplementationTypeName())); + ClassName.get(SingleEntityValidator.class), entityClasses.entityTypeName())); MethodSpec.Builder validateMethod = MethodSpec.methodBuilder("validate") .addModifiers(Modifier.PUBLIC) .addAnnotation(Override.class) .returns(void.class) - .addParameter(entityClasses.entityImplementationTypeName(), "entity") + .addParameter(entityClasses.entityTypeName(), "entity") .addParameter(NoticeContainer.class, "noticeContainer"); boolean hasEndRange = false; @@ -139,8 +138,7 @@ private static CodeBlock generateNoticeContext( GtfsFieldDescriptor startField, GtfsFieldDescriptor endField, StartEndRangeNoticeType noticeType) { - TypeName gtfsEntityTypeName = - new GtfsEntityClasses(fileDescriptor).entityImplementationTypeName(); + TypeName gtfsEntityTypeName = new GtfsEntityClasses(fileDescriptor).entityTypeName(); CodeBlock.Builder block = CodeBlock.builder().add("$T.FILENAME, entity.csvRowNumber(), ", gtfsEntityTypeName); if (fileDescriptor.hasSingleColumnPrimaryKey()) { diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EntityGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EntityGenerator.java new file mode 100644 index 0000000000..7ad07f11f5 --- /dev/null +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EntityGenerator.java @@ -0,0 +1,250 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mobilitydata.gtfsvalidator.processor; + +import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.fieldDefaultName; +import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.fieldNameField; +import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.getValueMethodName; +import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.getterMethodName; +import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.gtfsColumnName; +import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.hasMethodName; + +import com.google.common.collect.ImmutableMap; +import com.google.common.geometry.S2LatLng; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import java.math.BigDecimal; +import java.time.ZoneId; +import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.lang.model.element.Modifier; +import javax.lang.model.type.TypeMirror; +import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; +import org.mobilitydata.gtfsvalidator.annotation.Generated; +import org.mobilitydata.gtfsvalidator.table.GtfsEntity; +import org.mobilitydata.gtfsvalidator.type.GtfsColor; +import org.mobilitydata.gtfsvalidator.type.GtfsDate; +import org.mobilitydata.gtfsvalidator.type.GtfsTime; + +/** + * Generates a class that represent a single parsed row of a GTFS table. + * + *

E.g., GtfsStop class is generated for "stops.txt". + */ +public class EntityGenerator { + private final GtfsFileDescriptor fileDescriptor; + private final GtfsEntityClasses classNames; + + public EntityGenerator(GtfsFileDescriptor fileDescriptor) { + this.fileDescriptor = fileDescriptor; + this.classNames = new GtfsEntityClasses(fileDescriptor); + } + + static ImmutableMap createEnumIntegerFieldTypesMap( + List enumDescriptors) { + return enumDescriptors.stream() + .collect( + ImmutableMap.toImmutableMap( + GtfsEnumDescriptor::name, + EntityImplementationGenerator::chooseEnumIntegerFieldType)); + } + + static CodeBlock getDefaultValue(GtfsFieldDescriptor field) { + if (field.defaultValue().isPresent()) { + String valueString = field.defaultValue().get(); + switch (field.type()) { + case INTEGER: + case ENUM: + return CodeBlock.of(Integer.toString(Integer.parseInt(valueString))); + case FLOAT: + case LATITUDE: + case LONGITUDE: + return CodeBlock.of(Double.toString(Double.parseDouble(valueString))); + case COLOR: + return CodeBlock.of( + "$T.fromInt(0x$L)", + GtfsColor.class, + Integer.toHexString(Integer.parseInt(valueString, 16))); + case TEXT: + return CodeBlock.of("$S", valueString); + default: + // TODO: Support all types or throw an exception. + break; + } + } + switch (field.type()) { + case ENUM: + case INTEGER: + case FLOAT: + case LATITUDE: + case LONGITUDE: + return CodeBlock.of("0"); + case DECIMAL: + return CodeBlock.of("$T.ZERO", BigDecimal.class); + case COLOR: + return CodeBlock.of("$T.fromInt(0)", GtfsColor.class); + case TEXT: + case URL: + case PHONE_NUMBER: + case ID: + case EMAIL: + return CodeBlock.of("\"\""); + case DATE: + return CodeBlock.of("$T.fromEpochDay(0)", GtfsDate.class); + case TIME: + return CodeBlock.of("$T.fromSecondsSinceMidnight(0)", GtfsTime.class); + case TIMEZONE: + return CodeBlock.of("$T.of(\"UTC\")", ZoneId.class); + case CURRENCY_CODE: + case LANGUAGE_CODE: + default: + return CodeBlock.of("null"); + } + } + + static Class nullabilityAnnotation(GtfsFieldDescriptor field) { + return getDefaultValue(field).toString().equals("null") ? Nullable.class : Nonnull.class; + } + + public JavaFile generateGtfsEntityJavaFile() { + return JavaFile.builder(fileDescriptor.packageName(), generateGtfsEntityInterface()).build(); + } + + public TypeSpec generateGtfsEntityInterface() { + TypeSpec.Builder typeSpec = + TypeSpec.interfaceBuilder(classNames.entitySimpleName()) + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Generated.class) + .addSuperinterface(GtfsEntity.class); + + for (TypeMirror superinterface : fileDescriptor.interfaces()) { + typeSpec.addSuperinterface(superinterface); + } + + generateFilenameAndFieldNameConstants(typeSpec); + addDefaultValueFields(typeSpec); + + for (GtfsFieldDescriptor field : fileDescriptor.fields()) { + typeSpec.addMethod(generateGetterMethod(field)); + maybeAddEnumValueGetter(field, typeSpec); + typeSpec.addMethod(generateHasMethod(field)); + } + for (LatLonDescriptor latLonDescriptor : fileDescriptor.latLonFields()) { + typeSpec.addMethod(generateGetLatLonMethod(latLonDescriptor)); + typeSpec.addMethod(generateHasLatLonMethod(latLonDescriptor)); + } + + typeSpec.addMethod(generateBuilderMethod()); + + return typeSpec.build(); + } + + private void generateFilenameAndFieldNameConstants(TypeSpec.Builder typeSpec) { + typeSpec.addField( + FieldSpec.builder( + String.class, "FILENAME", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("$S", fileDescriptor.filename()) + .build()); + for (GtfsFieldDescriptor field : fileDescriptor.fields()) { + typeSpec.addField( + FieldSpec.builder( + String.class, + fieldNameField(field.name()), + Modifier.PUBLIC, + Modifier.STATIC, + Modifier.FINAL) + .initializer("$S", gtfsColumnName(field.name())) + .build()); + } + } + + private void addDefaultValueFields(TypeSpec.Builder typeSpec) { + for (GtfsFieldDescriptor field : fileDescriptor.fields()) { + typeSpec.addField( + FieldSpec.builder( + field.resolvedFieldTypeName(), + fieldDefaultName(field.name()), + Modifier.PUBLIC, + Modifier.STATIC, + Modifier.FINAL) + .initializer(getDefaultValue(field)) + .build()); + } + } + + private MethodSpec generateGetterMethod(GtfsFieldDescriptor field) { + return MethodSpec.methodBuilder(getterMethodName(field.name())) + .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) + .returns(TypeName.get(field.javaType())) + .addAnnotation(nullabilityAnnotation(field)) + .build(); + } + + private void maybeAddEnumValueGetter(GtfsFieldDescriptor field, TypeSpec.Builder typeSpec) { + if (!field.type().equals(FieldTypeEnum.ENUM)) { + return; + } + typeSpec.addMethod( + MethodSpec.methodBuilder(getValueMethodName(field.name())) + .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) + .returns(int.class) + .build()); + } + + private MethodSpec generateGetLatLonMethod(LatLonDescriptor latLonDescriptor) { + return MethodSpec.methodBuilder(latLonDescriptor.latLonField()) + .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT) + .returns(S2LatLng.class) + .addStatement( + "return $T.fromDegrees($L(), $L())", + S2LatLng.class, + latLonDescriptor.latField(), + latLonDescriptor.lonField()) + .build(); + } + + private MethodSpec generateHasLatLonMethod(LatLonDescriptor latLonDescriptor) { + return MethodSpec.methodBuilder(hasMethodName(latLonDescriptor.latLonField())) + .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT) + .returns(boolean.class) + .addStatement( + "return $L() && $L()", + hasMethodName(latLonDescriptor.latField()), + hasMethodName(latLonDescriptor.lonField())) + .build(); + } + + private MethodSpec generateHasMethod(GtfsFieldDescriptor field) { + return MethodSpec.methodBuilder(hasMethodName(field.name())) + .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) + .returns(boolean.class) + .build(); + } + + private MethodSpec generateBuilderMethod() { + return MethodSpec.methodBuilder("builder") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .returns(classNames.entityBuilderTypeName()) + .addStatement("return new $T()", classNames.entityBuilderTypeName()) + .build(); + } +} diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EntityImplementationGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EntityImplementationGenerator.java index e2aa25d1a8..091a23f3b1 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EntityImplementationGenerator.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EntityImplementationGenerator.java @@ -18,15 +18,11 @@ import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.clearMethodName; import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.fieldDefaultName; -import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.fieldNameField; import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.getValueMethodName; import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.getterMethodName; -import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.gtfsColumnName; import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.hasMethodName; import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.setterMethodName; -import static org.mobilitydata.gtfsvalidator.processor.GtfsEntityClasses.TABLE_PACKAGE_NAME; -import com.google.common.collect.ImmutableMap; import com.google.common.geometry.S2LatLng; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; @@ -39,15 +35,11 @@ import com.squareup.javapoet.TypeSpec; import java.math.BigDecimal; import java.time.ZoneId; -import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.lang.model.element.Modifier; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeMirror; import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; import org.mobilitydata.gtfsvalidator.annotation.Generated; -import org.mobilitydata.gtfsvalidator.table.GtfsEntity; import org.mobilitydata.gtfsvalidator.table.GtfsEntityBuilder; import org.mobilitydata.gtfsvalidator.type.GtfsColor; import org.mobilitydata.gtfsvalidator.type.GtfsDate; @@ -68,22 +60,10 @@ private enum ClassContext { private static final Class CSV_ROW_NUMBER_TYPE = int.class; private final GtfsFileDescriptor fileDescriptor; private final GtfsEntityClasses classNames; - private final ImmutableMap enumIntegerFieldTypes; - public EntityImplementationGenerator( - GtfsFileDescriptor fileDescriptor, List enumDescriptors) { + public EntityImplementationGenerator(GtfsFileDescriptor fileDescriptor) { this.fileDescriptor = fileDescriptor; this.classNames = new GtfsEntityClasses(fileDescriptor); - this.enumIntegerFieldTypes = createEnumIntegerFieldTypesMap(enumDescriptors); - } - - static ImmutableMap createEnumIntegerFieldTypesMap( - List enumDescriptors) { - return enumDescriptors.stream() - .collect( - ImmutableMap.toImmutableMap( - GtfsEnumDescriptor::name, - EntityImplementationGenerator::chooseEnumIntegerFieldType)); } static TypeName chooseEnumIntegerFieldType(GtfsEnumDescriptor enumDescriptor) { @@ -200,22 +180,14 @@ private static Class nullabilityAnnotation(GtfsFieldDescriptor field) { return getDefaultValue(field).toString().equals("null") ? Nullable.class : Nonnull.class; } - private TypeName getClassFieldType(GtfsFieldDescriptor field) { - if (field.type() == FieldTypeEnum.ENUM) { - return enumIntegerFieldTypes.getOrDefault( - ((DeclaredType) field.javaType()).asElement().getSimpleName().toString(), TypeName.INT); - } - return TypeName.get(field.javaType()); - } - public JavaFile generateGtfsEntityJavaFile() { - return JavaFile.builder(TABLE_PACKAGE_NAME, generateGtfsEntityClass()).build(); + return JavaFile.builder(fileDescriptor.packageName(), generateGtfsEntityClass()).build(); } private void addEntityOrBuilderFields(TypeSpec.Builder typeSpec) { typeSpec.addField(CSV_ROW_NUMBER_TYPE, CSV_ROW_NUMBER, Modifier.PRIVATE); for (GtfsFieldDescriptor field : fileDescriptor.fields()) { - typeSpec.addField(getClassFieldType(field), field.name(), Modifier.PRIVATE); + typeSpec.addField(field.resolvedFieldTypeName(), field.name(), Modifier.PRIVATE); } if (fileDescriptor.fields().size() <= 32) { typeSpec.addField( @@ -238,7 +210,7 @@ private void addDefaultValueFields(TypeSpec.Builder typeSpec) { for (GtfsFieldDescriptor field : fileDescriptor.fields()) { typeSpec.addField( FieldSpec.builder( - getClassFieldType(field), + field.resolvedFieldTypeName(), fieldDefaultName(field.name()), Modifier.PUBLIC, Modifier.STATIC, @@ -253,11 +225,7 @@ public TypeSpec generateGtfsEntityClass() { TypeSpec.classBuilder(classNames.entityImplementationSimpleName()) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addAnnotation(Generated.class) - .addSuperinterface(GtfsEntity.class); - - for (TypeMirror superinterface : fileDescriptor.interfaces()) { - typeSpec.addSuperinterface(superinterface); - } + .addSuperinterface(classNames.entityTypeName()); typeSpec.addMethod( MethodSpec.constructorBuilder() @@ -265,7 +233,6 @@ public TypeSpec generateGtfsEntityClass() { .addJavadoc("Use {@link Builder} class to construct an object.") .build()); - generateFilenameAndFieldNameConstants(typeSpec); addEntityOrBuilderFields(typeSpec); addDefaultValueFields(typeSpec); @@ -294,25 +261,6 @@ public TypeSpec generateGtfsEntityClass() { return typeSpec.build(); } - private void generateFilenameAndFieldNameConstants(TypeSpec.Builder typeSpec) { - typeSpec.addField( - FieldSpec.builder( - String.class, "FILENAME", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer("$S", fileDescriptor.filename()) - .build()); - for (GtfsFieldDescriptor field : fileDescriptor.fields()) { - typeSpec.addField( - FieldSpec.builder( - String.class, - fieldNameField(field.name()), - Modifier.PUBLIC, - Modifier.STATIC, - Modifier.FINAL) - .initializer("$S", gtfsColumnName(field.name())) - .build()); - } - } - private MethodSpec generateGetterMethod(GtfsFieldDescriptor field, ClassContext classContext) { MethodSpec.Builder method = MethodSpec.methodBuilder(getterMethodName(field.name())) @@ -369,7 +317,7 @@ private MethodSpec generateHasLatLonMethod(LatLonDescriptor latLonDescriptor) { } private MethodSpec generateSetterMethod(GtfsFieldDescriptor field, int fieldNumber) { - TypeName fieldType = getClassFieldType(field); + TypeName fieldType = field.resolvedFieldTypeName(); MethodSpec.Builder method = MethodSpec.methodBuilder(setterMethodName(field.name())) .addModifiers(Modifier.PUBLIC) diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EnumGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EnumGenerator.java index b5d36b9144..ea97ea03ce 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EnumGenerator.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/EnumGenerator.java @@ -18,7 +18,6 @@ import static java.lang.Math.max; import static java.lang.Math.min; -import static org.mobilitydata.gtfsvalidator.processor.GtfsEntityClasses.TABLE_PACKAGE_NAME; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; @@ -54,7 +53,7 @@ private static MethodSpec getNumberMethod() { } public JavaFile generateEnumJavaFile() { - return JavaFile.builder(TABLE_PACKAGE_NAME, generateEnumClass()).build(); + return JavaFile.builder(enumDescriptor.packageName(), generateEnumClass()).build(); } /** Returns the integer value for the special {@code UNRECOGNIZED} constant */ diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ForeignKeyValidatorGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ForeignKeyValidatorGenerator.java index 276e183b06..035e79ec99 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ForeignKeyValidatorGenerator.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/ForeignKeyValidatorGenerator.java @@ -113,8 +113,7 @@ private TypeSpec generateValidator( .returns(void.class) .addParameter(NoticeContainer.class, "noticeContainer") .beginControlFlow( - "for ($T childEntity: childContainer.getEntities())", - childClasses.entityImplementationTypeName()) + "for ($T childEntity: childContainer.getEntities())", childClasses.entityTypeName()) .beginControlFlow( "if (!childEntity.$L())", FieldNameConverter.hasMethodName(childField.name())) .addStatement("continue") diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsAnnotationProcessor.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsAnnotationProcessor.java index afa907421a..58f81d53c7 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsAnnotationProcessor.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsAnnotationProcessor.java @@ -16,10 +16,12 @@ package org.mobilitydata.gtfsvalidator.processor; +import static java.util.function.Function.identity; import static javax.lang.model.util.ElementFilter.typesIn; import static org.mobilitydata.gtfsvalidator.processor.GtfsEntityClasses.VALIDATOR_PACKAGE_NAME; import com.google.auto.service.AutoService; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.squareup.javapoet.JavaFile; @@ -36,6 +38,9 @@ import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.PrimitiveType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.util.Types; import javax.tools.Diagnostic; import org.mobilitydata.gtfsvalidator.annotation.GtfsEnumValue; import org.mobilitydata.gtfsvalidator.annotation.GtfsEnumValues; @@ -49,8 +54,6 @@ @AutoService(Processor.class) public class GtfsAnnotationProcessor extends AbstractProcessor { - private final Analyser analyser = new Analyser(); - /** * Sanitizes the result of {@link RoundEnvironment#getElementsAnnotatedWith}, which otherwise can * contain elements annotated with annotations of ERROR type. @@ -84,6 +87,11 @@ public synchronized void init(ProcessingEnvironment processingEnv) { @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { + Analyser analyser = new Analyser(processingEnv.getElementUtils()); + + Types typeUtils = processingEnv.getTypeUtils(); + PrimitiveType primitiveIntType = typeUtils.getPrimitiveType(TypeKind.INT); + List enumDescriptors = new ArrayList<>(); for (TypeElement type : typesIn(annotatedElementsIn(roundEnv, GtfsEnumValues.class))) { enumDescriptors.add(analyser.analyzeGtfsEnumType(type)); @@ -95,14 +103,19 @@ public boolean process(Set annotations, RoundEnvironment for (GtfsEnumDescriptor enumDescriptor : enumDescriptors) { writeJavaFile(new EnumGenerator(enumDescriptor).generateEnumJavaFile()); } + ImmutableMap enumDescriptorsByName = + enumDescriptors.stream() + .collect(ImmutableMap.toImmutableMap(GtfsEnumDescriptor::name, identity())); List fileDescriptors = new ArrayList<>(); for (TypeElement type : typesIn(annotatedElementsIn(roundEnv, GtfsTable.class))) { - fileDescriptors.add(analyser.analyzeGtfsFileType(type)); + fileDescriptors.add(analyser.analyzeGtfsFileType(type, enumDescriptorsByName)); } for (GtfsFileDescriptor fileDescriptor : fileDescriptors) { + writeJavaFile(new EntityGenerator(fileDescriptor).generateGtfsEntityJavaFile()); + writeJavaFile(new EntityImplementationGenerator(fileDescriptor).generateGtfsEntityJavaFile()); writeJavaFile( - new EntityImplementationGenerator(fileDescriptor, enumDescriptors) + new ColumnBasedEntityImplementationGenerator(fileDescriptor, primitiveIntType) .generateGtfsEntityJavaFile()); writeJavaFile(new TableDescriptorGenerator(fileDescriptor).generateGtfsDescriptorJavaFile()); writeJavaFile(new TableContainerGenerator(fileDescriptor).generateGtfsContainerJavaFile()); diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsEntityClasses.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsEntityClasses.java index 8c139b703f..e1ba7d8a84 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsEntityClasses.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsEntityClasses.java @@ -25,20 +25,22 @@ */ public final class GtfsEntityClasses { - public static final String TABLE_PACKAGE_NAME = "org.mobilitydata.gtfsvalidator.table"; public static final String VALIDATOR_PACKAGE_NAME = "org.mobilitydata.gtfsvalidator.validator"; public static final String SCHEMA_SUFFIX = "Schema"; + private final String packageName; + /** Upper camelcase name, e.g., GtfsStopTime. */ private final String className; - public GtfsEntityClasses(String className) { + public GtfsEntityClasses(String packageName, String className) { + this.packageName = packageName; this.className = className; } public GtfsEntityClasses(GtfsFileDescriptor fileDescriptor) { - this(fileDescriptor.className()); + this(fileDescriptor.packageName(), fileDescriptor.className()); } public static String entityImplementationSimpleName(String schemaName) { @@ -48,10 +50,18 @@ public static String entityImplementationSimpleName(String schemaName) { return schemaName.substring(0, schemaName.length() - SCHEMA_SUFFIX.length()); } - public String entityImplementationSimpleName() { + public String entitySimpleName() { return className; } + public String entityImplementationSimpleName() { + return className + "Impl"; + } + + public String columnBasedEntityImplementationSimpleName() { + return className + "ColumnBased"; + } + public String tableDescriptorSimpleName() { return className + "TableDescriptor"; } @@ -60,19 +70,35 @@ public String tableContainerSimpleName() { return className + "TableContainer"; } + public String tableContainerColumnBasedSimpleName() { + return className + "ColumnBasedTableContainer"; + } + + public ClassName entityTypeName() { + return ClassName.get(packageName, entitySimpleName()); + } + public ClassName entityImplementationTypeName() { - return ClassName.get(TABLE_PACKAGE_NAME, entityImplementationSimpleName()); + return ClassName.get(packageName, entityImplementationSimpleName()); + } + + public ClassName columnBasedEntityImplementationTypeName() { + return ClassName.get(packageName, columnBasedEntityImplementationSimpleName()); } public ClassName entityBuilderTypeName() { - return ClassName.get(TABLE_PACKAGE_NAME, entityImplementationSimpleName() + ".Builder"); + return ClassName.get(packageName, entityImplementationSimpleName() + ".Builder"); + } + + public ClassName columnBasedEntityBuilderTypeName() { + return ClassName.get(packageName, columnBasedEntityImplementationSimpleName() + ".Builder"); } public ClassName tableDescriptorTypeName() { - return ClassName.get(TABLE_PACKAGE_NAME, tableDescriptorSimpleName()); + return ClassName.get(packageName, tableDescriptorSimpleName()); } public ClassName tableContainerTypeName() { - return ClassName.get(TABLE_PACKAGE_NAME, tableContainerSimpleName()); + return ClassName.get(packageName, tableContainerSimpleName()); } } diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsEnumDescriptor.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsEnumDescriptor.java index c40c5cf30d..3ff6520cef 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsEnumDescriptor.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsEnumDescriptor.java @@ -18,6 +18,7 @@ import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; +import com.squareup.javapoet.TypeName; /** Describes a GTFS enumeration that consists of several integer constants. */ @AutoValue @@ -28,14 +29,22 @@ public static Builder builder() { public abstract String name(); + public abstract String packageName(); + public abstract ImmutableList values(); + public abstract TypeName fieldType(); + @AutoValue.Builder public abstract static class Builder { public abstract Builder setName(String value); + public abstract Builder setPackageName(String value); + public abstract ImmutableList.Builder valuesBuilder(); + public abstract Builder setFieldType(TypeName value); + public abstract GtfsEnumDescriptor build(); } } diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsFieldDescriptor.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsFieldDescriptor.java index c5c6374fac..66f7c8ddf3 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsFieldDescriptor.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsFieldDescriptor.java @@ -17,6 +17,7 @@ package org.mobilitydata.gtfsvalidator.processor; import com.google.auto.value.AutoValue; +import com.squareup.javapoet.TypeName; import java.util.Optional; import javax.lang.model.type.TypeMirror; import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; @@ -28,7 +29,14 @@ public abstract class GtfsFieldDescriptor { public static GtfsFieldDescriptor.Builder builder() { - return new AutoValue_GtfsFieldDescriptor.Builder(); + return new AutoValue_GtfsFieldDescriptor.Builder() + .setCached(false) + .setColumnRecommended(false) + .setColumnRequired(false) + .setIndex(false) + .setMixedCase(false) + .setRecommended(false) + .setValueRequired(false); } // Static properties. @@ -38,6 +46,15 @@ public static GtfsFieldDescriptor.Builder builder() { public abstract TypeMirror javaType(); + public abstract Optional enumDescriptor(); + + public TypeName resolvedFieldTypeName() { + if (type() == FieldTypeEnum.ENUM) { + return enumDescriptor().get().fieldType(); + } + return TypeName.get(javaType()); + } + public abstract Optional primaryKey(); public abstract boolean index(); @@ -77,6 +94,8 @@ public abstract static class Builder { public abstract Builder setJavaType(TypeMirror value); + public abstract Builder setEnumDescriptor(GtfsEnumDescriptor enumDescriptor); + public abstract Builder setRecommended(boolean value); public abstract Builder setValueRequired(boolean value); diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsFileDescriptor.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsFileDescriptor.java index aa7cc11057..227044db87 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsFileDescriptor.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/GtfsFileDescriptor.java @@ -40,6 +40,8 @@ public static Builder builder() { public abstract String className(); + public abstract String packageName(); + public abstract boolean recommended(); public abstract boolean required(); @@ -85,6 +87,8 @@ public abstract static class Builder { public abstract Builder setClassName(String value); + public abstract Builder setPackageName(String value); + public abstract Builder setRecommended(boolean value); public abstract Builder setRequired(boolean value); diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/LatLonValidatorGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/LatLonValidatorGenerator.java index bed95fd29a..701cd2afff 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/LatLonValidatorGenerator.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/LatLonValidatorGenerator.java @@ -66,15 +66,14 @@ private static TypeSpec generateValidator(GtfsFileDescriptor fileDescriptor) { .addAnnotation(GtfsValidator.class) .superclass( ParameterizedTypeName.get( - ClassName.get(SingleEntityValidator.class), - entityClasses.entityImplementationTypeName())); + ClassName.get(SingleEntityValidator.class), entityClasses.entityTypeName())); MethodSpec.Builder validateMethod = MethodSpec.methodBuilder("validate") .addModifiers(Modifier.PUBLIC) .addAnnotation(Override.class) .returns(void.class) - .addParameter(entityClasses.entityImplementationTypeName(), "entity") + .addParameter(entityClasses.entityTypeName(), "entity") .addParameter(NoticeContainer.class, "noticeContainer"); for (LatLonDescriptor latLonDescriptor : fileDescriptor.latLonFields()) { @@ -117,8 +116,7 @@ private static void validateLatLon( private static CodeBlock generateNoticeContext( GtfsFileDescriptor fileDescriptor, LatLonDescriptor latLonDescriptor) { - TypeName gtfsEntityTypeName = - new GtfsEntityClasses(fileDescriptor).entityImplementationTypeName(); + TypeName gtfsEntityTypeName = new GtfsEntityClasses(fileDescriptor).entityTypeName(); CodeBlock.Builder block = CodeBlock.builder().add("$T.FILENAME, entity.csvRowNumber(), ", gtfsEntityTypeName); if (fileDescriptor.hasSingleColumnPrimaryKey()) { diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/MixedCaseValidatorGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/MixedCaseValidatorGenerator.java index a8e9d413d9..2b15271f60 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/MixedCaseValidatorGenerator.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/MixedCaseValidatorGenerator.java @@ -55,15 +55,14 @@ private static TypeSpec generateValidator(GtfsFileDescriptor fileDescriptor) { .addAnnotation(GtfsValidator.class) .superclass( ParameterizedTypeName.get( - ClassName.get(SingleEntityValidator.class), - entityClasses.entityImplementationTypeName())); + ClassName.get(SingleEntityValidator.class), entityClasses.entityTypeName())); MethodSpec.Builder validateMethod = MethodSpec.methodBuilder("validate") .addModifiers(Modifier.PUBLIC) .addAnnotation(Override.class) .returns(void.class) - .addParameter(entityClasses.entityImplementationTypeName(), "entity") + .addParameter(entityClasses.entityTypeName(), "entity") .addParameter(NoticeContainer.class, "noticeContainer"); for (GtfsFieldDescriptor mixedCaseField : fileDescriptor.fields()) { diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/TableContainerGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/TableContainerGenerator.java index f215ecdf0a..42cc4fc57f 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/TableContainerGenerator.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/TableContainerGenerator.java @@ -16,9 +16,8 @@ package org.mobilitydata.gtfsvalidator.processor; -import static org.mobilitydata.gtfsvalidator.processor.GtfsEntityClasses.TABLE_PACKAGE_NAME; - import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterizedTypeName; @@ -52,15 +51,15 @@ public TableContainerGenerator(GtfsFileDescriptor fileDescriptor) { this.indexGenerator = new TableContainerIndexGenerator(fileDescriptor); this.tableDescriptorType = ParameterizedTypeName.get( - ClassName.get(GtfsTableDescriptor.class), classNames.entityImplementationTypeName()); + ClassName.get(GtfsTableDescriptor.class), classNames.entityTypeName()); } public JavaFile generateGtfsContainerJavaFile() { - return JavaFile.builder(TABLE_PACKAGE_NAME, generateGtfsContainerClass()).build(); + return JavaFile.builder(fileDescriptor.packageName(), generateGtfsContainerClass()).build(); } public TypeSpec generateGtfsContainerClass() { - TypeName gtfsEntityType = classNames.entityImplementationTypeName(); + TypeName gtfsEntityType = classNames.entityTypeName(); TypeSpec.Builder typeSpec = TypeSpec.classBuilder(classNames.tableContainerSimpleName()) .superclass( @@ -81,7 +80,7 @@ public TypeSpec generateGtfsContainerClass() { .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC) .returns(String.class) - .addStatement("return $T.FILENAME", classNames.entityImplementationTypeName()) + .addStatement("return $T.FILENAME", classNames.entityTypeName()) .build()); typeSpec.addField( @@ -103,7 +102,8 @@ public TypeSpec generateGtfsContainerClass() { typeSpec.addMethod(generateForEntitiesMethod()); typeSpec.addMethod(generateForStatusMethod()); - indexGenerator.generateMethods(typeSpec); + CodeBlock initializers = indexGenerator.generateMethods(typeSpec); + typeSpec.addMethod(generateInternalConstructor(initializers)); return typeSpec.build(); } @@ -114,11 +114,9 @@ private MethodSpec generateConstructorWithEntities() { .addParameter(tableDescriptorType, "descriptor") .addParameter(CsvHeader.class, "header") .addParameter( - ParameterizedTypeName.get( - ClassName.get(List.class), classNames.entityImplementationTypeName()), + ParameterizedTypeName.get(ClassName.get(List.class), classNames.entityTypeName()), "entities") - .addStatement("super(descriptor, TableStatus.PARSABLE_HEADERS_AND_ROWS, header)") - .addStatement("this.entities = entities") + .addStatement("this(descriptor, TableStatus.PARSABLE_HEADERS_AND_ROWS, header, entities)") .build(); } @@ -127,8 +125,23 @@ private MethodSpec generateConstructorWithStatus() { .addModifiers(Modifier.PUBLIC) .addParameter(tableDescriptorType, "descriptor") .addParameter(GtfsTableContainer.TableStatus.class, "tableStatus") - .addStatement("super(descriptor, tableStatus, $T.EMPTY)", CsvHeader.class) - .addStatement("this.entities = new $T<>()", ArrayList.class) + .addStatement( + "this(descriptor, tableStatus, $T.EMPTY, new $T<>())", CsvHeader.class, ArrayList.class) + .build(); + } + + private MethodSpec generateInternalConstructor(CodeBlock initializers) { + return MethodSpec.constructorBuilder() + .addModifiers(Modifier.PRIVATE) + .addParameter(tableDescriptorType, "descriptor") + .addParameter(GtfsTableContainer.TableStatus.class, "tableStatus") + .addParameter(CsvHeader.class, "header") + .addParameter( + ParameterizedTypeName.get(ClassName.get(List.class), classNames.entityTypeName()), + "entities") + .addStatement("super(descriptor, tableStatus, header)") + .addStatement("this.entities = entities") + .addCode(initializers) .build(); } @@ -141,8 +154,7 @@ private MethodSpec generateForHeaderAndEntitiesMethod() { .addParameter(tableDescriptorType, "descriptor") .addParameter(CsvHeader.class, "header") .addParameter( - ParameterizedTypeName.get( - ClassName.get(List.class), classNames.entityImplementationTypeName()), + ParameterizedTypeName.get(ClassName.get(List.class), classNames.entityTypeName()), "entities") .addParameter(NoticeContainer.class, "noticeContainer") .addStatement( @@ -163,8 +175,7 @@ private MethodSpec generateForEntitiesMethod() { + " used in tests.") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .addParameter( - ParameterizedTypeName.get( - ClassName.get(List.class), classNames.entityImplementationTypeName()), + ParameterizedTypeName.get(ClassName.get(List.class), classNames.entityTypeName()), "entities") .addParameter(NoticeContainer.class, "noticeContainer") .addStatement( diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/TableContainerIndexGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/TableContainerIndexGenerator.java index 3586d43200..1792cfe84d 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/TableContainerIndexGenerator.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/TableContainerIndexGenerator.java @@ -21,6 +21,7 @@ import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; +import com.squareup.javapoet.TypeSpec.Builder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -30,6 +31,7 @@ import javax.annotation.Nullable; import javax.lang.model.element.Modifier; import org.mobilitydata.gtfsvalidator.annotation.TranslationRecordIdType; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnBasedCollectionFactory; import org.mobilitydata.gtfsvalidator.notice.DuplicateKeyNotice; import org.mobilitydata.gtfsvalidator.notice.MoreThanOneEntityNotice; import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; @@ -51,14 +53,16 @@ class TableContainerIndexGenerator { this.classNames = new GtfsEntityClasses(fileDescriptor); } - void generateMethods(TypeSpec.Builder typeSpec) { + CodeBlock generateMethods(TypeSpec.Builder typeSpec) { + InitializerBlocks initBlocks = new InitializerBlocks(); + if (fileDescriptor.singleRow()) { typeSpec.addMethod( MethodSpec.methodBuilder("getSingleEntity") .addModifiers(Modifier.PUBLIC) .returns( ParameterizedTypeName.get( - ClassName.get(Optional.class), classNames.entityImplementationTypeName())) + ClassName.get(Optional.class), classNames.entityTypeName())) .addStatement( "return entities.isEmpty() ? Optional.empty() : Optional.of(entities.get(0))") .build()); @@ -66,9 +70,10 @@ void generateMethods(TypeSpec.Builder typeSpec) { addMapWithGetter( typeSpec, fileDescriptor.getSingleColumnPrimaryKey(), - classNames.entityImplementationTypeName()); + classNames.entityTypeName(), + initBlocks); } else if (fileDescriptor.hasMultiColumnPrimaryKey()) { - addMapByCompositeKey(typeSpec, classNames.entityImplementationTypeName()); + addMapByCompositeKey(typeSpec, classNames.entityTypeName(), initBlocks); } for (GtfsFieldDescriptor indexField : fileDescriptor.indices()) { @@ -76,7 +81,8 @@ void generateMethods(TypeSpec.Builder typeSpec) { typeSpec, indexField, resolveSequenceField(indexField), - classNames.entityImplementationTypeName()); + classNames.entityTypeName(), + initBlocks); } typeSpec.addMethod(generateByTranslationKeyMethod()); @@ -88,6 +94,8 @@ void generateMethods(TypeSpec.Builder typeSpec) { if (fileDescriptor.hasMultiColumnPrimaryKey()) { typeSpec.addType(compositeKeyClass()); } + + return generateInitializerCodeBlock(initBlocks); } private Optional resolveSequenceField(GtfsFieldDescriptor indexField) { @@ -107,16 +115,24 @@ private static void addListMultimapWithGetters( TypeSpec.Builder typeSpec, GtfsFieldDescriptor indexField, Optional sequenceField, - TypeName entityTypeName) { + TypeName entityTypeName, + InitializerBlocks initBlocks) { TypeName keyMapType = ParameterizedTypeName.get( ClassName.get(ListMultimap.class), TypeName.get(indexField.javaType()), entityTypeName); String methodName = byKeyMethodName(indexField.name()); String fieldName = byKeyMapName(indexField.name()); - typeSpec.addField( - FieldSpec.builder(keyMapType, fieldName, Modifier.PRIVATE) - .initializer("$T.create()", ParameterizedTypeName.get(ArrayListMultimap.class)) - .build()); + typeSpec.addField(keyMapType, fieldName, Modifier.PRIVATE); + initBlocks.simple.addStatement( + "this.$L = $T.create()", fieldName, ParameterizedTypeName.get(ArrayListMultimap.class)); + initBlocks.columnBased.addStatement( + "this.$L = $T.<$T, $T>newListMultimap(new $T<>(), factory::createSomeEntitiesList)", + fieldName, + Multimaps.class, + TypeName.get(indexField.javaType()), + ParameterizedTypeName.get(ClassName.get(List.class), entityTypeName), + HashMap.class); + String sortedBy = sequenceField .map((f) -> " sorted by " + FieldNameConverter.gtfsColumnName(f.name())) @@ -144,16 +160,19 @@ private static void addListMultimapWithGetters( } private static void addMapWithGetter( - TypeSpec.Builder typeSpec, GtfsFieldDescriptor indexField, TypeName entityTypeName) { + Builder typeSpec, + GtfsFieldDescriptor indexField, + TypeName entityTypeName, + InitializerBlocks initBlocks) { String methodName = byKeyMethodName(indexField.name()); String fieldName = byKeyMapName(indexField.name()); TypeName keyMapType = ParameterizedTypeName.get( ClassName.get(Map.class), TypeName.get(indexField.javaType()), entityTypeName); - typeSpec.addField( - FieldSpec.builder(keyMapType, fieldName, Modifier.PRIVATE) - .initializer("new $T<>()", ParameterizedTypeName.get(HashMap.class)) - .build()); + typeSpec.addField(keyMapType, fieldName, Modifier.PRIVATE); + initBlocks.simple.addStatement( + "this.$L = new $T<>()", fieldName, ParameterizedTypeName.get(HashMap.class)); + initBlocks.columnBased.addStatement("this.$L = factory.createSomeEntitiesMap()", fieldName); typeSpec.addMethod( MethodSpec.methodBuilder(methodName) .addModifiers(Modifier.PUBLIC) @@ -163,15 +182,19 @@ private static void addMapWithGetter( .build()); } - private static void addMapByCompositeKey(TypeSpec.Builder typeSpec, TypeName entityTypeName) { + private static void addMapByCompositeKey( + Builder typeSpec, TypeName entityTypeName, InitializerBlocks initBlocks) { // Field: Map byCompositeKeyMap; TypeName keyMapType = ParameterizedTypeName.get( ClassName.get(Map.class), ClassName.get("", "CompositeKey"), entityTypeName); - typeSpec.addField( - FieldSpec.builder(keyMapType, BY_COMPOSITE_KEY_MAP_FIELD_NAME, Modifier.PRIVATE) - .initializer("new $T<>()", ParameterizedTypeName.get(HashMap.class)) - .build()); + typeSpec.addField(keyMapType, BY_COMPOSITE_KEY_MAP_FIELD_NAME, Modifier.PRIVATE); + initBlocks.simple.addStatement( + "this.$L = new $T<>()", + BY_COMPOSITE_KEY_MAP_FIELD_NAME, + ParameterizedTypeName.get(HashMap.class)); + initBlocks.columnBased.addStatement( + "this.$L = factory.createSomeEntitiesMap()", BY_COMPOSITE_KEY_MAP_FIELD_NAME); } private FieldSpec generateKeyColumnNames() { @@ -186,11 +209,7 @@ private FieldSpec generateKeyColumnNames() { "ImmutableList.of($L)", fileDescriptor.primaryKeys().stream() .map( - (f) -> - CodeBlock.of( - "$T.$L", - classNames.entityImplementationTypeName(), - fieldNameField(f.name()))) + (f) -> CodeBlock.of("$T.$L", classNames.entityTypeName(), fieldNameField(f.name()))) .collect(CodeBlock.joining(",\n"))); return field.build(); } @@ -217,7 +236,7 @@ private MethodSpec generateByTranslationKeyMethod() { .addModifiers(Modifier.PUBLIC) .returns( ParameterizedTypeName.get( - ClassName.get(Optional.class), classNames.entityImplementationTypeName())) + ClassName.get(Optional.class), classNames.entityTypeName())) .addParameter(String.class, "recordId") .addParameter(String.class, "recordSubId"); if (fileDescriptor.hasSingleColumnPrimaryKey()) { @@ -287,7 +306,7 @@ private CodeBlock wrapStringAccessorWithTypeConversion( } private MethodSpec generateSetupIndicesMethod() { - TypeName gtfsEntityType = classNames.entityImplementationTypeName(); + TypeName gtfsEntityType = classNames.entityTypeName(); MethodSpec.Builder method = MethodSpec.methodBuilder("setupIndices") .addModifiers(Modifier.PRIVATE) @@ -316,7 +335,7 @@ private MethodSpec generateSetupIndicesMethod() { .collect(CodeBlock.joining("\n"))) .addStatement( "$T oldEntity = $L.getOrDefault(key, null)", - classNames.entityImplementationTypeName(), + classNames.entityTypeName(), BY_COMPOSITE_KEY_MAP_FIELD_NAME) .beginControlFlow("if (oldEntity != null)") .addStatement( @@ -347,7 +366,7 @@ private MethodSpec generateSetupIndicesMethod() { .endControlFlow() .addStatement( "$T oldEntity = $L.getOrDefault(newEntity.$L(), null)", - classNames.entityImplementationTypeName(), + classNames.entityTypeName(), byKeyMap, primaryKey.name()) .beginControlFlow("if (oldEntity != null)") @@ -458,4 +477,25 @@ private TypeSpec compositeKeyClass() { private static boolean isKeyTypeNullable(GtfsFieldDescriptor field) { return !field.javaType().getKind().isPrimitive(); } + + private CodeBlock generateInitializerCodeBlock(InitializerBlocks initBlocks) { + return CodeBlock.builder() + .addStatement( + "$T<$T> optFactory = $T.getForList(entities)", + Optional.class, + GtfsColumnBasedCollectionFactory.class, + GtfsColumnBasedCollectionFactory.class) + .beginControlFlow("if (optFactory.isPresent())") + .addStatement("$T factory = optFactory.get()", GtfsColumnBasedCollectionFactory.class) + .add(initBlocks.columnBased.build()) + .nextControlFlow("else") + .add(initBlocks.simple.build()) + .endControlFlow() + .build(); + } + + private static class InitializerBlocks { + private final CodeBlock.Builder simple = CodeBlock.builder(); + private final CodeBlock.Builder columnBased = CodeBlock.builder(); + } } diff --git a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/TableDescriptorGenerator.java b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/TableDescriptorGenerator.java index 514bbe98c9..babfccc6e9 100644 --- a/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/TableDescriptorGenerator.java +++ b/processor/src/main/java/org/mobilitydata/gtfsvalidator/processor/TableDescriptorGenerator.java @@ -20,11 +20,9 @@ import static org.mobilitydata.gtfsvalidator.annotation.FieldLevelEnum.RECOMMENDED; import static org.mobilitydata.gtfsvalidator.annotation.FieldLevelEnum.REQUIRED; import static org.mobilitydata.gtfsvalidator.processor.FieldNameConverter.fieldNameField; -import static org.mobilitydata.gtfsvalidator.processor.GtfsEntityClasses.TABLE_PACKAGE_NAME; import com.google.common.base.CaseFormat; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.JavaFile; @@ -38,13 +36,15 @@ import org.mobilitydata.gtfsvalidator.annotation.FieldLevelEnum; import org.mobilitydata.gtfsvalidator.annotation.FieldTypeEnum; import org.mobilitydata.gtfsvalidator.annotation.Generated; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnBasedEntityBuilder; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnStore; import org.mobilitydata.gtfsvalidator.notice.NoticeContainer; import org.mobilitydata.gtfsvalidator.parsing.CsvHeader; -import org.mobilitydata.gtfsvalidator.parsing.FieldCache; import org.mobilitydata.gtfsvalidator.parsing.RowParser; import org.mobilitydata.gtfsvalidator.table.GtfsColumnDescriptor; import org.mobilitydata.gtfsvalidator.table.GtfsEntityBuilder; -import org.mobilitydata.gtfsvalidator.table.GtfsFieldLoader; +import org.mobilitydata.gtfsvalidator.table.GtfsEnumDescriptor; +import org.mobilitydata.gtfsvalidator.table.GtfsSetter; import org.mobilitydata.gtfsvalidator.table.GtfsTableContainer; import org.mobilitydata.gtfsvalidator.table.GtfsTableDescriptor; @@ -92,7 +92,8 @@ private boolean cachingEnabled(final GtfsFieldDescriptor field) { } public JavaFile generateGtfsDescriptorJavaFile() { - return JavaFile.builder(TABLE_PACKAGE_NAME, generateGtfsTableDescriptorClass()).build(); + return JavaFile.builder(fileDescriptor.packageName(), generateGtfsTableDescriptorClass()) + .build(); } public TypeSpec generateGtfsTableDescriptorClass() { @@ -100,8 +101,7 @@ public TypeSpec generateGtfsTableDescriptorClass() { TypeSpec.classBuilder(classNames.tableDescriptorSimpleName()) .superclass( ParameterizedTypeName.get( - ClassName.get(GtfsTableDescriptor.class), - classNames.entityImplementationTypeName())) + ClassName.get(GtfsTableDescriptor.class), classNames.entityTypeName())) .addAnnotation(Generated.class) .addModifiers(Modifier.PUBLIC, Modifier.FINAL); @@ -110,9 +110,9 @@ public TypeSpec generateGtfsTableDescriptorClass() { typeSpec.addMethod(generateCreateContainerForInvalidStatusMethod()); typeSpec.addMethod(generateCreateContainerForHeaderAndEntitiesMethod()); typeSpec.addMethod(generateCreateEntityBuilderMethod()); + typeSpec.addMethod(generateCreateColumnBasedEntityBuilderMethod()); typeSpec.addMethod(generateGetEntityClassMethod()); typeSpec.addMethod(generateGetColumnsMethod()); - typeSpec.addMethod(generateGetFieldLoadersMethod()); typeSpec.addMethod(generateGtfsFilenameMethod()); typeSpec.addMethod(generateIsRecommendedMethod()); @@ -134,8 +134,7 @@ private MethodSpec generateCreateContainerForHeaderAndEntitiesMethod() { .addModifiers(Modifier.PUBLIC) .addParameter(CsvHeader.class, "header") .addParameter( - ParameterizedTypeName.get( - ClassName.get(List.class), classNames.entityImplementationTypeName()), + ParameterizedTypeName.get(ClassName.get(List.class), classNames.entityTypeName()), "entities") .addParameter(NoticeContainer.class, "noticeContainer") .returns(GtfsTableContainer.class) @@ -164,12 +163,23 @@ private MethodSpec generateCreateEntityBuilderMethod() { .build(); } + private MethodSpec generateCreateColumnBasedEntityBuilderMethod() { + return MethodSpec.methodBuilder("createColumnBasedEntityBuilder") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .addParameter(ClassName.get(GtfsColumnStore.class), "store") + .returns(GtfsColumnBasedEntityBuilder.class) + .addStatement( + "return new $T.Builder(store)", classNames.columnBasedEntityImplementationTypeName()) + .build(); + } + private MethodSpec generateGetEntityClassMethod() { return MethodSpec.methodBuilder("getEntityClass") .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC) .returns(Class.class) - .addStatement("return $T.class", classNames.entityImplementationTypeName()) + .addStatement("return $T.class", classNames.entityTypeName()) .build(); } @@ -186,26 +196,47 @@ private MethodSpec generateGetColumnsMethod() { ImmutableList.class, GtfsColumnDescriptor.class, ImmutableList.class); - TypeName gtfsEntityType = classNames.entityImplementationTypeName(); + TypeName gtfsEntityType = classNames.entityTypeName(); + ClassName gtfsEntityBuilderClassName = classNames.entityBuilderTypeName(); + ClassName columnBasedGtfsEntityBuilderClassName = classNames.columnBasedEntityBuilderTypeName(); for (GtfsFieldDescriptor field : fileDescriptor.fields()) { + TypeName nameThisSomethingBetter = + (field.type() == FieldTypeEnum.ENUM) ? ClassName.INT : ClassName.get(field.javaType()); CodeBlock.Builder descriptor = CodeBlock.builder() + .add("GtfsColumnDescriptor.builder()\n") + .add(".setColumnName($T.$L)\n", gtfsEntityType, fieldNameField(field.name())) + .add(".setHeaderRequired($L)\n", field.isHeaderRequired()) + .add(".setHeaderRecommended($L)\n", field.columnRecommended()) + .add(".setFieldLevel($T.$L)\n", FieldLevelEnum.class, getFieldLevel(field)) + .add(".setJavaType($T.class)\n", ClassName.get(field.javaType())) + .add(".setFieldType($T.$L)\n", ClassName.get(FieldTypeEnum.class), field.type()) .add( - "GtfsColumnDescriptor.builder()\n" - + ".setColumnName($T.$L)\n" - + ".setHeaderRequired($L)\n" - + ".setHeaderRecommended($L)\n" - + ".setFieldLevel($T.$L)\n" - + ".setIsMixedCase($L)\n" - + ".setIsCached($L)\n", - gtfsEntityType, - fieldNameField(field.name()), - field.isHeaderRequired(), - field.columnRecommended(), - FieldLevelEnum.class, - getFieldLevel(field), - field.mixedCase(), - cachingEnabled(field)); + ".setEntityBuilderSetter(($T) $T::$L)\n", + ParameterizedTypeName.get( + ClassName.get(GtfsSetter.class), + gtfsEntityBuilderClassName, + nameThisSomethingBetter.box()), + gtfsEntityBuilderClassName, + FieldNameConverter.setterMethodName(field.name())) + .add( + ".setColumnBasedEntityBuilderSetter(($T) $T::$L)\n", + ParameterizedTypeName.get( + ClassName.get(GtfsSetter.class), + columnBasedGtfsEntityBuilderClassName, + nameThisSomethingBetter.box()), + columnBasedGtfsEntityBuilderClassName, + FieldNameConverter.setterMethodName(field.name())) + .add(".setIsMixedCase($L)\n", field.mixedCase()) + .add(".setIsCached($L)\n", cachingEnabled(field)); + + if (field.type() == FieldTypeEnum.ENUM) { + descriptor.add( + ".setEnumDescriptor($T.create($T::forNumber, $T.UNRECOGNIZED))", + GtfsEnumDescriptor.class, + ClassName.get(field.javaType()), + ClassName.get(field.javaType())); + } field .numberBounds() .ifPresent( @@ -218,77 +249,6 @@ private MethodSpec generateGetColumnsMethod() { return method.build(); } - private MethodSpec generateGetFieldLoadersMethod() { - MethodSpec.Builder method = - MethodSpec.methodBuilder("getFieldLoaders") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .returns( - ParameterizedTypeName.get( - ClassName.get(ImmutableMap.class), - ClassName.get(String.class), - ClassName.get(GtfsFieldLoader.class))) - .addStatement( - "$T.Builder<$T, $T> builder = $T.builder()", - ImmutableMap.class, - String.class, - GtfsFieldLoader.class, - ImmutableMap.class); - ClassName gtfsEntityType = classNames.entityImplementationTypeName(); - for (GtfsFieldDescriptor field : fileDescriptor.fields()) { - TypeName boxedType = - field.type() == FieldTypeEnum.ENUM - ? ClassName.get(Integer.class) - : ClassName.get(field.javaType()).box(); - TypeSpec.Builder loaderClass = - TypeSpec.anonymousClassBuilder("") - .addSuperinterface( - ParameterizedTypeName.get( - ClassName.get(GtfsFieldLoader.class), - gtfsEntityType.nestedClass("Builder"), - boxedType)); - MethodSpec.Builder loadMethod = - MethodSpec.methodBuilder("load") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .addParameter(RowParser.class, "rowParser") - .addParameter(int.class, "columnIndex") - .addParameter(GtfsColumnDescriptor.class, "columnDescriptor") - .addParameter( - ParameterizedTypeName.get(ClassName.get(FieldCache.class), boxedType), - "fieldCache") - .addParameter(gtfsEntityType.nestedClass("Builder"), "builder"); - - CodeBlock fieldValue = - field.type() == FieldTypeEnum.ENUM - ? CodeBlock.of( - "rowParser.asEnum(columnIndex, columnDescriptor, $T::forNumber," - + " $T.UNRECOGNIZED)", - ClassName.get(field.javaType()), - ClassName.get(field.javaType())) - : CodeBlock.of( - "rowParser.$L(columnIndex, columnDescriptor$L)", - gtfsTypeToParserMethod(field.type()), - field.numberBounds().isPresent() - ? ", RowParser.NumberBounds." + field.numberBounds().get() - : ""); - - loadMethod.addStatement( - "builder.$L(\naddToCacheIfPresent(\n$L, fieldCache))", - FieldNameConverter.setterMethodName(field.name()), - fieldValue); - loaderClass.addMethod(loadMethod.build()); - - method.addStatement( - "builder.put($T.$L, $L)", - gtfsEntityType, - fieldNameField(field.name()), - loaderClass.build()); - } - method.addStatement("return builder.build()"); - return method.build(); - } - static FieldLevelEnum getFieldLevel(GtfsFieldDescriptor field) { return field.valueRequired() ? REQUIRED : field.recommended() ? RECOMMENDED : OPTIONAL; } @@ -298,7 +258,7 @@ private MethodSpec generateGtfsFilenameMethod() { .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC) .returns(String.class) - .addStatement("return $T.FILENAME", classNames.entityImplementationTypeName()) + .addStatement("return $T.FILENAME", classNames.entityTypeName()) .build(); } diff --git a/processor/src/test/java/org/mobilitydata/gtfsvalidator/processor/EnumGeneratorTest.java b/processor/src/test/java/org/mobilitydata/gtfsvalidator/processor/EnumGeneratorTest.java index d0870a1206..404c54c71a 100644 --- a/processor/src/test/java/org/mobilitydata/gtfsvalidator/processor/EnumGeneratorTest.java +++ b/processor/src/test/java/org/mobilitydata/gtfsvalidator/processor/EnumGeneratorTest.java @@ -2,6 +2,7 @@ import static com.google.common.truth.Truth.assertThat; +import com.squareup.javapoet.TypeName; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -10,7 +11,11 @@ public class EnumGeneratorTest { @Test public void testGetMinMaxValue() { - GtfsEnumDescriptor.Builder builder = GtfsEnumDescriptor.builder().setName("MyEnum"); + GtfsEnumDescriptor.Builder builder = + GtfsEnumDescriptor.builder() + .setName("MyEnum") + .setPackageName("") + .setFieldType(TypeName.INT); builder .valuesBuilder() .add(GtfsEnumValueDescriptor.create("STOP", 0)) diff --git a/processor/tests/src/main/java/org/mobilitydata/gtfsvalidator/processor/tests/EnumSizesSchema.java b/processor/tests/src/main/java/org/mobilitydata/gtfsvalidator/processor/tests/EnumSizesSchema.java index 1ce1807832..e4b69e12c3 100644 --- a/processor/tests/src/main/java/org/mobilitydata/gtfsvalidator/processor/tests/EnumSizesSchema.java +++ b/processor/tests/src/main/java/org/mobilitydata/gtfsvalidator/processor/tests/EnumSizesSchema.java @@ -1,9 +1,6 @@ package org.mobilitydata.gtfsvalidator.processor.tests; import org.mobilitydata.gtfsvalidator.annotation.GtfsTable; -import org.mobilitydata.gtfsvalidator.table.ByteGtfs; -import org.mobilitydata.gtfsvalidator.table.IntGtfs; -import org.mobilitydata.gtfsvalidator.table.ShortGtfs; @GtfsTable("enum_sizes.txt") public interface EnumSizesSchema { diff --git a/processor/tests/src/main/java/org/mobilitydata/gtfsvalidator/processor/tests/ManyTypesSchema.java b/processor/tests/src/main/java/org/mobilitydata/gtfsvalidator/processor/tests/ManyTypesSchema.java new file mode 100644 index 0000000000..5969ad9bb3 --- /dev/null +++ b/processor/tests/src/main/java/org/mobilitydata/gtfsvalidator/processor/tests/ManyTypesSchema.java @@ -0,0 +1,33 @@ +package org.mobilitydata.gtfsvalidator.processor.tests; + +import java.math.BigDecimal; +import java.time.ZoneId; +import java.util.Currency; +import java.util.Locale; +import org.mobilitydata.gtfsvalidator.annotation.GtfsTable; +import org.mobilitydata.gtfsvalidator.type.GtfsColor; +import org.mobilitydata.gtfsvalidator.type.GtfsDate; +import org.mobilitydata.gtfsvalidator.type.GtfsTime; + +@GtfsTable("many_types.txt") +public interface ManyTypesSchema { + int intValue(); + + double doubleValue(); + + String stringValue(); + + BigDecimal bigDecimalValue(); + + Currency currencyValue(); + + GtfsColor colorValue(); + + GtfsDate dateValue(); + + GtfsTime timeValue(); + + Locale localeValue(); + + ZoneId zoneIdValue(); +} diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/CurrencyAmountSchemaTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/CurrencyAmountSchemaTest.java index a2eafc802f..cdedf21e2e 100644 --- a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/CurrencyAmountSchemaTest.java +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/CurrencyAmountSchemaTest.java @@ -24,7 +24,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mobilitydata.gtfsvalidator.notice.InvalidCurrencyAmountNotice; -import org.mobilitydata.gtfsvalidator.table.CurrencyAmountTableDescriptor; import org.mobilitydata.gtfsvalidator.testing.LoadingHelper; import org.mobilitydata.gtfsvalidator.validator.CurrencyAmountCurrencyAmountValidator; import org.mobilitydata.gtfsvalidator.validator.ValidatorLoader; diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/EnumSizesSchemaTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/EnumSizesSchemaTest.java index 9fb0923b16..df6939cc00 100644 --- a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/EnumSizesSchemaTest.java +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/EnumSizesSchemaTest.java @@ -5,61 +5,57 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mobilitydata.gtfsvalidator.table.ByteGtfs; -import org.mobilitydata.gtfsvalidator.table.EnumSizes; -import org.mobilitydata.gtfsvalidator.table.IntGtfs; -import org.mobilitydata.gtfsvalidator.table.ShortGtfs; @RunWith(JUnit4.class) public class EnumSizesSchemaTest { @Test public void testByteEnumValid() { - assertThat(new EnumSizes.Builder().setByteEnum(ByteGtfs.ONE).build().byteEnum()) + assertThat(EnumSizes.builder().setByteEnum(ByteGtfs.ONE).build().byteEnum()) .isEqualTo(ByteGtfs.ONE); - assertThat(new EnumSizes.Builder().setByteEnum(ByteGtfs.MAX_BYTE).build().byteEnum()) + assertThat(EnumSizes.builder().setByteEnum(ByteGtfs.MAX_BYTE).build().byteEnum()) .isEqualTo(ByteGtfs.MAX_BYTE); - assertThat(new EnumSizes.Builder().setByteEnum(ByteGtfs.MIN_BYTE).build().byteEnum()) + assertThat(EnumSizes.builder().setByteEnum(ByteGtfs.MIN_BYTE).build().byteEnum()) .isEqualTo(ByteGtfs.MIN_BYTE); } @Test public void testByteEnumInvalid() { - EnumSizes enumSizes = new EnumSizes.Builder().setByteEnum(10).build(); + EnumSizes enumSizes = EnumSizes.builder().setByteEnum(10).build(); // 10 is not a valid constant for ByteGtfs. assertThat(enumSizes.byteEnum()).isEqualTo(ByteGtfs.UNRECOGNIZED); } @Test public void testShortEnumValid() { - assertThat(new EnumSizes.Builder().setShortEnum(ShortGtfs.ONE).build().shortEnum()) + assertThat(EnumSizes.builder().setShortEnum(ShortGtfs.ONE).build().shortEnum()) .isEqualTo(ShortGtfs.ONE); - assertThat(new EnumSizes.Builder().setShortEnum(ShortGtfs.MAX_SHORT).build().shortEnum()) + assertThat(EnumSizes.builder().setShortEnum(ShortGtfs.MAX_SHORT).build().shortEnum()) .isEqualTo(ShortGtfs.MAX_SHORT); - assertThat(new EnumSizes.Builder().setShortEnum(ShortGtfs.MIN_SHORT).build().shortEnum()) + assertThat(EnumSizes.builder().setShortEnum(ShortGtfs.MIN_SHORT).build().shortEnum()) .isEqualTo(ShortGtfs.MIN_SHORT); } @Test public void testShortEnumInvalid() { - EnumSizes enumSizes = new EnumSizes.Builder().setShortEnum(10).build(); + EnumSizes enumSizes = EnumSizes.builder().setShortEnum(10).build(); // 10 is not a valid constant for ShortGtfs. assertThat(enumSizes.shortEnum()).isEqualTo(ShortGtfs.UNRECOGNIZED); } @Test public void testIntEnumValid() { - assertThat(new EnumSizes.Builder().setIntEnum(IntGtfs.ONE).build().intEnum()) + assertThat(EnumSizes.builder().setIntEnum(IntGtfs.ONE).build().intEnum()) .isEqualTo(IntGtfs.ONE); - assertThat(new EnumSizes.Builder().setIntEnum(IntGtfs.MAX_INT).build().intEnum()) + assertThat(EnumSizes.builder().setIntEnum(IntGtfs.MAX_INT).build().intEnum()) .isEqualTo(IntGtfs.MAX_INT); - assertThat(new EnumSizes.Builder().setIntEnum(IntGtfs.MIN_INT).build().intEnum()) + assertThat(EnumSizes.builder().setIntEnum(IntGtfs.MIN_INT).build().intEnum()) .isEqualTo(IntGtfs.MIN_INT); } @Test public void testIntEnumInvalid() { - EnumSizes enumSizes = new EnumSizes.Builder().setIntEnum(10).build(); + EnumSizes enumSizes = EnumSizes.builder().setIntEnum(10).build(); // 10 is not a valid constant for ShortGtfs. assertThat(enumSizes.intEnum()).isEqualTo(IntGtfs.UNRECOGNIZED); } diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/IdAndSequencePrimaryKeySchemaTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/IdAndSequencePrimaryKeySchemaTest.java index d4301348f5..a7604b6b48 100644 --- a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/IdAndSequencePrimaryKeySchemaTest.java +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/IdAndSequencePrimaryKeySchemaTest.java @@ -23,9 +23,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mobilitydata.gtfsvalidator.table.IdAndSequencePrimaryKey; -import org.mobilitydata.gtfsvalidator.table.IdAndSequencePrimaryKeyTableContainer; -import org.mobilitydata.gtfsvalidator.table.IdAndSequencePrimaryKeyTableDescriptor; import org.mobilitydata.gtfsvalidator.testing.LoadingHelper; import org.mobilitydata.gtfsvalidator.validator.ValidatorLoaderException; diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/ManyFieldsSchemaTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/ManyFieldsSchemaTest.java index 218711bbc2..a68f9568ec 100644 --- a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/ManyFieldsSchemaTest.java +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/ManyFieldsSchemaTest.java @@ -5,13 +5,12 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mobilitydata.gtfsvalidator.table.ManyFields; @RunWith(JUnit4.class) public class ManyFieldsSchemaTest { @Test public void testHasField() { - ManyFields manyFields = new ManyFields.Builder().setField2(2).setField8(9).build(); + ManyFields manyFields = ManyFields.builder().setField2(2).setField8(9).build(); assertThat(manyFields.hasField1()).isFalse(); assertThat(manyFields.hasField2()).isTrue(); diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/ManyTypesColumnBasedTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/ManyTypesColumnBasedTest.java new file mode 100644 index 0000000000..7175682a87 --- /dev/null +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/ManyTypesColumnBasedTest.java @@ -0,0 +1,130 @@ +package org.mobilitydata.gtfsvalidator.processor.tests; + +import static com.google.common.truth.Truth.assertThat; + +import java.math.BigDecimal; +import java.time.ZoneId; +import java.util.Currency; +import java.util.Locale; +import org.junit.Test; +import org.mobilitydata.gtfsvalidator.columns.GtfsColumnStore; +import org.mobilitydata.gtfsvalidator.type.GtfsColor; +import org.mobilitydata.gtfsvalidator.type.GtfsDate; +import org.mobilitydata.gtfsvalidator.type.GtfsTime; + +public class ManyTypesColumnBasedTest { + + private final GtfsColumnStore store = new GtfsColumnStore(); + + @Test + public void testBuilder() { + ManyTypesColumnBased.Builder builder = new ManyTypesColumnBased.Builder(store); + + { + builder.clear(); + ManyTypesColumnBased entity = + builder + .setCsvRowNumber(1) + .setIntValue(2) + .setDoubleValue(3.14) + .setBigDecimalValue(BigDecimal.TEN) + .setCurrencyValue(Currency.getInstance("USD")) + .setColorValue(GtfsColor.fromString("ff00ff")) + .setDateValue(GtfsDate.fromString("20240416")) + .setTimeValue(GtfsTime.fromString("05:34:00")) + .setLocaleValue(Locale.CANADA) + .setZoneIdValue(ZoneId.of("America/New_York")) + .build(); + + assertThat(entity.csvRowNumber()).isEqualTo(1); + assertThat(entity.intValue()).isEqualTo(2); + assertThat(entity.doubleValue()).isEqualTo(3.14); + assertThat(entity.bigDecimalValue()).isEqualTo(BigDecimal.TEN); + assertThat(entity.currencyValue()).isEqualTo(Currency.getInstance("USD")); + assertThat(entity.colorValue()).isEqualTo(GtfsColor.fromString("ff00ff")); + assertThat(entity.dateValue()).isEqualTo(GtfsDate.fromString("20240416")); + assertThat(entity.timeValue()).isEqualTo(GtfsTime.fromString("05:34:00")); + assertThat(entity.localeValue()).isEqualTo(Locale.CANADA); + assertThat(entity.zoneIdValue()).isEqualTo(ZoneId.of("America/New_York")); + } + + { + builder.clear(); + ManyTypesColumnBased entity = + builder + .setCsvRowNumber(2) + .setIntValue(3) + .setDoubleValue(1.5) + .setBigDecimalValue(BigDecimal.ZERO) + .setCurrencyValue(Currency.getInstance("CAD")) + .setColorValue(GtfsColor.fromString("00ff00")) + .setDateValue(GtfsDate.fromString("20240401")) + .setTimeValue(GtfsTime.fromString("06:34:00")) + .setLocaleValue(Locale.FRANCE) + .setZoneIdValue(ZoneId.of("America/Los_Angeles")) + .build(); + + assertThat(entity.csvRowNumber()).isEqualTo(2); + assertThat(entity.intValue()).isEqualTo(3); + assertThat(entity.doubleValue()).isEqualTo(1.5); + assertThat(entity.bigDecimalValue()).isEqualTo(BigDecimal.ZERO); + assertThat(entity.currencyValue()).isEqualTo(Currency.getInstance("CAD")); + assertThat(entity.colorValue()).isEqualTo(GtfsColor.fromString("00ff00")); + assertThat(entity.dateValue()).isEqualTo(GtfsDate.fromString("20240401")); + assertThat(entity.timeValue()).isEqualTo(GtfsTime.fromString("06:34:00")); + assertThat(entity.localeValue()).isEqualTo(Locale.FRANCE); + assertThat(entity.zoneIdValue()).isEqualTo(ZoneId.of("America/Los_Angeles")); + } + + { + ManyTypesColumnBased entity = ManyTypesColumnBased.create(store, builder.getAssignments(), 0); + assertThat(entity.intValue()).isEqualTo(2); + } + + { + ManyTypesColumnBased entity = ManyTypesColumnBased.create(store, builder.getAssignments(), 1); + assertThat(entity.intValue()).isEqualTo(3); + } + } + + @Test + public void testHasValue() { + ManyTypesColumnBased.Builder builder = new ManyTypesColumnBased.Builder(store); + + { + // No fields set. + builder.clear(); + ManyTypesColumnBased entity = builder.build(); + + assertThat(entity.hasIntValue()).isFalse(); + assertThat(entity.hasDoubleValue()).isFalse(); + assertThat(entity.hasBigDecimalValue()).isFalse(); + assertThat(entity.hasCurrencyValue()).isFalse(); + assertThat(entity.hasColorValue()).isFalse(); + assertThat(entity.hasDateValue()).isFalse(); + assertThat(entity.hasTimeValue()).isFalse(); + assertThat(entity.hasLocaleValue()).isFalse(); + assertThat(entity.hasZoneIdValue()).isFalse(); + } + + { + // Some fields set. + builder.clear(); + builder.setDoubleValue(1.0); + builder.setCurrencyValue(Currency.getInstance("USD")); + builder.setDateValue(GtfsDate.fromString("20240416")); + builder.setLocaleValue(Locale.CANADA); + ManyTypesColumnBased entity = builder.build(); + + assertThat(entity.hasIntValue()).isFalse(); + assertThat(entity.hasDoubleValue()).isTrue(); + assertThat(entity.hasBigDecimalValue()).isFalse(); + assertThat(entity.hasCurrencyValue()).isTrue(); + assertThat(entity.hasColorValue()).isFalse(); + assertThat(entity.hasDateValue()).isTrue(); + assertThat(entity.hasTimeValue()).isFalse(); + assertThat(entity.hasLocaleValue()).isTrue(); + assertThat(entity.hasZoneIdValue()).isFalse(); + } + } +} diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MixedCaseSchemaTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MixedCaseSchemaTest.java index 46a4b9a1ca..2261c743ad 100644 --- a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MixedCaseSchemaTest.java +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MixedCaseSchemaTest.java @@ -25,8 +25,6 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.mobilitydata.gtfsvalidator.notice.MixedCaseRecommendedFieldNotice; -import org.mobilitydata.gtfsvalidator.table.MixedCaseTest; -import org.mobilitydata.gtfsvalidator.table.MixedCaseTestTableDescriptor; import org.mobilitydata.gtfsvalidator.testing.LoadingHelper; import org.mobilitydata.gtfsvalidator.validator.MixedCaseTestMixedCaseValidator; import org.mobilitydata.gtfsvalidator.validator.ValidatorLoader; diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MultiColumnLocalePrimaryKeySchemaTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MultiColumnLocalePrimaryKeySchemaTest.java index 69cb87d9e3..a7f5dde0b1 100644 --- a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MultiColumnLocalePrimaryKeySchemaTest.java +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MultiColumnLocalePrimaryKeySchemaTest.java @@ -21,8 +21,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mobilitydata.gtfsvalidator.table.MultiColumnLocalePrimaryKeyTableContainer; -import org.mobilitydata.gtfsvalidator.table.MultiColumnLocalePrimaryKeyTableDescriptor; import org.mobilitydata.gtfsvalidator.testing.LoadingHelper; import org.mobilitydata.gtfsvalidator.validator.ValidatorLoaderException; diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MultiColumnPrimaryKeySchemaTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MultiColumnPrimaryKeySchemaTest.java index 76fc085917..9108cc8a16 100644 --- a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MultiColumnPrimaryKeySchemaTest.java +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MultiColumnPrimaryKeySchemaTest.java @@ -24,9 +24,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mobilitydata.gtfsvalidator.table.MultiColumnPrimaryKey; -import org.mobilitydata.gtfsvalidator.table.MultiColumnPrimaryKeyTableContainer; -import org.mobilitydata.gtfsvalidator.table.MultiColumnPrimaryKeyTableDescriptor; import org.mobilitydata.gtfsvalidator.testing.LoadingHelper; import org.mobilitydata.gtfsvalidator.validator.ValidatorLoaderException; diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MultiColumnUnsupportedTranslationsPrimaryKeySchemaTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MultiColumnUnsupportedTranslationsPrimaryKeySchemaTest.java index 25b221132c..c8512c1458 100644 --- a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MultiColumnUnsupportedTranslationsPrimaryKeySchemaTest.java +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/MultiColumnUnsupportedTranslationsPrimaryKeySchemaTest.java @@ -6,8 +6,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mobilitydata.gtfsvalidator.table.MultiColumnUnsupportedTranslationsPrimaryKeyTableContainer; -import org.mobilitydata.gtfsvalidator.table.MultiColumnUnsupportedTranslationsPrimaryKeyTableDescriptor; import org.mobilitydata.gtfsvalidator.testing.LoadingHelper; import org.mobilitydata.gtfsvalidator.validator.ValidatorLoaderException; diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/RecommendedColumnAnnotationSchemaTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/RecommendedColumnAnnotationSchemaTest.java index fd600103e2..bba03cfc43 100644 --- a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/RecommendedColumnAnnotationSchemaTest.java +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/RecommendedColumnAnnotationSchemaTest.java @@ -7,7 +7,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mobilitydata.gtfsvalidator.notice.MissingRequiredColumnNotice; -import org.mobilitydata.gtfsvalidator.table.RecommendedColumnAnnotationTableDescriptor; import org.mobilitydata.gtfsvalidator.testing.LoadingHelper; import org.mobilitydata.gtfsvalidator.validator.ValidatorLoaderException; diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/RequiredAnnotationSchemaTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/RequiredAnnotationSchemaTest.java index 1ac4d38a6b..4bb6edf624 100644 --- a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/RequiredAnnotationSchemaTest.java +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/RequiredAnnotationSchemaTest.java @@ -8,7 +8,6 @@ import org.junit.runners.JUnit4; import org.mobilitydata.gtfsvalidator.notice.MissingRequiredColumnNotice; import org.mobilitydata.gtfsvalidator.notice.MissingRequiredFieldNotice; -import org.mobilitydata.gtfsvalidator.table.RequiredAnnotationTableDescriptor; import org.mobilitydata.gtfsvalidator.testing.LoadingHelper; import org.mobilitydata.gtfsvalidator.validator.ValidatorLoaderException; diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/RequiredColumnAnnotationSchemaTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/RequiredColumnAnnotationSchemaTest.java index 93fd06a205..79eafc64fa 100644 --- a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/RequiredColumnAnnotationSchemaTest.java +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/RequiredColumnAnnotationSchemaTest.java @@ -7,7 +7,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mobilitydata.gtfsvalidator.notice.MissingRequiredColumnNotice; -import org.mobilitydata.gtfsvalidator.table.RequiredColumnAnnotationTableDescriptor; import org.mobilitydata.gtfsvalidator.testing.LoadingHelper; import org.mobilitydata.gtfsvalidator.validator.ValidatorLoaderException; diff --git a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/SingleColumnPrimaryKeySchemaTest.java b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/SingleColumnPrimaryKeySchemaTest.java index fb9594c4ce..63cd05ea92 100644 --- a/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/SingleColumnPrimaryKeySchemaTest.java +++ b/processor/tests/src/test/java/org/mobilitydata/gtfsvalidator/processor/tests/SingleColumnPrimaryKeySchemaTest.java @@ -21,8 +21,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import org.mobilitydata.gtfsvalidator.table.SingleColumnPrimaryKeyTableContainer; -import org.mobilitydata.gtfsvalidator.table.SingleColumnPrimaryKeyTableDescriptor; import org.mobilitydata.gtfsvalidator.testing.LoadingHelper; import org.mobilitydata.gtfsvalidator.validator.ValidatorLoaderException; diff --git a/settings.gradle b/settings.gradle index 46bea48ddd..e22e9e8e3e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,8 +3,11 @@ include 'app:gui' include 'app:pkg' include 'cli' include 'core' +include 'core:testing' +include 'extensions' include 'processor' include 'processor:tests' +include 'processor:columns' include 'processor:notices' include 'processor:notices:tests' include 'main' @@ -14,3 +17,5 @@ include 'tests' include ':web:service' include ':web:client' include ':web:pipeline' + +