Java tutorial
/*- * #%L * utils-commons * %% * Copyright (C) 2016 - 2018 Gilles Landel * %% * 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. * #L% */ package fr.landel.utils.commons.tuple; import java.io.Serializable; import java.util.Iterator; import java.util.List; import java.util.Objects; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.CompareToBuilder; import org.apache.commons.lang3.builder.EqualsBuilder; /** * <p> * A generic consisting of elements of same type (may also be different if the * result is a generic of {@code Object} or a generic of common implementation). * </p> * * <p> * This class is an abstract implementation defining the basic API. It refers to * the elements through methods like 'get', 'set', 'getList' or 'size'. * </p> * * <p> * Subclass implementations may be mutable or immutable. However, there is no * restriction on the type of the stored objects that may be stored. If mutable * objects are stored in the generic, then the generic itself effectively * becomes mutable. * </p> * * <p> * Prefer to create a Data Transfer Object to be more comprehensible and * readable. The purpose of this is to create an entity Object, in Proof Of * Concept context, not a list. * </p> * * @param <T> * the element type * * @since Jul 27, 2016 * @author Gilles * */ public abstract class Generic<T> implements Comparable<Generic<T>>, Serializable { /** * serialVersionUID */ private static final long serialVersionUID = 2432145156034640731L; /** * Returns the element at the specified position in this list. * * @param index * index of the element to return * @return the element at the specified position in this list * @throws IndexOutOfBoundsException * if the index is out of range <tt>(index < 0 || index >= * size())</tt> */ public abstract T get(int index); /** * Returns an immutable list of parameters * * @return The list of elements */ public abstract List<T> getList(); /** * Returns the number of parameters * * @return The count of elements */ public abstract int size(); /** * Returns the internal list of parameters * * @return The list of elements */ protected abstract List<T> getAll(); /** * <p> * Compares the generic based on the elements in order from left to right. * The types must be {@code Comparable}. * </p> * * @param other * the other generic, not null * @return negative if this is less, zero if equal, positive if greater, * {@link Integer#MAX_VALUE} if other is {@code null} or has less * elements and {@link Integer#MIN_VALUE} if other has more elements */ @Override public int compareTo(final Generic<T> other) { if (other == null) { return Integer.MAX_VALUE; } else if (other == this) { return 0; } int length = this.getAll().size(); int otherLength = other.getAll().size(); if (length > otherLength) { return Integer.MAX_VALUE; } else if (length < otherLength) { return Integer.MIN_VALUE; } final CompareToBuilder compareBuilder = new CompareToBuilder(); final Iterator<T> iterator = this.getAll().iterator(); final Iterator<T> otherIterator = other.getAll().iterator(); while (iterator.hasNext() && otherIterator.hasNext()) { compareBuilder.append(iterator.next(), otherIterator.next()); } return compareBuilder.toComparison(); } /** * <p> * Compares this generic to another. Each sub-objects are checked. * </p> * * @param obj * the object to compare to, null returns false * @return true if the elements of the generic are equal */ @Override public boolean equals(final Object obj) { if (obj == this) { return true; } if (obj instanceof Generic) { final Generic<?> other = (Generic<?>) obj; if (this.getAll().size() != other.getAll().size()) { return false; } final EqualsBuilder equalsBuilder = new EqualsBuilder(); final Iterator<T> iterator = this.getAll().iterator(); final Iterator<?> otherIterator = other.getAll().iterator(); while (iterator.hasNext() && otherIterator.hasNext()) { equalsBuilder.append(iterator.next(), otherIterator.next()); } return equalsBuilder.isEquals(); } return false; } /** * <p> * Returns a suitable hash code. * </p> * * @return the hash code */ @Override public int hashCode() { return Objects.hash(this.getAll().toArray()); } /** * <p> * Returns a String representation of this generic using the format * {@code ($left,$right)}. * </p> * * @return a string describing this object, not null */ @Override public String toString() { return new StringBuilder("(").append(StringUtils.join(this.getAll(), ", ")).append(')').toString(); } /** * <p> * Formats the receiver using the given format. * </p> * * <p> * This uses {@link java.util.Formattable} to perform the formatting. All * variables may be used to embed. Use {@code %1$s} for the first element * (key), {@code %2$s} for the second element (value)... The default format * used by {@code toString()} is {@code (%1$s,%2$s...)}. * </p> * * @param format * the format string, optionally containing {@code %1$s}, * {@code %2$s}... but not null * @return the formatted string, not null */ public String toString(final String format) { return String.format(format, this.getAll().toArray()); } /** * <p> * Obtains an immutable generic of from objects inferring the generic types. * </p> * * <p> * This factory allows the generic to be created using inference to obtain * the generic types. * </p> * * @param <T> * the element type * @param objects * the elements, may be null * @return a generic formed from the parameters, not null */ @SafeVarargs public static <T> ImmutableGeneric<T> of(final T... objects) { return new ImmutableGeneric<T>(objects); } /** * <p> * Obtains a mutable generic of from objects inferring the generic type. * </p> * * <p> * This factory allows the generic to be created using inference to obtain * the generic types. * </p> * * @param <T> * the element type * @param objects * the elements, may be null * @return a generic formed from the parameters, not null */ @SafeVarargs public static <T> MutableGeneric<T> ofMutable(final T... objects) { return new MutableGeneric<T>(objects); } }