Search in sources :

Example 36 with FieldValue

use of org.activityinfo.model.type.FieldValue in project activityinfo by bedatadriven.

the class Updater method parseChange.

@VisibleForTesting
static TypedRecordUpdate parseChange(FormClass formClass, RecordUpdate changeObject, int userId) {
    // Build a lookup map to resolve the field name used in the JSON request.
    Map<String, FormField> idMap = new HashMap<>();
    Multimap<String, FormField> codeMap = HashMultimap.create();
    for (FormField formField : formClass.getFields()) {
        idMap.put(formField.getId().asString(), formField);
        codeMap.put(formField.getCode(), formField);
    }
    TypedRecordUpdate update = new TypedRecordUpdate();
    update.setUserId(userId);
    update.setFormId(formClass.getId());
    update.setRecordId(changeObject.getRecordId());
    update.setDeleted(changeObject.isDeleted());
    if (changeObject.getParentRecordId() != null) {
        update.setParentId(ResourceId.valueOf(changeObject.getParentRecordId()));
    }
    if (changeObject.getFields() != null) {
        for (Map.Entry<String, JsonValue> change : changeObject.getFields().entrySet()) {
            String fieldName = change.getKey();
            // Resolve what might be a human readable field name to the FormField
            // We accept FormField codes and ids
            FormField field;
            if (idMap.containsKey(fieldName)) {
                field = idMap.get(fieldName);
            } else {
                Collection<FormField> byCode = codeMap.get(fieldName);
                if (byCode.size() == 0) {
                    throw new InvalidUpdateException("Unknown field '" + fieldName + "'.");
                } else if (byCode.size() > 1) {
                    throw new InvalidUpdateException("Ambiguous field code '" + fieldName + "'");
                }
                field = Iterables.getOnlyElement(byCode);
            }
            // Now use the type information to parse the JSON element
            FieldValue fieldValue;
            try {
                fieldValue = parseFieldValue(field, changeObject.getFields().get(fieldName));
            } catch (Exception e) {
                throw new InvalidUpdateException(format("Invalid value for field '%s' (id: %s, code: %s): %s", field.getLabel(), field.getId(), field.getCode(), e.getMessage()), e);
            }
            update.set(field.getId(), validateType(field, fieldValue));
        }
    }
    return update;
}
Also used : JsonValue(org.activityinfo.json.JsonValue) JsonMappingException(org.activityinfo.json.JsonMappingException) FieldValue(org.activityinfo.model.type.FieldValue) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 37 with FieldValue

use of org.activityinfo.model.type.FieldValue in project activityinfo by bedatadriven.

the class FormWidgetCreator method createWidgets.

public Promise<Void> createWidgets(final FormClass formClass, final FieldUpdated fieldUpdated) {
    List<Promise<Void>> promises = Lists.newArrayList();
    for (final FormField field : formClass.getFields()) {
        if (field.getType() instanceof SubFormReferenceType) {
            FormClass subForm = model.getSubFormByOwnerFieldId(field.getId());
            if (subForm.getSubFormKind() != SubFormKind.REPEATING) {
                // for repeating we create it internally in sub SimpleFormPanel
                Promise<Void> subFormWidgetsPromise = createWidgets(subForm, fieldUpdated);
                promises.add(subFormWidgetsPromise);
            }
        } else {
            Promise<Void> promise = widgetFactory.createWidget(formClass, field, new FieldUpdater<FieldValue>() {

                @Override
                public void onInvalid(String errorMessage) {
                    containers.get(field.getId()).setInvalid(errorMessage);
                }

                @Override
                public void update(FieldValue value) {
                    containers.get(field.getId()).setValid();
                    fieldUpdated.onFieldUpdated(field, value);
                }
            }).then(new Function<FormFieldWidget, Void>() {

                @Override
                public Void apply(FormFieldWidget widget) {
                    FieldContainer fieldContainer = containerFactory.createContainer(field, widget, 4);
                    containers.put(field.getId(), fieldContainer);
                    model.addContainerOfClass(formClass.getId(), fieldContainer);
                    return null;
                }
            });
            promises.add(promise);
        }
    }
    return Promise.waitAll(promises);
}
Also used : FieldUpdater(org.activityinfo.ui.client.component.form.field.FieldUpdater) SubFormReferenceType(org.activityinfo.model.type.subform.SubFormReferenceType) Promise(org.activityinfo.promise.Promise) FormFieldWidget(org.activityinfo.ui.client.component.form.field.FormFieldWidget) FormClass(org.activityinfo.model.form.FormClass) FieldValue(org.activityinfo.model.type.FieldValue) FormField(org.activityinfo.model.form.FormField)

