001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 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 016import java.util.ArrayList; 017import java.util.Collection; 018import java.util.Collections; 019import java.util.List; 020 021import org.microbean.attributes.Attributes; 022 023/** 024 * A {@link org.microbean.assign.Qualifiers} extended to work with commonly-used {@linkplain #anyQualifier() any}, 025 * {@linkplain #defaultQualifier() default}, and {@linkplain #primordialQualifier() primordial} qualifiers. 026 * 027 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 028 * 029 * @see org.microbean.assign.Qualifiers 030 * 031 * @see Attributes 032 */ 033public class Qualifiers extends org.microbean.assign.Qualifiers { 034 035 private final Attributes ANY_QUALIFIER; 036 037 private final List<Attributes> ANY_QUALIFIERS; 038 039 private final Attributes DEFAULT_QUALIFIER; 040 041 private final List<Attributes> DEFAULT_QUALIFIERS; 042 043 private final List<Attributes> ANY_AND_DEFAULT_QUALIFIERS; 044 045 private final Attributes PRIMORDIAL_QUALIFIER; 046 047 private final List<Attributes> PRIMORDIAL_QUALIFIERS; 048 049 /** 050 * Creates a new {@link Qualifiers}. 051 */ 052 public Qualifiers() { 053 super(); 054 this.ANY_QUALIFIER = Attributes.of("Any", this.qualifiers()); 055 this.ANY_QUALIFIERS = List.of(this.ANY_QUALIFIER); 056 057 this.DEFAULT_QUALIFIER = Attributes.of("Default", this.qualifiers()); 058 this.DEFAULT_QUALIFIERS = List.of(this.DEFAULT_QUALIFIER); 059 060 this.ANY_AND_DEFAULT_QUALIFIERS = List.of(ANY_QUALIFIER, DEFAULT_QUALIFIER); 061 062 this.PRIMORDIAL_QUALIFIER = Attributes.of("Primordial", this.qualifiers()); 063 this.PRIMORDIAL_QUALIFIERS = List.of(PRIMORDIAL_QUALIFIER); 064 } 065 066 /** 067 * Returns an unmodifiable {@link List} consisting solely of the unattributed <dfn>any qualifier</dfn> and the 068 * <dfn>default qualifier</dfn>. 069 * 070 * @return an unmodifiable {@link List} consisting solely of the unattributed any qualifier and the default qualifier; 071 * never {@code null} 072 * 073 * @see #anyQualifier() 074 * 075 * @see #defaultQualifier() 076 */ 077 public List<Attributes> anyAndDefaultQualifiers() { 078 return ANY_AND_DEFAULT_QUALIFIERS; 079 } 080 081 /** 082 * Returns the unattributed <dfn>any qualifier</dfn>. 083 * 084 * @return the <dfn>any qualifier</dfn>; never {@code null} 085 * 086 * @see #anyQualifiers() 087 */ 088 public Attributes anyQualifier() { 089 return ANY_QUALIFIER; 090 } 091 092 /** 093 * Returns {@code true} if and only if the supplied {@link Attributes} {@linkplain Attributes#equals(Object) is equal 094 * to} the unattributed {@linkplain #anyQualifier() any qualifier}. 095 * 096 * @param a an {@link Attributes}; must not be {@code null} 097 * 098 * @return {@code true} if and only if the supplied {@link Attributes} {@linkplain Attributes#equals(Object) is equal 099 * to} the unattributed {@linkplain #anyQualifier() any qualifier} 100 * 101 * @exception NullPointerException if {@code a} is {@code null} 102 */ 103 public boolean anyQualifier(final Attributes a) { 104 return this.anyQualifier() == a || this.anyQualifier().equals(a) && this.qualifier(a); 105 } 106 107 /** 108 * Returns an immutable {@link List} consisting solely of the unattributed <dfn>any qualifier</dfn>. 109 * 110 * @return an immutable {@link List}; never {@code null} 111 * 112 * @see #anyQualifier() 113 */ 114 public List<Attributes> anyQualifiers() { 115 return ANY_QUALIFIERS; 116 } 117 118 /** 119 * Returns the <dfn>default qualifier</dfn>. 120 * 121 * @return the <dfn>default qualifier</dfn>; never {@code null} 122 * 123 * @see #defaultQualifiers() 124 */ 125 public Attributes defaultQualifier() { 126 return DEFAULT_QUALIFIER; 127 } 128 129 /** 130 * Returns {@code true} if and only if the supplied {@link Attributes} {@linkplain 131 * Attributes#equals(Object) is equal to} the {@linkplain #defaultQualifier() default qualifier}. 132 * 133 * @param a an {@link Attributes}; must not be {@code null} 134 * 135 * @return {@code true} if and only if the supplied {@link Attributes} {@linkplain 136 * Attributes#equals(Object) is equal to} the {@linkplain #defaultQualifier() default qualifier} 137 * 138 * @exception NullPointerException if {@code a} is {@code null} 139 */ 140 public boolean defaultQualifier(final Attributes a) { 141 return this.defaultQualifier() == a || this.defaultQualifier().equals(a) && qualifier(a); 142 } 143 144 /** 145 * Returns an immutable {@link List} consisting solely of the <dfn>default qualifier</dfn>. 146 * 147 * @return an immutable {@link List}; never {@code null} 148 * 149 * @see #defaultQualifier() 150 */ 151 public List<Attributes> defaultQualifiers() { 152 return DEFAULT_QUALIFIERS; 153 } 154 155 /** 156 * Returns an {@link Attributes} that is {@linkplain Attributes#equals(Object) equal to} the supplied {@link 157 * Attributes}. 158 * 159 * <p>The returned {@link Attributes} may be the supplied {@link Attributes} or a different instance.</p> 160 * 161 * @param a an {@link Attributes}; must not be {@code null} 162 * 163 * @return an {@link Attributes} that is {@linkplain Attributes#equals(Object) equal to} the supplied {@link 164 * Attributes}; never {@code null} 165 * 166 * @exception NullPointerException if {@code a} is {@code null} 167 */ 168 public Attributes normalize(final Attributes a) { 169 return switch (a) { 170 case null -> throw new NullPointerException("a"); 171 case Attributes q when this.defaultQualifier(q) -> this.defaultQualifier(); 172 default -> super.normalize(a); 173 }; 174 } 175 176 /** 177 * Returns an immutable {@link List} of {@link Attributes}s that is {@linkplain List#equals(Object) equal to} the 178 * supplied {@link List}. 179 * 180 * <p>The returned {@link List} may be the supplied {@link List} or a different instance.</p> 181 * 182 * @param list a {@link List} of {@link Attributes}s; must not be {@code null} 183 * 184 * @return an immutable {@link List} of {@link Attributes}s that is {@linkplain List#equals(Object) equal to} the 185 * supplied {@link List}; never {@code null} 186 * 187 * @exception NullPointerException if {@code list} is {@code null} 188 */ 189 public List<Attributes> normalize(final List<Attributes> list) { 190 return switch (list.size()) { 191 case 0 -> List.of(); 192 case 1 -> list.equals(this.defaultQualifiers()) ? this.defaultQualifiers() : List.copyOf(list); 193 default -> super.normalize(list); 194 }; 195 } 196 197 /** 198 * Returns the <dfn>primordial qualifier</dfn>. 199 * 200 * @return the <dfn>primordial qualifier</dfn>; never {@code null} 201 * 202 * @see #primordialQualifiers() 203 */ 204 public Attributes primordialQualifier() { 205 return PRIMORDIAL_QUALIFIER; 206 } 207 208 /** 209 * Returns {@code true} if and only if the supplied {@link Attributes} {@linkplain 210 * Attributes#equals(Object) is equal to} the {@linkplain #primordialQualifier() primordial qualifier}. 211 * 212 * @param a an {@link Attributes}; must not be {@code null} 213 * 214 * @return {@code true} if and only if the supplied {@link Attributes} {@linkplain 215 * Attributes#equals(Object) is equal to} the {@linkplain #primordialQualifier() primordial qualifier} 216 * 217 * @exception NullPointerException if {@code a} is {@code null} 218 */ 219 public boolean primordialQualifier(final Attributes a) { 220 return this.primordialQualifier() == a || this.primordialQualifier().equals(a) && this.qualifier(a); 221 } 222 223 /** 224 * Returns an immutable {@link List} consisting solely of the <dfn>primordial qualifier</dfn>. 225 * 226 * @return an immutable {@link List}; never {@code null} 227 * 228 * @see #primordialQualifier() 229 */ 230 public List<Attributes> primordialQualifiers() { 231 return PRIMORDIAL_QUALIFIERS; 232 } 233 234 /** 235 * Returns an unmodifiable {@link List} consisting only of those {@link Attributes} in the supplied {@link 236 * Collection} that {@linkplain #qualifier(Attributes) are qualifiers}. 237 * 238 * @param c a {@link Collection} of {@link Attributes}s; must not be {@code null} 239 * 240 * @return an unmodifiable {@link List} consisting only of those {@link Attributes}s in the supplied {@link 241 * Collection} that {@linkplain #qualifier(Attributes) are qualifiers}; never {@code null} 242 * 243 * @exception NullPointerException if {@code c} is {@code null} 244 */ 245 public List<Attributes> qualifiers(final Collection<? extends Attributes> c) { 246 return switch (c) { 247 case Collection<?> c0 when c0.isEmpty() -> List.of(); 248 case Collection<?> c0 when c0.equals(defaultQualifiers()) -> defaultQualifiers(); 249 case Collection<?> c0 when c0.equals(anyAndDefaultQualifiers()) -> anyAndDefaultQualifiers(); 250 default -> super.qualifiers(c); 251 }; 252 } 253 254}