001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2022–2023 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.scope;
015
016import java.lang.constant.Constable;
017import java.lang.constant.ConstantDesc;
018import java.lang.constant.DynamicConstantDesc;
019import java.lang.constant.MethodHandleDesc;
020import java.lang.constant.MethodTypeDesc;
021
022import java.util.List;
023import java.util.Map;
024import java.util.Objects;
025import java.util.Optional;
026
027import org.microbean.qualifier.NamedAttributeMap;
028
029import static java.lang.constant.ConstantDescs.BSM_INVOKE;
030import static java.lang.constant.ConstantDescs.CD_boolean;
031import static java.lang.constant.ConstantDescs.FALSE;
032import static java.lang.constant.ConstantDescs.TRUE;
033
034import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC;
035
036import static org.microbean.qualifier.ConstantDescs.CD_NamedAttributeMap;
037
038import static org.microbean.scope.ConstantDescs.CD_Scope;
039
040public record Scope(NamedAttributeMap<?> id, boolean normal, NamedAttributeMap<?> governingScopeId)
041  implements Constable, ScopeMember {
042
043
044  /*
045   * Static fields.
046   */
047
048
049  private static final NamedAttributeMap<?> QUALIFIER = NamedAttributeMap.of("Qualifier", Map.of(), Map.of(), List.of());
050
051  private static final NamedAttributeMap<?> SCOPE = NamedAttributeMap.of("Scope", Map.of(), Map.of(), List.of(QUALIFIER));
052
053  public static final NamedAttributeMap<?> SINGLETON_ID = NamedAttributeMap.of("Singleton", Map.of(), Map.of(), List.of(SCOPE));
054
055  public static final Scope SINGLETON = Scope.of(SINGLETON_ID, false, SINGLETON_ID);
056
057  public static final NamedAttributeMap<?> NONE_ID = NamedAttributeMap.of("None", Map.of(), Map.of(), List.of(SCOPE));
058
059  public static final Scope NONE = Scope.of(NONE_ID, false, SINGLETON_ID);
060
061
062  /*
063   * Constructors.
064   */
065
066
067  public Scope {
068    Objects.requireNonNull(id, "id");
069    Objects.requireNonNull(governingScopeId, "governingScopeId");
070  }
071
072
073  /*
074   * Instance methods.
075   */
076
077
078  @Override // Constable
079  public final Optional<? extends ConstantDesc> describeConstable() {
080    return this.id().describeConstable()
081      .flatMap(idDesc -> this.governingScopeId().describeConstable()
082               .map(governingScopeIdDesc -> DynamicConstantDesc.of(BSM_INVOKE,
083                                                                   MethodHandleDesc.ofMethod(STATIC,
084                                                                                             CD_Scope,
085                                                                                             "of",
086                                                                                             MethodTypeDesc.of(CD_Scope,
087                                                                                                               CD_NamedAttributeMap,
088                                                                                                               CD_boolean,
089                                                                                                               CD_NamedAttributeMap)),
090                                                                   idDesc,
091                                                                   this.normal() ? TRUE : FALSE,
092                                                                   governingScopeIdDesc)));
093  }
094
095  public final boolean primordial() {
096    return this.id().equals(this.governingScopeId());
097  }
098
099
100  /*
101   * Static methods.
102   */
103
104
105  // This method is referenced by the describeConstable() method.
106  public static final Scope of(final NamedAttributeMap<?> id, final boolean normal, final NamedAttributeMap<?> governingScopeId) {
107    return new Scope(id, normal, governingScopeId);
108  }
109
110
111}