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