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.attributes;
015
016import java.lang.constant.ClassDesc;
017import java.lang.constant.ConstantDesc;
018import java.lang.constant.ConstantDescs;
019import java.lang.constant.DynamicConstantDesc;
020import java.lang.constant.MethodHandleDesc;
021import java.lang.constant.MethodTypeDesc;
022
023import java.util.Optional;
024
025import static java.lang.constant.ConstantDescs.BSM_INVOKE;
026import static java.lang.constant.ConstantDescs.CD_boolean;
027import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC;
028
029/**
030 * A {@link Value} whose value is a {@code boolean}.
031 *
032 * @param value the value
033 *
034 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a>
035 */
036public final record BooleanValue(boolean value) implements Value<BooleanValue> {
037
038  /**
039   * The {@link BooleanValue} representing {@code true}.
040   */
041  public static final BooleanValue TRUE = new BooleanValue(true);
042
043  /**
044   * The {@link BooleanValue} representing {@code false}.
045   */
046  public static final BooleanValue FALSE = new BooleanValue(false);
047
048  @Override // Comparable<Value>
049  public final int compareTo(BooleanValue other) {
050    if (other == null) {
051      return -1;
052    } else if (this.equals(other)) {
053      return 0;
054    } else if (this.value()) {
055      return 1; // false comes first
056    } else {
057      return -1;
058    }
059  }
060
061  @Override // Constable
062  public final Optional<DynamicConstantDesc<BooleanValue>> describeConstable() {
063    final ClassDesc cd = ClassDesc.of(this.getClass().getName());
064    return
065      Optional.of(DynamicConstantDesc.of(BSM_INVOKE,
066                                         MethodHandleDesc.ofMethod(STATIC,
067                                                                   cd,
068                                                                   "of",
069                                                                   MethodTypeDesc.of(cd,
070                                                                                     CD_boolean)),
071                                         this.value() ? ConstantDescs.TRUE : ConstantDescs.FALSE));
072  }
073
074  @Override // Record
075  public final boolean equals(final Object other) {
076    return
077      other == this ||
078      // Follow java.lang.annotation.Annotation requirements
079      other != null && other.getClass() == this.getClass() && this.value() == ((BooleanValue)other).value();
080  }
081
082  @Override // Record
083  public final int hashCode() {
084    // Follow java.lang.annotation.Annotation requirements.
085    return Boolean.valueOf(this.value()).hashCode();
086  }
087
088  @Override // Record
089  public final String toString() {
090    return String.valueOf(this.value());
091  }
092
093  /**
094   * Returns a {@link BooleanValue} suitable for the supplied arguments.
095   *
096   * @param b a {@code boolean}
097   *
098   * @return {@link TRUE} if {@code b} is {@code true}; {@link FALSE} otherwise
099   */
100  public static final BooleanValue of(final boolean b) {
101    return b ? TRUE : FALSE;
102  }
103
104}