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