Использование аннотации java для анализа строки на основе индексов - PullRequest
1 голос
/ 10 марта 2020

Я пытаюсь разобрать строку на основе расположения символов в свойствах, что-то вроде того, что делает внешняя библиотека, такая как beanIo, но без реального использования beanIo (http://beanio.org/2.1/docs/reference/index.html#BuilderApiAndAnnotations)

I хотел бы использовать аннотации, и именно здесь я борюсь, я не думаю, что понимаю их достаточно. Мой вариант использования:

String stringToParse = "0_2_4_MYNAME_MYAGE_";

Объект, который я собираюсь построить после анализа приведенной выше строки, должен выглядеть примерно так:

Record record = new Record(stringToParse); // this should create a key value pairs
/*record = < 
     "Age":  Field{name:"Age",value:"MYAGE", at:13, length:5}
     "Name": Field{name:"Name",value:"MYNAME", at:6, length:6}
>

Я хочу добиться этого с помощью аннотации, хотя я не полностью понимаю, как они читаются или должны быть прочитаны, вот что я имею сейчас:

Моя полевая аннотация

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface  Field {
    public String name();
    public int at();
    public int length();
    public String value() default "[unassigned]"; //  should be determined using the other values, not passed-in
}

Моя запись аннотации:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Record {
  //Not sure what should goes here. Maybe: public HashMap<String, Field> record
}

Вот как я использую его в классе

@Record
public class PersonInfoLine {
   @Field(at = 5, length = 6)
   private String name;

   @Field(at = 13, length = 5)
   private String age;
}

Опять же, когда я создаю экземпляр PersonInfoLine со строкой, я хотел бы получить "name" и "age", что-то вроде:

String stringToParse = "0_2_4_MYNAME_MYAGE_";

PersonInfoLine personInfoLine = new PersonInfoLine(stringToParse);
String name = personInfoLine.record.get("name").value; //MYNAME
String age = personInfoLine.record.get("age").value; //MYAGE

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

Ответы [ 2 ]

0 голосов
/ 11 марта 2020

Это то, что я закончил, пожалуйста, не стесняйтесь комментировать возможные улучшения:

Я бросил класс записи и получил только аннотацию 'Field', я переименовал его в 'LineField', чтобы обойти конфликт с собственным классом 'Field'

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface  LineField {
    public int at();
    public int length();
}

Вызвана служебная функция из моего потребительского класса для создания карты fieldName-fieldValue

public class Person {
    private static Field[] fields = BatchDetail2.class.getDeclaredFields();

    @LineField(at = 0, length = 8, literal = "6")
    private String name;

    @LineField(at = 12, length = 2)
    private String age;

    private  HashMap<String, String> fieldNameValueMap;


    public BatchDetail2(String personLine){ //personLine = "SAMUEL__234_31";
        fieldNameValueMap = LineProcessorUtil.getFieldValueMap(fields, personLine);
        name = fieldNameValueMap.get("recordTypeCode"); //SAMUEL__
        age = fieldNameValueMap.get("dfiAccountNumber"); //31

    }

}

My utiltyClass:

public class LineProcessorUtil {

    public static String getFieldValue(LineField field, String rawString){
        int startIndex = field.at();
        int endIndex = startIndex + field.length();
        StringBuilder sb = new StringBuilder(rawString);
        return sb.substring(startIndex, endIndex);
    }

    public static HashMap<String, String> getFieldValueMap(Field[] fields, String rawString){
        HashMap<String, String> map = new HashMap<>();

        for(Field field:fields){
            if(field.isAnnotationPresent(LineField.class)){
                String fieldName = field.getName();
                LineField lineField = field.getAnnotation(LineField.class);
                String fieldValue = getFieldValue(lineField, rawString);
                map.put(fieldName, fieldValue);

            }
        }

        return map;
    }
}
0 голосов
/ 10 марта 2020

Это плохой дизайн для того, что вы пытаетесь сделать. Если вы собираетесь скомпилировать такие вещи в коде, вам лучше создать утилиту для непосредственного анализа этих значений. Вы ничего не можете с помощью аннотаций в этом контексте. Что-то вроде этого гораздо проще читать, понимать и поддерживать:

public static void main(String [] args) {
    System.out.println(resolveValue("0_2_4_MYNAME_MYAGE_", 6, 6, "MUD"));
    System.out.println(resolveValue("", 6, 6, "MUD"));
    System.out.println(resolveValue("0_2_4_MYNAME_MYAGE_", 13, 5, "DIRT"));
    System.out.println(resolveValue("0_2_4_MYNAME_", 13, 5, "DIRT"));
}

private static String resolveValue(String data, int start, int length, String defaultValue) {
    try {
        return data.substring(start, start + length);
    } catch (Exception e) {

    }
    return defaultValue;
}
...