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}