Конвертер для списка объектов, имеющих уникальный идентификатор, кортеж из двух переменных-членов - PullRequest
0 голосов
/ 23 июня 2019

Я пытаюсь отобразить list of objects в <p:selectOneMenu (код показан ниже):

Attribute.java

public class Attribute implements Serializable {
 private String name;
 private String type;
 private String value; //getters setters constructors ommitted

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Attribute attribute = (Attribute) o;
    return Objects.equals(name, attribute.name) &&
            Objects.equals(type, attribute.type);
}

@Override
public int hashCode() {
    return Objects.hash(name, type, value);
}

p: код выбора selectMenu

 <p:selectOneMenu label="Existing Attributes" value="#{cellBean.selectedAttributeFromExistings}"
                                                 converter="attrConverter">
      <f:selectItem itemLabel="Existing attribute" itemValue="#{null}" itemDisabled="true"/>
      <f:selectItems value="#{cellBean.allAttributes}" var="attr" itemLabel="#{attr.name}" itemValue="#{attr}"/>
  <p:ajax event="change" update="@form" process="@form"/>
  </p:selectOneMenu>

Код преобразователя атрибутов (attrConverter)

@FacesConverter(forClass=Attribute.class,  value = "attrConverter")
public class AttributeConverter implements Converter {

@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
    String type = s.substring(s.indexOf(":") + 2, s.indexOf(","));
    String name = s.substring(s.indexOf("name: ") + 6 , s.length());
    Attribute attribute = new Attribute(type, name);
    return attribute;
}

@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object attr) {
    if(attr == null) {
        return null;
    }
    else{
        Attribute attribute = new Attribute();
        String s = "";
        Iterator iterator = ((LinkedTreeMap)attr).keySet().iterator();
        while(iterator.hasNext()){
            String key = (String) iterator.next();
            String value = (String) ((LinkedTreeMap)attr).get(key);
            if(key.equals("name")){
                attribute.setName(value);
            }
            else if(key.equals("type")){
                attribute.setType(value);
            }

        }
        return attribute.toString();
    }
}

Однако, когда я выбираю значение из выпадающего меню, я получаю следующее исключение

Ошибка проверки: значение недопустимо: Ошибка проверки: значение недействительно

error message

, за которым следует сообщение об ошибке / всплывающее окно в правом верхнем углу моего экрана, есть идеи, что я делаю неправильно?

PS: Я видел много примеров того, как они используют unique id для извлечения объекта через DTO в методе getAsObject, в моем примере uniqueness объекта Attribute объект - это комбинация type && value переменных-членов.

Заранее спасибо за любую помощь :)

Ответы [ 2 ]

2 голосов
/ 24 июня 2019

Я не знаю, почему вы разыгрываете attr на LinkedTreeMap, вам нужно разыграть его на Attribute класс.Таким образом, ваш класс конвертера должен быть:

@FacesConverter(forClass=Attribute.class,  value = "attrConverter")
public class AttributeConverter implements Converter {

 @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {

        if (value != null && value.trim().length() > 0 && !value.isEmpty()) {
         /*I take your bean as ViewScoped */
            CellBean cellBean = (CellBean) context.getViewRoot().getViewMap().get("cellBean");
            for(Attribute a : cellBean.getAllAttributes()){
                String combined = a.getType()+a.getValue();
                if(combined.equals(value)){
                    return a;
                }
            }
        }
        return null;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value)            {
        if (value != null) {
            Attribute a = (Attribute) value;
            return a.getType()+a.getValue();
        }
        return null;
    }
}

ОБНОВЛЕНИЕ

Ориентированный на Аскера:

@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
    String[] typeAndName = s.split("#");
    return new Attribute(typeAndName[0], typeAndName[1]);

}

@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object attr) {
    if(attr == null) {
        return null;
    }
    else{
        /* I assume your type and name don't contain '#' charachter */
        return ((Attribute)attr).getType()+"#"+((Attribute)attr).getName();
    }
}
0 голосов
/ 24 июня 2019

Корень проблемы заключался в неправильной сериализации с моей стороны с использованием gson, я преобразовал объект Attribute в LinkedTreeMap, что является несоответствием, как также упоминалось в разделе комментариев.Когда я правильно выполнил сериализацию, функции getAsObject и getAsString имели следующий вид:

@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
    String type = s.substring(s.indexOf("type=") + 5, s.indexOf(" "));
    String name = s.substring(s.indexOf("name=") + 5 , s.length());
    Attribute attribute = new Attribute(type, name);
    return attribute;

}

@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object attr) {
    if(attr == null) {
        return null;
    }
    else{
        return "type="+((Attribute)attr).getType()+" name="+((Attribute)attr).getName();
    }
}
...