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