Example 38 with FieldValue

use of org.activityinfo.model.type.FieldValue in project activityinfo by bedatadriven.

the class SimpleFormPanel method validateField.

private boolean validateField(FieldContainer container) {
    FormField field = container.getField();
    FieldValue value = getCurrentValue(field);
    if (value != null && value.getTypeClass() != field.getType().getTypeClass()) {
        value = null;
    }
    if (!container.isInputValid()) {
        return false;
    }
    if (!container.getFieldWidget().isValid()) {
        return false;
    }
    Optional<Boolean> validatedBuiltInDates = validateBuiltinDates(container, field);
    if (validatedBuiltInDates.isPresent()) {
        return validatedBuiltInDates.get();
    }
    if (field.isRequired() && isEmpty(value) && field.isVisible() && !container.getFieldWidget().isReadOnly()) {
        // if field is not visible user doesn't have chance to fix it
        container.setInvalid(I18N.CONSTANTS.requiredFieldMessage());
        return false;
    } else {
        container.setValid();
        return true;
    }
}
Also used : FieldValue(org.activityinfo.model.type.FieldValue) FormField(org.activityinfo.model.form.FormField)

Example 39 with FieldValue

use of org.activityinfo.model.type.FieldValue in project activityinfo by bedatadriven.

the class SiteFormStorage method update.

