Going polymorph with ViewModels in DD4T Java 2.0

Plato (~423 BC – ~347 BC) was a pretty smart guy. Among his many ideas and thoughts, his Theory of Forms had an immense influence on how we perceive and solve the philosophical Problem of universals. It basically comes down to the idea that every physical object has one or more essences (or Forms) and that if that object would not have that Form, it would not be that object: a dog is Mammal, but a giraffe is also a Mammal. What makes both animals Mammals? It’s, simply put, the Idea of the Mammal.

In that sense, I see Plato and friends as great contributors to, or maybe even inventors of, at least the idea of Object Oriented Programming and the concepts of polymorphism it contains. So, why not use some of these age old ideas for DD4T’s ViewModel mechanism?

The release of DD4T Java version 2.0.7 has brought a new feature in its ViewModel functionality: it is now possible to use interfaces and / or abstract classes as ViewModel class properties so it becomes possible be polymorph when designing your ViewModel classes.

The following examples hopefully show the why of this feature and hopefully gives you an extra tool in your toolbox when designing your ViewModels:

Using interfaces

Consider the following example: you have five different Tridion Schemas for which you allow to Tridion Components to be linked in a Component Link field of a sixth Schema. If you then create ViewModels for all six content types, how would you then be able to link five different ViewModel classes in one parent class property? The answer is rather obvious: just have all five ViewModel classes implement an interface and use that interface as ViewModel class property:

public interface Mammal {
 // add whatever you like here
}

@ViewModel
public class Generic extends TridionViewModelBase {
   // List of an interface
   @ViewModelProperty
   private List<Mammal> mammals;
}

@ViewModel(rootElementNames=“Giraffe”)
public class Giraffe extends TridionViewModelBase implements Mammal {
   @ViewModelProperty
   private double neckLength;
}

@ViewModel(rootElementNames=“Cat”)
public class Cat extends TridionViewModelBase implements Mammal {
   @ViewModelProperty
   private Integer meowVolume;
}

//.. ETC

Abstract classes

As with interfaces, abstract classes are very useful when you want to share multiple ViewModel class definitions on one parent ViewModel property. The added benefit of using an abstract class is that you can pull up shared properties:

@ViewModel
public class Generic extends TridionViewModelBase {
    // List of an abstract class
    @ViewModelProperty
    private List<AbstractMammal> mammals;
}

public abstract class AbstractMammal extends TridionViewModelBase {
    @ViewModelProperty
    private String heading;

    @ViewModelProperty
    private double numberOfLegs;
}

@ViewModel(rootElementNames=“Cow”)
public class Cow extends AbstractMammal {
    @ViewModelProperty
    private double numberOfStomachs;
}

@ViewModel(rootElementNames=“Rabbit”)
public class Rabbit extends AbstractMammal {
   @ViewModelProperty
   private double numberOfRabbitHolesEncountered;
}

Behind the scenes, there’s a bit of voodoo code to determine the correct concrete ViewModel: the ViewModels derived from an abstract class or implementing an interfaces are found at deserialization time by searching for the Root Element Name, which, when using the mechanism, has to be set on that View Model.

Using the mechanism works in the following situations:

  • This only works inside parent ViewModels. If by popular demand this is wanted for parent ViewModels as well, please raise an issue here.
  • By mapping Component (regular or Multimedia) fields to ViewModel properties.
  • By mapping Embedded Schema content to ViewModel properties.

Please read the full explanation on mapping complex types here to understand how to map the field types described above.

Happy DD4Ting!

About Raimond Kempees

Raimond Kempees is an independent CMS consultant and has for the past 10 years been involved in many fast-paced web projects all over the world, specializing among others in the SDL Tridion platform and building integrations on just about any development platform known to man.