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    private void addField(final String name, final Object value) {
 33        addField(name, value, null);
 34    }
 35
 36    private void addField(final String name, final Object value, final String type) {
 37        if (value == null) {
 38            throw new IllegalArgumentException("Null values are not supported on data fields");
 39        }
 40        final var field = this.addExtension(new Field());
 41        field.setFieldName(name);
 42        if (type != null) {
 43            field.setType(type);
 44        }
 45        if (value instanceof Collection) {
 46            for (final Object subValue : (Collection<?>) value) {
 47                if (subValue instanceof String) {
 48                    final var valueExtension = field.addExtension(new Value());
 49                    valueExtension.setContent((String) subValue);
 50                } else {
 51                    throw new IllegalArgumentException(
 52                            String.format(
 53                                    "%s is not a supported field value",
 54                                    subValue.getClass().getSimpleName()));
 55                }
 56            }
 57        } else {
 58            final var valueExtension = field.addExtension(new Value());
 59            if (value instanceof String) {
 60                valueExtension.setContent((String) value);
 61            } else if (value instanceof Integer) {
 62                valueExtension.setContent(String.valueOf(value));
 63            } else if (value instanceof Boolean) {
 64                valueExtension.setContent(Boolean.TRUE.equals(value) ? "1" : "0");
 65            } else {
 66                throw new IllegalArgumentException(
 67                        String.format(
 68                                "%s is not a supported field value",
 69                                value.getClass().getSimpleName()));
 70            }
 71        }
 72    }
 73
 74    private void setFormType(final String formType) {
 75        this.addField(FORM_TYPE, formType, FIELD_TYPE_HIDDEN);
 76    }
 77
 78    public static Data of(final String formType, final Map<String, Object> values) {
 79        final var data = new Data();
 80        data.setType(FORM_TYPE_SUBMIT);
 81        data.setFormType(formType);
 82        for (final Map.Entry<String, Object> entry : values.entrySet()) {
 83            data.addField(entry.getKey(), entry.getValue());
 84        }
 85        return data;
 86    }
 87
 88    public Data submit(final Map<String, Object> values) {
 89        final String formType = this.getFormType();
 90        final var submit = new Data();
 91        submit.setType(FORM_TYPE_SUBMIT);
 92        if (formType != null) {
 93            submit.setFormType(formType);
 94        }
 95        for (final Field existingField : this.getFields()) {
 96            final var fieldName = existingField.getFieldName();
 97            final Object submittedValue = values.get(fieldName);
 98            if (submittedValue != null) {
 99                submit.addField(fieldName, submittedValue);
100            } else {
101                submit.addField(fieldName, existingField.getValues());
102            }
103        }
104        return submit;
105    }
106
107    private void setType(final String type) {
108        this.setAttribute("type", type);
109    }
110}