/* * 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.thirdparty.guava.common.collect.ListMultimap; import com.google.gwt.thirdparty.guava.common.collect.Maps; import com.google.gwt.thirdparty.guava.common.collect.Sets; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.Map.Entry; import java.util.SortedMap; import java.util.SortedSet; /** * A typed map of deferred binding properties. */ public class Properties { private final SortedSet<BindingProperty> bindingProperties = Sets.newTreeSet(); private final SortedSet<ConfigurationProperty> configurationProperties = Sets.newTreeSet(); private final SortedMap<String, Property> map = Maps.newTreeMap(); /** * Adds a previously created deferred-binding property. */ public void addBindingProperty(BindingProperty bindingProperty) { bindingProperties.add(bindingProperty); } /** * Creates the specified deferred-binding property, or returns an existing one * by the specified name if present. */ public BindingProperty createBinding(String name) { BindingProperty prop = create(name, BindingProperty.class); bindingProperties.add(prop); return prop; } /** * Creates the specified configuration property, or returns an existing one by * the specified name if present. */ public ConfigurationProperty createConfiguration(String name, boolean allowMultipleValues) { ConfigurationProperty prop = create(name, allowMultipleValues, ConfigurationProperty.class); configurationProperties.add(prop); return prop; } public Property find(String name) { return map.get(name); } /** * Returns the property if (and only if) it's a BindingProperty, otherwise null. */ public BindingProperty findBindingProp(String propName) { Property p = map.get(propName); if (p instanceof BindingProperty) { return (BindingProperty) p; } else { return null; } } /** * Returns the property if (and only if) it's a ConfigurationProperty, otherwise null. */ public ConfigurationProperty findConfigProp(String propName) { Property p = map.get(propName); if (p instanceof ConfigurationProperty) { return (ConfigurationProperty) p; } else { return null; } } /** * Gets all deferred binding properties in sorted order. */ public SortedSet<BindingProperty> getBindingProperties() { return bindingProperties; } public SortedSet<ConfigurationProperty> getConfigurationProperties() { return configurationProperties; } public void setProperties(ListMultimap<String, String> properties) { for (Entry<String, Collection<String>> property : properties.asMap().entrySet()) { String propertyName = property.getKey(); Collection<String> propertyValues = property.getValue(); BindingProperty bindingProp = findBindingProp(propertyName); ConfigurationProperty configProp = findConfigProp(propertyName); if (bindingProp != null) { bindingProp.setValues(bindingProp.getRootCondition(), propertyValues.toArray(new String[propertyValues.size()])); } else if (configProp != null) { if (configProp.allowsMultipleValues()) { configProp.clear(); for (String propertyValue : propertyValues) { configProp.addValue(propertyValue); } } else { String firstValue = propertyValues.iterator().next(); if (propertyValues.size() > 1) { throw new IllegalArgumentException( "Attemp to set multiple values to a single-valued configuration property '" + propertyName + "'."); } configProp.setValue(firstValue); } } else { throw new IllegalArgumentException("Unknown property: " + propertyName); } } } private <T extends Property> T create(String name, boolean flag, boolean useFlagArgument, Class<T> clazz) { if (clazz == null) { throw new NullPointerException("clazz"); } else if (name == null) { throw new NullPointerException("name"); } Property property = find(name); if (property != null) { try { return clazz.cast(property); } catch (ClassCastException e) { throw new IllegalArgumentException("Cannot create property " + name + " because one of another type (" + property.getClass().getSimpleName() + ") already exists."); } } Exception ex; try { T newInstance; if (useFlagArgument) { newInstance = clazz.getConstructor(String.class, boolean.class).newInstance( name, flag); } else { newInstance = clazz.getConstructor(String.class).newInstance(name); } map.put(name, newInstance); return newInstance; } catch (NoSuchMethodException e) { ex = e; } catch (InstantiationException e) { ex = e; } catch (IllegalAccessException e) { ex = e; } catch (InvocationTargetException e) { ex = e; } throw new RuntimeException("Unable to create Property instance", ex); } private <T extends Property> T create(String name, boolean flag, Class<T> clazz) { return create(name, flag, true, clazz); } private <T extends Property> T create(String name, Class<T> clazz) { return create(name, false, false, clazz); } }