Revision: 6913
Author: [email protected]
Date: Mon Nov 16 10:04:26 2009
Log: AttributeParsing was pretty much working by accident, and not at all  
for the
deprecated urn:with mechanism. I'm not 100% certain there weren't  
non-deprecated
paths that were broken too.

Attribute parsing is still too complicated, but it's better tested now and  
goes
through only two bottlenecks. Should be able to reduce that to one when the
deprecated code is dumped.

Also fixes a stray "null" in the deprecation message for urn:with

Reviewed by spoon
http://gwt-code-reviews.appspot.com/102818
http://code.google.com/p/google-web-toolkit/source/detail?r=6913

Modified:
   
/trunk/user/src/com/google/gwt/uibinder/attributeparsers/BundleAttributeParsers.java
  /trunk/user/src/com/google/gwt/uibinder/elementparsers/BeanParser.java
  /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
  /trunk/user/src/com/google/gwt/uibinder/rebind/XMLAttribute.java
  /trunk/user/src/com/google/gwt/uibinder/rebind/XMLElement.java
   
/trunk/user/test/com/google/gwt/uibinder/elementparsers/ElementParserTester.java
  /trunk/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java
  /trunk/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
  /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
  /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml

=======================================
---  
/trunk/user/src/com/google/gwt/uibinder/attributeparsers/BundleAttributeParsers.java
     
Fri Nov  6 16:08:46 2009
+++  
/trunk/user/src/com/google/gwt/uibinder/attributeparsers/BundleAttributeParsers.java
     
Mon Nov 16 10:04:26 2009
@@ -38,7 +38,6 @@
    private static final String BUNDLE_URI_SCHEME = "urn:with:";

    private final TypeOracle oracle;
-  private final String gwtPrefix;
    private final MortalLogger logger;
    private final OwnerClass ownerClass;
    private final String templatePath;
@@ -49,11 +48,9 @@
     */
    private final Map<String, BundleAttributeParser> parsers = new  
LinkedHashMap<String, BundleAttributeParser>();

