View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.trinidad.model;
20  
21  import java.beans.IntrospectionException;
22  
23  import java.util.HashMap;
24  import java.util.Map;
25  
26  import javax.faces.context.FacesContext;
27  import javax.faces.el.PropertyResolver;
28  
29  import org.apache.myfaces.trinidad.logging.TrinidadLogger;
30  
31  
32  /**
33   * Creates a MenuModel from a TreeModel where nodes in the treeModel contain
34   * viewId information.
35   * <p>
36   * Each node must have either a bean getter method or a Map property
37   * that returns a viewId. There are several restrictions on the data:
38   * <ul>
39   * <li>The nodes in the tree must either be all beans or all maps,
40   * but not a mix of beans and maps.
41   * <li>The viewId of a node can be null, but if set it must be unique.
42   * <li>The tree cannot be mutable.
43   * </ul>
44   * The getFocusPath method
45   * <ul>
46   * <li>gets the current viewId by calling
47   * FacesContext.getCurrentInstance().getViewRoot().getViewId()
48   * <li> compares the current viewId with the viewId's in
49   * the nodes of the tree
50   * <li>returns the path to the node with the current viewId or null if the current viewId can't be found
51   * </ul>
52   * <p>
53   * Assuming that NavigationTree is a tree of beans with a vieId getter, an
54   * example of creating a MenuModel with this class might look like:
55   * <pre><code>
56   *     CollectionModel collectionModel = ModelUtils.toCollectionModel(new NavigationTree());
57   *     TreeModel treeModel = new ChildPropertyTreeModel(collectionModel, "children");
58   *     MenuModel menuModel = new ViewIdPropertyMenuModel(treeModel, "viewId");
59   * </code></pre>
60   */
61  // TODO - support for mutable trees?
62  public class ViewIdPropertyMenuModel extends BaseMenuModel
63  {
64    /**
65     * No-arg constructor for use with managed-beans.
66     * Must call the {@link #setViewIdProperty} and
67     * {@link #setWrappedData} methods after constructing this instance.
68     */
69    public ViewIdPropertyMenuModel()
70    {
71      super();
72      _focusPathMap = new HashMap<Object, Object>();
73    }
74    /**
75     *
76     * @param instance a treeModel. This object will be passed to
77     * {@link ModelUtils#toTreeModel}
78     * @param viewIdProperty the property to use to retrieve a viewId
79     * from a node in the tree
80     * @throws IntrospectionException
81     */
82    public ViewIdPropertyMenuModel(Object instance, String viewIdProperty)
83      throws IntrospectionException
84    {
85      super(instance);
86      _focusPathMap = new HashMap<Object, Object>();
87      setViewIdProperty(viewIdProperty);
88      setWrappedData(instance);
89    }
90  
91    @Override
92    public void setWrappedData(Object data)
93    {
94      super.setWrappedData(data);
95      Object oldPath = getRowKey();
96  
97      //set the focus path map
98      _focusPathMap.clear();
99      setRowKey(null);
100     FacesContext context = FacesContext.getCurrentInstance();
101     _addToMap(context, this, _focusPathMap, getViewIdProperty());
102     setRowKey(oldPath);
103   }
104 
105   /**
106    * Returns the rowKey to the current viewId.
107    * <p>
108    *
109    * The getFocusRowKey method
110    * <ul>
111    * <li>gets the current viewId by calling
112    * FacesContext.getCurrentInstance().getViewRoot().getViewId()
113    * <li> compares the current viewId with the viewId's in
114    * the nodes of the tree
115    * <li>returns the rowKey to the node with the current viewId or null
116    * if the current viewId can't be found
117    * </ul>
118    *
119    * @return  the rowKey to the node with the current viewId or null if the current viewId can't be found
120    */
121   @Override
122   public Object getFocusRowKey()
123   {
124     String currentViewId = getCurrentViewId();
125     Object focusPath = _focusPathMap.get(currentViewId);
126     return focusPath;
127   }
128 
129   /**
130    * Maps the focusPath returned when the viewId is newViewId
131    * to the focusPath returned when the viewId is aliasedViewId.
132    * This allows view id's not in the treeModel to be mapped
133    * to a focusPath.
134    * @param newViewId the view id to add a focus path for
135    * @param aliasedViewId the view id to use to get the focusPath to use for newViewId
136    */
137   public void addViewId(
138     String newViewId,
139     String aliasedViewId
140   )
141   {
142     Object focusPath = _focusPathMap.get(aliasedViewId);
143     if (focusPath != null)
144     {
145       _focusPathMap.put(newViewId, focusPath);
146     }
147   }
148 
149   /**
150    * Gets the property to use to retrieve a viewId
151    * from a node in the tree
152    */
153   public String getViewIdProperty()
154   {
155     return _viewIdProperty;
156   }
157 
158   /**
159    * Sets the property to use to retrieve a viewId
160    * from a node in the tree
161    */
162   public void setViewIdProperty(String viewIdProperty)
163   {
164     _viewIdProperty = viewIdProperty;
165   }
166 
167   /**
168    * Returns the current viewId.
169    * <p>
170    *
171    *
172    * @return  the current viewId or null if the current viewId can't be found
173    */
174 
175   protected String getCurrentViewId()
176   {
177     String currentViewId =
178                    FacesContext.getCurrentInstance().getViewRoot().getViewId();
179 
180     return currentViewId;
181   }
182 
183 
184   private static void _addToMap(
185     FacesContext context,
186     TreeModel tree,
187     Map<Object, Object> focusPathMap,
188     String viewIdProperty
189     )
190   {
191     for ( int i = 0; i < tree.getRowCount(); i++)
192     {
193       tree.setRowIndex(i);
194       if (viewIdProperty != null)
195       {
196         Object focusPath = tree.getRowKey();
197         Object data = tree.getRowData();
198         PropertyResolver resolver =
199           context.getApplication().getPropertyResolver();
200         Object viewIdObject = resolver.getValue(data, viewIdProperty);
201         focusPathMap.put(viewIdObject, focusPath);
202       }
203       else
204       {
205         _LOG.warning("NULL_VIEWID");
206       }
207 
208       if (tree.isContainer() && !tree.isContainerEmpty())
209       {
210         tree.enterContainer();
211         _addToMap(context, tree, focusPathMap, viewIdProperty);
212         tree.exitContainer();
213       }
214 
215     }
216   }
217 
218 
219   private final Map<Object, Object> _focusPathMap;
220   private String _viewIdProperty = null;
221 
222 
223 
224   static private final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(ViewIdPropertyMenuModel.class);
225 }