View Javadoc

1   /**
2    * This file Copyright (c) 2010-2011 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.blossom.content2bean;
35  
36  import java.beans.Introspector;
37  import java.util.Map;
38  
39  import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
40  import org.springframework.util.ClassUtils;
41  
42  import info.magnolia.content2bean.Content2BeanException;
43  import info.magnolia.content2bean.TransformationState;
44  import info.magnolia.content2bean.TypeDescriptor;
45  import info.magnolia.content2bean.TypeMapping;
46  import info.magnolia.content2bean.impl.Content2BeanTransformerImpl;
47  import info.magnolia.objectfactory.ComponentProvider;
48  
49  /**
50   * Content2BeanTransformer that provides support for autowiring of properties, initialization callbacks and gives any
51   * configured BeanPostProcessors a chance to modify or proxy the bean.
52   * <p/>
53   * You can get access to the content node by implementing a method with the signature void setContent(Content). It will
54   * be called before bean post processors are called and initialization callbacks. More specifically before
55   * &#64;PostConstruct and afterPropertiesSet().
56   * <p/>
57   * Contrary to the normal Content2Bean mechanism it will NOT invoke a method with the signature void init(). Instead
58   * use &#64;PostConstruct or implement InitializingBean.
59   *
60   * @since 1.2
61   */
62  public class SpringContent2BeanTransformer extends Content2BeanTransformerImpl {
63  
64      private TypeDescriptor defaultType;
65      private Class<?> defaultClass;
66  
67      private String topLevelBeanName;
68      private AutowireCapableBeanFactory autowireCapableBeanFactory;
69  
70      public SpringContent2BeanTransformer(AutowireCapableBeanFactory autowireCapableBeanFactory) {
71          this.autowireCapableBeanFactory = autowireCapableBeanFactory;
72      }
73  
74      public void setDefaultClass(Class<?> defaultClass) {
75          this.defaultClass = defaultClass;
76      }
77  
78      public void setTopLevelBeanName(String topLevelBeanName) {
79          this.topLevelBeanName = topLevelBeanName;
80      }
81  
82      @Override
83      protected TypeDescriptor onResolveType(TypeMapping typeMapping, TransformationState state, TypeDescriptor resolvedType, ComponentProvider componentProvider) {
84          if (resolvedType == null && defaultType == null && defaultClass != null) {
85              defaultType = typeMapping.getTypeDescriptor(defaultClass);
86          }
87          return resolvedType == null ? defaultType : resolvedType;
88      }
89  
90      @Override
91      public Object newBeanInstance(TransformationState state, Map properties, ComponentProvider componentProvider) throws Content2BeanException {
92  
93          // Instantiates the bean
94          Object bean = super.newBeanInstance(state, properties, componentProvider);
95  
96          // Autowire dependencies
97          this.autowireCapableBeanFactory.autowireBean(bean);
98  
99          // After this the bean will have its properties set with the contents from the repository
100         return bean;
101     }
102 
103     @Override
104     public void initBean(TransformationState state, Map properties) throws Content2BeanException {
105 
106         Object bean = state.getCurrentBean();
107 
108         // Resolve the bean name to use.
109         String beanName = resolveBeanName(state, bean);
110 
111         // Apply BeanPostProcessors and call initialization callbacks.
112         bean = this.autowireCapableBeanFactory.initializeBean(state.getCurrentBean(), beanName);
113 
114         state.setCurrentBean(bean);
115     }
116 
117     protected String resolveBeanName(TransformationState state, Object bean) {
118 
119         // If this is the top level bean and we have a name set for it we'll use it.
120         if (state.getLevel() == 1 && topLevelBeanName != null) {
121             return topLevelBeanName;
122         }
123 
124         // This mirrors the policy used by AnnotationBeanNameGenerator.
125         String shortClassName = ClassUtils.getShortName(bean.getClass());
126         return Introspector.decapitalize(shortClassName);
127     }
128 }