Author: etnu
Date: Fri Aug 22 04:29:09 2008
New Revision: 688066

URL: http://svn.apache.org/viewvc?rev=688066&view=rev
Log:
Implemented SHINDIG-532 with patch from Nik Haldimann along with modifying 
MessageBundleFactory by moving logic out of GadgetServer and into the new 
AbstractMessageBundleFactory. Anyone wishing to implement their own 
MessageBundleFactory can now trivially do so and still get proper inheritance 
of message bundles.


Added:
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractMessageBundleFactory.java
Modified:
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicMessageBundleFactory.java
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/MessageBundleFactory.java
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTask.java
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/MessageBundle.java
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicMessageBundleFactoryTest.java
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/MessageBundleTest.java

Added: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractMessageBundleFactory.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractMessageBundleFactory.java?rev=688066&view=auto
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractMessageBundleFactory.java
 (added)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractMessageBundleFactory.java
 Fri Aug 22 04:29:09 2008
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.shindig.gadgets;
+
+import org.apache.shindig.gadgets.spec.GadgetSpec;
+import org.apache.shindig.gadgets.spec.LocaleSpec;
+import org.apache.shindig.gadgets.spec.MessageBundle;
+
+import java.util.List;
+import java.util.Locale;
+import java.net.URI;
+
+/**
+ * Core implementation of MessageBundleFactory that ensures proper 
MessageBundle creation and
+ * delegates caching and network retrieval to concreate implementations.
+ */
+public abstract class AbstractMessageBundleFactory implements 
MessageBundleFactory {
+  private static final Locale ALL_ALL = new Locale("all", "ALL");
+
+  public MessageBundle getBundle(GadgetSpec spec, Locale locale, boolean 
ignoreCache)
+      throws GadgetException {
+    MessageBundle parent = getParentBundle(spec, locale, ignoreCache);
+    MessageBundle child = null;
+    LocaleSpec localeSpec = spec.getModulePrefs().getLocale(locale);
+    if (localeSpec == null) {
+      return parent == null ? MessageBundle.EMPTY : parent;
+    }
+    URI messages = localeSpec.getMessages();
+    if (messages == null || messages.toString().length() == 0) {
+      child = localeSpec.getMessageBundle();
+    } else {
+      child = fetchBundle(localeSpec, ignoreCache);
+    }
+
+    return new MessageBundle(parent, child);
+  }
+
+  private MessageBundle getParentBundle(GadgetSpec spec, Locale locale, 
boolean ignoreCache)
+      throws GadgetException {
+    if (locale.getLanguage().equalsIgnoreCase("all")) {
+      // Top most locale already.
+      return null;
+    }
+
+    if (locale.getCountry().equalsIgnoreCase("ALL")) {
+      return getBundle(spec, ALL_ALL, ignoreCache);
+    }
+
+    return getBundle(spec, new Locale(locale.getLanguage(), "ALL"), 
ignoreCache);
+  }
+
+  /**
+   * Retrieve the MessageBundle for the given LocaleSpec from the network or 
cache.
+   */
+  protected abstract MessageBundle fetchBundle(LocaleSpec locale, boolean 
ignoreCache)
+      throws GadgetException;
+}

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicMessageBundleFactory.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicMessageBundleFactory.java?rev=688066&r1=688065&r2=688066&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicMessageBundleFactory.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicMessageBundleFactory.java
 Fri Aug 22 04:29:09 2008
@@ -20,7 +20,6 @@
 
 import org.apache.shindig.common.cache.Cache;
 import org.apache.shindig.common.cache.CacheProvider;
-import org.apache.shindig.common.cache.LruCache;
 import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.gadgets.http.HttpFetcher;
 import org.apache.shindig.gadgets.http.HttpRequest;
@@ -39,10 +38,9 @@
  * Basic implementation of a message bundle factory
  */
 @Singleton
