001/*
002 * Copyright 2002-2012 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.beans.factory.config;
018
019import org.springframework.beans.BeanMetadataElement;
020import org.springframework.beans.factory.BeanFactoryUtils;
021import org.springframework.util.Assert;
022import org.springframework.util.ObjectUtils;
023import org.springframework.util.StringUtils;
024
025/**
026 * Holder for a BeanDefinition with name and aliases.
027 * Can be registered as a placeholder for an inner bean.
028 *
029 * <p>Can also be used for programmatic registration of inner bean
030 * definitions. If you don't care about BeanNameAware and the like,
031 * registering RootBeanDefinition or ChildBeanDefinition is good enough.
032 *
033 * @author Juergen Hoeller
034 * @since 1.0.2
035 * @see org.springframework.beans.factory.BeanNameAware
036 * @see org.springframework.beans.factory.support.RootBeanDefinition
037 * @see org.springframework.beans.factory.support.ChildBeanDefinition
038 */
039public class BeanDefinitionHolder implements BeanMetadataElement {
040
041        private final BeanDefinition beanDefinition;
042
043        private final String beanName;
044
045        private final String[] aliases;
046
047
048        /**
049         * Create a new BeanDefinitionHolder.
050         * @param beanDefinition the BeanDefinition to wrap
051         * @param beanName the name of the bean, as specified for the bean definition
052         */
053        public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName) {
054                this(beanDefinition, beanName, null);
055        }
056
057        /**
058         * Create a new BeanDefinitionHolder.
059         * @param beanDefinition the BeanDefinition to wrap
060         * @param beanName the name of the bean, as specified for the bean definition
061         * @param aliases alias names for the bean, or {@code null} if none
062         */
063        public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, String[] aliases) {
064                Assert.notNull(beanDefinition, "BeanDefinition must not be null");
065                Assert.notNull(beanName, "Bean name must not be null");
066                this.beanDefinition = beanDefinition;
067                this.beanName = beanName;
068                this.aliases = aliases;
069        }
070
071        /**
072         * Copy constructor: Create a new BeanDefinitionHolder with the
073         * same contents as the given BeanDefinitionHolder instance.
074         * <p>Note: The wrapped BeanDefinition reference is taken as-is;
075         * it is {@code not} deeply copied.
076         * @param beanDefinitionHolder the BeanDefinitionHolder to copy
077         */
078        public BeanDefinitionHolder(BeanDefinitionHolder beanDefinitionHolder) {
079                Assert.notNull(beanDefinitionHolder, "BeanDefinitionHolder must not be null");
080                this.beanDefinition = beanDefinitionHolder.getBeanDefinition();
081                this.beanName = beanDefinitionHolder.getBeanName();
082                this.aliases = beanDefinitionHolder.getAliases();
083        }
084
085
086        /**
087         * Return the wrapped BeanDefinition.
088         */
089        public BeanDefinition getBeanDefinition() {
090                return this.beanDefinition;
091        }
092
093        /**
094         * Return the primary name of the bean, as specified for the bean definition.
095         */
096        public String getBeanName() {
097                return this.beanName;
098        }
099
100        /**
101         * Return the alias names for the bean, as specified directly for the bean definition.
102         * @return the array of alias names, or {@code null} if none
103         */
104        public String[] getAliases() {
105                return this.aliases;
106        }
107
108        /**
109         * Expose the bean definition's source object.
110         * @see BeanDefinition#getSource()
111         */
112        @Override
113        public Object getSource() {
114                return this.beanDefinition.getSource();
115        }
116
117        /**
118         * Determine whether the given candidate name matches the bean name
119         * or the aliases stored in this bean definition.
120         */
121        public boolean matchesName(String candidateName) {
122                return (candidateName != null && (candidateName.equals(this.beanName) ||
123                                candidateName.equals(BeanFactoryUtils.transformedBeanName(this.beanName)) ||
124                                ObjectUtils.containsElement(this.aliases, candidateName)));
125        }
126
127
128        /**
129         * Return a friendly, short description for the bean, stating name and aliases.
130         * @see #getBeanName()
131         * @see #getAliases()
132         */
133        public String getShortDescription() {
134                StringBuilder sb = new StringBuilder();
135                sb.append("Bean definition with name '").append(this.beanName).append("'");
136                if (this.aliases != null) {
137                        sb.append(" and aliases [").append(StringUtils.arrayToCommaDelimitedString(this.aliases)).append("]");
138                }
139                return sb.toString();
140        }
141
142        /**
143         * Return a long description for the bean, including name and aliases
144         * as well as a description of the contained {@link BeanDefinition}.
145         * @see #getShortDescription()
146         * @see #getBeanDefinition()
147         */
148        public String getLongDescription() {
149                StringBuilder sb = new StringBuilder(getShortDescription());
150                sb.append(": ").append(this.beanDefinition);
151                return sb.toString();
152        }
153
154        /**
155         * This implementation returns the long description. Can be overridden
156         * to return the short description or any kind of custom description instead.
157         * @see #getLongDescription()
158         * @see #getShortDescription()
159         */
160        @Override
161        public String toString() {
162                return getLongDescription();
163        }
164
165
166        @Override
167        public boolean equals(Object other) {
168                if (this == other) {
169                        return true;
170                }
171                if (!(other instanceof BeanDefinitionHolder)) {
172                        return false;
173                }
174                BeanDefinitionHolder otherHolder = (BeanDefinitionHolder) other;
175                return this.beanDefinition.equals(otherHolder.beanDefinition) &&
176                                this.beanName.equals(otherHolder.beanName) &&
177                                ObjectUtils.nullSafeEquals(this.aliases, otherHolder.aliases);
178        }
179
180        @Override
181        public int hashCode() {
182                int hashCode = this.beanDefinition.hashCode();
183                hashCode = 29 * hashCode + this.beanName.hashCode();
184                hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.aliases);
185                return hashCode;
186        }
187
188}