001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.cp;
014
015import static org.apache.juneau.collections.JsonMap.*;
016import static org.apache.juneau.common.internal.ArgUtils.*;
017import static org.apache.juneau.common.internal.StringUtils.*;
018import static org.apache.juneau.internal.ClassUtils.*;
019
020import java.util.function.*;
021
022import org.apache.juneau.collections.*;
023import org.apache.juneau.common.internal.*;
024import org.apache.juneau.internal.*;
025
026/**
027 * Represents a bean in a {@link BeanStore}.
028 *
029 * <p>
030 * A bean entry consists of the following:
031 * <ul>
032 *    <li>A class type.
033 *    <li>A bean or bean supplier that returns an instance of the class type.  This can be a subclass of the type.
034 *    <li>An optional name.
035 * </ul>
036 *
037 * @param <T> The bean type.
038 */
039public class BeanStoreEntry<T> {
040
041   //-----------------------------------------------------------------------------------------------------------------
042   // Static
043   //-----------------------------------------------------------------------------------------------------------------
044
045   /**
046    * Static creator.
047    *
048    * @param <T> The class type to associate with the bean.
049    * @param type The class type to associate with the bean.
050    * @param bean The bean supplier.
051    * @param name Optional name to associate with the bean.  Can be <jk>null</jk>.
052    * @return A new bean store entry.
053    */
054   public static <T> BeanStoreEntry<T> create(Class<T> type, Supplier<T> bean, String name) {
055      return new BeanStoreEntry<>(type, bean, name);
056   }
057
058   //-----------------------------------------------------------------------------------------------------------------
059   // Instance
060   //-----------------------------------------------------------------------------------------------------------------
061
062   final Supplier<T> bean;
063   final Class<T> type;
064   final String name;
065
066   /**
067    * Constructor.
068    *
069    * @param type The class type to associate with the bean.
070    * @param bean The bean supplier.
071    * @param name Optional name to associate with the bean.  Can be <jk>null</jk>.
072    */
073   protected BeanStoreEntry(Class<T> type, Supplier<T> bean, String name) {
074      this.bean = assertArgNotNull("bean", bean);
075      this.type = assertArgNotNull("type", type);
076      this.name = nullIfEmpty(name);
077   }
078
079   /**
080    * Returns <jk>true</jk> if this bean is exactly of the specified type.
081    *
082    * @param type The class to check.  Returns <jk>false</jk> if <jk>null</jk>.
083    * @return <jk>true</jk> if this bean is exactly of the specified type.
084    */
085   public boolean matches(Class<?> type) {
086      return this.type.equals(type);
087   }
088
089   /**
090    * Returns <jk>true</jk> if this bean is exactly of the specified type and has the specified name.
091    *
092    * @param type The class to check.  Returns <jk>false</jk> if <jk>null</jk>.
093    * @param name The name to check.  Can be <jk>null</jk> to only match if name of entry is <jk>null</jk>.
094    * @return <jk>true</jk> if this bean is exactly of the specified type and has the specified name.
095    */
096   public boolean matches(Class<?> type, String name) {
097      name = nullIfEmpty(name);
098      return matches(type) && StringUtils.eq(this.name, name);
099   }
100
101   /**
102    * Returns the bean associated with this entry.
103    *
104    * @return The bean associated with this entry.
105    */
106   public T get() {
107      return bean.get();
108   }
109
110   /**
111    * Returns the type this bean is associated with.
112    *
113    * @return The type this bean is associated with.
114    */
115   public Class<T> getType() {
116      return type;
117   }
118
119   /**
120    * Returns the name associated with this entry.
121    *
122    * @return the name associated with this entry.  <jk>null</jk> if no name is associated.
123    */
124   public String getName() {
125      return name;
126   }
127
128   /**
129    * Returns the properties in this object as a simple map for debugging purposes.
130    *
131    * @return The properties in this object as a simple map.
132    */
133   protected JsonMap properties() {
134      return filteredMap()
135         .append("type", simpleClassName(getType()))
136         .append("bean", ObjectUtils.identity(get()))
137         .append("name", getName());
138   }
139}