jaxb внешний XML-файл привязки: xjc javaType для одного XSD

Создайте собственный универсальный конвертер для сложных объектов в качестве выбранного элемента

. Balusc дает очень полезный обзорный обзор по этому вопросу. Но есть одна альтернатива, которую он не представляет: Roll-your-общий универсальный конвертер, который обрабатывает сложные объекты как выбранный элемент. Это очень сложно сделать, если вы хотите обрабатывать все случаи, но довольно просто для простых случаев.

В приведенном ниже коде содержится пример такого конвертера. Он работает в том же духе, что и OmniFaces SelectItemsConverter , поскольку он просматривает дочерние элементы компонента для объектов, содержащихся в UISelectItem(s). Разница в том, что он обрабатывает привязки только к простым коллекциям объектов сущности или к строкам. Он не обрабатывает группы элементов, коллекции SelectItem s, массивы и, возможно, много других вещей.

Сущности, к которым должен привязываться компонент, должны реализовать интерфейс IdObject. (Это можно решить другим способом, например, с помощью toString.)

Обратите внимание, что сущности должны реализовать equals таким образом, чтобы два объекта с одинаковым идентификатором сравнивались равными.

Единственное, что вам нужно сделать, чтобы использовать его, - это указать его как конвертер на компоненте select, привязать его к свойству сущности и списку возможных объектов:


  
  
  

Конвертер:

/**
 * A converter for select components (those that have select items as children).
 * 
 * It convertes the selected value string into one of its element entities, thus allowing
 * binding to complex objects.
 * 
 * It only handles simple uses of select components, in which the value is a simple list of
 * entities. No ItemGroups, arrays or other kinds of values.
 * 
 * Items it binds to can be strings or implementations of the {@link IdObject} interface.
 */
@FacesConverter("selectListConverter")
public class SelectListConverter implements Converter {

  public static interface IdObject {
    public String getDisplayId();
  }

  @Override
  public Object getAsObject(FacesContext context, UIComponent component, String value) {
    if (value == null || value.isEmpty()) {
      return null;
    }

    return component.getChildren().stream()
      .flatMap(child -> getEntriesOfItem(child))
      .filter(o -> value.equals(o instanceof IdObject ? ((IdObject) o).getDisplayId() : o))
      .findAny().orElse(null);
  }

  /**
   * Gets the values stored in a {@link UISelectItem} or a {@link UISelectItems}.
   * For other components returns an empty stream.
   */
  private Stream getEntriesOfItem(UIComponent child) {
    if (child instanceof UISelectItem) {
      UISelectItem item = (UISelectItem) child;
      if (!item.isNoSelectionOption()) {
        return Stream.of(item.getValue());
      }

    } else if (child instanceof UISelectItems) {
      Object value = ((UISelectItems) child).getValue();

      if (value instanceof Collection) {
        return ((Collection) value).stream();
      } else {
        throw new IllegalStateException("Unsupported value of UISelectItems: " + value);
      }
    }

    return Stream.empty();
  }

  @Override
  public String getAsString(FacesContext context, UIComponent component, Object value) {
    if (value == null) return null;
    if (value instanceof String) return (String) value;
    if (value instanceof IdObject) return ((IdObject) value).getDisplayId();

    throw new IllegalArgumentException("Unexpected value type");
  }

}

0
задан Filip 15 January 2019 в 21:39
поделиться