View Javadoc

1   /*
2    * $Id: TagModel.java 651946 2008-04-27 13:41:38Z apetrelli $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  package org.apache.struts2.views.freemarker.tags;
23  
24  import java.io.IOException;
25  import java.io.Writer;
26  import java.util.HashMap;
27  import java.util.Iterator;
28  import java.util.Map;
29  
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  
33  import org.apache.struts2.components.Component;
34  
35  import com.opensymphony.xwork2.ActionContext;
36  import com.opensymphony.xwork2.inject.Container;
37  import com.opensymphony.xwork2.util.ValueStack;
38  import com.opensymphony.xwork2.util.logging.Logger;
39  import com.opensymphony.xwork2.util.logging.LoggerFactory;
40  
41  import freemarker.template.DefaultObjectWrapper;
42  import freemarker.template.SimpleNumber;
43  import freemarker.template.SimpleSequence;
44  import freemarker.template.TemplateModel;
45  import freemarker.template.TemplateModelException;
46  import freemarker.template.TemplateTransformModel;
47  
48  public abstract class TagModel implements TemplateTransformModel {
49      private static final Logger LOG = LoggerFactory.getLogger(TagModel.class);
50  
51      protected ValueStack stack;
52      protected HttpServletRequest req;
53      protected HttpServletResponse res;
54  
55      public TagModel(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
56          this.stack = stack;
57          this.req = req;
58          this.res = res;
59      }
60  
61      public Writer getWriter(Writer writer, Map params)
62          throws TemplateModelException, IOException {
63          Component bean = getBean();
64          Container container = (Container) stack.getContext().get(ActionContext.CONTAINER);
65          container.inject(bean);
66  
67          Map unwrappedParameters = unwrapParameters(params);
68          bean.copyParams(unwrappedParameters);
69  
70          return new CallbackWriter(bean, writer);
71      }
72  
73      protected abstract Component getBean();
74  
75      protected Map unwrapParameters(Map params) {
76          Map map = new HashMap(params.size());
77          DefaultObjectWrapper objectWrapper = new DefaultObjectWrapper();
78          for (Iterator iterator = params.entrySet().iterator(); iterator.hasNext();) {
79              Map.Entry entry = (Map.Entry) iterator.next();
80  
81              Object value = entry.getValue();
82  
83              if (value != null) {
84                  // the value should ALWAYS be a decendant of TemplateModel
85                  if (value instanceof TemplateModel) {
86                      try {
87                          map.put(entry.getKey(), objectWrapper
88                              .unwrap((TemplateModel) value));
89                      } catch (TemplateModelException e) {
90                          LOG.error("failed to unwrap [" + value
91                              + "] it will be ignored", e);
92                      }
93                  }
94                  // if it doesn't, we'll do it the old way by just returning the toString() representation
95                  else {
96                      map.put(entry.getKey(), value.toString());
97                  }
98              }
99          }
100         return map;
101     }
102 
103     protected Map convertParams(Map params) {
104         HashMap map = new HashMap(params.size());
105         for (Iterator iterator = params.entrySet().iterator(); iterator.hasNext();) {
106             Map.Entry entry = (Map.Entry) iterator.next();
107             Object value = entry.getValue();
108             if (value != null && !complexType(value)) {
109                 map.put(entry.getKey(), value.toString());
110             }
111         }
112         return map;
113     }
114 
115     protected Map getComplexParams(Map params) {
116         HashMap map = new HashMap(params.size());
117         for (Iterator iterator = params.entrySet().iterator(); iterator.hasNext();) {
118             Map.Entry entry = (Map.Entry) iterator.next();
119             Object value = entry.getValue();
120             if (value != null && complexType(value)) {
121                 if (value instanceof freemarker.ext.beans.BeanModel) {
122                     map.put(entry.getKey(), ((freemarker.ext.beans.BeanModel) value).getWrappedObject());
123                 } else if (value instanceof SimpleNumber) {
124                     map.put(entry.getKey(), ((SimpleNumber) value).getAsNumber());
125                 } else if (value instanceof SimpleSequence) {
126                     try {
127                         map.put(entry.getKey(), ((SimpleSequence) value).toList());
128                     } catch (TemplateModelException e) {
129                         LOG.error("There was a problem converting a SimpleSequence to a list", e);
130                     }
131                 }
132             }
133         }
134         return map;
135     }
136 
137     protected boolean complexType(Object value) {
138         return value instanceof freemarker.ext.beans.BeanModel
139                 || value instanceof SimpleNumber
140                 || value instanceof SimpleSequence;
141     }
142 }