All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.model.base.ToStringBuilder Maven / Gradle / Ivy

There is a newer version: 2.5.0
Show newest version
package org.opentripplanner.model.base;

import org.opentripplanner.model.TransitEntity;
import org.opentripplanner.transit.raptor.util.TimeUtils;

import javax.validation.constraints.NotNull;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Locale;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * This toString builder witch add elements to a compact string of the form:
 * 

* {@code ClassName{field1:value, field2:value, ...}} *

* Fields equals to 'ignoreValue' is NOT added to the result string. This produces a short and easy * to read result. You should use {@code null} as 'ignoreValue' if the field is nullable. *

* The naming of the 'add' methods should give a hint to witch type the value have, this make it * easier to choose the right method and less error prune as compared with relaying on pure * override, witch often result in a wrong method call. *

* The builder should be independent of locale, the value should always be formatted the same way, * this allows us to use the toString in unit tests. */ public class ToStringBuilder { private static final String FIELD_SEPARATOR = ", "; private static final DecimalFormatSymbols DECIMAL_SYMBOLS = DecimalFormatSymbols.getInstance(Locale.US); private final StringBuilder sb = new StringBuilder(); private DecimalFormat integerFormat; private DecimalFormat decimalFormat; private DecimalFormat coordinateFormat; private SimpleDateFormat calendarTimeFormat; boolean first = true; private ToStringBuilder(String name) { sb.append(name).append("{"); } /** * Create a ToStringBuilder for a regular POJO type. This builder * will include metadata(class and field names) when building the to sting. */ public static ToStringBuilder of(Class clazz) { return new ToStringBuilder(clazz.getSimpleName()); } /* General purpose formatters */ public ToStringBuilder addNum(String name, Number num) { return addIfNotNull(name, num, this::formatNumber); } public ToStringBuilder addNum(String name, Number value, Number ignoreValue) { return addIfNotIgnored(name, value, ignoreValue, this::formatNumber); } public ToStringBuilder addNum(String name, Number num, String unit) { return addIfNotNull(name, num, n -> formatNumber(n) + unit); } public ToStringBuilder addBool(String name, Boolean value) { return addIfNotNull(name, value); } public ToStringBuilder addStr(String name, String value) { return addIfNotNull(name, value, v -> "'" + v + "'"); } public ToStringBuilder addEnum(String name, Enum value) { return addIfNotNull(name, value); } public ToStringBuilder addObj(String name, Object obj) { return addIfNotNull(name, obj); } public ToStringBuilder addEntityId(String name, TransitEntity entity) { return addIfNotNull(name, entity, e -> e.getId().toString()); } public ToStringBuilder addInts(String name, int[] intArray) { return addIfNotNull(name, intArray, Arrays::toString); } public ToStringBuilder addCol(String name, Collection c) { return addIfNotNull(name, c); } public ToStringBuilder addColLimited(String name, Collection c, int limit) { if(c == null) { return this; } if(c.size() > limit+1) { String value = c.stream() .limit(limit) .map(Object::toString) .collect(Collectors.joining(", ")); return addIt( name + "(" + limit + "/" + c.size() + ")", "[" + value + ", ..]" ); } return addIfNotNull(name, c); } /* Special purpose formatters */ /** Add a Coordinate location, longitude or latitude */ public ToStringBuilder addCoordinate(String name, Number num) { return addIfNotNull(name, num, this::formatCoordinate); } /** * Add the TIME part in the local system timezone using 24 hours. Format: HH:mm:ss. * Note! The DATE is not printed. {@code null} value is ignored. */ public ToStringBuilder addCalTime(String name, Calendar time) { return addIfNotNull(name, time, t -> formatTime(t.getTime())); } /** * Add time in seconds since midnight. Format: hh:mm:ss. Ignore default values. */ public ToStringBuilder addServiceTime(String name, int timeSecondsPastMidnight, int ignoreValue) { return addIfNotIgnored(name, timeSecondsPastMidnight, ignoreValue, TimeUtils::timeToStrCompact); } /** * Add times in seconds since midnight. Format: hh:mm. {@code null} value is ignored. */ public ToStringBuilder addServiceTimeSchedule(String name, int[] value) { return addIfNotNull( name, value, a -> Arrays.stream(a) .mapToObj(TimeUtils::timeToStrShort) .collect(Collectors.joining(", ", "[", "]")) ); } /** * Add a duration to the string in format like '3h4m35s'. Each component (hours, minutes, and or * seconds) is only added if they are not zero {@code 0}. This is the same format as the * {@link Duration#toString()}, but without the 'PT' prefix. {@code null} value is ignored. */ public ToStringBuilder addDuration(String name, Integer durationSeconds) { return addIfNotIgnored(name, durationSeconds, null, TimeUtils::durationToStr); } public ToStringBuilder addDuration(String name, Duration duration) { return addIfNotIgnored( name, duration, null, d -> TimeUtils.durationToStr((int)d.toSeconds()) ); } @Override public String toString() { return sb.append("}").toString(); } /** private methods */ private ToStringBuilder addIfNotNull(String name, T value) { return addIfNotIgnored(name, value, null, Object::toString); } private ToStringBuilder addIfNotNull(String name, T value, Function vToString) { return addIfNotIgnored(name, value, null, vToString); } private ToStringBuilder addIfNotIgnored(String name, T value, T ignoreValue, Function mapToString) { if(value == ignoreValue) { return this; } if(ignoreValue != null && ignoreValue.equals(value)) { return this; } if(value == null) { return addIt(name, "null"); } return addIt(name, mapToString.apply(value)); } private ToStringBuilder addIt(String name, @NotNull String value) { if (first) { first = false; } else { sb.append(FIELD_SEPARATOR); } sb.append(name).append(": "); sb.append(value); return this; } private String formatTime(Date time) { if(calendarTimeFormat == null) { calendarTimeFormat = new SimpleDateFormat("HH:mm:ss"); } return calendarTimeFormat.format(time.getTime()); } String formatCoordinate(Number value) { if(coordinateFormat == null) { coordinateFormat = new DecimalFormat("#0.0####", DECIMAL_SYMBOLS); } // This need to be null-safe, because one of the coordinates in // #addCoordinate(String name, Number lat, Number lon) could be null. return value == null ? "null" : coordinateFormat.format(value); } String formatNumber(Number value) { if (value == null) { return "null"; } if(value instanceof Integer || value instanceof Long || value instanceof BigInteger) { if(integerFormat == null) { integerFormat = new DecimalFormat("#,##0", DECIMAL_SYMBOLS); } return integerFormat.format(value); } if(decimalFormat == null) { decimalFormat = new DecimalFormat("#,##0.0##", DECIMAL_SYMBOLS); } return decimalFormat.format(value); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy