Creating custom traits with complex fields

This page provides code and configuration examples of creating custom traits with multi and complex fields.

The rule field is implicitly wrapped inside MultiField in Magnolia 6.2.x. Please keep this in mind when configuring fields and use the examples below as a reference.

Creating a trait with a multi field

Definition

#traitClass has to be unique, creating multiple traits with multiField requires using different List implementation per trait
traitClass: java.util.List
converterClass: info.magnolia.personalization.preview.parameter.ListParameterConverter
voterClass: info.magnolia.personalization.preview.ui.app.field.ListVoter
defaultPreviewTrait: true
valueField:
  $type: jcrMultiValueField
  name: multiFieldTrait
  canRemoveItems: false
  field:
    $type: textField
ruleField:
  $type: compositeField
  properties:
    list:
      $type: jcrMultiValueField
      field:
        $type: textField

Voter

package traits;

import info.magnolia.personalization.trait.TraitCollector;
import info.magnolia.voting.voters.AbstractBoolVoter;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class ListVoter extends AbstractBoolVoter<TraitCollector> {

    private List<String> list = new ArrayList<>();

    @Override
    protected boolean boolVote(final TraitCollector traitCollector) {
        return Optional.ofNullable(traitCollector)
                .map(collector -> collector.getTrait(List.class))
                .map(list::containsAll)
                .orElse(false);
    }

    public void setList(List<String> list) {
        this.list = list;
    }
}

Trait detector filter

This example filter detects all cookie names.

package traits;

import info.magnolia.personalization.trait.AbstractTraitDetectorFilter;
import info.magnolia.personalization.trait.TraitCollector;
import info.magnolia.personalization.trait.TraitDetectionException;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import javax.inject.Provider;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ListDetectorFilter extends AbstractTraitDetectorFilter<List<String>> {

    public ListDetectorFilter(Provider<TraitCollector> traitCollectorProvider) {
        super(traitCollectorProvider);
    }

    @Override
    protected List<String> detect(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws TraitDetectionException {
        return Arrays.stream(httpServletRequest.getCookies())
                .map(Cookie::getName)
                .collect(Collectors.toList());
    }

    @Override
    protected Class getTraitClass() {
        return List.class;
    }

}

Creating a trait with a complex field

Definition

#traitClass has to be unique, creating multiple traits with multiField requires using different Map implementation per trait
traitClass: java.util.Map
converterClass: info.magnolia.personalization.preview.ui.app.field.MapPreviewConverter
voterClass: info.magnolia.personalization.preview.ui.app.field.MapTraitVoter
defaultPreviewTrait: true
valueField:
  name: complexFieldTrait
  $type: textField
  placeholder: key=value
ruleField:
  $type: compositeField
  properties:
    key:
      $type: textField
    value:
      $type: textField

Voter

package traits;

import info.magnolia.personalization.trait.TraitCollector;
import info.magnolia.voting.voters.AbstractBoolVoter;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;

public class MapTraitVoter extends AbstractBoolVoter<TraitCollector> {

    private String key;
    private String value;

    @Override
    protected boolean boolVote(TraitCollector traitCollector) {
        return Optional.ofNullable(traitCollector)
                .map(collector -> collector.getTrait(Map.class))
                .map(map -> Objects.equals(map.get(key), value))
                .orElse(false);
    }

    public void setKey(String key) {
        this.key = key;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

Trait detector filter

This example filter detects all cookies.

package traits;

import info.magnolia.personalization.trait.AbstractTraitDetectorFilter;
import info.magnolia.personalization.trait.TraitCollector;
import info.magnolia.personalization.trait.TraitDetectionException;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.inject.Provider;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;

public class MapDetectorFilter extends AbstractTraitDetectorFilter<Map<String, Cookie>> {

    public MapDetectorFilter(Provider<TraitCollector> traitCollectorProvider) {
        super(traitCollectorProvider);
    }

    @Override
    protected Map<String, Cookie> detect(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws TraitDetectionException {
        return Arrays.stream(httpServletRequest.getCookies())
                .collect(Collectors.toMap(Cookie::getName, Function.identity()));
    }

    @Override
    protected Class getTraitClass() {
        return Map.class;
    }

}
Feedback

DX Core

×

Location

This widget lets you know where you are on the docs site.

You are currently perusing through the DX Core docs.

Main doc sections

DX Core Headless PaaS Legacy Cloud Incubator modules