Конвертер списков JSF - PullRequest
5 голосов
/ 02 октября 2011

Как мне написать конвертер для списка предметов класса A в JSF2? Я написал конвертер для класса A, но элементы отображаются с использованием функции toString () по умолчанию: «A @ hashcode».

Мне нужно использовать конвертер, а не метод базового компонента, чтобы можно было выполнить валидацию (Hibernate Validator).

подробнее

Вот как я использую список:

<h:inputText id="destinations" value="#{rule.destinations}" converter="gr.panayk.vinyls.Destination"/>

Где # {rule.destination} имеет тип List<Destination>. Я ожидаю разделенный запятыми список преобразованных адресатов.

решение

Я прилагаю конвертер списка, который предложил BalusC.

@FacesConverter(value="gr.panayk.vinyls.converter.DestinationList")
public class DestinationListConverter implements Converter
{
    @Override
    public Object getAsObject(final FacesContext context, final UIComponent component, final String values)
    {
        final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

        final List<Destination> result = new ArrayList<Destination>(); 
        for (String value : values.split(",", -1))
        {           
            final String trimmedValue = value.trim();

            final Set<ConstraintViolation<Destination>> violations = validator.validateValue(Destination.class, "data", trimmedValue);
            if (!violations.isEmpty())
            {
                throw new ConverterException(new FacesMessage(violations.iterator().next().getMessage()));
            }

            result.add(new Destination(trimmedValue));
        }       

        final Set<ConstraintViolation<Rule>> violations = validator.validateValue(Rule.class, "destinations", result);
        if (!violations.isEmpty())
        {
            throw new ConverterException(new FacesMessage(violations.iterator().next().getMessage()));
        }       

        return result;
    }

    @Override
    public String getAsString(final FacesContext context, final UIComponent component, final Object value)
    {
        if (value instanceof List<?>)
        {
            final StringBuffer result = new StringBuffer();

            final List<?> list = (List<?>) value;

            for (int i = 0; i < list.size()-1; i++)
            {               
                if (list.get(i) instanceof Destination)
                {
                    result.append(((Destination) list.get(i)).getData());
                    result.append(", ");
                }
                else
                {
                    throw new IllegalArgumentException( "Cannot convert " + value + " object to Destination in DestinationConverter." );
                }
            }

            if (!list.isEmpty())
            {
                if (list.get(list.size()-1) instanceof Destination)
                {
                    result.append(((Destination) list.get(list.size()-1)).getData());
                }
                else
                {
                    throw new IllegalArgumentException( "Cannot convert " + value + " object to Destination in DestinationConverter." );
                }
            }

            return result.toString();
        }
        else
        {
            throw new IllegalArgumentException( "Cannot convert " + value + " object to List in DestinationConverter." );
        }
    }
}

1 Ответ

6 голосов
/ 02 октября 2011

Я написал конвертер для класса A, но элементы отображаются с использованием функции toString () по умолчанию: "A @ hashcode".

Это может произойти, если вы явно не объявили конвертер в компоненте. Например, <h:selectManyCheckbox> и <h:selectManyListbox> явное объявление преобразователя является обязательным, поскольку все, что JSF / EL знает, это то, что значение имеет тип List, а не List<A> (универсальные типы теряются во время выполнения). Если вы не объявляете конвертер, то значения будут обрабатываться как String (поскольку это значения по умолчанию для вывода HTML и параметров запроса HTTP).

* 1014 Е.Г. *

<h:selectManyCheckbox converter="aConverter">

с

@FacesConverter(value="aConverter", forClass=A.class)
public class AConverter implements Converter {

    // ...

}

Явное объявление вышеупомянутого конвертера необязательно, когда вы используете входы с одним элементом, например <h:selectOneMenu>, так как forClass будет соответствовать ему в любом случае.

...