1 /*
2  * Copyright 2017-2020 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.springframework.data.jpa.repository.config;
17
18 import java.util.Collection;
19 import java.util.Set;
20
21 import javax.persistence.EntityManagerFactory;
22 import javax.persistence.metamodel.Metamodel;
23
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26 import org.springframework.beans.BeansException;
27 import org.springframework.beans.factory.BeanFactoryUtils;
28 import org.springframework.beans.factory.FactoryBean;
29 import org.springframework.beans.factory.ListableBeanFactory;
30 import org.springframework.beans.factory.config.AbstractFactoryBean;
31 import org.springframework.context.ApplicationContext;
32 import org.springframework.context.ApplicationContextAware;
33 import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext;
34 import org.springframework.data.util.StreamUtils;
35 import org.springframework.lang.Nullable;
36
37 /**
38  * {@link FactoryBean} to setup {@link JpaMetamodelMappingContext} instances from Spring configuration.
39  *
40  * @author Oliver Gierke
41  * @author Mark Paluch
42  * @since 1.6
43  */

44 class JpaMetamodelMappingContextFactoryBean extends AbstractFactoryBean<JpaMetamodelMappingContext>
45         implements ApplicationContextAware {
46
47     private static final Logger LOG = LoggerFactory.getLogger(JpaMetamodelMappingContextFactoryBean.class);
48
49     private @Nullable ListableBeanFactory beanFactory;
50
51     /*
52      * (non-Javadoc)
53      * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
54      */

55     @Override
56     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
57         this.beanFactory = applicationContext;
58     }
59
60     /*
61      * (non-Javadoc)
62      * @see org.springframework.beans.factory.config.AbstractFactoryBean#getObjectType()
63      */

64     @Override
65     public Class<?> getObjectType() {
66         return JpaMetamodelMappingContext.class;
67     }
68
69     /*
70      * (non-Javadoc)
71      * @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
72      */

73     @Override
74     protected JpaMetamodelMappingContext createInstance() throws Exception {
75
76         if (LOG.isDebugEnabled()) {
77             LOG.debug("Initializing JpaMetamodelMappingContext…");
78         }
79
80         JpaMetamodelMappingContext context = new JpaMetamodelMappingContext(getMetamodels());
81         context.initialize();
82
83         if (LOG.isDebugEnabled()) {
84             LOG.debug("Finished initializing JpaMetamodelMappingContext!");
85         }
86
87         return context;
88     }
89
90     /**
91      * Obtains all {@link Metamodel} instances of the current {@link ApplicationContext}.
92      *
93      * @return
94      */

95     private Set<Metamodel> getMetamodels() {
96
97         if (beanFactory == null) {
98             throw new IllegalStateException("BeanFactory must not be null!");
99         }
100
101         Collection<EntityManagerFactory> factories = BeanFactoryUtils
102                 .beansOfTypeIncludingAncestors(beanFactory, EntityManagerFactory.class).values();
103
104         return factories.stream() //
105                 .map(EntityManagerFactory::getMetamodel) //
106                 .collect(StreamUtils.toUnmodifiableSet());
107     }
108 }
109