I am learning to convert an object from one type of class to another using java 8. I have a bunch of xjc-generated jaxb classes. Classes do not have a sufficiently friendly structure because they display the xml structure more than the structure of a business object. I donβt want to edit the created classes, because I like to regenerate them whenever the circuit changes, without worrying about saving the settings.
I have a circuit like:
<xs:element name="farm"> <xs:sequence> <xs:element ref="animal" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:element> <xs:element name="animal"> <xs:complexType> <xs:sequence> <xs:element ref="goat"/> <xs:element ref="sheep"/> </xs:sequence> <xs:complexType> </xs:element> <xs:element name="goat"> <xs:complexType> <xs:sequence> goat fields </xs:sequence> <xs:complexType> </xs:element> <xs:element name="sheep"> <xs:complexType> <xs:sequence> sheep fields </xs:sequence> <xs:complexType> </xs:element>
This generates Java something like:
class Farm public List<Animal> getAnimals() class Animal public Goat getGoat() public String getGoatField() public Sheep getSheep() public String getSheepField()
getGoat and getSheep can return null, but they cannot be null. Similarly, at least one of them must be zero. This is done using business rules and database restrictions, but not in xml (although if anyone has a suggestion to structure xml more than desired VOs, Iβm all ears)
I would like to convert this class to
class FarmWrapper public ArrayList<AnimalVO> getAnimals() //optional features tbd //possibly public ArrayList<GoatVO> getGoats() //possibly public ArrayList<SheepVO> getSheep() class GoatVO extends AnimalVO class SheepVO extends AnimalVO
My idea was to do something like this:
herd.stream() .filter(Objects::nonNull) .map(a -> { Optional<AnimalVO> goatVO = Optional.ofNullable(a.getGoat()) .map(g -> new GoatVO(g.getGoatField())); Optional<AnimalVO> sheepVO = Optional.ofNullable(a.getSheep()) .map(s -> new SheepVO(s.getSheepField())); return goatVO.orElse(sheepVO.get()); }) .collect(Collectors.toList());
Now I fed him with a list, and as soon as he encounters a zero sheep, he throws a NoSuchElementException .
I suppose I have a few questions:
- Is this approach suitable for splitting my list into classes that use inheritance?
- What is the best way to use Optionally to protect against potentially null values ββwhen you cannot change the classes that pass you nulls
- What am I missing with
goatVO.orElse(sheepVO.get()) working as long as goatVO contains null and then throws NoSuchElementException when sheepVO contains null
What I'm really doing is working with the generated jaxb code and trying to take the generated classes and make the job easier. Traditionally, the project used a wrapper class that converts the generated classes to VO by a significant amount of null checking and int for manipulating BigInteger.
Editing created classes (Goat, Sheep, Animal) is not a starter, because I would like to maintain the ability to recover without worry