/* * 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; } }