001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2023–2025 microBean™.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
006 * the License.  You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
011 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
012 * specific language governing permissions and limitations under the License.
013 */
014package org.microbean.bean;
015
016/**
017 * An interface whose implementations can be ranked numerically in descending order (the highest or greatest rank
018 * <dfn>outranks</dfn>, or wins, or trumps, or comes first).
019 *
020 * <p>In addition, an implementation may be designated as an {@linkplain #alternate() alternate}, which may affect the
021 * interpretation of the implementation's {@linkplain #rank() rank}, usually by conferring a rank that cannot be
022 * outranked by any other.</p>
023 *
024 * <p>Given a series of {@link Ranked} implementations sorted by {@linkplain #rank() rank}, the first element of the
025 * series will bear the highest, or greatest, {@linkplain #rank() rank}.</p>
026 *
027 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a>
028 *
029 * @see #alternate()
030 *
031 * @see #rank()
032 *
033 * @see #outranks(Ranked)
034 *
035 * @see #outranks(int)
036 *
037 * @see #outranks(int, int)
038 */
039public interface Ranked {
040
041
042  /*
043   * Static fields.
044   */
045
046
047  /**
048   * The default rank ({@value}) when returned by an implementation of the {@link #rank()} method.
049   *
050   * @see #rank()
051   */
052  public static final int DEFAULT_RANK = 0;
053
054
055  /*
056   * Instance methods.
057   */
058
059
060  /**
061   * Returns the rank of this {@link Ranked} implementation.
062   *
063   * <p>Implementations of this method may return any integer: positive, zero, or negative.</p>
064   *
065   * <p>The default implementation of this method returns the value of the {@link #DEFAULT_RANK} field ({@value
066   * #DEFAULT_RANK}).</p>
067   *
068   * <p>Overrides of this method must return a determinate value.</p>
069   *
070   * @return the rank of this {@link Ranked} implementation
071   *
072   * @see #outranks(int, int)
073   */
074  // Highest rank wins (comes first), i.e. descending order
075  public default int rank() {
076    return DEFAULT_RANK;
077  }
078
079  /**
080   * Returns {@code true} if this {@link Ranked} is to be considered an <em>alternate</em>, which may have an effect on
081   * how the return value of the {@link #rank()} method is interpreted in some situations.
082   *
083   * <p>The default implementation of this method returns {@code false}.</p>
084   *
085   * <p>Overrides of this method must be idempotent and return a determinate value.</p>
086   *
087   * @return {@code true} if this {@link Ranked} is to be considered an <em>alternate</em>
088   */
089  public default boolean alternate() {
090    return false;
091  }
092
093  /**
094   * Returns {@code true} if this {@link Ranked} outranks the supplied {@link Ranked} according to the rules described
095   * in the {@linkplain #outranks(int, int) specification for the <code>outranks(int, int)</code> method}.
096   *
097   * <p>Overriding this method, while possible and permitted, is discouraged.</p>
098   *
099   * @param other a {@link Ranked}; may be {@code null} (in which case this method will return {@code true})
100   *
101   * @return {@code true} if this {@link Ranked} outranks the supplied {@link Ranked}
102   *
103   * @see #outranks(int, int)
104   */
105  public default boolean outranks(final Ranked other) {
106    return other == null || outranks(this.rank(), other.rank());
107  }
108
109  /**
110   * Returns {@code true} if this {@link Ranked} bears a {@linkplain #rank() rank} that outranks the rank represented by
111   * {@code j} according to the rules described in the {@linkplain #outranks(int, int) specification for the
112   * <code>outranks(int, int)</code> method}.
113   *
114   * <p>Overriding this method, while possible and permitted, is discouraged.</p>
115   *
116   * @param j a rank
117   *
118   * @return {@code true} if this {@link Ranked} bears a {@linkplain #rank() rank} that {@linkplain #outranks(int, int)
119   * outranks} the supplied rank
120   *
121   * @see #outranks(int, int)
122   */
123  public default boolean outranks(final int j) {
124    return outranks(this.rank(), j);
125  }
126
127
128  /*
129   * Static methods.
130   */
131
132
133  /**
134   * Returns {@code true} if and only if {@code r0} is non-{@code null} and {@linkplain #outranks(Ranked) outranks}
135   * {@code r1}.
136   *
137   * @param r0 a {@link Ranked}; may be {@code null} in which case {@code false} will be returned
138   *
139   * @param r1 a {@link Ranked}; may be {@code null}
140   *
141   * @return {@code true} if and only if {@code r0} is non-{@code null} and {@linkplain #outranks(Ranked) outranks}
142   * {@code r1}
143   *
144   * @see #outranks(Ranked)
145   */
146  public static boolean outranks(final Ranked r0, final Ranked r1) {
147    return r0 != null && r0.outranks(r1);
148  }
149
150  /**
151   * Returns {@code true} if and only if a rank represented by {@code i} outranks a rank represented by {@code j}.
152   *
153   * <p>Given two ranks, <em>i</em> and <em>j</em>, <em>i</em> <em>outranks</em> <em>j</em> if and only if <em>i</em> is
154   * greater than ({@code >}) <em>j</em>.</p>
155   *
156   * @param i an {@code int} representing a rank
157   *
158   * @param j an {@code int} representing a rank
159   *
160   * @return {@code true} if and only if {@code i} outranks {@code j}
161   *
162   * @microbean.idempotency This method is idempotent and deterministic.
163   *
164   * @microbean.threadsafety This method is safe for concurrent use by multiple threads.
165   */
166  public static boolean outranks(final int i, final int j) {
167    return i > j;
168  }
169
170}