Data.java

  1package im.conversations.android.xmpp.model.data;
  2
  3import com.google.common.collect.Collections2;
  4import com.google.common.collect.Iterables;
  5import im.conversations.android.annotation.XmlElement;
  6import im.conversations.android.xmpp.model.Extension;
  7import java.util.Collection;
  8import java.util.Map;
  9
 10@XmlElement(name = "x")
 11public class Data extends Extension {
 12
 13    private static final String FORM_TYPE = "FORM_TYPE";
 14    private static final String FIELD_TYPE_HIDDEN = "hidden";
 15    private static final String FORM_TYPE_SUBMIT = "submit";
 16
 17    public Data() {
 18        super(Data.class);
 19    }
 20
 21    public String getFormType() {
 22        final var fields = this.getExtensions(Field.class);
 23        final var formTypeField = Iterables.find(fields, f -> FORM_TYPE.equals(f.getFieldName()));
 24        return Iterables.getFirst(formTypeField.getValues(), null);
 25    }
 26
 27    public Collection<Field> getFields() {
 28        return Collections2.filter(
 29                this.getExtensions(Field.class), f -> !FORM_TYPE.equals(f.getFieldName()));
 30    }
 31
 32    public Field getFieldByName(final String name) {
 33        return Iterables.find(getFields(), f -> name.equals(f.getFieldName()), null);
 34    }
 35
 36    private void addField(final String name, final Object value) {
 37        addField(name, value, null);
 38    }
 39
 40    private void addField(final String name, final Object value, final String type) {
 41        if (value == null) {
 42            throw new IllegalArgumentException("Null values are not supported on data fields");
 43        }
 44        final var field = this.addExtension(new Field());
 45        field.setFieldName(name);
 46        if (type != null) {
 47            field.setType(type);
 48        }
 49        if (value instanceof Collection) {
 50            for (final Object subValue : (Collection<?>) value) {
 51                if (subValue instanceof String) {
 52                    final var valueExtension = field.addExtension(new Value());
 53                    valueExtension.setContent((String) subValue);
 54                } else {
 55                    throw new IllegalArgumentException(
 56                            String.format(
 57                                    "%s is not a supported field value",
 58                                    subValue.getClass().getSimpleName()));
 59                }
 60            }
 61        } else {
 62            final var valueExtension = field.addExtension(new Value());
 63            if (value instanceof String) {
 64                valueExtension.setContent((String) value);
 65            } else if (value instanceof Integer) {
 66                valueExtension.setContent(String.valueOf(value));
 67            } else if (value instanceof Boolean) {
 68                valueExtension.setContent(Boolean.TRUE.equals(value) ? "1" : "0");
 69            } else {
 70                throw new IllegalArgumentException(
 71                        String.format(
 72                                "%s is not a supported field value",
 73                                value.getClass().getSimpleName()));
 74            }
 75        }
 76    }
 77
 78    private void setFormType(final String formType) {
 79        this.addField(FORM_TYPE, formType, FIELD_TYPE_HIDDEN);
 80    }
 81
 82    public static Data of(final String formType, final Map<String, Object> values) {
 83        final var data = new Data();
 84        data.setType(FORM_TYPE_SUBMIT);
 85        data.setFormType(formType);
 86        for (final Map.Entry<String, Object> entry : values.entrySet()) {
 87            data.addField(entry.getKey(), entry.getValue());
 88        }
 89        return data;
 90    }
 91
 92    public Data submit(final Map<String, Object> values) {
 93        final String formType = this.getFormType();
 94        final var submit = new Data();
 95        submit.setType(FORM_TYPE_SUBMIT);
 96        if (formType != null) {
 97            submit.setFormType(formType);
 98        }
 99        for (final Field existingField : this.getFields()) {
100            final var fieldName = existingField.getFieldName();
101            final Object submittedValue = values.get(fieldName);
102            if (submittedValue != null) {
103                submit.addField(fieldName, submittedValue);
104            } else {
105                submit.addField(fieldName, existingField.getValues());
106            }
107        }
108        return submit;
109    }
110
111    private void setType(final String type) {
112        this.setAttribute("type", type);
113    }
114}