-  public BundleAttributeParsers(TypeOracle oracle, String gwtPrefix,
-      MortalLogger logger, OwnerClass ownerClass, String templatePath,
-      JClassType uiOwnerType) {
+  public BundleAttributeParsers(TypeOracle oracle, MortalLogger logger,
+      OwnerClass ownerClass, String templatePath, JClassType uiOwnerType) {
      this.oracle = oracle;
-    this.gwtPrefix = gwtPrefix;
      this.logger = logger;
      this.ownerClass = ownerClass;
      this.templatePath = templatePath;
@@ -66,12 +63,10 @@

    public BundleAttributeParser get(XMLAttribute attribute)
        throws UnableToCompleteException {
-    if (attribute.getNamespaceUri() == null) {
-      return null;
-    }
-
      String attributePrefixUri = attribute.getNamespaceUri();
-    if (!attributePrefixUri.startsWith(BUNDLE_URI_SCHEME)) {
+
+    if ((attributePrefixUri == null)
+        || !attributePrefixUri.startsWith(BUNDLE_URI_SCHEME)) {
        return null;
      }

@@ -100,10 +95,9 @@
        XMLAttribute attribute) throws UnableToCompleteException {

      final String templateResourceName = attribute.getName().split(":")[0];
-    warn("The %1$s mechanism is deprecated. Instead, declare the  
following "
-        + "%2$s:with element as a child of your %2$s:UiBinder element: "
-        + "<%2$s:with field='%3$s' type='%4$s.%5$s' />", BUNDLE_URI_SCHEME,
-        gwtPrefix, templateResourceName,  
bundleClass.getPackage().getName(),
+    warn("\"%s\" is deprecated by "
+        + "<ui:with field='%s' type='%s.%s' />", BUNDLE_URI_SCHEME,
+        templateResourceName, bundleClass.getPackage().getName(),
          bundleClass.getName());

      // Try to find any bundle instance created with UiField.
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/elementparsers/BeanParser.java      
 
Wed Nov 11 22:08:47 2009
+++ /trunk/user/src/com/google/gwt/uibinder/elementparsers/BeanParser.java      
 
Mon Nov 16 10:04:26 2009
@@ -116,7 +116,7 @@
        String propertyName = attribute.getLocalName();
        if (setterValues.keySet().contains(propertyName)
            || requiredValues.containsKey(propertyName)) {
-        writer.die("Duplicate attribute name: %s", propertyName);
+        writer.die("In %s, duplicate attribute name: %s", elem,  
propertyName);
        }

        if (unfilledRequiredParams.keySet().contains(propertyName)) {
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java  Wed  
Nov 11 22:08:47 2009
+++ /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java  Mon  
Nov 16 10:04:26 2009
@@ -262,8 +262,8 @@
      handlerEvaluator = new HandlerEvaluator(ownerClass, logger, oracle);

      attributeParsers = new AttributeParsers(oracle, fieldManager, logger);
-    bundleParsers = new BundleAttributeParsers(oracle, gwtPrefix, logger,
-        getOwnerClass(), templatePath, uiOwnerType);
+    bundleParsers = new BundleAttributeParsers(oracle, logger,  
getOwnerClass(),
+        templatePath, uiOwnerType);
    }

    /**
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/XMLAttribute.java    Fri  
Nov  6 16:08:46 2009
+++ /trunk/user/src/com/google/gwt/uibinder/rebind/XMLAttribute.java    Mon  
Nov 16 10:04:26 2009
@@ -67,6 +67,7 @@

    @Override
    public String toString() {
-    return w3cAttr.getName() + "='" + w3cAttr.getValue() + "'";
+    return String.format("<%s:%s ... %s=%s ...>", xmlElem.getPrefix(),
+        xmlElem.getLocalName(), w3cAttr.getName(), w3cAttr.getValue());
    }
  }
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/XMLElement.java      Wed Nov 
 
11 22:08:47 2009
+++ /trunk/user/src/com/google/gwt/uibinder/rebind/XMLElement.java      Mon Nov 
 
16 10:04:26 2009
@@ -197,9 +197,8 @@
    }

    /**
-   * Consumes the given attribute as a literal or field reference. The
-   * type parameter is required to determine how the value is parsed and
-   * validated.
+   * Consumes the given attribute as a literal or field reference. The type
+   * parameter is required to determine how the value is parsed and  
validated.
     *
     * @param name the attribute's full name (including prefix)
     * @param types the type(s) this attribute is expected to provide
@@ -208,14 +207,12 @@
     */
    public String consumeAttribute(String name, JType type)
        throws UnableToCompleteException {
-    String value = consumeRawAttribute(name);
-    return getParser(getAttribute(name), type).parse(value);
+    return consumeAttributeWithDefault(name, "", type);
    }

    /**
-   * Consumes the given attribute as a literal or field reference. The
-   * type parameter is required to determine how the value is parsed and
-   * validated.
+   * Consumes the given attribute as a literal or field reference. The type
+   * parameter is required to determine how the value is parsed and  
validated.
     *
     * @param name the attribute's full name (including prefix)
     * @param defaultValue the value to @return if the attribute was unset
@@ -230,20 +227,12 @@
    }

    /**
-   * Like {...@link #consumeAttributeWithDefault(String, String, JType)}, but
+   * Like {...@link #consumeAttributeWithDefault(String, String, JType)}, but
     * accomodates more complex type signatures.
     */
    public String consumeAttributeWithDefault(String name, String  
defaultValue,
        JType[] types) throws UnableToCompleteException {
-    String value = consumeRawAttribute(name);
-    if ("".equals(value)) {
-      return defaultValue;
-    }
-    value = getParser(getAttribute(name), types).parse(value);
-    if ("".equals(value)) {
-      return defaultValue;
-    }
-    return value;
+    return consumeAttributeWithDefault(false, name, defaultValue, types);
    }

    /**
@@ -272,11 +261,8 @@
     */
    public String consumeBooleanAttribute(String name, boolean defaultValue)
        throws UnableToCompleteException {
-    String parsed = consumeAttribute(name, getBooleanType());
-    if ("".equals(parsed)) {
-      return Boolean.toString(defaultValue);
-    }
-    return parsed;
+    return consumeAttributeWithDefault(name,  
Boolean.toString(defaultValue),
+        getBooleanType());
    }

    /**
@@ -517,7 +503,7 @@
    }

    /**
-   * Consumes the given required attribute as a literal or field  
reference. The
+   * Consumes the given required attribute as a literal or field  
reference. The
     * types parameters are required to determine how the value is parsed and
     * validated.
     *
@@ -529,8 +515,19 @@
     */
    public String consumeRequiredAttribute(String name, JType... types)
        throws UnableToCompleteException {
+    /*
+     * TODO(rjrjr) We have to get the attribute to
+     * get the parser, and we must get the attribute before we consume the
+     * value. This nasty subtlety is all down to BundleParsers, which we'll
+     * hopefully kill off soon.
+     */
+    XMLAttribute attribute = getAttribute(name);
+    if (attribute == null) {
+      failRequired(name);
+    }
+    AttributeParser parser = getParser(attribute, types);
      String value = consumeRequiredRawAttribute(name);
-    return getParser(getAttribute(name), types).parse(value);
+    return parser.parse(value);
    }

    /**
@@ -555,7 +552,7 @@
        throws UnableToCompleteException {
      String value = consumeRawAttribute(name);
      if ("".equals(value)) {
-      logger.die("In %s, missing required attribute \"%s\"", this, name);
+      failRequired(name);
      }
      return value;
    }
@@ -747,6 +744,30 @@
    public String toString() {
      return debugString;
    }
+
+  private String consumeAttributeWithDefault(boolean required, String name,
+      String defaultValue, JType[] types) throws UnableToCompleteException  
{
+    /*
+     * TODO(rjrjr) The only reason we need the attribute here is for  
getParser,
+     * and getParser only needs it for horrible old  
BundleAttributeParsers. When
+     * that dies, this gets much simpler.
+     */
+    XMLAttribute attribute = getAttribute(name);
+    if (attribute == null) {
+      if (required) {
+        failRequired(name);
+      }
+      return defaultValue;
+    }
+    String value = attribute.consumeRawValue();
+    if ("".equals(value)) {
+      if (required) {
+        failRequired(name);
+      }
+      return defaultValue;
+    }
+    return getParser(attribute, types).parse(value);
+  }

    private Iterable<XMLElement> consumeChildElementsNoEmptyCheck() {
      try {
@@ -757,6 +778,10 @@
        throw new RuntimeException("Impossible exception", e);
      }
    }
+
+  private void failRequired(String name) throws UnableToCompleteException {
+    logger.die("In %s, missing required attribute \"%s\"", this, name);
+  }

    private JType getBooleanType() {
      if (booleanType == null) {
@@ -804,13 +829,11 @@
    @SuppressWarnings("deprecation")
    private AttributeParser getParser(XMLAttribute xmlAttribute, JType...  
types)
        throws UnableToCompleteException {
-    AttributeParser rtn = null;
-    if (xmlAttribute != null) {
-      rtn = bundleParsers.get(xmlAttribute);
-    }
+    AttributeParser rtn = bundleParsers.get(xmlAttribute);
      if (rtn == null) {
        rtn = attributeParsers.get(types);
      }
+
      return rtn;
    }

=======================================
---  
/trunk/user/test/com/google/gwt/uibinder/elementparsers/ElementParserTester.java
         
Wed Nov 11 22:08:47 2009
+++  
/trunk/user/test/com/google/gwt/uibinder/elementparsers/ElementParserTester.java
         
Mon Nov 16 10:04:26 2009
@@ -25,6 +25,7 @@
  import com.google.gwt.dev.resource.Resource;
  import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
  import com.google.gwt.uibinder.attributeparsers.AttributeParsers;
+import com.google.gwt.uibinder.attributeparsers.BundleAttributeParsers;
  import com.google.gwt.uibinder.rebind.FieldManager;
  import com.google.gwt.uibinder.rebind.FieldWriter;
  import com.google.gwt.uibinder.rebind.MockMortalLogger;
@@ -87,6 +88,7 @@

    final ElementParser parser;

+  @SuppressWarnings("deprecation")
    ElementParserTester(String parsedTypeName, ElementParser parser)
        throws UnableToCompleteException {
      this.parser = parser;
@@ -97,7 +99,8 @@
      types = state.getTypeOracle();

      elemProvider = new XMLElementProviderImpl(new AttributeParsers(types,  
null,
-        logger), null, types, logger);
+        logger), new BundleAttributeParsers(types, logger, null,  
templatePath,
+        null), types, logger);

      fieldManager = new FieldManager(types, logger);
      JClassType baseType = types.findType("my.Ui.BaseClass");
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java Wed  
Nov 11 22:08:47 2009
+++ /trunk/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java Mon  
Nov 16 10:04:26 2009
@@ -22,6 +22,7 @@
  import com.google.gwt.dev.javac.CompilationStateBuilder;
  import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
  import com.google.gwt.uibinder.attributeparsers.AttributeParsers;
+import com.google.gwt.uibinder.attributeparsers.BundleAttributeParsers;
  import com.google.gwt.uibinder.elementparsers.NullInterpreter;
  import com.google.gwt.uibinder.test.UiJavaResources;

@@ -61,6 +62,7 @@

    private MockMortalLogger logger;

+  @SuppressWarnings("deprecation")
    @Override
    public void setUp() throws Exception {
      super.setUp();
@@ -69,7 +71,8 @@
      types = state.getTypeOracle();
      logger = new MockMortalLogger();
      elemProvider = new XMLElementProviderImpl(new AttributeParsers(types,  
null,
-        logger), null, types, logger);
+        logger), new BundleAttributeParsers(types, logger,  
null, "templatePath",
+            null), types, logger);

      init("<doc><elm attr1=\"attr1Value\" attr2=\"attr2Value\"/></doc>");
    }
@@ -247,7 +250,7 @@
          "otherDefault"));
    }

