How to find differences between two collections - java

I have following DTOs:
#Data
public class PersonDTO implements Diffable<PersonDTO> {
private String id;
private String firstName;
private String lastName;
private List<AddressDTO> addresses;
#Override
public DiffResult diff(PersonDTO personDTO) {
return new DiffBuilder(this, personDTO, SHORT_PREFIX_STYLE)
.append("id", this.id, personDTO.getId())
.append("firstName", this.firstName, personDTO.getFirstName())
.append("lastName", this.lastName, personDTO.getLastName())
.append("addresses", addresses, personDTO.getAddresses())
.build();
}
}
#Data
public class AddressDTO implements Diffable<AddressDTO> {
private String id;
private String personId;
private String addressType;
private String street;
private String houseNumber;
private String postalCode;
private String city;
private String countryId;
#Override
public DiffResult diff(AddressDTO addressDTO) {
return new DiffBuilder(this, addressDTO, SHORT_PREFIX_STYLE)
.append("id", this.id, addressDTO.getId())
.append("personId", this.personId, addressDTO.getPersonId())
.append("addressType", this.addressType, addressDTO.getAddressType())
.append("street", this.street, addressDTO.getStreet())
.append("houseNumber", this.houseNumber, addressDTO.getHouseNumber())
.append("postalCode", this.postalCode, addressDTO.getPostalCode())
.append("city", this.city, addressDTO.getCity())
.append("countryId", this.countryId, addressDTO.getCountryId())
.build();
}
}
My main goal is to find differences between two similar person objects. Currently I've tried to use Diffable interface from apache commons which is perfectly good for object. Please advise how to deal with collections when size of each collection can be different. For instance few addresses were removed, few was added and few was updated. Please see example below:
Probably there is another library which helps to achieve similar goals, please advice

