blob: be5be1f1951596205b007c6147189b4daf800ea8 [file] [log] [blame]
/*
* Copyright 2014 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.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.thirdparty.guava.common.base.Objects;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableMap;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
/**
* The properties for one hard permutation.
*
* <p>This is essentially a table where columns are soft permutations
* and rows are property names. Each values for each column are stored
* in an instance of {@link BindingProperties}).
*/
public class PermutationProperties {
private final ImmutableList<BindingProperties> softProperties;
public PermutationProperties(Iterable<BindingProperties> softProperties) {
this.softProperties = ImmutableList.copyOf(softProperties);
assert this.softProperties.size() >= 1;
assert sameBindingProperties(this.softProperties) :
"The binding properties should be the same for each soft permutation.";
}
/**
* Returns the permutation-independent properties.
*/
public ConfigurationProperties getConfigurationProperties() {
// They are all the same, so just take the first one.
return softProperties.get(0).getConfigurationProperties();
}
/**
* Returns the binding properties in dependency order (permutation-independent).
*/
public ImmutableList<BindingProperty> getBindingProperties() {
// Just take the first one.
return ImmutableList.copyOf(softProperties.get(0).getOrderedProps());
}
/**
* Returns the properties for each soft permutation, ordered by soft permutation id.
*
* <p>If soft permutations aren't turned on, the list will contain one item.
*/
public ImmutableList<BindingProperties> getSoftProperties() {
return softProperties;
}
/**
* Returns the value of a binding property as a string.
*
* @throws IllegalStateException if it doesn't exist or if the soft permutations
* don't all have the same value.
*/
public String mustGetString(String key) {
if (!isEqualInEachPermutation(key)) {
throw new IllegalStateException("The '" + key +
"' binding property must be the same in each soft permutation");
}
String value = softProperties.get(0).getString(key, null);
if (value == null) {
throw new IllegalStateException("The '" + key + "' binding property is not defined");
}
return value;
}
/**
* Returns true if a binding property has the same value in every soft permutation.
*/
public boolean isEqualInEachPermutation(String key) {
String expected = softProperties.get(0).getString(key, null);
for (BindingProperties prop : softProperties.subList(1, softProperties.size())) {
String actual = prop.getString(key, null);
if (!Objects.equal(expected, actual)) {
return false;
}
}
return true;
}
/**
* Checks if a boolean binding property is set to true in any soft permutation.
*/
public boolean isTrueInAnyPermutation(String name) {
for (BindingProperties bindingProperties : softProperties) {
if (bindingProperties.getBoolean(name, false)) {
return true;
}
}
return false;
}
/**
* Returns the binding property values to be embedded into the initial JavaScript fragment
* for this permutation. (There will be one map for each soft permutation.)
*/
public ImmutableList<ImmutableMap<String, String>> findEmbeddedProperties(TreeLogger logger) {
Set<String> propsWanted = Sets.newTreeSet(getConfigurationProperties().getStrings(
"js.embedded.properties"));
// Filter out any binding properties that don't exist.
SortedSet<String> propsToSave = Sets.newTreeSet();
for (BindingProperty prop : getBindingProperties()) {
String name = prop.getName();
if (propsWanted.remove(name)) {
propsToSave.add(name);
}
}
// Warn about binding properties that don't exist.
if (!propsWanted.isEmpty()) {
TreeLogger branch = logger.branch(Type.WARN,
propsWanted.size() + "properties listed in js.embedded.properties are undefined");
for (String prop : propsWanted) {
branch.log(Type.WARN, "undefined property: '" + prop + "'");
}
}
// Find the values.
List<ImmutableMap<String, String>> result = Lists.newArrayList();
for (BindingProperties properties : getSoftProperties()) {
ImmutableMap.Builder<String, String> values = ImmutableMap.builder();
for (String key : propsToSave) {
values.put(key, properties.getString(key, null));
}
result.add(values.build());
}
return ImmutableList.copyOf(result);
}
/**
* Dumps the properties for this hard permuation, for logging and soyc.
*/
public String prettyPrint() {
StringBuilder out = new StringBuilder();
for (BindingProperties properties : getSoftProperties()) {
if (out.length() > 0) {
out.append("; ");
}
out.append(properties.prettyPrint());
}
return out.toString();
}
private boolean sameBindingProperties(ImmutableList<BindingProperties> properties) {
BindingProperties expected = properties.get(0);
for (BindingProperties actual : properties.subList(1, properties.size())) {
if (!expected.hasSameBindingProperties(actual)) {
return false;
}
}
return true;
}
}