-public class BasicMessageBundleFactory implements MessageBundleFactory {
+public class BasicMessageBundleFactory extends AbstractMessageBundleFactory {
 
-  private static final Logger logger
-      = Logger.getLogger(BasicMessageBundleFactory.class.getName());
+  private static final Logger LOG = 
Logger.getLogger(BasicMessageBundleFactory.class.getName());
 
   private final HttpFetcher fetcher;
 
@@ -51,27 +49,18 @@
   private final long minTtl;
   private final long maxTtl;
 
-  public MessageBundle getBundle(LocaleSpec localeSpec, GadgetContext context)
+  protected MessageBundle fetchBundle(LocaleSpec locale, boolean ignoreCache)
       throws GadgetException {
-    if (localeSpec == null) {
-      return MessageBundle.EMPTY;
-    }
-    URI messages = localeSpec.getMessages();
-    if (messages == null || messages.toString().length() == 0) {
-      return localeSpec.getMessageBundle();
-    }
-    return getBundle(messages, context.getIgnoreCache());
-  }
-
-  public MessageBundle getBundle(URI url, boolean ignoreCache) throws 
GadgetException {
     if (ignoreCache) {
-      return fetchFromWeb(url, true);
+      return fetchFromWeb(locale, true);
     }
 
+    URI messages = locale.getMessages();
+
     MessageBundle bundle = null;
     long expiration = -1;
     synchronized (cache) {
-      TimeoutPair entry = cache.getElement(url);
+      TimeoutPair entry = cache.getElement(messages);
       if (entry != null) {
         bundle = entry.bundle;
         expiration = entry.timeout;
@@ -81,15 +70,15 @@
     long now = System.currentTimeMillis();
     if (bundle == null || expiration < now) {
       try {
-        return fetchFromWeb(url, false);
+        return fetchFromWeb(locale, false);
       } catch (GadgetException e) {
         if (bundle == null) {
           throw e;
         } else {
-          logger.info("Message bundle fetch failed for " + url + " -  using 
cached ");
+          LOG.info("Message bundle fetch failed for " + messages + " -  using 
cached ");
           // Try again later...
           synchronized (cache) {
-            cache.addElement(url, new TimeoutPair(bundle, now + minTtl));
+            cache.addElement(messages, new TimeoutPair(bundle, now + minTtl));
           }
         }
       }
@@ -97,7 +86,8 @@
     return bundle;
   }
 
-  private MessageBundle fetchFromWeb(URI url, boolean ignoreCache) throws 
GadgetException {
+  private MessageBundle fetchFromWeb(LocaleSpec locale, boolean ignoreCache) 
throws GadgetException {
+    URI url = locale.getMessages();
     HttpRequest request = new 
HttpRequest(Uri.fromJavaUri(url)).setIgnoreCache(ignoreCache);
     HttpResponse response = fetcher.fetch(request);
     if (response.getHttpStatusCode() != HttpResponse.SC_OK) {
@@ -106,7 +96,7 @@
           response.getHttpStatusCode());
     }
 
-    MessageBundle bundle  = new MessageBundle(url, 
response.getResponseAsString());
+    MessageBundle bundle  = new MessageBundle(locale, 
response.getResponseAsString());
 
     // We enforce the lower bound limit here for situations where a remote 
server temporarily serves
     // the wrong cache control headers. This allows any distributed caches to 
be updated and for the

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java?rev=688066&r1=688065&r2=688066&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetServer.java
 Fri Aug 22 04:29:09 2008
@@ -57,7 +57,6 @@
   private GadgetSpecFactory specFactory;
   private MessageBundleFactory bundleFactory;
 
-
   @Inject
   public GadgetServer(Executor executor,
       GadgetFeatureRegistry registry,
@@ -88,18 +87,6 @@
   }
 
   /**
-   *
-   * @param localeSpec
-   * @param context
-   * @return A new message bundle
-   * @throws GadgetException
-   */
-  private MessageBundle getBundle(LocaleSpec localeSpec, GadgetContext context)
-      throws GadgetException {
-    return bundleFactory.getBundle(localeSpec, context);
-  }
-
-  /**
    * Creates a Gadget from the specified gadget spec and context objects.
    * This performs message bundle substitution as well as feature processing.
    *
@@ -110,17 +97,9 @@
    */
   private Gadget createGadgetFromSpec(GadgetSpec spec, GadgetContext context)
       throws GadgetException {
-    LocaleSpec localeSpec
-        = spec.getModulePrefs().getLocale(context.getLocale());
-    MessageBundle bundle;
-    String dir;
-    if (localeSpec == null) {
-      bundle = MessageBundle.EMPTY;
-      dir = "ltr";
-    } else {
-      bundle = getBundle(localeSpec, context);
-      dir = localeSpec.getLanguageDirection();
-    }
+    MessageBundle bundle
+        = bundleFactory.getBundle(spec, context.getLocale(), 
context.getIgnoreCache());
+    String dir = bundle.getLanguageDirection();
 
     Substitutions substituter = new Substitutions();
     substituter.addSubstitutions(

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/MessageBundleFactory.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/MessageBundleFactory.java?rev=688066&r1=688065&r2=688066&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/MessageBundleFactory.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/MessageBundleFactory.java
 Fri Aug 22 04:29:09 2008
@@ -18,24 +18,27 @@
  */
 package org.apache.shindig.gadgets;
 
-import org.apache.shindig.gadgets.spec.LocaleSpec;
+import com.google.inject.ImplementedBy;
+import org.apache.shindig.gadgets.spec.GadgetSpec;
 import org.apache.shindig.gadgets.spec.MessageBundle;
 
-import java.net.URI;
-
-import com.google.inject.ImplementedBy;
+import java.util.Locale;
 
 /**
  * Factory of message bundles
  */
-
 @ImplementedBy(BasicMessageBundleFactory.class)
-
 public interface MessageBundleFactory {
-
-  MessageBundle getBundle(LocaleSpec localeSpec, GadgetContext context)
-      throws GadgetException;
-
-  MessageBundle getBundle(URI bundleUri, boolean ignoreCache)
+  /**
+   * Retrieves a messagMessageBundle for the provided GadgetSpec and Locale. 
Implementations must be
+   * sure to perform proper merging of message bundles of lower specifity with 
exact matches.
+   *
+   * @param spec The gadet to inspect for Locales.
+   * @param locale The language and country to get a message bundle for.
+   * @param ignoreCache  True to bypass any caching of message bundles for 
debugging purposes.
+   * @return The newly created MesageBundle.
+   * @throws GadgetException if retrieval fails for any reason.
+   */
+  MessageBundle getBundle(GadgetSpec spec, Locale locale, boolean ignoreCache)
       throws GadgetException;
 }

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTask.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTask.java?rev=688066&r1=688065&r2=688066&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTask.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/GadgetRenderingTask.java
 Fri Aug 22 04:29:09 2008
@@ -297,8 +297,9 @@
     appendJsConfig(gadget, libs, inlineJs);
 
     // message bundles for prefs object.
-    MessageBundle bundle
-        = messageBundleFactory.getBundle(gadget.getLocale(), 
gadget.getContext());
+    GadgetContext context = gadget.getContext();
+    MessageBundle bundle = messageBundleFactory.getBundle(
+        gadget.getSpec(), context.getLocale(), context.getIgnoreCache());
 
     String msgs = new JSONObject(bundle.getMessages()).toString();
     inlineJs.append("gadgets.Prefs.setMessages_(").append(msgs).append(");");

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/MessageBundle.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/MessageBundle.java?rev=688066&r1=688065&r2=688066&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/MessageBundle.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/MessageBundle.java
 Fri Aug 22 04:29:09 2008
@@ -17,9 +17,9 @@
  */
 package org.apache.shindig.gadgets.spec;
 
+import com.google.common.collect.Maps;
 import org.apache.shindig.common.xml.XmlException;
 import org.apache.shindig.common.xml.XmlUtil;
-
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 
@@ -36,6 +36,65 @@
   public static final MessageBundle EMPTY = new MessageBundle();
 
   private final Map<String, String> messages;
+  private final String languageDirection;
+
+   /**
+   * Constructs a message bundle from input xml (fetched from an external 
file).
+   *
+   * @param locale The LocaleSpec element that this bundle was constructed 
from.
+   * @param xml The content of the remote file.
+   * @throws SpecParserException if parsing fails.
+   */
+  public MessageBundle(LocaleSpec locale, String xml) throws 
SpecParserException {
+    Element doc;
+    try {
+      doc = XmlUtil.parse(xml);
+    } catch (XmlException e) {
+      throw new SpecParserException("Malformed XML in file " + 
locale.getMessages()
+          + ": " + e.getMessage());
+    }
+    messages = parseMessages(doc);
+    languageDirection = locale.getLanguageDirection();
+  }
+
+  /**
+   * Constructs a message bundle from a /ModulePrefs/Locale with nested 
messages.
+   */
+  public MessageBundle(Element element) throws SpecParserException {
+    messages = parseMessages(element);
+    languageDirection = XmlUtil.getAttribute(element, "language_direction", 
"ltr");
+  }
+
+  /**
+   * Create a MessageBundle by merging child messages into the parent.
+   *
+   * @param parent The base bundle.
+   * @param child The bundle containing overriding messages.
+   */
+  public MessageBundle(MessageBundle parent, MessageBundle child) {
+    Map<String, String> merged = Maps.newHashMap();
+    if (parent != null) {
+      merged.putAll(parent.messages);
+    }
+    if (child != null) {
+      merged.putAll(child.messages);
+    }
+    messages = Collections.unmodifiableMap(merged);
+    languageDirection = child.languageDirection;
+  }
+
+  private MessageBundle() {
+    this.messages = Collections.emptyMap();
+    languageDirection = "ltr";
+  }
+
+  /**
+   * @return The language direction associated with this message bundle, 
derived from the LocaleSpec
+   * element that the bundle was constructed from.
+   */
+  public String getLanguageDirection() {
+    return languageDirection;
+  }
 
   /**
    * @return A read-only view of the message bundle.
@@ -77,31 +136,4 @@
     buf.append("</messagebundle>");
     return buf.toString();
   }
-
-  /**
-   * Constructs a message bundle from input xml
-   * @param xml
-   * @throws SpecParserException
-   */
-  public MessageBundle(URI url, String xml) throws SpecParserException {
-    Element doc;
-    try {
-      doc = XmlUtil.parse(xml);
-    } catch (XmlException e) {
-      throw new SpecParserException("Malformed XML in file " + url.toString()
-          + ": " + e.getMessage());
-    }
-    messages = parseMessages(doc);
-  }
-
-  /**
-   * Constructs a message bundle from an existing element.
-   */
-  public MessageBundle(Element element) throws SpecParserException {
-    messages = parseMessages(element);
-  }
-
-  private MessageBundle() {
-    this.messages = Collections.emptyMap();
-  }
 }

Modified: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicMessageBundleFactoryTest.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicMessageBundleFactoryTest.java?rev=688066&r1=688065&r2=688066&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicMessageBundleFactoryTest.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicMessageBundleFactoryTest.java
 Fri Aug 22 04:29:09 2008
@@ -25,6 +25,7 @@
 import org.apache.shindig.gadgets.http.HttpRequest;
 import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.http.HttpResponseBuilder;
+import org.apache.shindig.gadgets.spec.GadgetSpec;
 import org.apache.shindig.gadgets.spec.LocaleSpec;
 import org.apache.shindig.gadgets.spec.MessageBundle;
 import org.easymock.EasyMock;
@@ -36,90 +37,96 @@
 import org.junit.Test;
 
 import java.net.URI;
+import java.util.Locale;
 
 /**
  * Tests for BasicMessageBundleFactory
  */
 public class BasicMessageBundleFactoryTest {
-  private final static URI BUNDLE_URI
-      = URI.create("http://example.org/messagex.xml";);
-  private final static URI SPEC_URI
-      = URI.create("http://example.org/gadget.xml";);
-
-  private final static String MSG_0_NAME = "messageZero";
-  private final static String MSG_1_NAME = "message1";
-  private final static String MSG_0_VALUE = "Message 0 VALUE";
-  private final static String MSG_1_VALUE = "msg one val";
-  private final static String BASIC_BUNDLE
+  private static final URI BUNDLE_URI = 
URI.create("http://example.org/messagex.xml";);
+  private static final URI SPEC_URI = 
URI.create("http://example.org/gadget.xml";);
+
+  private static final String MSG_0_NAME = "messageZero";
+  private static final String MSG_1_NAME = "message1";
+  private static final String MSG_2_NAME = "message 2";
+  private static final String MSG_0_VALUE = "Message 0 VALUE";
+  private static final String MSG_0_ALT_VALUE = "Message 0 Alternative VALUE";
+  private static final String MSG_1_VALUE = "msg one val";
+  private static final String MSG_2_VALUE = "message two val.";
+
+  private static final Locale PARENT_LOCALE = new Locale("en", "ALL");
+  private static final Locale LOCALE = new Locale("en", "US");
+
+  private static final String BASIC_BUNDLE
       = "<messagebundle>" +
         "  <msg name='" + MSG_0_NAME + "'>" + MSG_0_VALUE + "</msg>" +
         "  <msg name='" + MSG_1_NAME + "'>" + MSG_1_VALUE + "</msg>" +
         "</messagebundle>";
-  private final static GadgetContext NO_CACHE_CONTEXT = new GadgetContext() {
-    @Override
-    public boolean getIgnoreCache() {
-      return true;
-    }
-  };
+
+  private static final String BASIC_SPEC
+      = "<Module>" +
+        "<ModulePrefs title='foo'>" +
+        " <Locale lang='all' country='ALL'>" +
+        "  <msg name='" + MSG_0_NAME + "'>" + MSG_0_VALUE + "</msg>" +
+        " </Locale>" +
+        " <Locale lang='" + LOCALE.getLanguage() + "'>" +
+        "  <msg name='" + MSG_0_NAME + "'>" + MSG_0_ALT_VALUE + "</msg>" +
+        "  <msg name='" + MSG_1_NAME + "'>" + MSG_1_VALUE + "</msg>" +
+        "  <msg name='" + MSG_2_NAME + "'>" + MSG_2_VALUE + "</msg>" +
+        " </Locale>" +
+        " <Locale lang='" + LOCALE.getLanguage() + "' country='" + 
LOCALE.getCountry() + "' " +
+        "  messages='" + BUNDLE_URI + "'/>" +
+        "</ModulePrefs>" +
+        "<Content type='html'/>" +
+        "</Module>";
+
 
   private final HttpFetcher fetcher = 
EasyMock.createNiceMock(HttpFetcher.class);
   private final MessageBundleFactory bundleFactory;
   private final CacheProvider cacheProvider;
+  private final GadgetSpec gadgetSpec;
 
   public BasicMessageBundleFactoryTest() {
     cacheProvider = new DefaultCacheProvider();
     bundleFactory = new BasicMessageBundleFactory(fetcher, cacheProvider, 5, 
-1000, 1000);
+    try {
+      gadgetSpec = new GadgetSpec(SPEC_URI, BASIC_SPEC);
+    } catch (GadgetException e) {
+      throw new RuntimeException(e);
+    }
   }
 
+
   @Test
-  public void getBundleByUri() throws Exception {
+  public void getBundle() throws Exception {
     HttpResponse response = new HttpResponse(BASIC_BUNDLE);
-
     expect(fetcher.fetch(isA(HttpRequest.class))).andReturn(response);
     replay(fetcher);
 
-    MessageBundle bundle = bundleFactory.getBundle(BUNDLE_URI, true);
+    MessageBundle bundle = bundleFactory.getBundle(gadgetSpec, LOCALE, true);
 
     assertEquals(MSG_0_VALUE, bundle.getMessages().get(MSG_0_NAME));
     assertEquals(MSG_1_VALUE, bundle.getMessages().get(MSG_1_NAME));
+    assertEquals(MSG_2_VALUE, bundle.getMessages().get(MSG_2_NAME));
   }
 
   @Test
-  public void getBundleByLocaleSpec() throws Exception {
-    String localeXml = "<Locale messages='" + BUNDLE_URI + "'/>";
-    LocaleSpec locale = new LocaleSpec(XmlUtil.parse(localeXml), SPEC_URI);
-    HttpResponse response = new HttpResponse(BASIC_BUNDLE);
-
-    expect(fetcher.fetch(isA(HttpRequest.class))).andReturn(response);
-    replay(fetcher);
-
-    MessageBundle bundle = bundleFactory.getBundle(locale, NO_CACHE_CONTEXT);
+  public void getParentBundle() throws Exception {
+    MessageBundle bundle = bundleFactory.getBundle(gadgetSpec, PARENT_LOCALE, 
true);
 
-    assertEquals(MSG_0_VALUE, bundle.getMessages().get(MSG_0_NAME));
+    assertEquals(MSG_0_ALT_VALUE, bundle.getMessages().get(MSG_0_NAME));
     assertEquals(MSG_1_VALUE, bundle.getMessages().get(MSG_1_NAME));
+    assertEquals(MSG_2_VALUE, bundle.getMessages().get(MSG_2_NAME));
   }
 
   @Test
-  public void getBundleByLocaleSpecWithNestedMessages() throws Exception {
-    String localeXml
-        = "<Locale>" +
-          "<msg name='" + MSG_0_NAME + "'>" + MSG_0_VALUE + "</msg>" +
-          "</Locale>";
-    LocaleSpec locale = new LocaleSpec(XmlUtil.parse(localeXml), SPEC_URI);
-
-    MessageBundle bundle = bundleFactory.getBundle(locale, NO_CACHE_CONTEXT);
-
+  public void getAllAllBundle() throws Exception {
+    MessageBundle bundle = bundleFactory.getBundle(gadgetSpec, new 
Locale("all", "ALL"), true);
     assertEquals(MSG_0_VALUE, bundle.getMessages().get(MSG_0_NAME));
   }
 
   @Test
   public void badResponseServedFromCache() throws Exception {
-    String localeXml
-        = "<Locale>" +
-          "<msg name='" + MSG_0_NAME + "'>" + MSG_0_VALUE + "</msg>" +
-          "</Locale>";
-    LocaleSpec locale = new LocaleSpec(XmlUtil.parse(localeXml), SPEC_URI);
-    assertEquals("all", locale.getLanguage());    
     HttpResponse expiredResponse = new HttpResponseBuilder()
         .setResponse(BASIC_BUNDLE.getBytes("UTF-8"))
         .addHeader("Pragma", "no-cache")
@@ -132,17 +139,11 @@
         .andReturn(badResponse).once();
     replay(fetcher);
 
-    MessageBundle bundle = bundleFactory.getBundle(BUNDLE_URI, true);
-    bundle = bundleFactory.getBundle(BUNDLE_URI, false);
+    MessageBundle bundle = bundleFactory.getBundle(gadgetSpec, LOCALE, true);
+    bundle = bundleFactory.getBundle(gadgetSpec, LOCALE, false);
 
     verify(fetcher);
 
     assertEquals(MSG_0_VALUE, bundle.getMessages().get(MSG_0_NAME));
   }
-
-  @Test
-  public void badLocaleGetsEmptyBundle() throws Exception {
-    assertEquals(0,
-        bundleFactory.getBundle(null, NO_CACHE_CONTEXT).getMessages().size());
-  }
 }

Modified: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/MessageBundleTest.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/MessageBundleTest.java?rev=688066&r1=688065&r2=688066&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/MessageBundleTest.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/MessageBundleTest.java
 Fri Aug 22 04:29:09 2008
@@ -19,12 +19,10 @@
 
 package org.apache.shindig.gadgets.spec;
 
-import static org.junit.Assert.assertEquals;
-
-import org.apache.shindig.common.xml.XmlUtil;
-
 import com.google.common.collect.Maps;
-
+import org.apache.shindig.common.xml.XmlUtil;
+import static org.junit.Assert.assertEquals;
+import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Element;
 
@@ -33,6 +31,13 @@
 
 public class MessageBundleTest {
   private static final URI BUNDLE_URL = URI.create("http://example.org/m.xml";);
+  private static final String LOCALE
+      = "<Locale lang='en' country='US' messages='" + BUNDLE_URL + "'/>";
+  private static final String PARENT_LOCALE
+      = "<Locale lang='en' country='ALL' language_direction='rtl'>" +
+        " <msg name='one'>VALUE</msg>" +
+        " <msg name='foo'>adfdfdf</msg>" +
+        "</Locale>";
   private static final Map<String, String> MESSAGES = Maps.newHashMap();
   private static final String XML;
   static {
@@ -49,22 +54,29 @@
     XML = buf.toString();
   }
 
+  private LocaleSpec locale;
+
+  @Before
+  public void setUp() throws Exception {
+    locale = new LocaleSpec(XmlUtil.parse(LOCALE), 
URI.create("http://example.org/gadget";));
+  }
+
   @Test
   public void normalMessageBundleParsesOk() throws Exception {
-    MessageBundle bundle = new MessageBundle(BUNDLE_URL, XML);
+    MessageBundle bundle = new MessageBundle(locale, XML);
     assertEquals(MESSAGES, bundle.getMessages());
   }
 
   @Test(expected = SpecParserException.class)
   public void missingNameThrows() throws SpecParserException {
     String xml = "<messagebundle><msg>foo</msg></messagebundle>";
-    new MessageBundle(BUNDLE_URL, xml);
+    new MessageBundle(locale, xml);
   }
 
   @Test(expected = SpecParserException.class)
   public void malformedXmlThrows() throws SpecParserException {
     String xml = "</messagebundle>";
-    new MessageBundle(BUNDLE_URL, xml);
+    new MessageBundle(locale, xml);
   }
 
   @Test
@@ -74,6 +86,13 @@
     assertEquals(MESSAGES, bundle.getMessages());
   }
 
+  @Test
+  public void extractFromElementWithLanguageDir() throws Exception {
+    Element element = XmlUtil.parse(PARENT_LOCALE);
+    MessageBundle bundle = new MessageBundle(element);
+    assertEquals("rtl", bundle.getLanguageDirection());
+  }
+
   @Test(expected = SpecParserException.class)
   public void extractFromElementsWithNoName() throws Exception {
     String xml = "<messagebundle><msg>foo</msg></messagebundle>";
@@ -82,9 +101,19 @@
   }
 
   @Test
+  public void merge() throws Exception {
+    MessageBundle parent = new MessageBundle(XmlUtil.parse(PARENT_LOCALE));
+    MessageBundle child = new MessageBundle(XmlUtil.parse(XML));
+    MessageBundle bundle = new MessageBundle(parent, child);
+    assertEquals("ltr", bundle.getLanguageDirection());
+    assertEquals("VALUE", bundle.getMessages().get("one"));
+    assertEquals("bar", bundle.getMessages().get("foo"));
+  }
+
+  @Test
   public void toStringIsSane() throws Exception {
-    MessageBundle b0 = new MessageBundle(BUNDLE_URL, XML);
-    MessageBundle b1 = new MessageBundle(BUNDLE_URL, b0.toString());
+    MessageBundle b0 = new MessageBundle(locale, XML);
+    MessageBundle b1 = new MessageBundle(locale, b0.toString());
     assertEquals(b0.getMessages(), b1.getMessages());
   }
 }


Reply via email to