/* * Copyright 2013 the original author or authors. * * 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 org.springframework.xd.module.options; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.PropertySource; import org.springframework.validation.BindException; import org.springframework.validation.FieldError; import org.springframework.validation.MapBindingResult; /** * An implementation of {@link ModuleOptionsMetadata} that only knows how to list options and does not support advanced * facilities such as derived options, profile activation or validation. * * @author Eric Bottard * @author David Turanski */ public class SimpleModuleOptionsMetadata implements ModuleOptionsMetadata { private Map<String, ModuleOption> options = new LinkedHashMap<String, ModuleOption>(); public void add(ModuleOption option) { if (option.getDefaultValue() != null) { validateByType(option, option.getDefaultValue().toString()); } options.put(option.getName(), option); } @Override public Iterator<ModuleOption> iterator() { return options.values().iterator(); } @Override public ModuleOptions interpolate(final Map<String, String> raw) throws BindException { MapBindingResult bindingResult = new MapBindingResult(new HashMap<String, String>(), "options"); for (String provided : raw.keySet()) { if (!options.containsKey(provided)) { bindingResult.addError(new FieldError("options", provided, String.format( "Module option '%s' does not exist", provided))); } } if (bindingResult.hasErrors()) { throw new BindException(bindingResult); } ModuleOptions moduleOptions = new ModuleOptions() { @Override public EnumerablePropertySource<?> asPropertySource() { // Return a property source with only the intersection // between declared properties and actual provided values return new EnumerablePropertySource<Object>(this.toString(), this) { @Override public Object getProperty(String name) { ModuleOption option = options.get(name); if (option != null) { String provided = raw.get(name); if (provided != null) { validateByType(option, provided); return provided; } else { return option.getDefaultValue(); } } // option is not in the allowed list else { return null; } } @Override public String[] getPropertyNames() { return options.keySet().toArray(new String[options.size()]); } }; } }; // Validate option values PropertySource<?> ps = moduleOptions.asPropertySource(); for (String name : options.keySet()) { ps.getProperty(name); } return moduleOptions; } /** * @param option option metadata * @param value the value as String */ private void validateByType(ModuleOption option, String value) { if (value == null || option.getType() == null) { return; } // Boolean conversion accepts any string, so need to check explicit values if (boolean.class.getName().equals(option.getType()) || Boolean.class.getName().equals(option.getType())) { if (!(value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false") || value.equals("1") || value.equals("0"))) { throw new RuntimeException(String.format( "The value '%s' is the wrong type for option '%s'. The required type is %s.", value, option.getName(), option.getType())); } } else { try { if (int.class.getName().equals(option.getType()) || Integer.class.getName().equals(option.getType())) { Integer.parseInt(value); } else if (float.class.getName().equals(option.getType()) || Float.class.getName().equals(option.getType())) { Float.parseFloat(value); } else if (double.class.getName().equals(option.getType()) || Double.class.getName().equals(option.getType())) { Double.parseDouble(value); } else if (short.class.getName().equals(option.getType()) || Short.class.getName().equals(option.getType())) { Short.parseShort(value); } } catch (NumberFormatException e) { //TODO: SpringXDException not available to this library throw new RuntimeException(String.format( "The value '%s' is the wrong type for option '%s'. The required type is %s.", value, option.getName(), option.getType())); } } } }