001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2026 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.lang.constant.Constable; 017import java.lang.constant.DynamicConstantDesc; 018 019import java.util.List; 020import java.util.Optional; 021 022import javax.lang.model.element.AnnotationMirror; 023 024import org.microbean.constant.Constables; 025 026import static java.lang.constant.ConstantDescs.BSM_INVOKE; 027import static java.lang.constant.ConstantDescs.CD_List; 028 029import static java.lang.constant.MethodHandleDesc.ofConstructor; 030 031import static java.util.Objects.requireNonNull; 032 033/** 034 * An identifier for a {@link Bean}. 035 * 036 * <p>Note that because an {@link Id} houses a {@link BeanTypeList}, and because a {@link BeanTypeList} houses {@link 037 * javax.lang.model.type.TypeMirror} instances, and because many {@link javax.lang.model.type.TypeMirror} instances may 038 * model the same type, two {@link Id}s that might appear as equal at first glance may not be.</p> 039 * 040 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 041 * 042 * @see javax.lang.model.type.TypeMirror#equals(Object) 043 */ 044public final class Id implements Constable { 045 046 private final BeanTypeList types; 047 048 private final List<AnnotationMirror> annotations; 049 050 /** 051 * Creates a new {@link Id}. 052 * 053 * @param types a non-{@code null} {@link BeanTypeList} 054 * 055 * @param annotations a non-{@code null} {@link List} of {@link AnnotationMirror}s further describing the supplied 056 * {@code types} 057 * 058 * @see BeanTypeList 059 * 060 * @see BeanTypes#beanTypes(java.util.Collection) 061 */ 062 public Id(final BeanTypeList types, final List<AnnotationMirror> annotations) { 063 super(); 064 this.types = requireNonNull(types, "types"); 065 this.annotations = List.copyOf(annotations); 066 } 067 068 /** 069 * Returns a non-{@code null}, immutable, determinate {@link List} of {@link AnnotationMirror}s describing this {@link 070 * Id}. 071 * 072 * @return a non-{@code null}, immutable, determinate {@link List} of {@link AnnotationMirror}s describing this {@link 073 * Id} 074 * 075 * @see #Id(BeanTypeList, List) 076 */ 077 public final List<AnnotationMirror> annotations() { 078 return this.annotations; 079 } 080 081 @Override // Constable 082 public final Optional<DynamicConstantDesc<Id>> describeConstable() { 083 return Constables.describeConstable(this.annotations) 084 .flatMap(annotationsDesc -> this.types.describeConstable() 085 .map(typesDesc -> DynamicConstantDesc.of(BSM_INVOKE, 086 ofConstructor(this.getClass().describeConstable().orElseThrow(), 087 BeanTypeList.class.describeConstable().orElseThrow(), 088 CD_List), 089 typesDesc, 090 annotationsDesc))); 091 } 092 093 @Override // Object 094 public final boolean equals(final Object other) { 095 return this == other || switch (other) { 096 case null -> false; 097 case Id i when this.getClass() == i.getClass() -> this.types.equals(i.types) && this.annotations.equals(i.annotations()); 098 default -> false; 099 }; 100 } 101 102 @Override // Object 103 public final int hashCode() { 104 return this.types.hashCode() ^ this.annotations.hashCode(); 105 } 106 107 @Override // Object 108 public final String toString() { 109 return this.annotations.toString() + " " + this.types.toString(); // TODO: improve 110 } 111 112 /** 113 * Returns a non-{@code null} determinate {@link BeanTypeList} describing this {@link Id}. 114 * 115 * @return a non-{@code null} determinate {@link BeanTypeList} describing this {@link Id} 116 * 117 * @see #Id(BeanTypeList, List) 118 * 119 * @see BeanTypeList 120 * 121 * @see BeanTypes#beanTypes(java.util.Collection) 122 */ 123 public final BeanTypeList types() { 124 return this.types; 125 } 126 127}