Search in sources :

Example 21 with FormulaNode

use of org.activityinfo.model.formula.FormulaNode in project activityinfo by bedatadriven.

the class FormScanBatch method computePermissionFilter.

private Slot<TableFilter> computePermissionFilter(ResourceId formId) {
    FormPermissions permissions = supervisor.getFormPermissions(formId);
    if (!permissions.isVisible()) {
        return new PendingSlot<>(TableFilter.NONE_SELECTED);
    }
    if (!permissions.hasVisibilityFilter()) {
        return new PendingSlot<>(TableFilter.ALL_SELECTED);
    }
    // Otherwise apply per-record permissions
    try {
        FormTreeBuilder formTreeBuilder = new FormTreeBuilder(formClassProvider);
        FormTree formTree = formTreeBuilder.queryTree(formId);
        FormulaNode formula = FormulaParser.parse(permissions.getViewFilter());
        QueryEvaluator evaluator = new QueryEvaluator(FilterLevel.NONE, formTree, this);
        Slot<ColumnView> filterView = evaluator.evaluateExpression(formula);
        return new MemoizedSlot<>(filterView, new Function<ColumnView, TableFilter>() {

            @Override
            public TableFilter apply(ColumnView columnView) {
                return new TableFilter(columnView);
            }
        });
    } catch (Exception e) {
        LOGGER.log(Level.SEVERE, "Failed to parse visibility filter", e);
        LOGGER.severe("Error parsing visibility filter '" + permissions.getViewFilter() + " in form " + formId + ": " + e.getMessage() + ". " + "For security reasons, no results will be shown");
        return new PendingSlot<>(TableFilter.NONE_SELECTED);
    }
}
Also used : FormPermissions(org.activityinfo.model.form.FormPermissions) ColumnView(org.activityinfo.model.query.ColumnView) FormTreeBuilder(org.activityinfo.model.formTree.FormTreeBuilder) FormulaNode(org.activityinfo.model.formula.FormulaNode) FormTree(org.activityinfo.model.formTree.FormTree)

Example 22 with FormulaNode

use of org.activityinfo.model.formula.FormulaNode in project activityinfo by bedatadriven.

the class NodeMatch method joinsTo.

private static List<JoinNode> joinsTo(List<List<FormTree.Node>> partitions, Optional<StatFunction> aggregation) {
    /*
         *  Given a parent: "Site.Location.Territoire.District"
         *  This is represented as a tree of nodes:
         *      District -> Territoire -> Location -> Site
         *      
         *  We want to turn into a list of joins: 
         *      (site field -> form site), 
         *      (location field -> form school),
         *      (field territoire -> form Territoire)
         *      (field district -> form District)
         */
    LinkedList<JoinNode> joins = new LinkedList<>();
    for (int i = 0; i < partitions.size() - 1; i++) {
        // Reference field that functions as a foreign key
        List<FormTree.Node> left = partitions.get(i);
        FormField leftField = left.get(0).getField();
        ResourceId leftFormId = left.get(0).getDefiningFormClass().getId();
        FormulaNode leftFieldExpr = toExpr(left);
        // "RIGHT" side
        // Joining fom left to right using resource ids (primary key)
        List<FormTree.Node> right = partitions.get(i + 1);
        ResourceId rightFormId = right.get(0).getDefiningFormClass().getId();
        if (leftField.getType() instanceof ReferenceType) {
            // Join based on the (left) foreign key ==> (right) primary key
            joins.add(new JoinNode(JoinType.REFERENCE, leftFormId, leftFieldExpr, rightFormId, Optional.<StatFunction>absent()));
        } else if (leftField.getType() instanceof SubFormReferenceType) {
            joins.add(new JoinNode(JoinType.SUBFORM, leftFormId, new SymbolNode(ColumnModel.ID_SYMBOL), rightFormId, aggregation));
        } else {
            throw new IllegalStateException("Invalid field for joining: " + leftField.getType());
        }
    }
    return joins;
}
Also used : JoinNode(org.activityinfo.store.query.shared.join.JoinNode) SymbolNode(org.activityinfo.model.formula.SymbolNode) FormulaNode(org.activityinfo.model.formula.FormulaNode) JoinNode(org.activityinfo.store.query.shared.join.JoinNode) LinkedList(java.util.LinkedList) SubFormReferenceType(org.activityinfo.model.type.subform.SubFormReferenceType) ReferenceType(org.activityinfo.model.type.ReferenceType) SubFormReferenceType(org.activityinfo.model.type.subform.SubFormReferenceType) SymbolNode(org.activityinfo.model.formula.SymbolNode) FormulaNode(org.activityinfo.model.formula.FormulaNode) ResourceId(org.activityinfo.model.resource.ResourceId) StatFunction(org.activityinfo.model.formula.functions.StatFunction) FormField(org.activityinfo.model.form.FormField)

Example 23 with FormulaNode

use of org.activityinfo.model.formula.FormulaNode in project activityinfo by bedatadriven.

the class NodeMatch method toExpr.

private static FormulaNode toExpr(List<FormTree.Node> partition) {
    Iterator<FormTree.Node> it = partition.iterator();
    FormulaNode expr = new SymbolNode(it.next().getFieldId());
    while (it.hasNext()) {
        expr = new CompoundExpr(expr, new SymbolNode(it.next().getFieldId()));
    }
    return expr;
}
Also used : CompoundExpr(org.activityinfo.model.formula.CompoundExpr) SymbolNode(org.activityinfo.model.formula.SymbolNode) FormulaNode(org.activityinfo.model.formula.FormulaNode) SymbolNode(org.activityinfo.model.formula.SymbolNode) FormulaNode(org.activityinfo.model.formula.FormulaNode) JoinNode(org.activityinfo.store.query.shared.join.JoinNode)

