Как создать динамический интерфейс с файлом свойств во время компиляции?

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

Файл свойств

A=Apple
B=Bannana
C=Cherry

Должен генерировать следующий интерфейс

interface Properties{
public static final String A = "A" // keys
public static final String B = "B"; 
public static final String C = "C"; 

}

Итак, в моем коде приложения

String a_value = PROP.getString(Properties.A);

person Njax3SmmM2x2a0Zf7Hpd    schedule 19.08.2014    source источник
comment
Похоже, вы будете изучать Maven.   -  person Unihedron    schedule 19.08.2014
comment
Считали ли вы, что изменение файла свойств приведет к ошибкам компиляции в вашем приложении? Лично я бы один раз сгенерировал интерфейс Properties, а затем поддерживал бы его вручную. Возможно, я бы использовал перечисления вместо интерфейса.   -  person Absurd-Mind    schedule 19.08.2014


Ответы (2)


В программировании и не только в нем есть старое правило: если что-то выглядит красиво, то, скорее всего, так и надо делать.

Такой подход не выглядит хорошим, с моей точки зрения.

Первое:

Не объявляйте константы в интерфейсах. Это нарушает подход инкапсуляции. Ознакомьтесь с этой статьей: http://en.wikipedia.org/wiki/Constant_interface

Второе:

Используйте префикс для имен ваших свойств, которые являются особыми, например: key_

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


ОБНОВЛЕНИЕ

Предположим, мы создаем огромный файл свойств в процессе компиляции, используя наш скрипт Apache Ant.

Например, пусть файл свойств (myapp.properties) выглядит так:

key_A = Apple
key_B = Banana
key_C = Cherry
anotherPropertyKey1 = blablabla1
anotherPropertyKey2 = blablabla2

имена наших специальных свойств, которые мы хотим обрабатывать, начинаются с префикса key_.

Итак, пишем следующий код (обратите внимание, он не оптимизирован, это просто проверка концепции):

package propertiestest;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;


public class PropertiesTest {

  public static void main(String[] args) throws IOException {
       final String PROPERTIES_FILENAME = "myapp.properties";      

       SpecialPropertyKeysStore spkStore = 
                            new SpecialPropertyKeysStore(PROPERTIES_FILENAME);

       System.out.println(Arrays.toString(spkStore.getKeysArray()));

   }
}


class SpecialPropertyKeysStore {

    private final Set<String> keys;

    public SpecialPropertyKeysStore(String propertiesFileName) 
                                    throws FileNotFoundException, IOException {


        // prefix of name of a special property key
        final String KEY_PREFIX = "key_";        

    Properties propertiesHandler = new Properties();
        keys = new HashSet<>();

    try (InputStream input = new FileInputStream(propertiesFileName)) {

            propertiesHandler.load(input);

            Enumeration<?> enumeration = propertiesHandler.propertyNames();
            while (enumeration.hasMoreElements()) {
                String key = (String) enumeration.nextElement();
                if (key.startsWith(KEY_PREFIX)) {
                    keys.add(key);
                }
            }
    }        
    }

    public boolean isKeyPresent(String keyName) {
        return keys.contains(keyName);
    }

    public String[] getKeysArray() {
        String[] strTypeParam = new String[0];

        return keys.toArray(strTypeParam);
    }
}

Класс SpecialPropertyKeysStore фильтрует и собирает в свой экземпляр все специальные ключи.

И вы можете получить массив этих ключей или проверить, присутствует ли ключ или нет.

Если вы запустите этот код, вы получите:

[key_C, key_B, key_A]

Это строковое представление возвращаемого массива со специальными именами ключей.

Измените этот код, если хотите, чтобы он соответствовал вашим требованиям.

person Community    schedule 19.08.2014
comment
вы можете изменить свой файл свойств во время компиляции, например, используя Apache Ant. И в этом случае вам не нужно менять свой код. Просто измените файл свойств по своему усмотрению. Ваш код будет извлекать все свойства, используя описанный подход. - person ; 19.08.2014
comment
ответ не ясен. что вы имеете в виду перебирать ключи и извлекать ключи? - person Njax3SmmM2x2a0Zf7Hpd; 19.08.2014
comment
в классе Properties есть метод названия свойств. Вызовите его, чтобы получить Enumeration с именами свойств. . Пройдитесь по этому перечислению, чтобы получить имена свойств и обработать их. Чтобы убедиться, что имя свойства начинается с key_ (например), используйте String.startsWith. - person ; 19.08.2014
comment
о, это обычная процедура для получения собственности, не так ли? В этом случае ключ свойств безумно подвержен ошибкам. Поэтому мы хотели, чтобы он был сгенерирован в поле интерфейса, чтобы мы не делали ошибок с ключами жесткого кодирования. - person Njax3SmmM2x2a0Zf7Hpd; 19.08.2014
comment
Давайте продолжим обсуждение в чате. - person Njax3SmmM2x2a0Zf7Hpd; 19.08.2014

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

  • задокументируйте эти свойства, поскольку они будут представлены элементом java + javadocs
  • ссылается на эти свойства в вашем коде, поскольку они будут воспроизводить старые константы Java, и компилятор будет иметь полное представление о них. Их рефакторинг также был бы возможен, в то время как это было бы невозможно с автоматическими именами.

Вы также можете использовать перечисления или создать специальный класс Property с именем в качестве единственного и конечного поля. Тогда вам нужен только метод get, который будет принимать Properties, Map или что-то еще.

Что касается вашего запроса, вы можете выполнить код с помощью maven-exec-плагин.

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

  • преобразовать ключ в допустимый идентификатор Java (вы можете использовать isJavaIdentifierStart и isJavaIdentifierPart для замены недействительного символа на _)
  • напишите свой класс/интерфейс/все, что вам нравится, используя старую простую Java (и не забудьте избежать возможных двойных кавычек или обратной косой черты!)

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

Тем не менее, я бы действительно не стал этого делать и использовал POJO, загруженный любыми потребностями (CDI, Spring, статическая инициализация и т. д.).

person NoDataFound    schedule 19.08.2014