Java tutorial
/* * Copyright 2014 the original author or authors. * * 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 com.carlomicieli.jtrains.core.models; import com.carlomicieli.jtrains.infrastructure.mapping.EntityLink; import com.carlomicieli.jtrains.util.Fun; import com.carlomicieli.jtrains.util.Slug; import com.carlomicieli.jtrains.validation.constraints.ContainsDefault; import com.carlomicieli.jtrains.validation.constraints.ISOCountry; import com.carlomicieli.jtrains.value.objects.LocalizedField; import org.apache.commons.lang.builder.EqualsBuilder; import org.bson.types.ObjectId; import org.hibernate.validator.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Locale; import java.util.Objects; import java.util.Optional; import java.util.function.UnaryOperator; /** * It represents a operator of the rail transport. * * @author Carlo Micieli * @since 1.0 */ public final class Railway { private final ObjectId _id; @NotBlank(message = "railway.name.required") @Size(min = 2, max = 10, message = "railway.name.size.notmet") private final String name; @NotBlank(message = "railway.slug.required") private final String slug; @Size(max = 100, message = "railway.companyName.size.notmet") private final String companyName; @NotNull(message = "railway.description.required") @ContainsDefault(message = "railway.description.default.required") private final LocalizedField<String> description; @NotBlank(message = "railway.country.required") @ISOCountry(message = "railway.country.code.invalid") private final String country; //@Past(message = "railway.operatingSince.past.notmet") private final LocalDate operatingSince; //@Past(message = "railway.operatingUntil.past.notmet") private final LocalDate operatingUntil; private final LocalDateTime lastModified; protected Railway(ObjectId id, String name, String slug, String companyName, LocalizedField<String> description, String country, LocalDate operatingSince, LocalDate operatingUntil, LocalDateTime lastModified) { this._id = id; this.name = name; this.slug = slug; this.companyName = companyName; this.description = description; this.country = country; this.operatingSince = operatingSince; this.operatingUntil = operatingUntil; this.lastModified = lastModified; } private Railway(Builder b) { this._id = b.id; this.name = b.name; this.slug = Slug.orElseGet(b.slug, () -> Slug.of(b.name)); this.companyName = b.companyName; this.description = b.description; this.country = b.country; this.operatingSince = b.operatingSince; this.operatingUntil = b.operatingUntil; this.lastModified = b.lastModified; } public static Railway build(UnaryOperator<Builder> op) { return op.apply(new Builder()).build(); } public EntityLink asLink() { return EntityLink.to(Railway.class).with(this, Railway::getSlug, Railway::getName); } /** * The {@code Railway} builder class. */ public static class Builder { private String name; private ObjectId id; private LocalizedField<String> description; private String companyName; private String country; private String slug; private LocalDate operatingSince; private LocalDate operatingUntil; private LocalDateTime lastModified; private Builder() { } public Builder id(ObjectId id) { this.id = id; return this; } public Builder name(String n) { this.name = n; return this; } public Builder companyName(String cm) { this.companyName = cm; return this; } public Builder country(String c) { this.country = c; return this; } public Builder slug(String s) { this.slug = s; return this; } public Builder operatingSince(LocalDate start) { this.operatingSince = start; return this; } public Builder operatingUntil(LocalDate end) { this.operatingUntil = end; return this; } public Builder lastModified(LocalDateTime lm) { this.lastModified = lm; return this; } public Builder description(String desc) { this.description = Fun.lazy(description, () -> LocalizedField.of(desc)); return this; } public Builder description(Locale lang, String desc) { this.description = Fun.lazyApply(description, () -> LocalizedField.of(lang, desc), field -> field.with(lang, desc)); return this; } private Railway build() { return new Railway(this); } } /** * Returns the {@code Railway} id. * * @return the unique id */ public ObjectId getId() { return _id; } /** * Returns the {@code Railway} name. * <p> * This field usually contains the acronym from the company name. * </p> * * @return the railway name */ public String getName() { return name; } /** * Returns the {@code Railway} slug. * <p> * If the slug is not set this method will return * the encoded value for {@link com.carlomicieli.jtrains.core.models.Railway#getName()}. * </p> * * @return the slug */ public String getSlug() { return slug; } /** * Returns the full {@code Railway} company name. * * @return the full company name */ public String getCompanyName() { return companyName; } /** * Returns the {@code Railway} description. * * @return the description */ public LocalizedField<String> getDescription() { return description; } /** * Returns the {@code Railway} country code. * <p> * The country is following {@code ISO 3166-1 alpha-2} code standard. * </p> * * @return the country code */ public String getCountry() { return country; } /** * Returns the starting year of operations. * * @return the year */ public LocalDate getOperatingSince() { return operatingSince; } /** * Returns the finishing year of operations. * * @return the year */ public LocalDate getOperatingUntil() { return operatingUntil; } /** * Returns the last modified timestamp. * * @return the timestamp */ public LocalDateTime getLastModified() { return lastModified; } /** * Returns a keyword for the current {@code Railway}. * <p> * The application could opt to show this value as string representation * for the current {@code Railway} instead of the usual {@code Railway#toString()}. * </p> * <p> * Valid labels include the {@code Railway#getName()} and the {@code Railway#getCompanyName()} (if available). * </p> * * @return the keyword string */ public String getLabel() { return Optional.ofNullable(getCompanyName()).map(cn -> String.join("", getName(), " (", cn, ")")) .orElse(getName()); } /** * Checks whether the {@code Railway} company is still active. * @return {@code true} if active, {@code false} otherwise. */ public boolean isActive() { return operatingUntil == null; } @Override public int hashCode() { return Objects.hash(name, slug, companyName, description, country, operatingSince, operatingUntil); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Railway)) return false; Railway that = (Railway) obj; return new EqualsBuilder().append(name, that.name).append(slug, that.slug) .append(companyName, that.companyName).append(description, that.description) .append(country, that.country).append(operatingSince, that.operatingSince) .append(operatingUntil, that.operatingUntil).isEquals(); } @Override public String toString() { return com.google.common.base.Objects.toStringHelper(this).omitNullValues().add("name", name) .add("slug", slug).add("companyName", companyName).add("active", isActive()).toString(); } }