001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2023–2024 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 (highest rank wins, or comes first). 018 * 019 * <p>In addition, an implementation may be designated as an {@linkplain #alternate() alternate}, which may affect the 020 * interpretation of the implementation's {@linkplain #rank() rank}.</p> 021 * 022 * <p>Given a series of {@link Ranked} implementations sorted by {@linkplain #rank() rank}, the first element of the 023 * series will bear the greatest {@linkplain #rank() rank}.</p> 024 * 025 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 026 * 027 * @see #alternate() 028 * 029 * @see #rank() 030 * 031 * @see #outranks(Ranked) 032 * 033 * @see #outranks(int) 034 * 035 * @see #outranks(int, int) 036 */ 037public interface Ranked { 038 039 040 /* 041 * Static fields. 042 */ 043 044 045 /** 046 * The default rank ({@value}) when returned by an implementation of the {@link #rank()} method. 047 * 048 * @see #rank() 049 */ 050 public static final int DEFAULT_RANK = 0; 051 052 053 /* 054 * Instance methods. 055 */ 056 057 058 /** 059 * Returns the rank of this {@link Ranked} implementation. 060 * 061 * <p>Implementations of this method may return any integer: positive, zero, or negative.</p> 062 * 063 * <p>The default implementation of this method returns the value of the {@link #DEFAULT_RANK} field ({@value 064 * #DEFAULT_RANK}).</p> 065 * 066 * <p>Overrides of this method must return a determinate value.</p> 067 * 068 * @return the rank of this {@link Ranked} implementation 069 * 070 * @see #outranks(int, int) 071 */ 072 // Highest rank wins (comes first), i.e. descending order 073 public default int rank() { 074 return DEFAULT_RANK; 075 } 076 077 /** 078 * Returns {@code true} if this {@link Ranked} is to be considered an <em>alternate</em>, which may have an effect on 079 * how the return value of the {@link #rank()} method is interpreted in some situations. 080 * 081 * <p>The default implementation of this method returns {@code false}.</p> 082 * 083 * <p>Overrides of this method must be idempotent and return a determinate value.</p> 084 * 085 * @return {@code true} if this {@link Ranked} is to be considered an <em>alternate</em> 086 */ 087 public default boolean alternate() { 088 return false; 089 } 090 091 /** 092 * Returns {@code true} if this {@link Ranked} outranks the supplied {@link Ranked} according to the rules described 093 * in the {@linkplain #outranks(int, int) specification for the <code>outranks(int, int)</code> method}. 094 * 095 * <p>Overriding this method, while possible and permitted, is discouraged.</p> 096 * 097 * @param other a {@link Ranked}; may be {@code null} (in which case this method will return {@code true}) 098 * 099 * @return {@code true} if this {@link Ranked} outranks the supplied {@link Ranked} 100 * 101 * @see #outranks(int, int) 102 */ 103 public default boolean outranks(final Ranked other) { 104 return other == null || outranks(this.rank(), other.rank()); 105 } 106 107 /** 108 * Returns {@code true} if this {@link Ranked} bears a {@linkplain #rank() rank} that outranks the rank represented by 109 * {@code j} according to the rules described in the {@linkplain #outranks(int, int) specification for the 110 * <code>outranks(int, int)</code> method}. 111 * 112 * <p>Overriding this method, while possible and permitted, is discouraged.</p> 113 * 114 * @param j a rank 115 * 116 * @return {@code true} if this {@link Ranked} bears a {@linkplain #rank() rank} that {@linkplain #outranks(int, int) 117 * outranks} the supplied rank 118 * 119 * @see #outranks(int, int) 120 */ 121 public default boolean outranks(final int j) { 122 return outranks(this.rank(), j); 123 } 124 125 126 /* 127 * Static methods. 128 */ 129 130 131 /** 132 * Returns {@code true} if and only if {@code r0} is non-{@code null} and {@linkplain #outranks(Ranked) outranks} 133 * {@code r1}. 134 * 135 * @param r0 a {@link Ranked}; may be {@code null} in which case {@code false} will be returned 136 * 137 * @param r1 a {@link Ranked}; may be {@code null} 138 * 139 * @return {@code true} if and only if {@code r0} is non-{@code null} and {@linkplain #outranks(Ranked) outranks} 140 * {@code r1} 141 * 142 * @see #outranks(Ranked) 143 */ 144 public static boolean outranks(final Ranked r0, final Ranked r1) { 145 return r0 != null && r0.outranks(r1); 146 } 147 148 /** 149 * Returns {@code true} if and only if a rank represented by {@code i} outranks a rank represented by {@code j}. 150 * 151 * <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 152 * greater than ({@code >}) <em>j</em>.</p> 153 * 154 * @param i an {@code int} representing a rank 155 * 156 * @param j an {@code int} representing a rank 157 * 158 * @return {@code true} if and only if {@code i} outranks {@code j} 159 * 160 * @idempotency This method is idempotent and deterministic. 161 * 162 * @threadsafety This method is safe for concurrent use by multiple threads. 163 */ 164 public static boolean outranks(final int i, final int j) { 165 return i > j; 166 } 167 168}