Nous allons voir dans ce billet comment ajouter une valeur par défaut à une relation. Pour cela, reprenons notre application précédente.
Ajouter une relation CarColor dans le modèle de données
Color.java
Nous allons commencer par ajouter le type Color grâce à la configuration statique de Generic System.
1 2 |
@SystemGeneric public class Color {} |
Nous avons vu que le paramétrage statique permettait d’ajouter des types dans Generic System. De la même manière, nous pouvons grâce au paramétrage statique créer des instances.
Nous allons maintenant ajouter de manière statique des instances de
Color. Nous utiliserons pour cela les annotations :
- @SystemGeneric qui déclare que la classe annotée correspond à un noeud du graphe statiquement paramétré ;
- @Meta qui permet de définir le méta, donc le type de notre instance ;
- @StringValue qui permet de définir la valeur qui sera une String.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
@SystemGeneric public class Color { @SystemGeneric @Meta(Color.class) @StringValue("White") public static class White { } @SystemGeneric @Meta(Color.class) @StringValue("Red") public static class Red { } @SystemGeneric @Meta(Color.class) @StringValue("Blue") public static class Blue { } @SystemGeneric @Meta(Color.class) @StringValue("Yellow") public static class Yellow { } } |
CarColor.java
Ajoutons de manière statique la relation
CarColor. Les annotations utilisées sont :
L’annotation @SystemGeneric qui déclare que la classe
CarColor correspond à un noeud du graphe statiquement paramétré.
L’annotation @Components qui spécifie que notre classe annotée est un composite des classes indiquées dans l’annotation.
L’annotation @SingularConstraint ; nous allons ainsi créer une relation 1-n. Une
Car n’aura qu’une seule
Color, mais une
Color pourra correspondre à plusieurs
Car.
1 2 3 4 |
@SystemGeneric @Components({ Car.class, Color.class }) @SingularConstraint public class CarColor {} |
Pour créer une valeur par défaut d’une relation, il suffit de créer un lien entre le type auquel nous voulons ajouter la valeur par défaut et l’instance correspondant à la valeur que nous souhaitons ajouter.
Par exemple, ici nous allons ajouter l’instance de
Color White par défaut en faisant le lien entre le type
Car et l’instance
White.
1 2 3 4 5 6 7 8 9 10 11 12 |
@SystemGeneric @Components({ Car.class, Color.class }) @SingularConstraint public class CarColor { @SystemGeneric @Meta(CarColor.class) @StringValue("DefaultCarColor") @Components({ Car.class, White.class }) public static class DefaultCarColor { } } |
Modifier notre application pour l’affichage et la modification de la Color
Pour afficher les couleurs, nous ajoutons un bean ColorBean avec une méthode permettant de récupérer les instances de Color.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@Named @SessionScoped public class ColorBean implements Serializable { private static final long serialVersionUID = 9201611589820526869L; @Inject private transient Engine engine; private transient Generic color; private transient List<String> colors; @PostConstruct public void init() { color = engine.find(Color.class); colors = color.getInstances().stream().map(generic -> Objects.toString(generic.getValue())).collect(Collectors.toList()); } public List<String> getColors() { return colors; } } |
Pour afficher et modifier la couleur d’une instance de Car, nous ajoutons au bean CarBean une méthode permettant de récupérer (getValue) et assigner (setValue) la valeur de la couleur pour l’instance Car, de la même manière que ce que nous avions fait pour la puissance.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
@Named @RequestScoped public class CarBean { @Inject private Engine engine; private Generic car; private Generic power; private Generic color; private Generic carColor; private String newCarName; private Integer newCarPower; @PostConstruct public void init() { car = engine.find(Car.class); power = engine.find(Power.class); color = engine.find(Color.class); carColor = engine.find(CarColor.class); } [...] public ValueExpressionWrapper getColor(Generic instance) { return new ValueExpressionWrapper() { @Override public void setValue(String value) { // The value color is a string to convert in Generic Generic searchedColor = color.setInstance(value); instance.setLink(carColor, "link", searchedColor); } @Override public String getValue() { Generic link = instance.getLinks(carColor).first(); return (link != null) ? (String) link.getTargetComponent().getValue() : null; } }; } [...] |
Nous gardons le même formulaire d’ajout du
Car et du
Power, pour mettre en évidence que la couleur va bien être ajoutée par défaut.
Nous rajoutons une colonne dans notre tableau de
Car, afin de visualiser pour chaque
Car sa
Color et de pouvoir modifier celle-ci.
La modification de la
Color se fait au moment de la sortie de la liste déroulante par un appel AJAX. Voyons l’extrait de la page xhtml correspondant :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
[...] <h:column> <f:facet name="header">Car</f:facet> <h:outputText value="#{car.getValue()}" /> </h:column> <h:column> <f:facet name="header">Power</f:facet> <h:inputText size="10" value="#{carBean.getPower(car).value}"> <f:convertNumber integerOnly="true" /> <f:ajax event="blur" execute="@this" render="@this message" /> </h:inputText> </h:column> <h:column> <f:facet name="header">Color</f:facet> <h:selectOneMenu value="#{carBean.getColor(car).value}"> <f:selectItems value="#{colorBean.colors}" var="color" itemLabel="#{color}" itemValue="#{color}"> </f:selectItems> <f:ajax event="change" execute="@this" render="@this message"/> </h:selectOneMenu> </h:column> [...] |