View Javadoc

1   /*
2    *  Copyright 2001-2013 Stephen Colebourne
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    *      http://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.joda.beans.integrate.freemarker;
17  
18  import org.joda.beans.Bean;
19  import org.joda.beans.MetaProperty;
20  
21  import freemarker.ext.beans.BeanModel;
22  import freemarker.ext.beans.BeansWrapper;
23  import freemarker.template.AdapterTemplateModel;
24  import freemarker.template.SimpleCollection;
25  import freemarker.template.SimpleScalar;
26  import freemarker.template.TemplateCollectionModel;
27  import freemarker.template.TemplateHashModelEx;
28  import freemarker.template.TemplateModel;
29  import freemarker.template.TemplateModelException;
30  import freemarker.template.WrappingTemplateModel;
31  
32  /**
33   * Template model converting a Joda-Bean to a Freemarker model.
34   * <p>
35   * Although this class is public, it should not normally be use directly.
36   * Follow the instructions in {@link FreemarkerObjectWrapper} to use this class.
37   */
38  public class FreemarkerTemplateModel
39          extends WrappingTemplateModel
40          implements TemplateHashModelEx, AdapterTemplateModel {
41  
42      /**
43       * The bean being wrapped.
44       */
45      private final Bean bean;
46  
47      /**
48       * Creates an instance of the model.
49       * @param bean  the bean being wrapped, not null
50       * @param wrapper  the default wrapper for further wrapping, not null
51       */
52      public FreemarkerTemplateModel(final Bean bean, final FreemarkerObjectWrapper wrapper) {
53          super(wrapper);
54          this.bean = bean;
55      }
56  
57      //-------------------------------------------------------------------------
58      /**
59       * Gets the value for the specified key, wrapping the result in another model.
60       * @param key  the property name, not null
61       * @return the model, null if not found
62       */
63      @Override
64      public TemplateModel get(String key) throws TemplateModelException {
65          MetaProperty<?> metaProperty = bean.metaBean().metaPropertyMap().get(key);
66          if (metaProperty == null) {
67              // try standard approach via BeanModel for non-bean properties and methods
68              BeanModel model = new BeanModel(bean, (BeansWrapper) getObjectWrapper());
69              TemplateModel result = model.get(key);
70              if (result instanceof SimpleScalar) {
71                  // have to map empty string to null
72                  String str = ((SimpleScalar) result).getAsString();
73                  if (str == null || str.isEmpty()) {
74                      return null;
75                  }
76              }
77              return result;
78          }
79          return wrap(metaProperty.get(bean));
80      }
81  
82      /**
83       * Checks if there are no properties.
84       * @return true if no properties
85       */
86      @Override
87      public boolean isEmpty() {
88          return size() == 0;
89      }
90  
91      /**
92       * Gets the number of properties.
93       * @return the number of properties
94       */
95      @Override
96      public int size() {
97          return bean.metaBean().metaPropertyCount();
98      }
99  
100     /**
101      * Gets the full set of property names, allowing the bean to be accessed as a sequence.
102      * @return the property names, not null
103      */
104     @Override
105     public TemplateCollectionModel keys() {
106         return new SimpleCollection(bean.propertyNames(), getObjectWrapper());
107     }
108 
109     /**
110      * Gets the full set of property values, allowing the bean to be accessed as a sequence.
111      * @return the wrapped property values, not null
112      */
113     @Override
114     public TemplateCollectionModel values() {
115         return new SimpleCollection(bean.metaBean().createPropertyMap(bean).flatten().values(), getObjectWrapper());
116     }
117 
118     /**
119      * Unwraps the model, returning the bean.
120      * @param hint  the class hint
121      * @return the underlying bean, not null
122      */
123     @SuppressWarnings("rawtypes")
124     @Override
125     public Object getAdaptedObject(Class hint) {
126         return bean;
127     }
128 
129 }