001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2025–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.construct.element; 015 016import java.lang.constant.ClassDesc; 017import java.lang.constant.Constable; 018import java.lang.constant.DynamicConstantDesc; 019import java.lang.constant.MethodHandleDesc; 020import java.lang.constant.MethodTypeDesc; 021 022import java.util.Objects; 023import java.util.Optional; 024 025import java.util.stream.IntStream; 026 027import javax.lang.model.element.Name; 028 029import static java.lang.constant.ConstantDescs.BSM_INVOKE; 030import static java.lang.constant.ConstantDescs.CD_String; 031 032import static java.lang.constant.MethodHandleDesc.ofConstructor; 033 034import static java.util.Objects.requireNonNull; 035 036/** 037 * A {@link Name} implementation based on {@link String}s. 038 * 039 * <p>This {@link Name} implementation differs from {@link StringName} in that there is no {@link 040 * org.microbean.construct.PrimordialDomain} involved, and therefore no notion of any kind of delegate.</p> 041 * 042 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a> 043 * 044 * @see Name 045 * 046 * @see StringName 047 */ 048public final class SyntheticName implements Constable, Name { 049 050 051 /* 052 * Instance fields. 053 */ 054 055 056 private final String value; 057 058 059 /* 060 * Constructors. 061 */ 062 063 064 /** 065 * Creates a new {@link SyntheticName}. 066 * 067 * @param value the actual name; must not be {@code null} 068 * 069 * @exception NullPointerException if {@code value} is {@code null} 070 */ 071 public SyntheticName(final Name value) { 072 super(); 073 this.value = value instanceof SyntheticName sn ? sn.value : value.toString(); 074 } 075 076 /** 077 * Creates a new {@link SyntheticName}. 078 * 079 * @param value the actual name; must not be {@code null} 080 * 081 * @exception NullPointerException if {@code value} is {@code null} 082 */ 083 public SyntheticName(final String value) { 084 super(); 085 this.value = requireNonNull(value, "value"); 086 } 087 088 089 /* 090 * Instance methods. 091 */ 092 093 094 @Override // Name (CharSequence) 095 public final char charAt(final int index) { 096 return this.value.charAt(index); 097 } 098 099 @Override // Name (CharSequence) 100 public final IntStream chars() { 101 return this.value.chars(); 102 } 103 104 @Override // Name (CharSequence) 105 public final IntStream codePoints() { 106 return this.value.codePoints(); 107 } 108 109 @Override // Name 110 public final boolean contentEquals(final CharSequence cs) { 111 return this == cs || cs != null && this.value.contentEquals(cs.toString()); 112 } 113 114 @Override // Constable 115 public final Optional<DynamicConstantDesc<SyntheticName>> describeConstable() { 116 return 117 Optional.of(DynamicConstantDesc.ofNamed(BSM_INVOKE, 118 this.value, 119 this.getClass().describeConstable().orElseThrow(), 120 ofConstructor(this.getClass().describeConstable().orElseThrow(), 121 CD_String), 122 this.value)); 123 } 124 125 @Override // Object 126 public final boolean equals(final Object other) { 127 return this == other || switch (other) { 128 case null -> false; 129 case SyntheticName sn when this.getClass() == sn.getClass() -> Objects.equals(this.value, sn.value); 130 default -> false; 131 }; 132 } 133 134 @Override // Object 135 public final int hashCode() { 136 return this.value.hashCode(); 137 } 138 139 @Override // Name (CharSequence) 140 public final boolean isEmpty() { 141 return this.value.isEmpty(); 142 } 143 144 @Override // Name (CharSequence) 145 public final int length() { 146 return this.value.length(); 147 } 148 149 @Override // Name (CharSequence) 150 public final CharSequence subSequence(final int start, final int end) { 151 return this.value.subSequence(start, end); 152 } 153 154 @Override // Name (CharSequence) 155 public final String toString() { 156 return this.value; 157 } 158 159}