Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2008 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.linker.PropertyProviderGenerator;
import com.google.gwt.dev.util.collect.IdentityHashSet;
import com.google.gwt.dev.util.collect.Lists;
import com.google.gwt.dev.util.collect.Sets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Map.Entry;
import java.util.regex.Pattern;
/**
* Represents a single named deferred binding or configuration property that can
* answer with its value. The BindingProperty maintains two sets of values, the
* "defined" set and the "allowed" set. The allowed set must always be a subset
* of the defined set.
*/
public class BindingProperty extends Property {
public static final String GLOB_STAR = "*";
private static final String EMPTY = "";
private List> collapsedValues = Lists.create();
private final Map> conditionalValues = new LinkedHashMap>();
private final SortedSet definedValues = new TreeSet();
private String fallback;
private HashMap>> fallbackValueMap;
private HashMap> fallbackValues = new HashMap>();
private PropertyProvider provider;
private Class extends PropertyProviderGenerator> providerGenerator;
private final ConditionAll rootCondition = new ConditionAll();
{
conditionalValues.put(rootCondition, new TreeSet());
}
public BindingProperty(String name) {
super(name);
fallback = EMPTY;
}
/**
* Add an equivalence set of property values.
*/
public void addCollapsedValues(String... values) {
// Sanity check caller
for (String value : values) {
if (value.contains(GLOB_STAR)) {
// Expanded in normalizeCollapsedValues()
continue;
} else if (!definedValues.contains(value)) {
throw new IllegalArgumentException(
"Attempting to collapse unknown value " + value);
}
}
// We want a mutable set, because it simplifies normalizeCollapsedValues
SortedSet temp = new TreeSet(Arrays.asList(values));
collapsedValues = Lists.add(collapsedValues, temp);
}
public void addDefinedValue(Condition condition, String newValue) {
definedValues.add(newValue);
SortedSet set = conditionalValues.get(condition);
if (set == null) {
set = new TreeSet();
set.addAll(conditionalValues.get(rootCondition));
conditionalValues.put(condition, set);
}
set.add(newValue);
}
/**
* Adds fall back value to given property name.
* @param value the property value.
* @param fallbackValue the fall back value for given property value.
*/
public void addFallbackValue(String value, String fallbackValue) {
LinkedList values = fallbackValues.get(fallbackValue);
if (values == null) {
values = new LinkedList();
fallbackValues.put(fallbackValue, values);
}
values.addFirst(value);
}
/**
* Returns the set of allowed values in sorted order when a certain condition
* is satisfied.
*/
public String[] getAllowedValues(Condition condition) {
Set allowedValues = conditionalValues.get(condition);
return allowedValues.toArray(new String[allowedValues.size()]);
}
public List> getCollapsedValues() {
return collapsedValues;
}
public Map> getConditionalValues() {
return Collections.unmodifiableMap(conditionalValues);
}
/**
* If the BindingProperty has exactly one value across all conditions and
* permutations, return that value otherwise return null.
*/
public String getConstrainedValue() {
String constrainedValue = null;
for (SortedSet allowedValues : conditionalValues.values()) {
if (allowedValues.size() != 1) {
return null;
} else if (constrainedValue == null) {
constrainedValue = allowedValues.iterator().next();
} else if (!constrainedValue.equals(allowedValues.iterator().next())) {
return null;
}
}
return constrainedValue;
}
/**
* Returns the set of defined values in sorted order.
*/
public String[] getDefinedValues() {
return definedValues.toArray(new String[definedValues.size()]);
}
/**
* Returns the fallback value for this property, or the empty string if none.
*
* @return the fallback value
*/
public String getFallback() {
return fallback;
}
/**
* Returns the map of values to fall back values. the list of fall
* back values is in decreasing order of preference.
* @return map of property value to fall back values.
*/
public Map>> getFallbackValuesMap() {
if (fallbackValueMap == null) {
HashMap>> valuesMap = new HashMap>>();
// compute closure of fall back values preserving order
for (Entry> e : fallbackValues.entrySet()) {
String from = e.getKey();
LinkedList> alternates = new LinkedList>();
valuesMap.put(from, alternates);
LinkedList childList = fallbackValues.get(from);
LinkedHashSet children = new LinkedHashSet();
children.addAll(childList);
while (children != null && children.size() > 0) {
alternates.add(children);
LinkedHashSet newChildren = new LinkedHashSet();
for (String child : children) {
childList = fallbackValues.get(child);
if (null == childList) {
continue;
}
for (String val : childList) {
newChildren.add(val);
}
}
children = newChildren;
}
}
fallbackValueMap = valuesMap;
}
return fallbackValueMap;
}
/**
* Returns the first legal value for this property that can be found.
*/
public String getFirstLegalValue() {
if (getConstrainedValue() != null) {
return getConstrainedValue();
} else if (getDefinedValues().length > 0) {
return getDefinedValues()[0];
}
return fallback;
}
public PropertyProvider getProvider() {
return provider;
}
/**
* @return the provider generator class, or null if none.
*/
public Class extends PropertyProviderGenerator> getProviderGenerator() {
return providerGenerator;
}
public Set getRequiredProperties() {
Set toReturn = Sets.create();
for (Condition cond : conditionalValues.keySet()) {
toReturn = Sets.addAll(toReturn, cond.getRequiredProperties());
}
return toReturn;
}
public ConditionAll getRootCondition() {
return rootCondition;
}
/**
* Returns true if the supplied value is legal under some condition.
*/
public boolean isAllowedValue(String value) {
for (Set values : conditionalValues.values()) {
if (values.contains(value)) {
return true;
}
}
return false;
}
/**
* Returns true if the value was previously provided to
* {@link #addDefinedValue(Condition,String)}.
*/
public boolean isDefinedValue(String value) {
return definedValues.contains(value);
}
/**
* Returns true if the value of this BindingProperty is always
* derived from other BindingProperties. That is, for each Condition in the
* BindingProperty, there is exactly one allowed value.
*/
public boolean isDerived() {
for (Set allowedValues : conditionalValues.values()) {
if (allowedValues.size() != 1) {
return false;
}
}
return true;
}
/**
* Set the currently allowed values. The values provided must be a subset of
* the currently-defined values.
*
* @throws IllegalArgumentException if any of the provided values were not
* provided to {@link #addDefinedValue(Condition,String)}.
*/
public void setAllowedValues(Condition condition, String... values) {
SortedSet temp = new TreeSet(Arrays.asList(values));
if (!definedValues.containsAll(temp)) {
throw new IllegalArgumentException(
"Attempted to set an allowed value that was not previously defined");
}
// XML has a last-one-wins semantic which we reflect in our evaluation order
if (condition == rootCondition) {
/*
* An unconditional set-property would undo any previous conditional
* setters, so we can just clear out this map.
*/
conditionalValues.clear();
} else {
/*
* Otherwise, we'll just ensure that this condition is moved to the end.
*/
conditionalValues.remove(condition);
}
conditionalValues.put(condition, temp);
}
public void setFallback(String token) {
fallback = token;
}
public void setProvider(PropertyProvider provider) {
this.provider = provider;
}
/**
* Set a provider generator for this property.
*
* @param generator
*/
public void setProviderGenerator(Class extends PropertyProviderGenerator> generator) {
providerGenerator = generator;
}
/**
* Create a minimal number of equivalence sets, expanding any glob patterns.
*/
void normalizeCollapsedValues() {
if (collapsedValues.isEmpty()) {
return;
}
// Expand globs
for (Set set : collapsedValues) {
// Compile a regex that matches all glob expressions that we see
StringBuilder pattern = new StringBuilder();
for (Iterator it = set.iterator(); it.hasNext();) {
String value = it.next();
if (value.contains(GLOB_STAR)) {
it.remove();
if (pattern.length() > 0) {
pattern.append("|");
}
// a*b ==> (a.*b)
pattern.append("(");
// We know value is a Java ident, so no special escaping is needed
pattern.append(value.replace(GLOB_STAR, ".*"));
pattern.append(")");
}
}
if (pattern.length() == 0) {
continue;
}
Pattern p = Pattern.compile(pattern.toString());
for (String definedValue : definedValues) {
if (p.matcher(definedValue).matches()) {
set.add(definedValue);
}
}
}
// Minimize number of sets
// Maps a value to the set that contains that value
Map> map = new HashMap>();
// For each equivalence set we have
for (SortedSet set : collapsedValues) {
// Examine each original value in the set
for (String value : new LinkedHashSet(set)) {
// See if the value was previously assigned to another set
SortedSet existing = map.get(value);
if (existing == null) {
map.put(value, set);
} else {
// If so, merge the existing set into this one and update pointers
set.addAll(existing);
for (String mergedValue : existing) {
map.put(mergedValue, set);
}
}
}
}
// The values of the maps will now contain the minimal number of sets
collapsedValues = new ArrayList>(
new IdentityHashSet>(map.values()));
// Sort the list
Lists.sort(collapsedValues, new Comparator>() {
public int compare(SortedSet o1, SortedSet o2) {
String s1 = o1.toString();
String s2 = o2.toString();
assert !s1.equals(s2) : "Should not have seen equal sets";
return s1.compareTo(s2);
}
});
}
}