View Javadoc

1   /*
2    * $Id: TagModel.java 539660 2007-05-19 01:25:31Z musachy $
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  package org.apache.struts2.views.freemarker.tags;
22  
23  import java.io.IOException;
24  import java.io.Writer;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.Map;
28  
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.struts2.components.Component;
35  import org.apache.struts2.dispatcher.Dispatcher;
36  
37  import com.opensymphony.xwork2.inject.Container;
38  import com.opensymphony.xwork2.util.ValueStack;
39  
40  import freemarker.template.DefaultObjectWrapper;
41  import freemarker.template.SimpleNumber;
42  import freemarker.template.SimpleSequence;
43  import freemarker.template.TemplateModel;
44  import freemarker.template.TemplateModelException;
45  import freemarker.template.TemplateTransformModel;
46  
47  public abstract class TagModel implements TemplateTransformModel {
48      private static final Log LOG = LogFactory.getLog(TagModel.class);
49  
50      protected ValueStack stack;
51      protected HttpServletRequest req;
52      protected HttpServletResponse res;
53  
54      public TagModel(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
55          this.stack = stack;
56          this.req = req;
57          this.res = res;
58      }
59  
60      public Writer getWriter(Writer writer, Map params)
61          throws TemplateModelException, IOException {
62          Component bean = getBean();
63          Container container = Dispatcher.getInstance().getConfigurationManager().getConfiguration().getContainer();
64          container.inject(bean);
65  
66          Map unwrappedParameters = unwrapParameters(params);
67          bean.copyParams(unwrappedParameters);
68  
69          return new CallbackWriter(bean, writer);
70      }
71  
72      protected abstract Component getBean();
73  
74      protected Map unwrapParameters(Map params) {
75          Map map = new HashMap(params.size());
76          DefaultObjectWrapper objectWrapper = new DefaultObjectWrapper();
77          for (Iterator iterator = params.entrySet().iterator(); iterator.hasNext();) {
78              Map.Entry entry = (Map.Entry) iterator.next();
79  
80              Object value = entry.getValue();
81  
82              if (value != null) {
83                  // the value should ALWAYS be a decendant of TemplateModel
84                  if (value instanceof TemplateModel) {
85                      try {
86                          map.put(entry.getKey(), objectWrapper
87                              .unwrap((TemplateModel) value));
88                      } catch (TemplateModelException e) {
89                          LOG.error("failed to unwrap [" + value
90                              + "] it will be ignored", e);
91                      }
92                  }
93                  // if it doesn't, we'll do it the old way by just returning the toString() representation
94                  else {
95                      map.put(entry.getKey(), value.toString());
96                  }
97              }
98          }
99          return map;
100     }
101 
102     protected Map convertParams(Map params) {
103         HashMap map = new HashMap(params.size());
104         for (Iterator iterator = params.entrySet().iterator(); iterator.hasNext();) {
105             Map.Entry entry = (Map.Entry) iterator.next();
106             Object value = entry.getValue();
107             if (value != null && !complexType(value)) {
108                 map.put(entry.getKey(), value.toString());
109             }
110         }
111         return map;
112     }
113 
114     protected Map getComplexParams(Map params) {
115         HashMap map = new HashMap(params.size());
116         for (Iterator iterator = params.entrySet().iterator(); iterator.hasNext();) {
117             Map.Entry entry = (Map.Entry) iterator.next();
118             Object value = entry.getValue();
119             if (value != null && complexType(value)) {
120                 if (value instanceof freemarker.ext.beans.BeanModel) {
121                     map.put(entry.getKey(), ((freemarker.ext.beans.BeanModel) value).getWrappedObject());
122                 } else if (value instanceof SimpleNumber) {
123                     map.put(entry.getKey(), ((SimpleNumber) value).getAsNumber());
124                 } else if (value instanceof SimpleSequence) {
125                     try {
126                         map.put(entry.getKey(), ((SimpleSequence) value).toList());
127                     } catch (TemplateModelException e) {
128                         LOG.error("There was a problem converting a SimpleSequence to a list", e);
129                     }
130                 }
131             }
132         }
133         return map;
134     }
135 
136     protected boolean complexType(Object value) {
137         return value instanceof freemarker.ext.beans.BeanModel
138                 || value instanceof SimpleNumber
139                 || value instanceof SimpleSequence;
140     }
141 }