Skip to content

Commit

Permalink
feat/recommended-field-annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
KClough committed May 27, 2022
1 parent 57dfb7b commit 1ecfcd2
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 106 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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.annotation;

/** The level for fields. */
public enum FieldLevelEnum {
REQUIRED,
RECOMMENDED,
OPTIONAL,
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Locale;
import java.util.function.Function;
import javax.annotation.Nullable;
import org.mobilitydata.gtfsvalidator.annotation.FieldLevelEnum;
import org.mobilitydata.gtfsvalidator.notice.EmptyRowNotice;
import org.mobilitydata.gtfsvalidator.notice.InvalidColorNotice;
import org.mobilitydata.gtfsvalidator.notice.InvalidCurrencyNotice;
Expand Down Expand Up @@ -52,8 +53,9 @@
*/
public class RowParser {

public static final boolean REQUIRED = true;
public static final boolean OPTIONAL = false;
public static final FieldLevelEnum OPTIONAL = FieldLevelEnum.OPTIONAL;
public static final FieldLevelEnum RECOMMENDED = FieldLevelEnum.RECOMMENDED;
public static final FieldLevelEnum REQUIRED = FieldLevelEnum.REQUIRED;
private final String fileName;
private final CsvHeader header;
private final GtfsFieldValidator fieldValidator;
Expand Down Expand Up @@ -107,9 +109,9 @@ public boolean checkRowLength() {
}

@Nullable
public String asString(int columnIndex, boolean required) {
public String asString(int columnIndex, FieldLevelEnum level) {
String s = row.asString(columnIndex);
if (required && s == null) {
if (level == FieldLevelEnum.REQUIRED && s == null) {
noticeContainer.addValidationNotice(
new MissingRequiredFieldNotice(
fileName, row.getRowNumber(), header.getColumnName(columnIndex)));
Expand All @@ -126,23 +128,23 @@ public String asString(int columnIndex, boolean required) {
}

@Nullable
public String asText(int columnIndex, boolean required) {
return asString(columnIndex, required);
public String asText(int columnIndex, FieldLevelEnum level) {
return asString(columnIndex, level);
}

@Nullable
public String asId(int columnIndex, boolean required) {
return asValidatedString(columnIndex, required, fieldValidator::validateId);
public String asId(int columnIndex, FieldLevelEnum level) {
return asValidatedString(columnIndex, level, fieldValidator::validateId);
}

@Nullable
public String asUrl(int columnIndex, boolean required) {
return asValidatedString(columnIndex, required, fieldValidator::validateUrl);
public String asUrl(int columnIndex, FieldLevelEnum level) {
return asValidatedString(columnIndex, level, fieldValidator::validateUrl);
}

@Nullable
public String asEmail(int columnIndex, boolean required) {
return asValidatedString(columnIndex, required, fieldValidator::validateEmail);
public String asEmail(int columnIndex, FieldLevelEnum level) {
return asValidatedString(columnIndex, level, fieldValidator::validateEmail);
}

/**
Expand All @@ -157,39 +159,38 @@ public String asEmail(int columnIndex, boolean required) {
* unknown, only phone number starting by "+" are validated.
*/
@Nullable
public String asPhoneNumber(int columnIndex, boolean required) {
return asValidatedString(columnIndex, required, fieldValidator::validatePhoneNumber);
public String asPhoneNumber(int columnIndex, FieldLevelEnum level) {
return asValidatedString(columnIndex, level, fieldValidator::validatePhoneNumber);
}

@Nullable
public Locale asLanguageCode(int columnIndex, boolean required) {
return parseAsType(
columnIndex, required, Locale::forLanguageTag, InvalidLanguageCodeNotice::new);
public Locale asLanguageCode(int columnIndex, FieldLevelEnum level) {
return parseAsType(columnIndex, level, Locale::forLanguageTag, InvalidLanguageCodeNotice::new);
}

@Nullable
public ZoneId asTimezone(int columnIndex, boolean required) {
return parseAsType(columnIndex, required, ZoneId::of, InvalidTimezoneNotice::new);
public ZoneId asTimezone(int columnIndex, FieldLevelEnum level) {
return parseAsType(columnIndex, level, ZoneId::of, InvalidTimezoneNotice::new);
}

@Nullable
public Currency asCurrencyCode(int columnIndex, boolean required) {
return parseAsType(columnIndex, required, Currency::getInstance, InvalidCurrencyNotice::new);
public Currency asCurrencyCode(int columnIndex, FieldLevelEnum level) {
return parseAsType(columnIndex, level, Currency::getInstance, InvalidCurrencyNotice::new);
}

@Nullable
public Double asFloat(int columnIndex, boolean required) {
return parseAsType(columnIndex, required, Double::parseDouble, InvalidFloatNotice::new);
public Double asFloat(int columnIndex, FieldLevelEnum level) {
return parseAsType(columnIndex, level, Double::parseDouble, InvalidFloatNotice::new);
}

@Nullable
public Double asFloat(int columnIndex, boolean required, NumberBounds bounds) {
return checkBounds(asFloat(columnIndex, required), 0.0, columnIndex, "float", bounds);
public Double asFloat(int columnIndex, FieldLevelEnum level, NumberBounds bounds) {
return checkBounds(asFloat(columnIndex, level), 0.0, columnIndex, "float", bounds);
}

@Nullable
public Double asLatitude(int columnIndex, boolean required) {
Double value = asFloat(columnIndex, required);
public Double asLatitude(int columnIndex, FieldLevelEnum level) {
Double value = asFloat(columnIndex, level);
if (value != null && !(-90 <= value && value <= 90)) {
noticeContainer.addValidationNotice(
new NumberOutOfRangeNotice(
Expand All @@ -204,8 +205,8 @@ public Double asLatitude(int columnIndex, boolean required) {
}

@Nullable
public Double asLongitude(int columnIndex, boolean required) {
Double value = asFloat(columnIndex, required);
public Double asLongitude(int columnIndex, FieldLevelEnum level) {
Double value = asFloat(columnIndex, level);
if (value != null && !(-180 <= value && value <= 180)) {
noticeContainer.addValidationNotice(
new NumberOutOfRangeNotice(
Expand All @@ -220,24 +221,24 @@ public Double asLongitude(int columnIndex, boolean required) {
}

@Nullable
public Integer asInteger(int columnIndex, boolean required) {
return parseAsType(columnIndex, required, Integer::parseInt, InvalidIntegerNotice::new);
public Integer asInteger(int columnIndex, FieldLevelEnum level) {
return parseAsType(columnIndex, level, Integer::parseInt, InvalidIntegerNotice::new);
}

@Nullable
public Integer asInteger(int columnIndex, boolean required, NumberBounds bounds) {
return checkBounds(asInteger(columnIndex, required), 0, columnIndex, "integer", bounds);
public Integer asInteger(int columnIndex, FieldLevelEnum level, NumberBounds bounds) {
return checkBounds(asInteger(columnIndex, level), 0, columnIndex, "integer", bounds);
}

@Nullable
public BigDecimal asDecimal(int columnIndex, boolean required) {
return parseAsType(columnIndex, required, BigDecimal::new, InvalidFloatNotice::new);
public BigDecimal asDecimal(int columnIndex, FieldLevelEnum level) {
return parseAsType(columnIndex, level, BigDecimal::new, InvalidFloatNotice::new);
}

@Nullable
public BigDecimal asDecimal(int columnIndex, boolean required, NumberBounds bounds) {
public BigDecimal asDecimal(int columnIndex, FieldLevelEnum level, NumberBounds bounds) {
return checkBounds(
asDecimal(columnIndex, required), new BigDecimal(0), columnIndex, "decimal", bounds);
asDecimal(columnIndex, level), new BigDecimal(0), columnIndex, "decimal", bounds);
}

/**
Expand Down Expand Up @@ -296,13 +297,13 @@ private <T extends Comparable<T>> T checkBounds(
}

@Nullable
public GtfsColor asColor(int columnIndex, boolean required) {
return parseAsType(columnIndex, required, GtfsColor::fromString, InvalidColorNotice::new);
public GtfsColor asColor(int columnIndex, FieldLevelEnum level) {
return parseAsType(columnIndex, level, GtfsColor::fromString, InvalidColorNotice::new);
}

@Nullable
public <E> Integer asEnum(int columnIndex, boolean required, EnumCreator<E> enumCreator) {
Integer i = asInteger(columnIndex, required);
public <E> Integer asEnum(int columnIndex, FieldLevelEnum level, EnumCreator<E> enumCreator) {
Integer i = asInteger(columnIndex, level);
if (i == null) {
return null;
}
Expand All @@ -315,13 +316,13 @@ public <E> Integer asEnum(int columnIndex, boolean required, EnumCreator<E> enum
}

@Nullable
public GtfsTime asTime(int columnIndex, boolean required) {
return parseAsType(columnIndex, required, GtfsTime::fromString, InvalidTimeNotice::new);
public GtfsTime asTime(int columnIndex, FieldLevelEnum level) {
return parseAsType(columnIndex, level, GtfsTime::fromString, InvalidTimeNotice::new);
}

@Nullable
public GtfsDate asDate(int columnIndex, boolean required) {
return parseAsType(columnIndex, required, GtfsDate::fromString, InvalidDateNotice::new);
public GtfsDate asDate(int columnIndex, FieldLevelEnum level) {
return parseAsType(columnIndex, level, GtfsDate::fromString, InvalidDateNotice::new);
}

public enum NumberBounds {
Expand All @@ -341,7 +342,7 @@ public interface EnumCreator<E> {
* parsing failed.
*
* @param columnIndex index of the column to parse
* @param required whether the value is required according to GTFS
* @param level whether the value is required, recommended or optional according to GTFS
* @param parsingFunction function that converts string to an object to return
* @param noticingFunction function to create a notice about parse errors
* @param <T> the type to return
Expand All @@ -350,10 +351,10 @@ public interface EnumCreator<E> {
@Nullable
private <T> T parseAsType(
int columnIndex,
boolean required,
FieldLevelEnum level,
Function<String, T> parsingFunction,
NoticingFunction noticingFunction) {
String s = asString(columnIndex, required);
String s = asString(columnIndex, level);
if (s == null) {
return null;
}
Expand All @@ -376,14 +377,14 @@ private <T> T parseAsType(
* error is emitted, the value is considered invalid.
*
* @param columnIndex index of the column to parse
* @param required whether the value is required according to GTFS
* @param level whether the value is required, recommended or optional according to GTFS
* @param validatingFunction the predicate to validate a given string
* @return the cell value at the given column or null if the value is missing
*/
@Nullable
private String asValidatedString(
int columnIndex, boolean required, FieldValidatingFunction validatingFunction) {
String s = asString(columnIndex, required);
int columnIndex, FieldLevelEnum level, FieldValidatingFunction validatingFunction) {
String s = asString(columnIndex, level);
if (s == null) {
return null;
}
Expand Down
Loading

0 comments on commit 1ecfcd2

Please sign in to comment.