Использование конфигурации Apache Commons для интерполяции переменных, то есть $ {variable}, со списком значений в файле свойств - PullRequest
5 голосов
/ 23 февраля 2012

Я использую конфигурацию Apache Commons для чтения файла свойств, и я прекрасно могу выполнять интерполяцию переменных, а также извлекать многозначные свойства в виде списка. Однако я не смог правильно загрузить свойство, имеющее несколько значений, одно из которых является ссылкой (интерполяция переменной) на другое многозначное свойство.

Вот пример моего файла свойств (я также пытался использовать синтаксис через запятую):

doc.mime=application/msword
doc.mime=application/vnd.openxmlformats-officedocument.wordprocessingml.document
doc.mime=${office.mime}

office.mime=application/x-tika-msoffice
office.mime=application/x-tika-ooxml

А как я из него прочитал:

Configuration config = new PropertiesConfiguration("myFile");
final String[] mimesArray = config.getStringArray("doc.mime");
for(String mime : mimesArray) System.out.println(mime);
final List<Object> mimesList = config.getList("doc.mime");
System.out.println(mimesList);

Это содержимое, которое я получаю любым способом (getStringArray и getList):

[application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/x-tika-msoffice]

Это отличается от того, что я ожидал: полное содержание doc.mime и office.mime

Кто-нибудь знает, возможно ли интерполировать весь список значений в моем другом списке? И если да, то как это делается?

Ответы [ 2 ]

4 голосов
/ 23 февраля 2012

Что делает конфигурация Commons

Как вы узнали: при интерполяции многозначного свойства Commons Configuration будет разрешать только первое значение этого свойства.См. Код в AbstractConfiguration # resolContainerStore (), строка 1177 .

Я обнаружил некоторые связанные проблемы:

CONFIGURATION-28 : кто-то хочет (иполучает) полную противоположность того, что вы хотите: только первое значение в многозначном свойстве.

CONFIGURATION-55 : дополнительные сведения об интерполяции многозначных свойств:

вероятно, нет правильного решения этой проблемы, потому что ожидаемые результаты сильно зависят от конкретного варианта использования

Обходной путь: Объедините два списка в коде

Определенно проще, чем Настройка интерполяции :

List<Object> mimesList = config.getList("doc.mime");
List<Object> officeList = config.getList("office.mime");
mimesList.addAll(officeList);
System.out.println(mimesList);

Поднять эту проблему с проектом конфигурации Commons

Изменение всей переменнойСистема интерполяции, вероятно, сложная.Но они могли хотя бы уточнить документацию.

1 голос
/ 02 июля 2014

Ну, мне нужна была эта функция для: привязки нескольких значений к свойствам и возможности извлечения их всех даже путем интерполяции.

Итак, я написал собственный класс интерполяции и конфигурацию пользовательских свойств.Хорошо работает даже со значениями с обратной косой чертой и разделителем по умолчанию.

Итак, здесь пользовательский класс интерполяции:

Класс CustomInterPolation

public class CustomInterpolation extends StrLookup {

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.commons.lang.text.StrLookup#lookup(java.lang.String)
     */
    @Override
    public String lookup(String arg0) {

        String result = null;

        // Get the default delimiter.
        String delimiter = ""
                + PropertiesConfiguration.getDefaultListDelimiter();

        try {

            // Load the properties file.
            Configuration config = new PropertiesConfiguration(
                    "ressources/macro.properties");

            if (config.containsKey(arg0)) {

                // Get all values associated with the propertie.
                ArrayList<Object> values = (ArrayList<Object>) config
                        .getList(arg0);

                StringBuilder strBuild = new StringBuilder();
                Iterator<Object> itr = values.iterator();

                while (itr.hasNext()) {

                    // Append the property to the string.
                    strBuild.append((String) itr.next());

                    if (itr.hasNext()) {
                        // Adds the delimiter and backslash in order to retrieve
                        // all properties later.
                        strBuild.append("\\" + delimiter);
                    }

                }
                result = strBuild.toString();
            }

        } catch (ConfigurationException e) {
            // Nothing to do here...
        }
        // return null or all values concatenated
        return result;
    }

}

Теперь,Чтобы правильно использовать этот класс customInterpolation, нам нужно использовать конфигурацию пользовательских свойств:

Класс CustomPropertiesConfiguration

/**
 * The Class CustomPropertiesConfiguration.
 */
public class CustomPropertiesConfiguration extends PropertiesConfiguration {

    private String delimiter;

