Search code examples
lambdajava-8streamwsdloption-type

how to use optional and filter along to retrieve an object from chained/cascaded objects generated by wsdl2java


I understand flatMap is recommended when dealing with hierarchical objects in Java, particularly while extracting values from objects created out of XML files.

Whithout relying on Optional and since getCommercieleNaam() will bring me a list, I coded:

NaamOndernemingLijstCommercieelType naamOndernemingLijstCommercieel = onderneming.getNamen()
        .getCommercieleNamen();
NaamOndernemingType naamOndernemingType = naamOndernemingLijstCommercieel.getCommercieleNaam().stream()
        .filter(x -> x.getTaalcode().getValue() == "nl").findFirst().get();

In few words, it will walk throw the cascade object and return the first name found for language Netherlands. I see this as very unsafe and, instead of checking all objects if they are null, I prefer to use Optional.

Then I try code what I understand it is the correct way but I don't know how to apply filter in order to retrieve only the object from the list matching a criteria (language == "nl" in my scenario):

    Optional<NamenOndernemingType> optionalNamenOnderneming = onderneming.getNamen(); 
    NaamOndernemingType naamOndernemingType = optionalNamenOnderneming.flatMap(NamenOndernemingType::getCommercieleNamen)
            .flatMap(NaamOndernemingLijstCommercieelType::getCommercieleNaam)
            .filter(x -> "nl".equals(x.toString()));

PS.: in dutch, naam means name (singular) and Namen means names (plural)

Well, the closest I got was

    Optional<NamenOndernemingType> optionalNamenOnderneming = Optional.ofNullable(onderneming.getNamen());
    List<NaamOndernemingType> listNaamOndernemingType = optionalNamenOnderneming
            .flatMap(NamenOndernemingType::getCommercieleNamen)
            .map(NaamOndernemingLijstCommercieelType::getCommercieleNaam);

But it is neither working and after I fix this, I need to filter also.

*edited

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "NamenOndernemingType", propOrder = {
    "maatschappelijkeNamen",
    "afgekorteNamen",
    "commercieleNamen"
})
public class NamenOndernemingType {

...

    public NaamOndernemingLijstCommercieelType getCommercieleNamen() {
        return commercieleNamen;
    }


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "NaamOndernemingLijstCommercieelType", propOrder = {
    "commercieleNaam"
})
public class NaamOndernemingLijstCommercieelType {
...

    public List<NaamOndernemingType> getCommercieleNaam() {

enter image description here

* Solution *

Optional.ofNullable(onderneming.getNamen()).map(NamenOndernemingType::getCommercieleNamen)
                .map(NaamOndernemingLijstCommercieelType::getCommercieleNaam).get().stream().filter(Objects::nonNull)
                .filter(x -> x.getTaalcode().getValue() == "nl").findFirst()
                .ifPresent(o -> myMethod("onderneming_commerciele_naam", o.getNaam().getValue()));

PS.: future readers my find worth read my other question as weel: how use Optional with cascaded objects not created with Optional


Solution

  • Thanks to the Aominè recommendations and to the discussion based on how use Optional with cascaded objects not created with Optional

    I reached this solution:

    Optional.ofNullable(onderneming.getNamen()).map(NamenOndernemingType::getCommercieleNamen)
                    .map(NaamOndernemingLijstCommercieelType::getCommercieleNaam).get().stream().filter(Objects::nonNull)
                    .filter(x -> x.getTaalcode().getValue() == "nl").findFirst()
                    .ifPresent(o -> myMethod("onderneming_commerciele_naam", o.getNaam().getValue()));