blob: 2a7f62c68baeb57b7c96bfcc064392fddce27a5f [file] [log] [blame]
/*
* Copyright 2013 Google Inc.
*
* Licensed 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 com.google.gwt.dev.cfg;
import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.ConfigurationProperty;
import com.google.gwt.core.ext.DefaultConfigurationProperty;
import com.google.gwt.core.ext.DefaultSelectionProperty;
import com.google.gwt.core.ext.PropertyOracle;
import com.google.gwt.core.ext.SelectionProperty;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
/**
* An implementation of {@link PropertyOracle} that helps discover the property values associated
* with specific rebind results for generators.<br />
*
* It does so by recording the properties that are queried, providing a first legal answer for
* properties not previously queried and allowing an external driver to prescribe values for
* properties that have been discovered as dependencies.
*/
// TODO(stalcup): get rid of foo.ConfigurationProperty and bar.ConfigurationProperty class name
// collisions.
public class DynamicPropertyOracle implements PropertyOracle {
private static SelectionProperty createSelectionProperty(
String value, BindingProperty bindingProperty) {
SortedSet<String> possibleValues =
Sets.newTreeSet(Arrays.asList(bindingProperty.getDefinedValues()));
return new DefaultSelectionProperty(value, bindingProperty.getFallback(),
bindingProperty.getName(), possibleValues, bindingProperty.getFallbackValuesMap());
}
private final Set<BindingProperty> accessedProperties = Sets.newHashSet();
private boolean accessedPropertiesChanged;
private final Map<String, String> prescribedPropertyValuesByName = Maps.newHashMap();
private final Properties properties;
public DynamicPropertyOracle(Properties properties) {
this.properties = properties;
}
public boolean haveAccessedPropertiesChanged() {
return accessedPropertiesChanged;
}
public Set<BindingProperty> getAccessedProperties() {
return accessedProperties;
}
@Override
public ConfigurationProperty getConfigurationProperty(String propertyName)
throws BadPropertyValueException {
com.google.gwt.dev.cfg.ConfigurationProperty prop = properties.findConfigProp(propertyName);
if (prop != null) {
return new DefaultConfigurationProperty(prop.getName(), prop.getValues());
}
throw new BadPropertyValueException(propertyName);
}
/**
* Returns the mapping from property names to its currently prescribed value. The internal mapping
* changes between runs so the returned value is a stable copy.
*/
public Map<String, String> getPrescribedPropertyValuesByName() {
return Maps.newHashMap(prescribedPropertyValuesByName);
}
@Override
public SelectionProperty getSelectionProperty(TreeLogger logger, String propertyName)
throws BadPropertyValueException {
BindingProperty bindingProperty = getBindingProperty(propertyName);
accessedPropertiesChanged |= accessedProperties.add(bindingProperty);
String propertyValue = prescribedPropertyValuesByName.isEmpty()
? bindingProperty.getFirstGeneratedValue() : prescribedPropertyValuesByName.get(propertyName);
return createSelectionProperty(propertyValue, bindingProperty);
}
public void prescribePropertyValue(String propertyName, String propertyValue) {
prescribedPropertyValuesByName.put(propertyName, propertyValue);
}
/**
* Clears state in preparation for another round of rebind analysis on the same generator. Since
* some per generator state is not cleared it is necessary to create a new instance per generator.
*/
public void reset() {
accessedPropertiesChanged = false;
prescribedPropertyValuesByName.clear();
}
private BindingProperty getBindingProperty(String propertyName) throws BadPropertyValueException {
BindingProperty property = properties.findBindingProp(propertyName);
if (property != null) {
return property;
}
throw new BadPropertyValueException(propertyName);
}
}