View Javadoc

    1   /*
    2    * $Id: StrutsBeanWrapper.java 474191 2006-11-13 08:30:40Z mrdon $
    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;
    22
    23  import java.util.Map;
    24  import java.util.Set;
    25
    26  import org.apache.struts2.StrutsConstants;
    27
    28  import freemarker.core.CollectionAndSequence;
    29  import freemarker.ext.beans.BeansWrapper;
    30  import freemarker.ext.beans.MapModel;
    31  import freemarker.ext.util.ModelFactory;
    32  import freemarker.template.ObjectWrapper;
    33  import freemarker.template.SimpleSequence;
    34  import freemarker.template.TemplateBooleanModel;
    35  import freemarker.template.TemplateCollectionModel;
    36  import freemarker.template.TemplateHashModelEx;
    37  import freemarker.template.TemplateModel;
    38  import freemarker.template.TemplateModelException;
    39
    40  /***
    41   * <!-- START SNIPPET: javadoc -->
    42   *
    43   * The StrutsBeanWrapper extends the default FreeMarker BeansWrapper and provides almost no change in functionality,
    44   * <b>except</b> for how it handles maps. Normally, FreeMarker has two modes of operation: either support for friendly
    45   * map built-ins (?keys, ?values, etc) but only support for String keys; OR no special built-in support (ie: ?keys
    46   * returns the methods on the map instead of the keys) but support for String and non-String keys alike. Struts
    47   * provides an alternative implementation that gives us the best of both worlds.
    48   *
    49   * <p/> It is possible that this special behavior may be confusing or can cause problems. Therefore, you can set the
    50   * <b>struts.freemarker.wrapper.altMap</b> property in struts.properties to false, allowing the normal BeansWrapper
    51   * logic to take place instead.
    52   *
    53   * <!-- END SNIPPET: javadoc -->
    54   */
    55  public class StrutsBeanWrapper extends BeansWrapper {
    56      private boolean altMapWrapper;
    57
    58      StrutsBeanWrapper(boolean altMapWrapper) {
    59          this.altMapWrapper = altMapWrapper;
    60      }
    61
    62      public TemplateModel wrap(Object object) throws TemplateModelException {
    63          if (object instanceof TemplateBooleanModel) {
    64              return super.wrap(object);
    65          }
    66
    67          // attempt to get the best of both the SimpleMapModel and the MapModel of FM.
    68          if (altMapWrapper && object instanceof Map) {
    69              return getInstance(object, FriendlyMapModel.FACTORY);
    70          }
    71
    72          return super.wrap(object);
    73      }
    74
    75      /***
    76       * Attempting to get the best of both worlds of FM's MapModel and SimpleMapModel, by reimplementing the isEmpty(),
    77       * keySet() and values() methods. ?keys and ?values built-ins are thus available, just as well as plain Map
    78       * methods.
    79       */
    80      private final static class FriendlyMapModel extends MapModel implements TemplateHashModelEx {
    81          static final ModelFactory FACTORY = new ModelFactory() {
    82              public TemplateModel create(Object object, ObjectWrapper wrapper) {
    83                  return new FriendlyMapModel((Map) object, (BeansWrapper) wrapper);
    84              }
    85          };
    86
    87          public FriendlyMapModel(Map map, BeansWrapper wrapper) {
    88              super(map, wrapper);
    89          }
    90
    91          public boolean isEmpty() {
    92              return ((Map) object).isEmpty();
    93          }
    94
    95          protected Set keySet() {
    96              return ((Map) object).keySet();
    97          }
    98
    99          public TemplateCollectionModel values() {
    100             return new CollectionAndSequence(new SimpleSequence(((Map) object).values(), wrapper));
    101         }
    102     }
    103 }