-  public void testConsumeRequired() throws UnableToCompleteException {
+  public void testConsumeRequiredRaw() throws UnableToCompleteException {
      assertEquals("attr1Value", elm.consumeRequiredRawAttribute("attr1"));
      try {
        elm.consumeRequiredRawAttribute("unsetthing");
@@ -256,6 +259,11 @@
        assertNotNull(logger.died);
      }
    }
+
+  public void testConsumeRequired() throws UnableToCompleteException {
+    assertEquals("\"attr1Value\"", elm.consumeRequiredAttribute("attr1",
+        types.findType("java.lang.String")));
+  }

    public void testConsumeRequiredDouble() throws UnableToCompleteException,
        SAXException, IOException {
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java      
 
Wed Nov 11 22:08:47 2009
+++ /trunk/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java      
 
Mon Nov 16 10:04:26 2009
@@ -137,6 +137,21 @@
      foo.setPojo(pojo);
      assertEquals(foo.getText(), widgetUi.theFoo.getText());
    }
+
+  public void testBundleLegacyBeansText() {
+    assertEquals(widgetUi.legacyValuesForBeans.helloText(),
+        widgetUi.bundledLabelLegacy.getText());
+  }
+
+  public void testBundleLegacyBeansOther() {
+    assertEquals(widgetUi.legacyValuesForBeans.helloText(),
+        widgetUi.bundledLabelLegacy.getStyleName());
+  }
+
+  public void testBundleLegacyHtml() {
+    assertEquals(widgetUi.legacyValuesForHtml.helloText(),
+        widgetUi.bundledDivLegacy.getClassName());
+  }

    public void testCenter() {
      // TODO(rjrjr) More of a test of HTMLPanelParser
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java     
 
Wed Nov 11 22:08:47 2009
+++ /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java     
 
Mon Nov 16 10:04:26 2009
@@ -62,8 +62,13 @@

    interface Binder extends UiBinder<Widget, WidgetBasedUi> {
    }
-  private static final Binder binder = GWT.create(Binder.class);
-
+  static class FakeBundle2 extends FakeBundle {
+  }
+
+  static class FakeBundle3 extends FakeBundle {
+  }
+  private static final Binder binder = GWT.create(Binder.class);
+
    @UiField(provided = true)
    final WidgetBasedUiExternalResources external =  
GWT.create(WidgetBasedUiExternalResources.class);

@@ -137,6 +142,12 @@
    @UiField FooLabel objectBooleanIntoPrimitive;
    @UiField FooLabel allObjectBoolean;
    @UiField FooLabel allPrimitiveBoolean;
+  @UiField(provided = true)
+  FakeBundle2 legacyValuesForBeans = new FakeBundle2();
+  @UiField(provided = true)
+  FakeBundle3 legacyValuesForHtml = new FakeBundle3();
+  @UiField Label bundledLabelLegacy;
+  @UiField DivElement bundledDivLegacy;

    public WidgetBasedUi() {
      external.style().ensureInjected();
=======================================
---  
/trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml       
 
Wed Nov 11 22:08:47 2009
+++  
/trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml       
 
Mon Nov 16 10:04:26 2009
@@ -49,6 +49,9 @@
  <ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    xmlns:gwt='urn:import:com.google.gwt.user.client.ui'
    xmlns:demo='urn:import:com.google.gwt.uibinder.test.client'
+
+   
xmlns:legacyValuesForBeans='urn:with:com.google.gwt.uibinder.test.client.WidgetBasedUi.FakeBundle2'
+   
xmlns:legacyValuesForHtml='urn:with:com.google.gwt.uibinder.test.client.WidgetBasedUi.FakeBundle3'

    ui:defaultLocale="en_US"
    ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
@@ -407,6 +410,8 @@
         this label gets its text from somplace tricky and its style from a  
ClientBundle
         defined outside of this UI:</p>
        <gwt:Label ui:field='bundledLabel' text="{values.helloText}"  
styleName="{external.style.prettyText}"/>
+      <gwt:Label ui:field='bundledLabelLegacy'  
legacyValuesForBeans:text="helloText"  
legacyValuesForBeans:styleName="helloText" />
+      <div ui:field='bundledDivLegacy'  
legacyValuesForHtml:class="helloText"/>
        <!-- Note use of id rather than ui:field, to test that ids work on  
dom elements -->
        <p class="{external.style.prettyText}" id='prettyPara'>
          This stylish paragraph also gets its good looks from the

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to