source can be your first object
target can be your second object
Iterator targetIt = target.iterator();
for (Object obj:source)
if (!obj.equals(targetIt.next())
// Element has changed

Related

How to combine data from two reactive streams in project reactor?

I started using Project Reactor recently and I can't work out how to work with nested streams. I want to update data of outer Mono with some data of inner Mono.
#GetMapping("/search")
public Mono<Github> combineGithubData() {
WebClient client = WebClient.create("https://api.github.com");
Mono<Github> data = client.get().uri(URI.create("https://api.github.com/users/autocorrectoff")).retrieve().bodyToMono(Github.class);
data = data.map(s -> {
client.get().uri(URI.create("https://api.github.com/users/Kukilej")).retrieve().bodyToMono(Github.class).map(m -> {
s.setXXX(m.getName());
return m;
});
return s;
});
return data;
}
The field XXX is always returned as null, although I have set it to a value from inner Mono. I'm pretty sure this would work in RxJs. How do I make this work with Project Reactor?
edit:
the code of the Github class
import lombok.*;
#Getter #Setter
#Builder
#ToString
#NoArgsConstructor
#AllArgsConstructor
public class Github {
private String login;
private int id;
private String node_id;
private String avatar_url;
private String gravatar_id;
private String url;
private String html_url;
private String followers_url;
private String following_url;
private String gists_url;
private String starred_url;
private String subscriptions_url;
private String organizations_url;
private String repos_url;
private String events_url;
private String received_events_url;
private String type;
private boolean site_admin;
private String name;
private String company;
private String blog;
private String location;
private String email;
private String hireable;
private String bio;
private int public_repos;
private int public_gists;
private int followers;
private int following;
private String created_at;
private String updated_at;
private String XXX;
}
Your inner stream is not getting subscribed to. Either us flatMap, or better yet, use zip:
data
.zipWith(client.get().uri(...).retrieve().bodyToMono(Github.class))
.map(tuple2 -> {
//update tuple2.getT1() with m.getName() and return the updated tuple
return tuple2.mapT1(tuple2.getT1().setXXX(tuple2.getT2().getName()));
})
.map(tuple2 -> tuple2.getT1() //updated s);
zipWith() subscribes to the inner stream.

How may I convert java custom Object to String and back again

I would like to write a converter to convert my custom object to DTO and back. How do I approach it?
I have 2 classes Appointment and Doctor which is a subclass of Appointment. I would like to have the converter as simple as possible.
I am not looking for straight answer, would appreciate tips on how to approach it.
below classes have getters and setters:
public class Doctor {
private long id;
private String name;
private String surname;
private String key;
}
public class Appointment {
private long id;
private String description;
private Doctor doctor;
private Date appointmentDate;
}
//converter
public class ConverterComponent {
public AppointmentDTO convert(Appointment appointment){
AppointmentDTO appointmentDTO = new AppointmentDTO();
appointmentDTO.id = appointment.getId();
appointmentDTO.description = appointment.getDescription();
appointmentDTO.doctor = appointment.getDoctor().toString();
appointmentDTO.appointmentDate = appointment.getAppointmentDate().toString();
return appointmentDTO;
}
}
I would like to write another convert(AppointmentDTO appointmentDTO) method in ConverterComponent which will return the Appointment object back.
Could it be done just by parsing Object to json and back again?
Thanks,

Mapstruct mapping - String to List<String>

I am struggling to map a string object from source(Relation.class) and to a List of target(RelationListDTO.class) .
Relation.java
public class Relation {
private String name;
private String email;
private String completeAddress;
// getters and setters
}
RelationListDTO.java
public class RelationListDTO {
private String name;
private String email;
private List<Address> address;
// getters and setters
}
Address.java
public class Address{
private String street;
private String city;
// getters and setters
}
Mapper class
#Mapper
public interface RelationMapper {
#Mapping(source = "completeAddress", target = "address.get(0).city")
RelationListDTO relationToListDto(Relation relation);
}
But it is not working. Could anyone please help.
What you are trying to do using MapStruct is not possible. Because MapStruct doesn't work with run time objects. MapStruct only generated plain java code for mapping two beans. And I find your requirement is little unique. You have a list of Addresses but want to map only city from source object? You can still do like this
#Mapping( target = "address", source = "completeAddress")
RelationListDTO relationToListDto(Relation relation);
// MapStruct will know to use this method to map between a `String` and `List<Address>`
default List<Address> mapAddress(String relation){
//create new arraylist
// create new AddressObject and set completeAddress to address.city
// add that to list and return list
}
Not sure if this was possible at the time of the accepted answer but I had the same problem as you and ended up doing it this way.
#Mapper(imports = Collections.class)
public interface RelationMapper {
#Mapping(expression = "java(Collections.singletonList(relation.getCompleteAddress()))", target = "address")
RelationListDTO relationToListDto(Relation relation);
}

With Android Room, do I need to add setter and getter for nested object?

In the code below, class Address is nested in Entity User. I wonder if all the attributes of Address are private, do we need getter and setter for each of the field in Address? Notice there is a List<String>, so I'm not sure if Room will work well with #TypeConverter in this case.
public class Address {
public String street;
public String state;
public List<String> city;
#ColumnInfo(name = "post_code")
public int postCode;
}
#Entity
public class User {
#PrimaryKey
public int id;
public String firstName;
#Embedded
public Address address;
}
You can easily add getter/setters with #Ignore annotation and the converter will ignore these methods.
#Ignore
public List<String> getCity() {
return city;
}
You can refer here
Create the entity

Hibernate validation on static inner classes

Can you not validate static inner classes using hibernate validation? I have the following form:
public class Thing {
#NotNull // WORKS!
private String message;
private someClass obj1;
private someOtherClass obj2;
public static class someClass
{
#NotNull //DOES NOT WORK
private String someField;
}
public static class someOtherClass
{
#NotNull //Does NOT WORK
private String someOtherField;
}
}
I got it, you need to mark #Valid on the instances of the someClass and someOtherClass. This fixed the issue for me. Looks like the #Valid annotation I had on my controller for my Thing object wasn't applying recursively to the state of its nested objects.
You can use #Valid on the address property in a combination of other constraints inside Address class. A valid example would be:
public class Person {
#NotEmpty
private String fullName;
#Email
private String email;
#Pattern (regexp = "[0-9]+")
private String telNo;
#NotNull
#Valid
private Address address;
}
class Address {
#NotEmpty
private String houseNumber;
#NotEmpty
private String streetName;
private String province;
private String country;
}

Categories

Resources