My favorites | Sign in
Google
                
Search
for
Updated Apr 24, 2009 by br...@google.com
Labels: Phase-Design
MultiValuedConfigProperties  
Design doc describing how to enhance config properties to support multiple values

Background

In GWT 1.6, a new module XML element was introduced called <set-configuration-property>. Its purpose is to provide to generators and linkers configuration parameters that cannot be appropriately expressed via deferred binding properties, either because they would never drive multiple permutations or because they have values that aren't enumerable. For example, if a generator needs to be passed a filename at compile-time, deferred binding properties make no sense, but a configuration property is perfect.

However, in a recent design discussion for RPC blacklist support, we found <set-configuration-property> a bit deficient. The subsequent sections explain the current behavior, spotlighting the problematic aspects.

Shared namespace

At present, the namespaces of deferred binding properties and configuration properties are the same. This was intentional, and the original motivations were good:

Based on the reasoning above, PropertyOracle#getPropertyValue is specified to return either a deferred binding property or a configuration property. Generators can simply query for a property value without knowing whether they are receiving a configuration property or a deferred binding property as an answer.

In retrospect, unifying the namespace creates more problems than it solves. Although deferred binding properties have a strict identifier-like token syntax, configuration properties do not, so the idea of swapping a property from one type to the other could break accidental assumptions about the format of a result value of a getPropertyValue call in generators. Additionally, PropertyOracle#getProperyValueSet has no relevant meaning for configuration properties, creating the hard-to-understand behavior that a given property name can succeed in a call to getPropertyValue even though getPropertyValueSet with the same property name will throw an exception (that is, in the case where the name refers to a configuration property).

Single-valued versus multi-valued configuration properties

The original design of configuration properties was supposed to be very simple, similar to Java system properties. But what happens when a multi-valued configuration property is needed? In the case of RPC blacklists, we needed to allow multiple modules to contribute to an accumulated value -- the list of types that should not participate in RPC.

There are two main ways to approach this. The most obvious is something like <append-configuration-property> which simply appends to the string value, perhaps adding a delimiter. This has the virtue of being simple and not requiring APIs changes. However, it pushes extra complications onto generator writers. Questions such as

So, it gets tricky using strings fro multi-valued configuration properties.

Proposal

To address the above weakness, approximately the following changes are proposed.

1) Deprecate PropertyOracle#getPropertyValue and #getPropertyValueSet, leaving their behavior unchanged

2) Add com.google.gwt.core.ext.generator.SelectionProperty

package com.google.gwt.core.ext.generator;
public interface SelectionProperty {
  // The name of the property.
  String getName();

  // The value for the permutation currently being considered.
  String getCurrentValue();

  // In unspecified but consistent order.
  SortedSet<String> getPossibleValues(); 
}

3) Add com.google.gwt.core.ext.generator.ConfigurationProperty

package com.google.gwt.core.ext.generator;
public interface ConfigurationProperty {
  // The name of the property.
  String getName(); 

  // Values are guaranteed to be listed in lexical order (i.e. the last <extends> appears at the end).
  // If the value has never been set or extended, returns the empty list.
  List<String> getValues();
}

4) Add methods to PropertyOracle

public com.google.gwt.core.ext.generator.SelectionProperty getSelectionProperty(String name);

and

public com.google.gwt.core.ext.generator.ConfigurationProperty getConfigurationProperty(String name);

5) Add new module XML element <define-configuration-property name="the-name" is-multi-valued="true|false"/>

6) Add <extend-configuration-property name="the-name" value="any-string-value"/>

7) Remove <append-configuration-property> which landed in trunk as part of runtime locales

8) Keep <set-configuration-property name="the-name" value="any-string-value"/>

9) Add new module XML element <clear-configuration-property name="the-name"/>

10) Fix runtime locales generator to use new config properties behavior


Comment by scottb@google.com, Apr 27, 2009

Recording that I think the simplest approach is actually <append-configuration-property>. I think there are sane answers to all the question raised:

  • Should a delimiter be added automatically? If not, what happens if the string was previously empty, thus creating a bogus initial delimiter?

No automatic delimiter. It'd be up to the user to provide whatever delimiter they needed. The "initial delimiter" problem isn't too hard to solve with careful design. As an example, with a Java path it's harmless to have an initial delimiter, or even multiple delimiters in a row, since empty string is distinct from a single dot for current directory.

  • How do we differentiate the concept of 'no value' from the concept of 'has a value that is the empty string'?

Our APIs could return 'null' vs. "". However, ideally generators wouldn't care and would just treat them the same.

  • Can you append a 'no value'?

It would have no effect since it would not change the property string (since GWT would not automatically add delimiters).

  • How would we recommend people parse this string within generators?

String.split(delimiter), ignore any empty pieces.


Sign in to add a comment