private static boolean evalFilter(TypedFormRecord record, FormClass formClass, FormulaNode filter) { EvalContext context = new FormEvalContext(formClass, record); return filter.evaluate(context) == BooleanFieldValue.TRUE; }
public FormEvalContext(FormClass formClass, TypedFormRecord instance) { this(formClass); setInstance(instance); }
public FieldValue getFieldValue(ResourceId fieldId) { return getFieldValue(fieldId.asString()); }
@Test public void circularRefs() { FormField a = new FormField(ResourceId.generateId()); a.setCode("A"); a.setType(new CalculatedFieldType("B+1")); a.setLabel("A"); FormField b = new FormField(ResourceId.generateId()); b.setCode("B"); b.setType(new CalculatedFieldType("A/50")); b.setLabel("B"); FormClass formClass = new FormClass(ResourceId.generateId()); formClass.addElement(a); formClass.addElement(b); FormEvalContext context = new FormEvalContext(formClass); context.setInstance(new TypedFormRecord(ResourceId.generateSubmissionId(formClass), formClass.getId())); assertThat(context.getFieldValue(a.getId()), instanceOf(ErrorValue.class)); }
private String computeSerialNumberPrefix( FormClass formClass, SerialNumberType type, TypedFormRecord effectiveRecord) { if(!type.hasPrefix()) { return null; } try { FormEvalContext evalContext = new FormEvalContext(formClass); evalContext.setInstance(effectiveRecord); FormulaNode formula = FormulaParser.parse(type.getPrefixFormula()); FieldValue prefixValue = formula.evaluate(evalContext); if(prefixValue instanceof TextValue) { return ((TextValue) prefixValue).asString(); } else { throw new IllegalStateException("Prefix " + type.getPrefixFormula() + " resolves to type " + prefixValue.getTypeClass().getId()); } } catch (Exception e) { LOGGER.log(Level.SEVERE, "Failed to compute prefix for serial number", e); return null; } }
public FormEvalContext(FormClass formClass) { for (FormField field : formClass.getFields()) { ValueSource source = createValueSource(field); if (field.hasCode()) { symbolMap.put(field.getCode(), source); } symbolMap.put(field.getId().asString(), source); fieldMap.put(field.getId().asString(), source); } // Need to add an additional symbol to map to the Partner Form in the Database Optional<FormElement> partnerField = findPartnerField(formClass); if (partnerField.isPresent()) { FormField partnerFormField = (FormField) partnerField.get(); symbolMap.put(partnerFormId(formClass), createValueSource(partnerFormField)); } // TODO: cleanup hack: enum values need to be treated as constants, not symbols! for (FormField field : formClass.getFields()) { if (field.getType() instanceof EnumType) { for (EnumItem item : ((EnumType) field.getType()).getValues()) { symbolMap.put(item.getId().asString(), new ConstantValue(new EnumValue(item.getId()))); } } } }
private static boolean evalPermission(FormMetadata form, TypedFormRecord record, Operation operation) { if(!form.getPermissions().isAllowed(operation)) { return false; } if(!form.getPermissions().isFiltered(operation)) { return true; } String filter = form.getPermissions().getFilter(operation); try { FormEvalContext context = new FormEvalContext(form.getSchema(), record); FormulaNode formula = FormulaParser.parse(filter); FieldValue result = formula.evaluate(context); return result == BooleanFieldValue.TRUE; } catch (Exception e) { LOGGER.log(Level.SEVERE, "Failed to evaluate permission filter '" + filter + "'", e); return false; } }
private void buildRelevanceCalculator(FormTree.Node node) { String formula = node.getField().getRelevanceConditionExpression(); FormulaNode rootNode; try { rootNode = FormulaParser.parse(formula); } catch (Exception e) { LOGGER.log(Level.WARNING, "Invalid relevance formula: " + formula, e); return; } relevanceCalculators.put(node.getFieldId(), instance -> { evalContext.setInstance(instance); try { return rootNode.evaluateAsBoolean(evalContext); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Failed to evaluate relevance condition", e); return true; } }); }
private void eval(String relevanceExpression, boolean expectedValue, TypedFormRecord instance) { FormulaLexer lexer = new FormulaLexer(relevanceExpression); FormulaParser parser = new FormulaParser(lexer); FormulaNode expr = parser.parse(); Assert.assertEquals(relevanceExpression, expectedValue, Casting.toBoolean(expr.evaluate(new FormEvalContext(formClass, instance)))); }
private void eval(String relevanceExpression, boolean expectedValue, TypedFormRecord instance) { FormulaLexer lexer = new FormulaLexer(relevanceExpression); FormulaParser parser = new FormulaParser(lexer); FormulaNode expr = parser.parse(); Assert.assertEquals(relevanceExpression, expectedValue, Casting.toBoolean(expr.evaluate(new FormEvalContext(formClass, instance)))); }
public FormInputViewModelBuilder(FormStore formStore, FormTree formTree, ActivePeriodMemory memory) { this.formTree = formTree; this.locks = formTree.getRootMetadata().getPermissions().getLocks(); this.evalContext = new FormEvalContext(this.formTree.getRootFormClass()); for (FormTree.Node node : this.formTree.getRootFields()) { if(node.isSubForm() && node.isSubFormVisible()) { subBuilders.add(new SubFormViewModelBuilder(formStore, formTree, node, memory)); } if(node.getField().hasRelevanceCondition()) { buildRelevanceCalculator(node); } if(node.getType() instanceof TextType) { TextType textType = (TextType) node.getType(); if(textType.hasInputMask()) { validators.add(new FieldValidator(node.getFieldId(), new InputMaskValidator(textType.getInputMask()))); } } } }
boolean relevant; if (instance.isPresent()) { relevant = expr.evaluateAsBoolean(new FormEvalContext(formClass, instance.get())); relevant = expr.evaluateAsBoolean(new FormEvalContext(formClass, new TypedFormRecord(ResourceId.generateSubmissionId(formClass), formClass.getId())));