/*
* Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
* Copyright [2016-2017] EMBL-European Bioinformatics Institute
*
* 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.ensembl.healthcheck.configurationmanager;
import java.util.Map;
import java.util.Set;
import uk.co.flamingpenguin.jewel.cli.OptionNotPresentException;
/**
* <p>
* Abstract class that provides the methods mockGetMethod and mockIsMethod
* which implement get and is functionality.
* </p>
*
* <p>
* The user has to implement mockDirectGetMethod and mockDirectIsMethod which
* don't deal with aliases for configuration variable names, but instead are
* simple lookup methods in the underlying configuration source.
* </p>
*
* <p>
* Parameters accessed by the configuration objects can appear under different
* names. The reason for this are shortcuts like -c instead of --conf or
* alternative names like output.databases which can't be implemented as a
* get method, because getoutput.databases is an invalid method name. In
* the latter case the get method is called getOutputDatabases and an
* annotation is added to make the configuration object aware that the actual
* name is output.databases. For an example of this, see:
* </p>
*
* @see org.ensembl.healthcheck.configuration.ConfigureDatabases
* @author michael
* @param <T>
*
*/
public abstract class AbstractAliasAwareConfigurationBacking<T> extends AbstractConfigurationBacking<T> {
/**
*
* A Map that maps the name of a variable as a string to a set of Strings
* with all of the possible aliases it can have.
*
* The keys of the map are the variable names in the get methods of the
* configuration interface. So "getFoo" would produce the key "foo" in
* this map.
*
*/
protected final Map<String,Set<String>> canonicalVarName2AllAliases;
/**
*
* A map that maps the name of a configuration variable to the data type
* it is supposed to be in. Supported data types are the elements of the
* enum configurationDataType:
*
*/
protected final Map<String,configurationDataType> canonicalVarName2DataType;
/**
*
* A map that maps the possible aliases for parameters to their canonical
* name.
*
*/
protected final Map<String,String> alias2CanonicalVarName;
/**
* Enumeration of possible return data types for configuration values.
*
*/
public enum configurationDataType {
String, List_Of_Strings
}
public AbstractAliasAwareConfigurationBacking (Class<T> configurationClass) {
canonicalVarName2AllAliases = createVarName2AllAliases (configurationClass);
canonicalVarName2DataType = createVarName2DataType (configurationClass);
alias2CanonicalVarName = createAlias2CanonicalVarName (configurationClass);
}
/**
*
* A method that gets a variable of exactly this name. This method
* is wrapped by mockGetMethod which iterates through all known
* aliases for the variable.
*
* @param varRequested
* @return variable for name
*
*/
abstract protected Object mockDirectGetMethod(String varRequested);
/**
*
* A method that tests whether a variable of this name has been
* declared in the configuration. Again, to be useful, this method
* is wrapped by mockIsMethod which calls this methods for all
* possible aliases.
*
* @param varRequested
* @return true if variable declared
*/
abstract protected boolean mockDirectIsMethod(String varRequested);
/**
* <p>
* Performs the get method for a variable. When a configuration object is
* calles like config.getFoo then the call is dispatched to
* mockGetMethod(foo) from the invoke method.
* </p>
*
* <p>
* This method iterates over all possible names under which this vairable
* could be known by using the canonicalVarName2AllAliases map. For each
* alias it calls the mockDirectIsMethod and the mockDirectGetMethod to
* obtain the actual values.
* </p>
*
* <p>
* mockDirectGetMethod and mockDirectIsMethod are both variants of the
* mockGetMethod and the mockIsMethod which just do a simple lookup in
* whatever the source of information the subclass uses. (e.g. property
* file, system property etc)
* </p>
*
* @param varRequested
* @return mock method
*/
protected Object mockGetMethod(String varRequested) {
Set<String> allAliases = canonicalVarName2AllAliases.get(varRequested);
for (String currentAlias : allAliases) {
if (mockDirectIsMethod(currentAlias)) {
return mockDirectGetMethod(currentAlias);
}
}
throw new OptionNotPresentException(varRequested + " not found!");
}
/**
* <p>
* This is the companion piece of the mockGetMethod for is* method calls.
* </p>
*
* @param varRequested
* @return whether method has been mocked
*
*/
protected boolean mockIsMethod(String varRequested) {
Set<String> allAliases = canonicalVarName2AllAliases.get(varRequested);
for (String currentAlias : allAliases) {
if (mockDirectIsMethod(currentAlias)) {
return true;
}
}
return false;
}
}