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.menu;
20  
21  import java.lang.reflect.Array;
22  
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import org.apache.myfaces.trinidad.logging.TrinidadLogger;
27  
28  /**
29   * Code specific to a Menu Model's GroupNode.
30   *
31   */
32  
33  public class GroupNode extends MenuNode
34  {
35    /**
36      * Constructs a GroupNode
37      */
38    public GroupNode()
39    {
40      super();
41    }
42  
43    /**
44      * Called by the Default ActionListener
45      * when a menu node is clicked/selected.
46      *
47      * @return String outcome or viewId used
48      *         during a POST for navigation.
49      */
50    @Override
51    public String doAction()
52    {
53      // Call the doAction method of my idref node
54      return getRefNode().doAction();
55    }
56  
57    /**
58      * Get the Destination URL of a page for a
59      * GET.
60      *
61      * @return String URL of a page.
62      */
63    @Override
64    public String getDestination()
65    {
66      // Call the getDestination method of my idref node
67      return getRefNode().getDestination();
68    }
69  
70    /**
71      * Sets the idref of the node.
72      *
73      * The value of this attribute is an "id" of another node
74      * This tells the pointing node where to obtain its viewId and
75      * takes precedence (and will replace) the pointing nodes viewId,
76      * if one exists.  This should point to a node of the same style,
77      * e.g. actionNode points to actionNode.
78      *
79      * @param idref - String name pointing to the "id" of another node
80      */
81    public void setIdRef(String idref)
82    {
83      _idref = idref;
84  
85      // Create a list of idref's for easier access
86      if (_idref != null)
87        _makeIdRefList (idref);
88    }
89  
90    /**
91      * Get the node whose id matches this node's
92      * idref attribute value.
93      *
94      * @return the MenuNode whose id matches this
95      *         node's idref attribute value.
96      */
97    @Override
98    public MenuNode getRefNode()
99    {
100     MenuNode refNode = null;
101 
102     // create one if it does not exist
103     // should not happen, but can't hurt
104     if (_idrefList == null)
105     {
106       String idref = getIdRef();
107       _makeIdRefList(idref);
108     }
109 
110     // Get idrefList
111     String[] idrefList = _getIdRefList();
112 
113     // get group node's children
114     List<MenuNode> children = getChildren();
115 
116     // Traverse the list. Do the following:
117     //    o get Node from Model's hashMap of nodes and ids
118     //    o check attributes (rendered, disabled, readOnly)
119     //    o if they are ok, return the node
120     for (int i=0; i < Array.getLength(idrefList); i++)
121     {
122       Iterator<MenuNode> childIter = children.iterator();
123 
124       // All node "id" attribute values had the node's
125       // system hashcode id appended to the id when
126       // placed in the model's idNodeMap.
127       //
128       // Each id in the idreflist of a group node does
129       // NOT have this node sys id appended it to it
130       // and needs to or we won't find the group's
131       // ref node.
132       //
133       // Since group nodes can only point to one of
134       // its children, we iterate through them, get
135       // their sys id and append it to idref until
136       // we find a match (or not).
137       while (childIter.hasNext())
138       {
139         MenuNode childNode = childIter.next();
140         String modelId = childNode.getModelId();
141 
142         // Need to append mode's sys id here to create a
143         // unique id.
144         String refNodeId = idrefList[i] + modelId;
145 
146         refNode = (MenuNode) getRootModel().getNode(refNodeId);
147 
148         // if nothing found, move on to the next child
149         if (refNode != null)
150          break;
151       }
152 
153       if (refNode == null)
154         continue;
155 
156       // Check the attributes of the found node
157       if (   !refNode.getRendered()
158           ||  refNode.getDisabled()
159           ||  refNode.getReadOnly()
160           || !refNode.getVisible()
161          )
162       {
163         refNode = null;
164         continue;
165       }
166 
167       // Ok, we have a valid RefNode
168       break;
169     }
170 
171     // If no valid node is found,
172     // log an error
173     if (refNode == null)
174     {
175         _LOG.severe("GroupNode " + getLabel() + " refers to no valid node.\n");
176         return null;
177     }
178 
179     return refNode;
180   }
181 
182   /**
183     * Get the id of the node referred to by
184     * the idref attribute of this node.
185     *
186     * @return String id of the node referred
187     *         to by the idref attribure of
188     *         this node.
189     */
190   public String getIdRef()
191   {
192     return _idref;
193   }
194   
195   public String[] getIdRefListProperty()
196   {
197     return _idrefList;
198   }
199 
200   @Override
201   public MenuNode getThreadSafeCopy()
202   {
203     return new ImmutableGroupNode(this);
204   }
205   
206   /* =============================================================
207    * Private methods
208    * =============================================================*/
209 
210   /**
211     * _getIdRefList. gets the list of idrefs for this node.
212     *
213     * @return String[] list of idrefs for this node.
214     */
215   private String[] _getIdRefList()
216   {
217     return _idrefList;
218   }
219 
220   /**
221     * Make a list of idref entries from the nodes String
222     * of idref's.
223     *
224     * This should only be called from the node's setIdRef
225     * method.  So if it is called more than once (highly
226     * unlikely), simply empty out the previous contents.
227     *
228     * @param entries - String of String entries
229     *
230     */
231   private void _makeIdRefList (String entries)
232   {
233     _idrefList = entries.trim().split("\\s+");
234   }
235 
236   private String   _idref     = null;
237   private String[] _idrefList = null;
238 
239   private final static TrinidadLogger _LOG =
240        TrinidadLogger.createTrinidadLogger(GroupNode.class);
241 }