// Copyright 2017 The Nomulus Authors. All Rights Reserved. // // 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 google.registry.tools.params; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import java.util.Map; import org.joda.money.CurrencyUnit; /** * Combined converter and validator class for key-value map JCommander argument strings. * *

These strings have the form {@code =,[=]*} where * {@code } and {@code } are strings that can be parsed into instances of some key * type {@code K} and value type {@code V}, respectively. This class converts a string into an * ImmutableMap mapping {@code K} to {@code V}. Validation and conversion share the same logic; * validation is just done by attempting conversion and throwing exceptions if need be. * *

Subclasses must implement parseKey() and parseValue() to define how to parse {@code } * and {@code } into {@code K} and {@code V}, respectively. * * @param instance key type * @param instance value type */ public abstract class KeyValueMapParameter extends ParameterConverterValidator> { public KeyValueMapParameter(String messageForInvalid) { super(messageForInvalid); } public KeyValueMapParameter() { super("Not formatted correctly."); } /** Override to define how to parse rawKey into an object of type K. */ protected abstract K parseKey(String rawKey); /** Override to define how to parse rawValue into an object of type V. */ protected abstract V parseValue(String rawValue); /** Override to perform any post-processing on the map. */ protected ImmutableMap processMap(ImmutableMap map) { return map; } @Override public final ImmutableMap convert(String keyValueMapString) { ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); if (!Strings.isNullOrEmpty(keyValueMapString)) { for (Map.Entry entry : Splitter.on(',').withKeyValueSeparator('=').split(keyValueMapString).entrySet()) { builder.put(parseKey(entry.getKey()), parseValue(entry.getValue())); } } return processMap(builder.build()); } /** Combined converter and validator class for string-to-string Map argument strings. */ public static class StringToStringMap extends KeyValueMapParameter { @Override protected String parseKey(String rawKey) { return rawKey; } @Override protected String parseValue(String value) { return value; } } /** Combined converter and validator class for string-to-integer Map argument strings. */ public static class StringToIntegerMap extends KeyValueMapParameter { @Override protected String parseKey(String rawKey) { return rawKey; } @Override protected Integer parseValue(String value) { return Integer.parseInt(value); } } /** Combined converter and validator class for currency unit-to-string Map argument strings. */ public static class CurrencyUnitToStringMap extends KeyValueMapParameter { @Override protected CurrencyUnit parseKey(String rawKey) { return CurrencyUnit.of(rawKey); } @Override protected String parseValue(String value) { return value; } } }