You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beehive.apache.org by ek...@apache.org on 2004/07/21 15:50:54 UTC

svn commit: rev 23122 - in incubator/beehive/trunk/netui: src/pageflow/org/apache/beehive/netui/script/common test/src/junitTests/org/apache/beehive/netui/test/script test/src/junitTests/org/apache/beehive/netui/test/script/el

Author: ekoneil
Date: Wed Jul 21 06:50:54 2004
New Revision: 23122

Modified:
   incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/AbstractScriptableMap.java
   incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/BundleMap.java
   incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/ScriptablePageInput.java
   incubator/beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/script/BundleScriptTest.java
   incubator/beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/script/el/NetUIELBundleScriptTest.java
Log:
Provide implementations of entrySet in the data binding related maps below.

These are used to provide access to resource bundles and page inputs from expression languages.

In general, the implementations are optimized for read in which cases, the entrySet is not created eagerly and is created only when asked for.  Subclasses of AbstractScriptableMap generally provide their own implementations of Map.get(Object).

BB: self
DRT: NetUI (junit + server) pass
CR: Daryl



Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/AbstractScriptableMap.java
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/AbstractScriptableMap.java	(original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/AbstractScriptableMap.java	Wed Jul 21 06:50:54 2004
@@ -19,7 +19,12 @@
 package org.apache.beehive.netui.script.common;
 
 // java imports
+import org.apache.beehive.netui.util.iterator.IteratorFactory;
+
 import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Iterator;
 import java.util.Map;
 
 // internal imports
@@ -27,73 +32,107 @@
 // external imports
 
 /**
- *
+ * Base {@link java.util.Map} implementation that can be used by
+ * clients that need to expose implicit objects to an expression
+ * language through a Map.  This Map implementation is read-only.
  */
 public abstract class AbstractScriptableMap
     extends AbstractMap
 {
-    public AbstractScriptableMap()
-    {
-    }
-    
-    public void clear()
-    {
-        throw new UnsupportedOperationException("The clear method is not supported");
-    }
-    
-    public Object put(Object key, Object value)
-    {
-        throw new UnsupportedOperationException("The put method is not supported");
-    }
+    public AbstractScriptableMap() {}
 
-    public void putAll(Map map)
+    /**
+     * Default implementation of a {@link java.util.Set} that can be returned by the
+     * entrySet method of {@link java.util.Map}.  This implementation simply takes an
+     * array of entries and implements iterator() and size().
+     */
+    class EntrySet
+        extends AbstractSet
     {
-        throw new UnsupportedOperationException("The putAll method is not supported");
-    }
+        private Entry[] _entries = null;
 
-    public Object remove(Object key)
-    {
-        throw new UnsupportedOperationException("The key method is not supported");
+        public EntrySet(Entry[] entries)
+        {
+            _entries = entries;
+        }
+        public Iterator iterator()
+        {
+            return IteratorFactory.createIterator(_entries);
+        }
+
+        public int size()
+        {
+            return (_entries != null ? _entries.length : 0);
+        }
+
+        public boolean add(Object object) {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean addAll(Collection coll) {
+            throw new UnsupportedOperationException();
+        }
+
+        public void clear() {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean remove(Object object) {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean removeAll(Collection coll) {
+            throw new UnsupportedOperationException();
+        }
+
+        public boolean retainAll(Collection coll) {
+            throw new UnsupportedOperationException();
+        }
     }
 
-    public static class Entry 
+    /**
+     * Default implementation of {@link java.util.Map.Entry} that handles
+     * key / value pairs in a very basic way.  This is meant as a convenience
+     * to subclasses that need to provide an entrySet() to satisfy the
+     * {@link java.util.AbstractMap} contract.
+     */
+    class Entry
         implements Map.Entry
     {
         private final Object _key;
         private final Object _value;
-        
+
         Entry(Object key, Object value)
         {
             _key = key;
             _value = value;
         }
-        
+
         public Object getKey() {return _key;}
         public Object getValue() {return _value;}
-        
+
         public Object setValue(Object value)
         {
-            throw new UnsupportedOperationException("The setValue method is not supported");
+            throw new UnsupportedOperationException();
         }
-        
+
         public int hashCode()
         {
             return ((_key == null ? 0 : _key.hashCode()) ^ (_value == null ? 0 : _value.hashCode()));
         }
-        
+
         public boolean equals(Object obj)
         {
             if(obj == null || !(obj instanceof Map.Entry))
                 return false;
-            
+
             Map.Entry entry = (Map.Entry)obj;
             Object key = entry.getKey();
             Object value = entry.getValue();
-            if((key == null || (key != null && key.equals(_key)))
-               &&
+            if((key == null || (key != null && key.equals(_key))) &&
                (value == null || (value != null && value.equals(_value))))
                 return true;
-            
+
             return false;
         }
     }

Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/BundleMap.java
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/BundleMap.java	(original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/BundleMap.java	Wed Jul 21 06:50:54 2004
@@ -19,9 +19,11 @@
 package org.apache.beehive.netui.script.common;
 
 // java imports
+import java.util.ArrayList;
+import java.util.Set;
 import java.util.Iterator;
 import java.util.Locale;
-import java.util.Set;
+import java.util.Enumeration;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
@@ -38,7 +40,14 @@
 import org.apache.struts.util.MessageResources;
 
 /**
+ * Provide a {@link java.util.Map} of {@link ScriptableBundle} objects that can expose
+ * various implementations of {@link BundleContext.BundleNode} to expression languages.
+ *
+ * This {@link java.util.Map} implementation is optimized for read as the entrySet()
+ * is created lazily.  In addition, the entrySet does not contain all possible ScriptableBundle
+ * objects as named "message-resources" bundles are discovered at runtime and requested by name.
  *
+ * todo: need to implement Serializable here as this ends up in the request
  */
 public class BundleMap
     extends AbstractScriptableMap
@@ -103,7 +112,29 @@
 
     public Set entrySet()
     {
-        throw new UnsupportedOperationException("The entrySet method is not supported");
+        ArrayList entries = new ArrayList();
+
+        // add BundleNode objects that have been explicitly declared
+        if(_bundleContext != null)
+        {
+            Iterator iterator = _bundleContext.getBundleNames();
+            while(iterator.hasNext())
+            {
+                String name = (String)iterator.next();
+                BundleNode node = _bundleContext.getBundle(name);
+                entries.add(new Entry(name, node));
+            }
+        }
+
+        // add the default JPF bundle if one exists
+        MessageResources resources = getDefaultStrutsModuleBundle();
+        if(resources != null)
+            entries.add(new Entry(BundleContext.DEFAULT_STRUTS_BUNDLE_NAME,
+                                  BundleContext.createBundleNode(BundleContext.DEFAULT_STRUTS_BUNDLE_NAME, resources, retrieveUserLocale())));
+
+        // todo: the named "message-resource" bundles aren't supported here yet; need a way from the JPF runtime to look them up
+
+        return new EntrySet((Entry[])entries.toArray(new Entry[]{}));
     }
 
     private Object createScriptableBundle(String name)
@@ -134,7 +165,7 @@
         else if(_application.getAttribute(name) != null)
         {
             MessageResources resources = getNamedStrutsModuleBundle(name);
-            
+
             if(resources != null)
             {
                 BundleNode bundleNode = BundleContext.createBundleNode(name, resources, retrieveUserLocale());
@@ -144,8 +175,8 @@
 
         String bundleList = createBundleList();
         String strutsBundleList = createStrutsBundleList();
-        
-        String msg = "The bundle named \"" + name + "\" was not found in the list of registered bundles with names " + 
+
+        String msg = "The bundle named \"" + name + "\" was not found in the list of registered bundles with names " +
             bundleList + " or implicit bundle names " + strutsBundleList + ".";
 
         if(_logger.isErrorEnabled()) _logger.error(msg);
@@ -263,8 +294,13 @@
         return strutsNameList.toString();
     }
 
-    /*
-     * 
+    /**
+     * Provide a {@link java.util.Map} implementation that exposes a
+     * {@link org.apache.beehive.netui.script.common.BundleContext.BundleNode} object
+     * to an expression language as a Map.  Access to the values in the map is by
+     * key and depends on the implementation of the BundleNode.
+     *
+     * Access is read optimized and the complete entrySet() is only constructed when needed.
      */
     public class ScriptableBundle
         extends AbstractScriptableMap
@@ -283,7 +319,15 @@
 
         public Set entrySet()
         {
-            throw new UnsupportedOperationException("The entrySet method is not supported");
+            ArrayList list = new ArrayList();
+            Enumeration enumeration = _bundle.getKeys();
+            while(enumeration.hasMoreElements())
+            {
+                String key = (String)enumeration.nextElement();
+                String msg = _bundle.getString(key);
+                list.add(new Entry(key, msg));
+            }
+            return new EntrySet((Entry[])list.toArray(new Entry[] {}));
         }
 
         public Object get(Object name)

Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/ScriptablePageInput.java
==============================================================================
--- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/ScriptablePageInput.java	(original)
+++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/ScriptablePageInput.java	Wed Jul 21 06:50:54 2004
@@ -19,7 +19,8 @@
 package org.apache.beehive.netui.script.common;
 
 // java imports
-import java.util.Collection;
+import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
@@ -34,7 +35,12 @@
 // external imports
 
 /**
- * @todo: need to finish this implementation
+ * Provide a {@link java.util.Map} object that exposes a set of page inputs to
+ * expression language clients.  Access to these page inputs is based on the
+ * name of the page input.
+ *
+ * Access is optimized for read in that the "get" method is fast.  The entrySet()
+ * method is only used if needed, which is generally to toString the Map.
  */
 public class ScriptablePageInput
     extends AbstractScriptableMap
@@ -42,6 +48,7 @@
     private static final Logger _logger = Logger.getInstance(ScriptablePageInput.class);
 
     private HttpServletRequest _request = null;
+    private Set _entrySet = null;
 
     public ScriptablePageInput(ServletRequest request)
     {
@@ -58,10 +65,35 @@
 
         return PageFlowUtils.getActionOutput((String)name, _request);
     }
-    
+
+    /**
+     * Create a {@link java.util.Set} of page input entries.  This implementation
+     * assumes that the page input set does not change, which is acceptable for
+     * JSP clients as the page inputs have been specified when the JSP starts
+     * to render.
+     * @return
+     */
     public Set entrySet()
     {
-        throw new UnsupportedOperationException("Operation entrySet not supported on the PageInput Map");
+        if(_entrySet == null)
+        {
+            Map piMap = InternalUtils.getActionOutputMap(_request, false);
+            ArrayList list = new ArrayList();
+            if(piMap != null)
+            {
+                Iterator iterator = piMap.keySet().iterator();
+                while(iterator.hasNext())
+                {
+                    Object name = iterator.next();
+                    Object value = piMap.get(name);
+                    list.add(new Entry(name, value));
+                }
+            }
+
+            _entrySet = new EntrySet((Entry[])list.toArray(new Entry[]{}));
+        }
+
+        return _entrySet;
     }
     
     public boolean equals(Object obj)

Modified: incubator/beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/script/BundleScriptTest.java
==============================================================================
--- incubator/beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/script/BundleScriptTest.java	(original)
+++ incubator/beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/script/BundleScriptTest.java	Wed Jul 21 06:50:54 2004
@@ -82,6 +82,32 @@
         assertEquals("This message is never localized", val);
     }
 
+    /**
+     * Simple test to make sure that BundleMap.toString() doesn't throw exceptions and generally works.
+     * @throws Exception
+     */
+    public void testToString()
+        throws Exception
+    {
+        BundleContext bc = createBundleContext();
+        BundleMap bundleMap = new BundleMap((HttpServletRequest)_fauxPageContext.getRequest(),
+                                            _fauxPageContext.getServletContext(),
+                                            bc);
+        // toString an empty map
+        System.out.println("budleMap.toString(): " + bundleMap.toString());
+
+        _fauxPageContext.setAttribute("bundle", bundleMap);
+
+        bc.addBundle("bundle1", "org/apache/beehive/netui/test/databinding/testdata/bundle1");
+        bc.addBundle("bundle2", "org/apache/beehive/netui/test/databinding/testdata/bundle2");
+
+        String val = (String)evaluateExpression("{bundle.bundle1.simpleKey}", _fauxPageContext);
+        assertEquals("This is a simple message.", val);
+
+        // toString a BundleMap that has bundles
+        System.out.println("bundleMap.toString(): " + bundleMap.toString());
+    }
+    
     private BundleContext createBundleContext()
         throws Exception
     {

Modified: incubator/beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/script/el/NetUIELBundleScriptTest.java
==============================================================================
--- incubator/beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/script/el/NetUIELBundleScriptTest.java	(original)
+++ incubator/beehive/trunk/netui/test/src/junitTests/org/apache/beehive/netui/test/script/el/NetUIELBundleScriptTest.java	Wed Jul 21 06:50:54 2004
@@ -51,6 +51,7 @@
         TestSuite suite = new TestSuite();
         suite.addTest(new NetUIELBundleScriptTest("testSimple"));
         suite.addTest(new NetUIELBundleScriptTest("testLocaleSupport"));
+        suite.addTest(new NetUIELBundleScriptTest("testToString"));
         return suite;
     }