    /**
     * Instantiates a new custom properties configuration.
     */
    public CustomPropertiesConfiguration() {
        super();
        delimiter = PropertiesConfiguration.getDefaultListDelimiter()
                + "";
    }

    /**
     * Instantiates a new custom properties configuration.
     *
     * @param file the file
     * @throws ConfigurationException the configuration exception
     */
    public CustomPropertiesConfiguration (File file) throws ConfigurationException{
        super(file);
        delimiter = PropertiesConfiguration.getDefaultListDelimiter()
                + "";
    }

    /**
     * Instantiates a new custom properties configuration.
     *
     * @param fileName the file name
     * @throws ConfigurationException the configuration exception
     */
    public CustomPropertiesConfiguration(String fileName) throws ConfigurationException {
        super(fileName);
        delimiter = PropertiesConfiguration.getDefaultListDelimiter()
                + "";
    }

    /**
     * Instantiates a new custom properties configuration.
     *
     * @param url the url
     * @throws ConfigurationException the configuration exception
     */
    public CustomPropertiesConfiguration(URL url) throws ConfigurationException{
        super(url);
        delimiter = PropertiesConfiguration.getDefaultListDelimiter()
                + "";
    }

    /* (non-Javadoc)
     * @see org.apache.commons.configuration.AbstractConfiguration#getList(java.lang.String)
     */
    @Override
    public List<Object> getList(String key) {

        // Get the list of values associated with the property
        // Implicit call to the custom interpolation class
        List<Object> properties = super.getList(key);


        ArrayList<Object> extendedProperties = new ArrayList<Object>();

        Iterator<Object> itrProperties = properties.iterator();
        // Go through all properties and retrieve values concatenated by the custom interpolation
        while (itrProperties.hasNext()) {

            String propertie = (String) itrProperties.next();

            if (propertie.contains(delimiter)) {

                //Split concatenated values.
                String[] extendedPropertiesTab = propertie.split("\\\\"+delimiter);

                // Add the retrieved values to the list of values.
                for (int i = 0; i< extendedPropertiesTab.length; ++i){
                    extendedProperties.add(extendedPropertiesTab[i]);
                }

            } else {
                extendedProperties.add(propertie);
            }

        }
        return extendedProperties;
    }

} 

А здесь небольшой основной класс:

public class TestMacro {

    /**
     * @param args
     */
    public static void main(String[] args) {

        // Load properties file :

        try {

            // Add an interpolation to the configuration.
            // The string "custom" will be used to find value to interpolate
            // with the custom interpolation
            ConfigurationInterpolator.registerGlobalLookup("custom",
                    new CustomInterpolation());

            // Set the properties configuration.
            Configuration config = new CustomPropertiesConfiguration(
                    "ressources/macro.properties");

            String baseProp = "base.prop";
            String firstProp = "first.prop";
            String secondProp = "second.prop";

            ArrayList<Object> values = (ArrayList<Object>) config
                    .getList(baseProp);
            System.out.println(baseProp + "=>");
            for (int i = 0; i < values.size(); ++i) {
                System.out.println("[" + i + "]" + values.get(i));
            }

            System.out.println();

            values = (ArrayList<Object>) config.getList(firstProp);
            System.out.println(firstProp + "=>");
            for (int i = 0; i < values.size(); ++i) {
                System.out.println("[" + i + "]" + values.get(i));
            }

            System.out.println();

            values = (ArrayList<Object>) config.getList(secondProp);
            System.out.println(secondProp + "=>");
            for (int i = 0; i < values.size(); ++i) {
                System.out.println("[" + i + "]" + values.get(i));
            }

        } catch (ConfigurationException e) {
            e.printStackTrace();
        }

    }
}

Для тестов я использовал следующий файл свойств:

base.prop = /base, /root\\\\\\\\, t\\,t\\,t\\,t\\,
first.prop = ${custom:base.prop}, /first\\,/base
second.prop = ${custom:first.prop}, /second

И я получаю следующий вывод:

base.prop=>
[0]/base
[1]/root\\
[2]t,t,t,t,

first.prop=>
[0]/base
[1]/root\\
[2]t,t,t,t,
[3]/first,/base

second.prop=>
[0]/base
[1]/root\\
[2]t,t,t,t,
[3]/first,/base
[4]/second

Как видите, решениевозможность обрабатывать свойства 'значения с обратной косой чертой и разделителем по умолчанию', '.Некоторые шаблоны, содержащие эти два элемента, могут обрабатываться некорректно, но это решение должно обрабатывать основные значения.

...