|
MultiValuedConfigProperties
Design doc describing how to enhance config properties to support multiple values
Phase-Design BackgroundIn 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 namespaceAt 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 propertiesThe 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
ProposalTo 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 |
Recording that I think the simplest approach is actually <append-configuration-property>. I think there are sane answers to all the question raised:
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.
Our APIs could return 'null' vs. "". However, ideally generators wouldn't care and would just treat them the same.
It would have no effect since it would not change the property string (since GWT would not automatically add delimiters).
String.split(delimiter), ignore any empty pieces.
why there is no API to access that properties at runtime? or are there plans to support "runtime properties"? use case:
there is a queue which allows to configurate its QUEUE_SIZE 1) I want a default setting <runtime-property name="QUEUE_SIZE" value="20"/> 2) HTML meta tag gwt:property QUEUE_SIZE=30 overrides that default 3) URL parameter &QUEUE_SIZE=40 overrides META tag configuration