/* * Licensed to Elasticsearch under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch licenses this file to you 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.elasticsearch.common.xcontent; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.collect.Tuple; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * Registry for looking things up using ParseField semantics. */ public class ParseFieldRegistry<T> { private final Map<String, Tuple<ParseField, T>> registry = new HashMap<>(); private final String registryName; /** * Build the registry. * @param registryName used for error messages */ public ParseFieldRegistry(String registryName) { this.registryName = registryName; } /** * All the names under which values are registered. Expect this to be used mostly for testing. */ public Set<String> getNames() { return registry.keySet(); } /** * Register a parser. */ public void register(T value, String name) { register(value, new ParseField(name)); } /** * Register a parser. */ public void register(T value, ParseField parseField) { Tuple<ParseField, T> parseFieldParserTuple = new Tuple<>(parseField, value); for (String name: parseField.getAllNamesIncludedDeprecated()) { Tuple<ParseField, T> previousValue = registry.putIfAbsent(name, parseFieldParserTuple); if (previousValue != null) { throw new IllegalArgumentException("[" + previousValue.v2() + "] already registered for [" + registryName + "][" + name + "] while trying to register [" + value + "]"); } } } /** * Lookup a value from the registry by name while checking that the name matches the ParseField. * * @param name The name of the thing to look up. * @return The value being looked up. Never null. * @throws ParsingException if the named thing isn't in the registry or the name was deprecated and deprecated names aren't supported. */ public T lookup(String name, XContentLocation xContentLocation) { T value = lookupReturningNullIfNotFound(name); if (value == null) { throw new ParsingException(xContentLocation, "no [" + registryName + "] registered for [" + name + "]"); } return value; } /** * Lookup a value from the registry by name while checking that the name matches the ParseField. * * @param name The name of the thing to look up. * @return The value being looked up or null if it wasn't found. * @throws ParsingException if the named thing isn't in the registry or the name was deprecated and deprecated names aren't supported. */ public T lookupReturningNullIfNotFound(String name) { Tuple<ParseField, T> parseFieldAndValue = registry.get(name); if (parseFieldAndValue == null) { return null; } ParseField parseField = parseFieldAndValue.v1(); T value = parseFieldAndValue.v2(); boolean match = parseField.match(name); //this is always expected to match, ParseField is useful for deprecation warnings etc. here assert match : "ParseField did not match registered name [" + name + "][" + registryName + "]"; return value; } }