Добавить в список на основе свойства объекта

#java #if-statement #java-stream #filtering

Вопрос:

 private static CodeList prepareChangeObject(CodeList codeList, CodeList existingCodeList, boolean dataExists)
            throws EntityValidationException {
        CodeList UpdatedCodeList = new CodeList();
        BeanUtils.copyProperties(codeList, UpdatedCodeList);
        Set<CodeListData> updatedDataList =UpdatedCodeList.getData().stream().collect(Collectors.toSet());
        updatedDataList.addAll(existingCodeList.getData());
        List<CodeListData> finalData = updatedDataList.stream().collect(
                collectingAndThen(toCollection(() -> new TreeSet<>(comparing(CodeListData::getKey))), ArrayList::new));
        finalData = finalData.stream().filter(data -> {
            if (data.getOperation() == null)
                data.setOperation(MetaConstants.OPERATION_ADD);
            if (null != data.getOperation()) {
                if (data.getOperation().equals(MetaConstants.OPERATION_DELETE) amp;amp; dataExists)
                    exceptionMessagesList.add(
                            new ExceptionMessage("foundation.OperationNotAllowed", new String[] { data.getKey() }));
                if (data.getOperation().equals(MetaConstants.OPERATION_DELETE) amp;amp; !dataExists)
                    return false;
                if (data.getOperation().equals(MetaConstants.OPERATION_ADD))
                    return true;
            }
            return false;

        }).collect(Collectors.toList());
        UpdatedCodeList.setData(finalData);
        if(!CollectionUtils.isEmpty(exceptionMessagesList))
            throw new EntityValidationException(HTTPClientError.BAD_REQUEST, exceptionMessagesList);
        return UpdatedCodeList;
    }
 

1.Описанный выше метод должен возвращать объект изменения на основе указанной операции.

     public static void main(String[] args) throws JsonMappingException, JsonProcessingException, EntityValidationException {
    String jsonPost = "{n"
              "  "id": "temperature101",n"
              "  "descriptions": [n"
              "    {n"
              "      "languageCode": "en",n"
              "      "description": "description",n"
              "      "longDescription": "long description"n"
              "    },n"
              "    {n"
              "      "languageCode": "de",n"
              "      "description": "description",n"
              "      "longDescription": "long description"n"
              "    }n"
              "  ],n"
              "  "dataType": "String",n"
              "  "data": [n"
              "    {n"
              "      "key": "val1",n"
              "      "value": "High"n"
              "    },n"
              "    {n"
              "      "key": "val4",n"
              "      "value": "Medium"n"
              "    },n"
              "    {n"
              "      "key": "val3",n"
              "      "value": "Low"n"
              "    }n"
              "  ]n"
              "}";
    String jsonPatch = "{n"
              "  "id": "temperature101",n"
              "  "descriptions": [n"
              "    {n"
              "      "languageCode": "en",n"
              "      "description": "description1",n"
              "      "longDescription": "long description1"n"
              "    },n"
              "    {n"
              "      "languageCode": "de",n"
              "      "description": "description1",n"
              "      "longDescription": "long description1"n"
              "    }n"
              "  ],n"
              "  "dataType": "String",n"
              "  "data": [n"
              "    {n"
              "      "key": "val1",n"
              "      "value": "High",n"
              "      "operation": "DELETE"n"
              "n"
              "    },n"
              "    {n"
              "      "key": "val4",n"
              "      "value": "Medium",n"
              "      "operation": "DELETE"n"
              "    }n"
              "  ]n"
              "}";
    ObjectMapper mapper = new ObjectMapper();
    CodeList ExistingodeList = mapper.readValue(jsonPost, CodeList.class);
    CodeList currentCodeList = mapper.readValue(jsonPatch, CodeList.class);
    CodeList upDatetedCodeList = prepareChangeObject(currentCodeList, ExistingodeList, false);
    Gson gson = new Gson();
    System.out.println(upDatetedCodeList.toString());
    System.out.println(gson.toJson(upDatetedCodeList));
    
}
 
  1. приведенный выше основной метод проверки кода
 @Data
public class CodeListData {
    
    @Column("ID")
    @JsonIgnore
    private String id;
    
    @Column("KEY")
    private String key;
    
    @Column("VALUE")
    private String value;
    
    @Column("ETAG")
    @JsonIgnore
    private String etag;
    
    @JsonIgnore
    @Column("VERSION")
    @Version
    private Long version;
    
    @Transient
    @JsonProperty(access = Access.WRITE_ONLY)
    private String operation;

}
 
  1. Pojo for reference
 @Data
public class CodeList implements Persistable<String>{

    @NotNull
    @Id
    @Column("ID")
    private String id;
    
    @MappedCollection(idColumn = "ID", keyColumn = "ID_SEQ")
    private List<CodeListDescriptions> descriptions = new ArrayList<>();
    
    @Column("DATA_TYPE")
    private String dataType;
    
    @Column("LENGTH")
    private String length;
    
    @MappedCollection(idColumn = "ID", keyColumn = "ID_SEQ")
    private List<CodeListData> data = new ArrayList<CodeListData>();
    
    @JsonIgnore
    @Column("VERSION")
    private Long version;
    
    @Column("ETAG")
    @JsonIgnore
    private String etag;
    
    @Transient
    @JsonIgnore
    @Setter
    private boolean isInsert;

    @JsonIgnore
    public boolean isNew() {
        return isInsert;
    }
}
 

4.pojo из списка кодов

 @Data
public class CodeListDescriptions{

    @Column("ISO")
    public String languageCode;
    
    @Column("DESCRIPTION")
    public String description;
    
    @Column("LONG_DESCRIPTION")
    public String longDescription;
    
    @Column("ID")
    @JsonIgnore
    private String id;

}
 

5.конечный результат, необходимый только "val3" для того, чтобы присутствовать. Предполагается, что метод удаляет или добавляет на основе операций DELETE или ADD . Проблема в том, что val4 все еще находится в выводе, потому что при создании окончательных данных он предпочитает хранить "val4" данные из существующих, которые не содержат никаких операций. Конечный вывод должен содержать добавленные значения и значения, не указанные в полезной нагрузке, но существующие в первом.

Ответ №1:

он предпочитает хранить val4 из существующих данных, которые не содержат никаких операций

вы выполняете add операцию по умолчанию с помощью этого кода, поэтому независимо от того, существует операция или нет, вы явно задаете ее

 if (data.getOperation() == null)
  data.setOperation(MetaConstants.OPERATION_ADD);
 

Затем вы проверяете это, как

 if (null != data.getOperation()) { // this is always true, because you use the default one line before
  ...
  if (data.getOperation().equals(MetaConstants.OPERATION_ADD))
    return true;
}

 

так что в конце концов финал

 return false;
 

никогда не будет достигнуто.

Комментарии:

1. «не используйте равенства для перечислений», похоже, это строки, для которых equals правильный выбор.

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

Ответ №2:

Вы создаете a Set<CodeListData> как из существующего, так и из обновленного набора данных. CodeListData определяет его equals и hashCode методы во всех полях. Обратите внимание, что Ломбок игнорирует transient поля, но они отличаются от полей с аннотациями @Transient . Таким образом, у вас есть val4 два раза в Set один раз с DELETE операцией и один раз без какой-либо операции. Тот, у DELETE которого есть, будет отфильтрован, но тот, у которого нет операции, будет по умолчанию ADD и останется в SET .

Примечание: Я считаю неудачным называть переменную типа Set чем-либо, что заканчивается List .