@Override
public void update(TypedRecordUpdate update) {
    FormRecord formRecord = get(update.getRecordId()).get();
    FormInstance formInstance = FormInstance.toFormInstance(getFormClass(), formRecord);
    BaseTableUpdater baseTable = new BaseTableUpdater(baseMapping, update.getRecordId());
    IndicatorValueTableUpdater indicatorValues = new IndicatorValueTableUpdater(update.getRecordId());
    AttributeValueTableUpdater attributeValues = new AttributeValueTableUpdater(activity, update.getRecordId());
    if (update.isDeleted()) {
        baseTable.delete();
        indicatorValues.delete();
    } else {
        for (Map.Entry<ResourceId, FieldValue> change : update.getChangedFieldValues().entrySet()) {
            if (change.getKey().getDomain() == CuidAdapter.INDICATOR_DOMAIN) {
                indicatorValues.update(change.getKey(), change.getValue());
            } else if (change.getKey().getDomain() == CuidAdapter.ATTRIBUTE_GROUP_FIELD_DOMAIN) {
                attributeValues.update(change.getKey(), change.getValue());
            } else if (change.getKey().equals(CuidAdapter.locationField(activity.getId()))) {
                ReferenceValue value = (ReferenceValue) change.getValue();
                if (value.getOnlyReference().getRecordId().getDomain() == CuidAdapter.LOCATION_DOMAIN) {
                    baseTable.update(change.getKey(), change.getValue());
                } else {
                    baseTable.update(change.getKey(), dummyLocationReference(value.getOnlyReference()));
                }
            } else {
                baseTable.update(change.getKey(), change.getValue());
            }
        }
    }
    long newVersion;
    try {
        newVersion = incrementSiteVersion();
        baseTable.executeUpdates(queryExecutor);
        indicatorValues.execute(queryExecutor);
        attributeValues.executeUpdates(queryExecutor);
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
    Map<ResourceId, FieldValue> fieldValues = new HashMap<>();
    fieldValues.putAll(formInstance.getFieldValueMap());
    fieldValues.putAll(update.getChangedFieldValues());
    RecordChangeType changeType = update.isDeleted() ? RecordChangeType.DELETED : RecordChangeType.UPDATED;
    dualWriteToHrd(changeType, update, newVersion, fieldValues);
}
Also used : SQLException(java.sql.SQLException) ReferenceValue(org.activityinfo.model.type.ReferenceValue) ResourceId(org.activityinfo.model.resource.ResourceId) FieldValue(org.activityinfo.model.type.FieldValue)

Example 40 with FieldValue

use of org.activityinfo.model.type.FieldValue in project activityinfo by bedatadriven.

the class MySqlUpdateTest method createFormWithSerialNumber.

@Test
public void createFormWithSerialNumber() {
    userId = 1;
    KeyGenerator generator = new KeyGenerator();
    int activityId = generator.generateInt();
    FormClass formClass = new FormClass(CuidAdapter.activityFormClass(activityId));
    formClass.setDatabaseId(1);
    formClass.setLabel("New Form");
    FormField serialNumField = new FormField(CuidAdapter.generateIndicatorId()).setType(new SerialNumberType()).setLabel("NUM").setRequired(true);
    formClass.addElement(serialNumField);
    FormField nameField = new FormField(CuidAdapter.generateIndicatorId()).setType(TextType.SIMPLE).setLabel("Name").setRequired(true);
    formClass.addElement(nameField);
    catalog.createOrUpdateFormSchema(formClass);
    newRequest();
    ResourceId siteId = CuidAdapter.generateSiteCuid();
    // Create the record
    FormInstance creation = new FormInstance(siteId, formClass.getId());
    creation.set(nameField.getId(), TextValue.valueOf("Bob"));
    creation.set(partnerField(activityId), CuidAdapter.partnerRef(1, 1));
    executeUpdate(creation);
    newRequest();
    // Verify that the record has been created
    FormInstance created = FormInstance.toFormInstance(formClass, catalog.getForm(formClass.getId()).get().get(siteId).get());
    assertThat(created.get(nameField.getId()), equalTo((FieldValue) TextValue.valueOf("Bob")));
    assertThat(created.get(serialNumField.getId()), equalTo((FieldValue) new SerialNumber(1)));
    newRequest();
    // Now update the record's name
    JsonValue fieldValues = createObject();
    fieldValues.put(nameField.getName(), TextValue.valueOf("Sue").toJson());
    // the UI may send null values
    fieldValues.put(serialNumField.getName(), Json.createNull());
    JsonValue update = createObject();
    update.put("fieldValues", fieldValues);
    updater().execute(formClass.getId(), siteId, update);
    newRequest();
    // Finally verify that the serial number is unchanged
    FormInstance updated = FormInstance.toFormInstance(formClass, catalog.getForm(formClass.getId()).get().get(siteId).get());
    assertThat(updated.get(nameField.getId()), equalTo((FieldValue) TextValue.valueOf("Sue")));
    assertThat(updated.get(serialNumField.getId()), equalTo((FieldValue) new SerialNumber(1)));
}
Also used : SerialNumber(org.activityinfo.model.type.SerialNumber) ResourceId(org.activityinfo.model.resource.ResourceId) FormClass(org.activityinfo.model.form.FormClass) JsonValue(org.activityinfo.json.JsonValue) FieldValue(org.activityinfo.model.type.FieldValue) FormInstance(org.activityinfo.model.form.FormInstance) KeyGenerator(org.activityinfo.model.legacy.KeyGenerator) FormField(org.activityinfo.model.form.FormField) SerialNumberType(org.activityinfo.model.type.SerialNumberType) GeoPoint(org.activityinfo.model.type.geo.GeoPoint) Test(org.junit.Test)

Aggregations

FieldValue (org.activityinfo.model.type.FieldValue)49 ResourceId (org.activityinfo.model.resource.ResourceId)16 FormField (org.activityinfo.model.form.FormField)13 Test (org.junit.Test)12 FormInstance (org.activityinfo.model.form.FormInstance)10 Quantity (org.activityinfo.model.type.number.Quantity)9 JsonValue (org.activityinfo.json.JsonValue)8 FormClass (org.activityinfo.model.form.FormClass)8 ReferenceValue (org.activityinfo.model.type.ReferenceValue)7 RecordRef (org.activityinfo.model.type.RecordRef)6 ResultSet (java.sql.ResultSet)5 HashMap (java.util.HashMap)5 Map (java.util.Map)5 SerialNumberType (org.activityinfo.model.type.SerialNumberType)5 BooleanFieldValue (org.activityinfo.model.type.primitive.BooleanFieldValue)5 SerialNumber (org.activityinfo.model.type.SerialNumber)4 GeoPoint (org.activityinfo.model.type.geo.GeoPoint)4 LocalDate (org.activityinfo.model.type.time.LocalDate)4 JsonMappingException (org.activityinfo.json.JsonMappingException)3 FormulaNode (org.activityinfo.model.formula.FormulaNode)3