You are viewing a plain text version of this content. The canonical link for it is here.
Posted to adffaces-commits@incubator.apache.org by aw...@apache.org on 2006/08/25 18:01:19 UTC

svn commit: r436881 - in /incubator/adffaces/trunk/trinidad: trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/

Author: awiner
Date: Fri Aug 25 11:01:18 2006
New Revision: 436881

URL: http://svn.apache.org/viewvc?rev=436881&view=rev
Log:
Commit patch for ADFFACES-125: provides getStream() hook that lets subclasses override how the model finds its content (default impl. is just off of ExternalContext.getResourceAsStream()).  Also, a bit of code cleanup.

Modified:
    incubator/adffaces/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/XMLMenuModel.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/GroupNode.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuContentHandlerImpl.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuNode.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuUtils.java

Modified: incubator/adffaces/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/XMLMenuModel.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/XMLMenuModel.java?rev=436881&r1=436880&r2=436881&view=diff
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/XMLMenuModel.java (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/XMLMenuModel.java Fri Aug 25 11:01:18 2006
@@ -17,25 +17,24 @@
  */
 package org.apache.myfaces.trinidad.model;
 
+import java.io.InputStream;
 import java.io.Serializable;
 
+import java.net.URL;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
 import javax.faces.context.FacesContext;
-
 import javax.faces.el.PropertyResolver;
-
 import javax.faces.el.ValueBinding;
 import javax.faces.webapp.UIComponentTag;
 
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
-
-import org.xml.sax.Attributes;
-
 import org.apache.myfaces.trinidad.util.ClassLoaderUtils;
 
+
 /**
  * Creates a Menu Model from a TreeModel where nodes in the treeModel
  * contain viewId information.
@@ -146,7 +145,7 @@
   {
     if (menuMetadataUri == null || "".equals(menuMetadataUri))
       return;
-      
+
     _mdSource = menuMetadataUri;
     _createModel();
   }
@@ -157,7 +156,7 @@
    * 
    * @param data.  The Tree Model instance
    */
-  @Override
+  @Override  
   public void setWrappedData(Object data)
   {
     super.setWrappedData(data);
@@ -167,11 +166,11 @@
     // There is no need to create the hashmaps or anything
     // on the child menu models.  A lot of overhead (performance and
     // memory) would be wasted.
-    if (_mdSource.equals(_getRootUri()))
+    if (this == _getRootModel())
     {
-      _viewIdFocusPathMap = _contentHandler.getViewIdFocusPathMap();
-      _nodeFocusPathMap   = _contentHandler.getNodeFocusPathMap();
-      _idNodeMap          = _contentHandler.getIdNodeMap();
+      _viewIdFocusPathMap = _contentHandler.getViewIdFocusPathMap(_mdSource);
+      _nodeFocusPathMap   = _contentHandler.getNodeFocusPathMap(_mdSource);
+      _idNodeMap          = _contentHandler.getIdNodeMap(_mdSource);
     }
   }
   
@@ -198,7 +197,7 @@
    * current viewId can't be found. 
    */
   @SuppressWarnings("unchecked")
-  @Override
+  @Override  
   public Object getFocusRowKey()
   {
     Object focusPath        = null;
@@ -208,7 +207,6 @@
 
     _begunRequest = true;    
 
-    
     if (beginNewRequest)
     {
         // Initializations
@@ -231,7 +229,7 @@
       if (_getRequestMethod() != _METHOD_POST)
       {
         // Case 2: GET method.  We have hung the selected node's id off the 
-        // requests URL, which enables us to get the selected node and also 
+        // request's URL, which enables us to get the selected node and also 
         // to know that the request method is GET.
         Map<String, String> paramMap = 
           context.getExternalContext().getRequestParameterMap();
@@ -355,6 +353,7 @@
   { 
     List<Object> focusPath = 
       _viewIdFocusPathMap.get(aliasedViewId);
+      
     if (focusPath != null)
     {
       _viewIdFocusPathMap.put(newViewId, focusPath);
@@ -405,14 +404,13 @@
     FacesContext context = FacesContext.getCurrentInstance();
     PropertyResolver resolver = context.getApplication().getPropertyResolver();
     
-    // =-=AEW Attributes?  A Map<String, String> would be more appropriate
-    Attributes propList = 
-      (Attributes) resolver.getValue(node, _CUSTOM_ATTR_LIST);
+    Map<String, String> propMap = 
+      (Map<String, String>) resolver.getValue(node, _CUSTOM_ATTR_LIST);
    
-    if (propList == null)
+    if (propMap == null)
       return null;
       
-    String value = propList.getValue(propName);
+    String value = propMap.get(propName);
     
     // If it is an El expression, we must evaluate it
     // and return its value
@@ -439,7 +437,32 @@
      
     return value;
   }
-  
+
+  /**
+   * getStream - Opens an InputStream to the provided URI.
+   * 
+   * @param uri - String uri to a data source.
+   * @return InputStream to the data source.
+   */
+  public InputStream getStream(String uri)
+  {
+    // This is public so that extended menu models can override
+    // and provide their own InputStream metadata source.
+    // And it is called by the MenuContentHandlerImpl.
+    try
+    {
+      // Open the metadata  
+      FacesContext context = FacesContext.getCurrentInstance();
+      URL url = context.getExternalContext().getResource(uri);
+      return url.openStream();
+    }
+    catch (Exception ex)
+    {
+      _LOG.severe("Exception opening URI " + uri, ex);
+      return null;
+    }    
+  }
+
   /* ====================================================================
    * Private Methods
    * ==================================================================== */
@@ -467,7 +490,9 @@
           ClassLoaderUtils.getServices(_MENUCONTENTHANDLER_SERVICE);
          
         if (services.isEmpty())
+        {
           throw new IllegalStateException("No MenuContentHandler was registered.");
+        }
         
         _contentHandler = services.get(0);
         if (_contentHandler == null)
@@ -480,7 +505,7 @@
       // In this model, the menu content handler and nodes need to have
       // access to the model's data structures and to notify the model
       // of the currently selected node (in the case of a POST).
-      _setRootModelUri(_contentHandler);
+      _setRootModelKey(_contentHandler);
 
       // Set the local model (model created by a sharedNode) on the
       // contentHandler so that nodes can get back to their local model
@@ -492,54 +517,54 @@
     }
     catch (Exception ex)
     {
-      _LOG.severe(  "Exception creating menu model " 
-                  + _mdSource, ex);
+      _LOG.severe(  "Exception creating menu model " + _mdSource, ex);
       return;
     }
   }
 
   /**
-   * _setRootModelUri - sets the top-level, menu model's Uri on the 
+   * _setRootModelKey - sets the top-level, menu model's Key on the 
    * menu content handler. This is so nodes will only operate
    * on the top-level, root model. 
    * 
    */
   @SuppressWarnings("unchecked")
-  private void _setRootModelUri(MenuContentHandler contentHandler)
+  private void _setRootModelKey(MenuContentHandler contentHandler)
   {
-    if (_rootUri == null)
-    {
-      _rootUri = _mdSource;
-      
-      // Put the root model on the Application Map so that it
+    if (_getRootModel() == null)
+    {      
+      // Put the root model on the Request Map so that it
       // Can be picked up by the nodes to call back into the 
       // root model
       FacesContext facesContext = FacesContext.getCurrentInstance();
       Map<String, Object> requestMap = 
         facesContext.getExternalContext().getRequestMap();
       
-      requestMap.put(_rootUri, this);
-
-      // Set the key (_rootUri) to the root model on the content
+      requestMap.put(_ROOT_MODEL_KEY, this);
+      
+      // Set the key to the root model on the content
       // handler so that it can then be set on each of the nodes
-      contentHandler.setRootModelUri(_rootUri);
+      contentHandler.setRootModelKey(_ROOT_MODEL_KEY);
     }
   }
   
   /**
-   * Returns the root menu model's Uri.
+   * Returns the root menu model.
    * 
-   * @return the root menu model's Uri.
+   * @return XMLMenuModel the root menu model.
    */
-  private String _getRootUri()
+  @SuppressWarnings("unchecked")
+  private XMLMenuModel _getRootModel()
   {
-    return _rootUri;
+    FacesContext facesContext = FacesContext.getCurrentInstance();
+    Map<String, Object> requestMap = 
+      facesContext.getExternalContext().getRequestMap();
+    return (XMLMenuModel) requestMap.get(_ROOT_MODEL_KEY);
   }
   
   /**
    * _setModelUri - sets the local, menu model's Uri on the 
-   * menu content handler. 
-   * 
+   * menu content handler.  
    */
   @SuppressWarnings("unchecked")
   private void _setModelUri(MenuContentHandler contentHandler)
@@ -555,7 +580,7 @@
     
     requestMap.put(localUri, this);
     
-    // Set the key (_rootUri) to the root model on the content
+    // Set the key (_localUri) to the local model on the content
     // handler so that it can then be set on each of the nodes
     contentHandler.setModelUri(localUri);
   }
@@ -617,9 +642,10 @@
    
   /*
    * Interface corresponding to the MenuContentHandlerImpl
-   * inorg.apache.myfaces.trinidadinternal.menu.   This is used to achieve 
-   * separation between the api (trinidad) and the implementation (trinidadinternal).
-   * It is only used by the XMLMenuModel, thus it is an internal interface.
+   * in org.apache.myfaces.trinidadinternal.menu.   This is used to achieve 
+   * separation between the api (trinidad) and the implementation 
+   * (trinidadinternal). It is only used by the XMLMenuModel, thus it is 
+   * an internal interface.
    */
   public interface MenuContentHandler 
   {
@@ -633,15 +659,15 @@
     public TreeModel getTreeModel(String uri);
 
     /**
-      * Sets the root Uri on the ContentHandler so that the nodes
-      * can get back to the root model of the application menu tree
+      * Sets the root model's request map key on the ContentHandler so 
+      * that the nodes can get back to their root model
       * through the request map.
       */
-    public void setRootModelUri(String uri);
+    public void setRootModelKey(String key);
     
     /**
       * Sets the local, sharedNode model's Uri on the ContentHandler so that
-      * the local model can be gotte too if necessary.
+      * the local model can be gotten to, if necessary.
       */
     public void setModelUri(String uri);
 
@@ -650,21 +676,21 @@
      * 
      * @return the Model's idNodeMap
      */
-    public Map<String, Object> getIdNodeMap();
+    public Map<String, Object> getIdNodeMap(Object modelKey);
 
     /**
      * Get the Model's nodeFocusPathMap
      * 
      * @return the Model's nodeFocusPathMap
      */
-    public Map<Object, List<Object>> getNodeFocusPathMap();
+    public Map<Object, List<Object>> getNodeFocusPathMap(Object modelKey);
 
     /**
      * Get the Model's viewIdFocusPathMap
      * 
      * @return the Model's viewIdFocusPathMap
      */
-    public Map<String, List<Object>> getViewIdFocusPathMap();
+    public Map<String, List<Object>> getViewIdFocusPathMap(Object modelKey);
   }
      
   private Object  _currentNode       = null;
@@ -676,10 +702,11 @@
 
   private Map<String, List<Object>> _viewIdFocusPathMap;
   private Map<Object, List<Object>> _nodeFocusPathMap;
-  private Map<String, Object> _idNodeMap;
+  private Map<String, Object>       _idNodeMap;
 
-  static private String _rootUri                    = null;  
   static private MenuContentHandler _contentHandler = null;
+  
+  static private final String _ROOT_MODEL_KEY = "org.apache.myfaces.trinidad.model.XMLMenuModel.__root_menu__";
   
   static private final String _NODE_ID_PROPERTY     = "nodeId";
   static private final String _METHOD_GET           = "get";

Modified: incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/GroupNode.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/GroupNode.java?rev=436881&r1=436880&r2=436881&view=diff
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/GroupNode.java (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/GroupNode.java Fri Aug 25 11:01:18 2006
@@ -19,6 +19,9 @@
 
 import java.lang.reflect.Array;
 
+import java.util.Iterator;
+import java.util.List;
+
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 
 /**
@@ -106,34 +109,59 @@
     
     // Get idrefList
     String[] idrefList = _getIdRefList();
+
+    // get group node's children
+    List<MenuNode> children = getChildren();
     
     // Traverse the list. Do the following:
     //    o get Node from Model's hashMap of nodes and ids
     //    o check attributes (rendered, disabled, readOnly)
     //    o if they are ok, return the node    
     for (int i=0; i < Array.getLength(idrefList); i++)
-    {
-      String refNodeId = idrefList[i];
-      
-      refNode = (MenuNode) getRootModel().getNode(refNodeId);
+    {      
+      Iterator<MenuNode> childIter = children.iterator();
+
+      // All node "id" attribute values had the node's
+      // system hashcode id appended to the id when
+      // placed in the model's idNodeMap.
+      //
+      // Each id in the idreflist of a group node does
+      // NOT have this node sys id appended it to it 
+      // and needs to or we won't find the group's 
+      // ref node.
+      //
+      // Since group nodes can only point to one of
+      // its children, we iterate through them, get 
+      // their sys id and append it to idref until 
+      // we find a match (or not).
+      while (childIter.hasNext())
+      {
+        MenuNode childNode = childIter.next();
+        String nodeSysId = childNode.getNodeSysId();
+        
+        // Need to append mode's sys id here to create a
+        // unique id.
+        String refNodeId = idrefList[i] + nodeSysId;
+        
+        refNode = (MenuNode) getRootModel().getNode(refNodeId);
+        
+        // if nothing found, move on to the next child
+        if (refNode != null)
+         break;
+      }
       
-      // if nothing found, move on to the next idref
       if (refNode == null)
-       continue;
-       
+        continue;
+        
       // Check the attributes of the found node
-      // IMPORTANT NOTE: nodes whose rendered attribute
-      // is set to false never get created, so the first
-      // test should never return true.  But just in 
-      // case the creation ever changes, we will leave
-      // this test.
-      if (  !refNode.getRendered()
-          || refNode.getDisabled()
-          || refNode.getReadOnly()
+      if (   !refNode.getRendered()
+          ||  refNode.getDisabled()
+          ||  refNode.getReadOnly()
+          || !refNode.getVisible()
          )
       {
-       refNode = null;
-       continue;
+        refNode = null;
+        continue;
       }
        
       // Ok, we have a valid RefNode
@@ -144,7 +172,7 @@
     // log an error
     if (refNode == null)
     {
-        _LOG.severe("GroupNode " + getLabel() + "refers to no valid node.\n");
+        _LOG.severe("GroupNode " + getLabel() + " refers to no valid node.\n");
         return null;
     }    
     

Modified: incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuContentHandlerImpl.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuContentHandlerImpl.java?rev=436881&r1=436880&r2=436881&view=diff
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuContentHandlerImpl.java (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuContentHandlerImpl.java Fri Aug 25 11:01:18 2006
@@ -20,8 +20,6 @@
 import java.io.InputStream;
 import java.io.IOException;
 
-import java.net.URL;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -46,7 +44,6 @@
 
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
-import org.xml.sax.helpers.AttributesImpl;
 
 /**
  * Handler called by the SAXParser when parsing menu metadata
@@ -112,9 +109,18 @@
   {
     super();
     
-    // Init the menu list map
+    // Init the essential maps
     if (_treeModelMap == null)
       _treeModelMap = new HashMap<String, TreeModel>();
+
+    if (_viewIdFocusPathMapMap == null)
+      _viewIdFocusPathMapMap = new HashMap<Object, Map<String, List<Object>>>();
+
+    if (_nodeFocusPathMapMap == null)
+      _nodeFocusPathMapMap = new HashMap<Object, Map<Object, List<Object>>>();
+
+    if (_idNodeMapMap == null)
+      _idNodeMapMap = new HashMap<Object, Map<String, Object>>();
   }
   
   /**
@@ -128,7 +134,7 @@
     _menuList  = null;
    
     // Handler Id will have to change also to be unique 
-    _handlerId = Integer.toString(System.identityHashCode(_menuNodes));
+    _handlerId = Integer.toString(System.identityHashCode((Object) _menuNodes));
   }
   
   /**
@@ -198,7 +204,7 @@
           _menuNodes.add(new ArrayList<MenuNode>());
         }
 
-        _attrList = new AttributesImpl(attrList);
+        _attrMap = _getMapFromList(attrList);
           
         // Create either an itemNode or groupNode.
         MenuNode menuNode = _createMenuNode();
@@ -228,7 +234,7 @@
           // Set the root model on the node so we can call into
           // the root model from the node to populate its
           // idNodeMap (See CombinationMenuModel.java)
-          menuNode.setRootModelUri(getRootModelUri());
+          menuNode.setRootModelKey(getRootModelKey());
           
           // Set the local model (created when parsing a sharedNode)
           // on the node in case the node needs to get back to its
@@ -333,8 +339,8 @@
       if (_nodeDepth > 0)
       {
         // The parent menu item is the last menu item at the previous depth
-        List<MenuNode> parentList = _menuNodes.get(_nodeDepth-1);
-        MenuNode       parentNode = parentList.get(parentList.size()-1);
+        List      parentList = _menuNodes.get(_nodeDepth-1);
+        MenuNode  parentNode = (MenuNode)parentList.get(parentList.size()-1);
         
         parentNode.setChildren(_menuNodes.get(_nodeDepth));
       }
@@ -359,9 +365,11 @@
     
     // If Model is the Root, then build Model's hashmaps 
     // and set them on the Root Model.
-    if (getRootModelUri().equals(getModelUri()))
+    XMLMenuModel rootModel = getRootModel();
+    
+    if (rootModel == getModel())
     {
-      _viewIdFocusPathMap = new HashMap<String, List<Object>>();
+      _viewIdFocusPathMap = new HashMap<String,List<Object>>();
       _nodeFocusPathMap   = new HashMap<Object, List<Object>>();
       _idNodeMap          = new HashMap<String, Object>();
       Object oldPath      = treeModel.getRowKey(); 
@@ -370,7 +378,14 @@
 
       // Populate the maps
       _addToMaps(treeModel, _viewIdFocusPathMap, _nodeFocusPathMap, _idNodeMap);
-
+      
+      // Cache the maps.  There is a possibility of multiple
+      // root models so we must cache the maps on a per root model
+      // basis.
+      _viewIdFocusPathMapMap.put(_currentTreeModelMapKey, _viewIdFocusPathMap);
+      _nodeFocusPathMapMap.put(_currentTreeModelMapKey, _nodeFocusPathMap);
+      _idNodeMapMap.put(_currentTreeModelMapKey, _idNodeMap);
+      
       treeModel.setRowKey(oldPath);
     }
   }
@@ -380,9 +395,9 @@
    * 
    * @return the Model's viewIdFocusPathMap
    */
-  public Map<String, List<Object>> getViewIdFocusPathMap()
+  public Map<String, List<Object>> getViewIdFocusPathMap(Object modelKey)
   {
-    return _viewIdFocusPathMap;
+    return _viewIdFocusPathMapMap.get(modelKey);  
   }
   
   /**
@@ -390,9 +405,9 @@
    * 
    * @return the Model's nodeFocusPathMap
    */
-  public Map<Object, List<Object>> getNodeFocusPathMap()
+  public Map<Object, List<Object>> getNodeFocusPathMap(Object modelKey)
   {
-    return _nodeFocusPathMap;
+    return _nodeFocusPathMapMap.get(modelKey);  
   }
 
   /**
@@ -400,9 +415,9 @@
    * 
    * @return the Model's idNodeMap
    */
-  public Map<String, Object> getIdNodeMap()
+  public Map<String, Object> getIdNodeMap(Object modelKey)
   {
-    return _idNodeMap;
+    return _idNodeMapMap.get(modelKey);  
   }
 
   /**
@@ -413,34 +428,41 @@
   public TreeModel getTreeModel(String uri)
   {
     TreeModel model = _treeModelMap.get(uri);
-    if (model == null)
+
+    // If we have a cached model, return it.    
+    if (model != null)
+      return model;
+
+    // Build a Tree model.  Parsing puts the tree model
+    // in the map, see method endDocument().
+    _currentTreeModelMapKey = uri;
+
+    try
     {
-      _currentTreeModelMapKey = uri;
+      // Get a parser.  NOTE: we are using the jdk's 1.5 SAXParserFactory
+      // and SAXParser here.
+      SAXParserFactory factory = SAXParserFactory.newInstance();
+      SAXParser parser = factory.newSAXParser();
+             
+      // Call the local menu model's getStream() method. This is a model
+      // method so that it can be overridden by any model extending 
+      // XmlMenuModel.
+      InputStream inStream = getModel().getStream(uri);
 
-      try
-      {
-        // Get a parser.  NOTE: we are using the jdk's 1.5 SAXParserFactory
-        // and SAXParser here.
-        SAXParserFactory factory = SAXParserFactory.newInstance();
-        SAXParser parser = factory.newSAXParser();
-        
-        
-        // Parse the metadata
-        InputStream inStream = _getStream(uri);
-        parser.parse(inStream, this);
-      }
-      catch (SAXException saxex)
-      {
-        _LOG.severe ( "Exception creating model " + uri, saxex);
-      }
-      catch (IOException ioe)
-      {
-        _LOG.severe ( "Exception creating model " + uri, ioe);
-      }
-      catch (ParserConfigurationException pce)
-      {
-        _LOG.severe ( "Exception creating model " + uri, pce);
-      }
+      // Parse the metadata
+      parser.parse(inStream, this);
+    }
+    catch (SAXException saxex)
+    {
+      _LOG.severe ( "Exception creating model " + uri, saxex);
+    }
+    catch (IOException ioe)
+    {
+      _LOG.severe ( "Exception creating model " + uri, ioe);
+    }
+    catch (ParserConfigurationException pce)
+    {
+      _LOG.severe ( "Exception creating model " + uri, pce);
     }
 
     return _treeModelMap.get(uri);
@@ -459,34 +481,37 @@
     Map<String, Object> requestMap = 
       facesContext.getExternalContext().getRequestMap();
     
-    return (XMLMenuModel) requestMap.get(getRootModelUri());
+    XMLMenuModel model = (XMLMenuModel) requestMap.get(getRootModelKey());
+    return model;
   }
   
   /**
-   * Get the top-level, root menu model's Uri.
+   * Get the top-level, root menu model's Request Map Key.
    * 
-   * @return root, top-level XMLMenuModel's Uri
+   * @return root, top-level XMLMenuModel's Request Map Key.
    */
-  public String getRootModelUri()
+  public static String getRootModelKey()
   {
-    return _rootModelUri;
+    return _rootModelKey;
   }
   
   /**
-   * Sets the root menu Model's Uri.
+   * Sets the root menu Model's Request map key.
    * <p>
-   * This is always only the top-level, root model's Uri.
+   * This is always only the top-level, root model's Request map key.
    * We do this because the MenuContentHandlerImpl and nodes need to be able 
    * to call into the root model to:
    * <ul>
    * <li>notify them root menu model of the currently selected node on a POST
+   * <li>group node needs to find its referenced item node.
    * </ul>
    * 
-   * @param rootModelUri - String the root, top-level menu model's Uri.
+   * @param rootModelKey - String the root, top-level menu model's Request
+   *        map key.
    */
-  public void setRootModelUri(String rootModelUri)
+  public void setRootModelKey(String rootModelKey)
   {
-    _rootModelUri = rootModelUri;
+    _rootModelKey = rootModelKey;
   }
 
   /**
@@ -571,7 +596,27 @@
   // Private Methods
   //=======================================================================
   
-  /**
+ /**
+   * Create a Map of name/value pairs from the attrList given 
+   * to us by the Sax parser.
+   * 
+   * @param attrList List of attributes of an XML element
+   * @return Map hashMap of attributes converted to name/value pairs.
+   */
+  @SuppressWarnings("unchecked")
+  private Map<String, String> _getMapFromList(Attributes attrList)
+  {
+    Map<String, String> attrMap = new HashMap<String, String>();
+      
+    for (int i=0; i < attrList.getLength(); i++)
+    {
+      attrMap.put(attrList.getQName(i), attrList.getValue(i) );
+    }
+    
+    return attrMap;
+  }
+  
+ /**
    * Creates a MenuNode from attribute list.
    *
    * @return MenuNode used in the Menu List.
@@ -632,9 +677,9 @@
       menuNode.setLabelAndAccessKey(labelAndAccessKey);
 
     // Set the Any Attributes Attrlist
-    if (_attrList.getLength() > 0)
+    if (_attrMap.size() > 0)
     {
-      menuNode.setCustomPropList(_attrList);
+      menuNode.setCustomPropList(_attrMap);
     }
     
     return menuNode;
@@ -715,6 +760,7 @@
    * Note: if you add a new push in this method, you must also add
    * a corresponding pop in _restoreModelData() below in the correct order.
    */
+  @SuppressWarnings("unchecked")
   private void _saveModelData()
   {
     if (_saveDataStack == null)
@@ -723,20 +769,23 @@
     }
 
     // DO NOT CHANGE THE ORDER HERE.  IT MUST MATCH
-    // "pushes" DONE BELOW in _restoreModelData.
+    // "pops" DONE BELOW in _restoreModelData.
     int nodeDepthSave       = _nodeDepth;
     ArrayList<List<MenuNode>> menuNodesSave = 
       new ArrayList<List<MenuNode>>(_menuNodes);
     
     
     ArrayList<Object> menuListSave  = 
-      _menuList != null ? new ArrayList<Object>(_menuList) : null;
+      (  _menuList != null
+       ? new ArrayList<Object>(_menuList)
+       : null
+      );
                               
-    String mapTreeKeySave   = _currentTreeModelMapKey;
-    String localModelUriSave   = _localModelUri;
-    String handlerId = _handlerId;
-    String resBundleName = _resBundleName;
-    String resBundleKey = _resBundleKey;
+    String mapTreeKeySave    = _currentTreeModelMapKey;
+    String localModelUriSave = _localModelUri;
+    String handlerId         = _handlerId;
+    String resBundleName     = _resBundleName;
+    String resBundleKey      = _resBundleKey;
     _saveDataStack.push(nodeDepthSave);
     _saveDataStack.push(menuNodesSave);
     _saveDataStack.push(menuListSave);
@@ -780,13 +829,11 @@
    */
   private String _getAndRemoveAttrValue(String attrName)  
   {
-    int idx = _attrList.getIndex(attrName);
+    String attrValue = _attrMap.get(attrName);
+    
+    if (attrValue != null)
+      _attrMap.remove(attrName);
     
-    if (idx == -1)
-      return null;
-      
-    String attrValue = _attrList.getValue(idx);
-    _attrList.removeAttribute(idx);
     return attrValue;
   }
 
@@ -802,9 +849,9 @@
   @SuppressWarnings("unchecked")
   private void _addToMaps(
     TreeModel tree,
-    Map<String, List<Object>> viewIdFocusPathMap,
-    Map<Object, List<Object>> nodeFocusPathMap,
-    Map<String, Object> idNodeMap)
+    Map viewIdFocusPathMap,
+    Map nodeFocusPathMap,
+    Map idNodeMap)
   {
     for ( int i = 0; i < tree.getRowCount(); i++)
     {
@@ -817,16 +864,16 @@
       List<Object> focusPath = (List<Object>)tree.getRowKey();
       
       // Get the focusViewId of the node
-      String viewIdObject = node.getFocusViewId(); 
+      Object viewIdObject = node.getFocusViewId(); 
       
       if (viewIdObject != null)
       {          
         // Put this entry in the nodeFocusPathMap
-        nodeFocusPathMap.put(node, focusPath);
+        nodeFocusPathMap.put(node, (Object)focusPath);
 
         // Does this viewId already exist in the _viewIdFocusPathMap?
         List<Object> existingFpArrayList = 
-          viewIdFocusPathMap.get(viewIdObject);
+          _viewIdFocusPathMap.get(viewIdObject);
         
         if (existingFpArrayList == null)
         {
@@ -836,7 +883,7 @@
           // ArrayList in the focusPath HashMap.
           List<Object> fpArrayList = new ArrayList<Object>();
           fpArrayList.add(focusPath);
-          viewIdFocusPathMap.put(viewIdObject, fpArrayList);
+          viewIdFocusPathMap.put(viewIdObject, (Object)fpArrayList);
         }
         else
         {
@@ -851,11 +898,11 @@
           
           if (defFocusPath)
           {
-            existingFpArrayList.add(0, focusPath);
+            existingFpArrayList.add(0, (Object)focusPath);
           }
           else
           {
-            existingFpArrayList.add(focusPath);
+            existingFpArrayList.add((Object)focusPath);
           }              
         }
       }
@@ -877,30 +924,6 @@
     }
   }  
   
-
-  /**
-   * getStream - Opens an InputStream to the provided URI.
-   * 
-   * @param uri - String uri to a data source.
-   * @return InputStream to the data source.
-   */
-  private InputStream _getStream(String uri)
-  {
-    try
-    {
-      // Open the metadata  
-      FacesContext context = FacesContext.getCurrentInstance();
-      URL url = context.getExternalContext().getResource(uri);
-      return url.openStream();
-    }
-    catch (Exception ex)
-    {
-      _LOG.severe("Exception opening URI " + uri, ex);
-      return null;
-    }    
-  }
-
-
   //========================================================================
   // Private variables
   //========================================================================
@@ -914,17 +937,23 @@
   private String _handlerId;
   private String _resBundleKey;
   private String _resBundleName;
-  private AttributesImpl _attrList;
+  
+  private Map<String, String>    _attrMap;
   private Map<String, TreeModel> _treeModelMap;
-  private Stack<Object>  _saveDataStack;
+  private Map<Object, Map<String, List<Object>>> _viewIdFocusPathMapMap;
+  private Map<Object, Map<String, Object>>       _idNodeMapMap;
+  private Map<Object, Map<Object, List<Object>>> _nodeFocusPathMapMap;  
+  private Stack<Object>             _saveDataStack;
   private Map<String, List<Object>> _viewIdFocusPathMap;
   private Map<Object, List<Object>> _nodeFocusPathMap;
-  private Map<String, Object> _idNodeMap;
+  private Map<String, Object>       _idNodeMap;
 
   
-  // Menu model Uri's
-  private String _rootModelUri  = null;
+  // Local (shared) Menu models Uri
   private String _localModelUri = null;
+  
+  // Root Menu model's Session map key
+  private static String _rootModelKey  = null;
 
   // Nodes
   private final static String _GROUP_NODE        = "groupNode";

Modified: incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuNode.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuNode.java?rev=436881&r1=436880&r2=436881&view=diff
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuNode.java (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuNode.java Fri Aug 25 11:01:18 2006
@@ -24,8 +24,6 @@
 import javax.faces.context.FacesContext;
 import javax.faces.webapp.UIComponentTag;
 
-import org.xml.sax.Attributes;
-
 import org.apache.myfaces.trinidad.model.XMLMenuModel;
 
 /**
@@ -43,7 +41,9 @@
     * Constructs a MenuNode
     */
   public MenuNode()
-  {}
+  {
+    _nodeSysId = (new Integer(System.identityHashCode(this))).toString();
+  }
   
   /**
     * Set the menu item's label.
@@ -476,7 +476,9 @@
    */
   public String getId()
   {
-    return _id;
+    // This must be made unique so that we do not have duplicates 
+    // in the idNodeMap on the menu's tree.      
+    return _id + _nodeSysId;
   }
 
   /*===========================================================================
@@ -532,7 +534,7 @@
    */
   public Object getCustomProperty(String name)
   {
-    String value = _customPropList.getValue(name);
+    String value = _customPropList.get(name);
     
     if (   value != null
         && UIComponentTag.isValueReference(value)
@@ -550,19 +552,49 @@
    * 
    * @return Attributes list containing the custom attributes on this node
    */
-  public Attributes getCustomPropList()
+  public Map<String, String> getCustomPropList()
   {
     return _customPropList;
   }
   
   /**
+   * Get the top-level, root menu model Request Map Key.
+   * 
+   * @return root, top-level XMLMenuModel's Request Map Key.
+   */
+  public String getRootModelKey()
+  {
+    return _rootModelKey;
+  }
+  
+  /**
+   * Sets the root menu Model's Request map key.
+   * <p>
+   * This is always only the top-level, root model's Request map key.
+   * We do this because the MenuContentHandlerImpl and nodes need to be able 
+   * to call into the root model to:
+   * <ul>
+   * <li>notify them root menu model of the currently selected node on a POST
+   * <li>group node needs to find its referenced item node.
+   * </ul>
+   * 
+   * @param rootModelKey - String the root, top-level menu model's Request
+   *        map key.
+   */
+  public void setRootModelKey(String rootModelKey)
+  {
+    _rootModelKey = rootModelKey;
+  }
+
+  /**
    * Set the list of custom attributes.
    * 
-   * @param attrList Attributes List for this node from MenuContentHandlerImpl
+   * @param attrMap Map of attibute name/values for this node
+   * from MenuContentHandlerImpl
    */
-  protected void setCustomPropList(Attributes attrList)
+  protected void setCustomPropList(Map<String, String> attrMap)
   {
-    _customPropList = attrList;
+    _customPropList = attrMap;
   }
   
   /**
@@ -626,6 +658,19 @@
   }
   
   /**
+   * Set the Menu Node's System id.
+   * 
+   * This is appended to the node's id in getId() to 
+   * ensure that each node's id is unique.
+   * 
+   * @return String object System id of the node.
+   */
+  protected String getNodeSysId()
+  {
+    return _nodeSysId;
+  }
+  
+  /**
    * Get the top-level, root menu model, which contains
    * the entire menu tree.
    * 
@@ -638,37 +683,11 @@
     Map<String, Object> requestMap = 
       facesContext.getExternalContext().getRequestMap();
     
-    return (XMLMenuModel) requestMap.get(getRootModelUri());
-  }
-  
-  /**
-   * Get the top-level, root menu model's Uri.
-   * 
-   * @return root, top-level XMLMenuModel's Uri
-   */
-  public String getRootModelUri()
-  {
-    return _rootModelUri;
+    XMLMenuModel model =  (XMLMenuModel) requestMap.get(getRootModelKey());
+    return model;
   }
   
   /**
-   * Sets the root menu Model's Uri.
-   * <p>
-   * This is always only the top-level, root model's Uri.
-   * We do this because the MenuContentHandlerImpl and nodes need to be able 
-   * to call into the root model to:
-   * <ul>
-   * <li>notify them root menu model of the currently selected node on a POST
-   * </ul>
-   * 
-   * @param rootModelUri - String the root, top-level menu model's Uri.
-   */
-  public void setRootModelUri(String rootModelUri)
-  {
-    _rootModelUri = rootModelUri;
-  }
-
-  /**
    * _joinLabelAndAccessKey - takes a string label and string accessKey
    * and combines them into a single labelAndAccessKey string.
    * 
@@ -794,13 +813,14 @@
   private String         _bundleName  = null;
   private String         _accessKey   = null;
   private String         _id          = null;
+  private String         _nodeSysId   = null;
   private boolean        _labelAndAccessKeyEL = false;
   private String         _labelAndAccessKey   = null;
   private String         _defaultFocusPathStr = null;
   
   // Map for Custom attributes (properties)
-  private Attributes _customPropList = null;
+  private Map<String, String> _customPropList = null;
   
-  // Menu model Uri's
-  private String _rootModelUri  = null;
+  // Root Menu model's Request Map Key
+  private String _rootModelKey  = null;
 } 

Modified: incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuUtils.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuUtils.java?rev=436881&r1=436880&r2=436881&view=diff
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuUtils.java (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuUtils.java Fri Aug 25 11:01:18 2006
@@ -154,7 +154,7 @@
    * @param resBundle - String containing name of class containing the resource
    *                    bundle.
    * @param key - ThreadLocal key for the resource bundle being put on the
-   *              sessionMap
+   *              requestMap
    */
   @SuppressWarnings("unchecked")
   static void loadBundle(String resBundle, ThreadLocal<String> key)
@@ -240,8 +240,9 @@
    * @param resBundleName - String containing name of class containing the 
    *                        resource bundle.
    * @param resBundleKey - String key for the resource bundle being put on the
-   *                       sessionMap
+   *                       requestMap
    */
+  @SuppressWarnings("unchecked")
   static void loadBundle(String resBundleName, String resBundleKey)
   {
     ThreadLocal<String> bundleKey = new ThreadLocal<String>();
@@ -256,6 +257,7 @@
    * model metadata to externalize strings, such as tab labels, for 
    * translation.
    */
+  @SuppressWarnings("unchecked")
   static private class _BundleMap implements Map<String, String>
   {
     private ResourceBundle _bundle;
@@ -331,7 +333,7 @@
       for (Enumeration<String> enumer = _bundle.getKeys(); enumer.hasMoreElements(); )
       {
         final String k = enumer.nextElement();
-        set.add(new Map.Entry<String, String>() 
+        set.add(new Map.Entry<String, String>()
         {
           public String getKey()
           {