001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2022 microBean™.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
014 * implied.  See the License for the specific language governing
015 * permissions and limitations under the License.
016 */
017package org.microbean.qualifier;
018
019import java.util.Map;
020
021import java.lang.constant.MethodHandleDesc;
022import java.lang.constant.MethodTypeDesc;
023
024import static java.lang.constant.ConstantDescs.CD_Map;
025import static java.lang.constant.ConstantDescs.CD_Object;
026import static java.lang.constant.ConstantDescs.CD_String;
027
028import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC;
029
030import static org.microbean.qualifier.ConstantDescs.CD_Qualifier;
031
032/**
033 * A {@link Binding} used to qualify objects.
034 *
035 * <p>This is a <a
036 * href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/doc-files/ValueBased.html">value-based</a>
037 * class.</p>
038 *
039 * @param <V> the type of a {@link Qualifier}'s {@linkplain #value()
040 * value} and of its {@linkplain #attributes() attribute values}
041 *
042 * @author <a href="https://about.me/lairdnelson"
043 * target="_parent">Laird Nelson</a>
044 *
045 * @see Binding
046 */
047public final class Qualifier<V> extends Binding<V, Qualifier<V>> {
048
049
050  /*
051   * Constructors.
052   */
053
054
055  /**
056   * Creates a new {@link Qualifier}.
057   *
058   * @param name the name; must not be {@code null}
059   *
060   * @param value the value; may be {@code null}
061   *
062   * @param attributes further describing this {@link Qualifier}; may
063   * be {@code null}
064   *
065   * @param info informational attributes further describing this
066   * {@link Qualifier} that are not considered by its {@link
067   * #equals(Object)} implementation; may be {@code null}
068   *
069   * @see #name()
070   *
071   * @see #value()
072   *
073   * @see #attributes()
074   *
075   * @see #info()
076   *
077   * @see Binding#Binding(String, Object, Map, Map)
078   */
079  private Qualifier(final String name,
080                    final V value,
081                    final Map<? extends String, ?> attributes,
082                    final Map<? extends String, ?> info) {
083    super(name, value, attributes, info);
084  }
085
086
087  /*
088   * Instance methods.
089   */
090
091
092  /**
093   * Returns a {@link MethodHandleDesc} describing the constructor or
094   * {@code static} method that will be used to create a <a
095   * href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/invoke/package-summary.html#condycon">dynamic
096   * constant</a> representing this {@link Qualifier}.
097   *
098   * <p>End users have no need to call this method.</p>
099   *
100   * @return a {@link MethodHandleDesc} describing the constructor or
101   * {@code static} method that will be used to create a <a
102   * href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/invoke/package-summary.html#condycon">dynamic
103   * constant</a> representing this {@link Qualifier}
104   *
105   * @nullability This method does not return {@code null}.
106   *
107   * @idempotency This method is idempotent and deterministic.
108   *
109   * @threadsafety This method is safe for concurrent use by multiple
110   * threads.
111   */
112  @Override // Binding<V, Qualifier<V>>
113  protected final MethodHandleDesc describeConstructor() {
114    return
115      MethodHandleDesc.ofMethod(STATIC,
116                                CD_Qualifier,
117                                "of",
118                                MethodTypeDesc.of(CD_Qualifier, CD_String, CD_Object, CD_Map, CD_Map));
119  }
120
121
122  /*
123   * Static methods.
124   */
125
126
127  /**
128   * Returns a {@link Qualifier}, which may or may not be newly
129   * created, representing the supplied arguments.
130   *
131   * @param <V> the type of the {@link Qualifier}'s {@linkplain #value()
132   * value} and of its {@linkplain #attributes() attribute values}
133   *
134   * @param name the {@link Qualifier}'s {@linkplain Qualifier#name()
135   * name}; must not be {@code null}
136   *
137   * @return a {@link Qualifier}
138   *
139   * @nullability This method never returns {@code null}.
140   *
141   * @idempotency This method is idempotent and deterministic.
142   *
143   * @threadsafety This method is safe for concurrent use by multiple
144   * threads.
145   */
146  public static final <V> Qualifier<V> of(final String name) {
147    return of(name, null, null, null);
148  }
149
150  /**
151   * Returns a {@link Qualifier}, which may or may not be newly
152   * created, representing the supplied arguments.
153   *
154   * @param <V> the type of the {@link Qualifier}'s {@linkplain #value()
155   * value} and of its {@linkplain #attributes() attribute values}
156   *
157   * @param name the {@link Qualifier}'s {@linkplain Qualifier#name()
158   * name}; must not be {@code null}
159   *
160   * @param value the {@link Qualifier}'s {@linkplain
161   * Qualifier#value() value}; may be {@code null}
162   *
163   * @return a {@link Qualifier}
164   *
165   * @nullability This method never returns {@code null}.
166   *
167   * @idempotency This method is idempotent and deterministic.
168   *
169   * @threadsafety This method is safe for concurrent use by multiple
170   * threads.
171   */
172  public static final <V> Qualifier<V> of(final String name, final V value) {
173    return of(name, value, null, null);
174  }
175
176  /**
177   * Returns a {@link Qualifier}, which may or may not be newly
178   * created, representing the supplied arguments.
179   *
180   * @param <V> the type of the {@link Qualifier}'s {@linkplain #value()
181   * value} and of its {@linkplain #attributes() attribute values}
182   *
183   * @param name the {@link Qualifier}'s {@linkplain Qualifier#name()
184   * name}; must not be {@code null}
185   *
186   * @param value the {@link Qualifier}'s {@linkplain
187   * Qualifier#value() value}; may be {@code null}
188   *
189   * @param attributes the {@link Qualifier}'s {@linkplain
190   * Qualifier#attributes() attributes}; may be {@code null}
191   *
192   * @return a {@link Qualifier}
193   *
194   * @nullability This method never returns {@code null}.
195   *
196   * @idempotency This method is idempotent and deterministic.
197   *
198   * @threadsafety This method is safe for concurrent use by multiple
199   * threads.
200   */
201  public static final <V> Qualifier<V> of(final String name,
202                                          final V value,
203                                          final Map<? extends String, ?> attributes) {
204    return of(name, value, attributes, null);
205  }
206
207  /**
208   * Returns a {@link Qualifier}, which may or may not be newly
209   * created, representing the supplied arguments.
210   *
211   * @param <V> the type of the {@link Qualifier}'s {@linkplain #value()
212   * value} and of its {@linkplain #attributes() attribute values}
213   *
214   * @param name the {@link Qualifier}'s {@linkplain Qualifier#name()
215   * name}; must not be {@code null}
216   *
217   * @param value the {@link Qualifier}'s {@linkplain
218   * Qualifier#value() value}; may be {@code null}
219   *
220   * @param attributes the {@link Qualifier}'s {@linkplain
221   * Qualifier#attributes() attributes}; may be {@code null}
222   *
223   * @param info the {@link Qualifier}'s {@linkplain Qualifier#info()
224   * informational attributes}; may be {@code null}
225   *
226   * @return a {@link Qualifier}
227   *
228   * @nullability This method never returns {@code null}.
229   *
230   * @idempotency This method is idempotent and deterministic.
231   *
232   * @threadsafety This method is safe for concurrent use by multiple
233   * threads.
234   */
235  public static final <V> Qualifier<V> of(final String name,
236                                          final V value,
237                                          final Map<? extends String, ?> attributes,
238                                          final Map<? extends String, ?> info) {
239    return new Qualifier<>(name, value, attributes, info);
240  }
241
242}