Example 24 with FormulaNode

use of org.activityinfo.model.formula.FormulaNode in project activityinfo by bedatadriven.

the class LookupKeySetTest method simpleHierarchyTest.

/**
 * In the case of a simple hierarchy, we are referencing a single form that
 * in turn has key reference fields.
 *
 * For example, if the field references a Village form, this should yield:
 *
 * <pre>
 *     Province.Name
 *        ^
 *        |
 *     District.Name
 *        ^
 *        |
 *     Village.Name
 * </pre>
 *
 * All fields are required because we ultimately need the reference to the village record.
 */
@Test
public void simpleHierarchyTest() {
    TestingStorageProvider catalog = new TestingStorageProvider();
    NfiForm nfiForm = catalog.getNfiForm();
    VillageForm villageForm = catalog.getVillageForm();
    AdminLevelForm territoryForm = catalog.getVillageForm().getParentForm();
    AdminLevelForm provinceForm = territoryForm.getParentForm().get();
    FormTree formTree = catalog.getFormTree(nfiForm.getFormId());
    LookupKeySet lookupKeySet = new LookupKeySet(formTree, nfiForm.getVillageField());
    // Keys need to be topologically sorted,
    // with parent keys preceding child keys in the list
    assertThat(lookupKeySet.getKey(0).getKeyLabel(), equalTo("Province Name"));
    assertThat(lookupKeySet.getKey(1).getKeyLabel(), equalTo("Territory Name"));
    assertThat(lookupKeySet.getKey(2).getKeyLabel(), equalTo("Village Name"));
    SymbolNode villageName = Formulas.symbol(villageForm.getNameField().getId());
    SymbolNode villageTerritory = new SymbolNode(villageForm.getAdminFieldId());
    FormulaNode territoryName = new CompoundExpr(villageTerritory, territoryForm.getNameFieldId());
    FormulaNode territoryProvince = new CompoundExpr(villageTerritory, territoryForm.getParentFieldId());
    FormulaNode provinceName = new CompoundExpr(territoryProvince, provinceForm.getNameFieldId());
    assertThat(lookupKeySet.getLeafKeys(), hasSize(1));
    LookupKey leafKey = Iterables.getOnlyElement(lookupKeySet.getLeafKeys());
    assertThat(leafKey.getKeyFormulas().values(), containsInAnyOrder(villageName, territoryName, provinceName));
}
Also used : CompoundExpr(org.activityinfo.model.formula.CompoundExpr) SymbolNode(org.activityinfo.model.formula.SymbolNode) LookupKeySet(org.activityinfo.model.formTree.LookupKeySet) FormulaNode(org.activityinfo.model.formula.FormulaNode) FormTree(org.activityinfo.model.formTree.FormTree) LookupKey(org.activityinfo.model.formTree.LookupKey) Test(org.junit.Test)

Example 25 with FormulaNode

use of org.activityinfo.model.formula.FormulaNode in project activityinfo by bedatadriven.

the class LookupKeySetTest method overlappingHierarchiesParse.

@Test
public void overlappingHierarchiesParse() {
    TestingStorageProvider catalog = setup.getCatalog();
    LocaliteForm localiteForm = catalog.getLocaliteForm();
    FormTree formTree = setup.getFormTree(localiteForm.getFormId());
    LookupKeySet lookupKeySet = new LookupKeySet(formTree, localiteForm.getAdminField());
    Map<LookupKey, FormulaNode> formulas = lookupKeySet.getKeyFormulas(localiteForm.getAdminField().getId());
    ParsedFormula province = new ParsedFormula(formTree, formulas.get(lookupKeySet.getKey(0)).asExpression());
    assertThat(province.isValid(), equalTo(true));
    assertThat(province.getResultType(), instanceOf(TextType.class));
}
Also used : ParsedFormula(org.activityinfo.analysis.ParsedFormula) LookupKeySet(org.activityinfo.model.formTree.LookupKeySet) FormulaNode(org.activityinfo.model.formula.FormulaNode) FormTree(org.activityinfo.model.formTree.FormTree) LookupKey(org.activityinfo.model.formTree.LookupKey) TextType(org.activityinfo.model.type.primitive.TextType) Test(org.junit.Test)

Aggregations

FormulaNode (org.activityinfo.model.formula.FormulaNode)27 SymbolNode (org.activityinfo.model.formula.SymbolNode)8 FormTree (org.activityinfo.model.formTree.FormTree)7 CompoundExpr (org.activityinfo.model.formula.CompoundExpr)7 Test (org.junit.Test)7 LookupKey (org.activityinfo.model.formTree.LookupKey)5 LookupKeySet (org.activityinfo.model.formTree.LookupKeySet)5 ColumnView (org.activityinfo.model.query.ColumnView)4 FormulaParser (org.activityinfo.model.formula.FormulaParser)3 ResourceId (org.activityinfo.model.resource.ResourceId)3 ForeignKeyId (org.activityinfo.store.query.shared.join.ForeignKeyId)3 FormEvalContext (org.activityinfo.model.form.FormEvalContext)2 FormField (org.activityinfo.model.form.FormField)2 FormPermissions (org.activityinfo.model.form.FormPermissions)2 FormulaLexer (org.activityinfo.model.formula.FormulaLexer)2 FieldValue (org.activityinfo.model.type.FieldValue)2 JoinNode (org.activityinfo.store.query.shared.join.JoinNode)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 Optional (com.google.common.base.Optional)1 HashMultimap (com.google.common.collect.HashMultimap)1