aboutsummaryrefslogtreecommitdiffstats
path: root/document/src/vespa/document/fieldvalue/iteratorhandler.h
blob: bbf24b77fb262d7e7e92ca177e71873c783094a6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#pragma once

#include "variablemap.h"
#include "modificationstatus.h"
#include <vector>

namespace document::fieldvalue {

class IteratorHandler {
public:
    class CollectionScope {
    public:
        CollectionScope(IteratorHandler &handler, const FieldValue &value)
                : _handler(handler), _value(value) {
            _handler.handleCollectionStart(_value);
        }

        ~CollectionScope() {
            _handler.handleCollectionEnd(_value);
        }

    private:
        IteratorHandler &_handler;
        const FieldValue &_value;
    };

    class StructScope {
    public:
        StructScope(IteratorHandler &handler, const FieldValue &value)
                : _handler(handler), _value(value) {
            _handler.handleStructStart(_value);
        }

        ~StructScope() {
            _handler.handleStructEnd(_value);
        }

    private:
        IteratorHandler &_handler;
        const FieldValue &_value;
    };

protected:
    class Content {
    public:
        Content(const FieldValue &fv, int weight = 1) : _fieldValue(fv), _weight(weight) {}

        int getWeight() const { return _weight; }

        const FieldValue &getValue() const { return _fieldValue; }

    private:
        const FieldValue &_fieldValue;
        int _weight;
    };

    IteratorHandler();

public:
    virtual ~IteratorHandler();
    void handlePrimitive(uint32_t fid, const FieldValue &fv);

    /**
       Handles a complex type (struct/array/map etc) that is at the end of the
       field path.
       @return Return true if you want to recurse into the members.
    */
    bool handleComplex(const FieldValue &fv);
    void handleCollectionStart(const FieldValue &fv);
    void handleCollectionEnd(const FieldValue &fv);
    void handleStructStart(const FieldValue &fv);
    void handleStructEnd(const FieldValue &fv);
    void setWeight(int weight) { _weight = weight; }
    uint32_t getArrayIndex() const { return _arrayIndexStack.back(); }
    void setArrayIndex(uint32_t index) { _arrayIndexStack.back() = index; }
    ModificationStatus modify(FieldValue &fv) { return doModify(fv); }
    fieldvalue::VariableMap &getVariables() { return _variables; }
    fieldvalue::VariableMap && stealVariables() { return std::move(_variables); }
    void setVariables(fieldvalue::VariableMap vars) { _variables = std::move(vars); }
    virtual bool createMissingPath() const { return false; }
private:
    virtual bool onComplex(const Content &fv) {
        (void) fv;
        return true;
    }

    virtual void onPrimitive(uint32_t fid, const Content &fv);
    virtual void onCollectionStart(const Content &fv) { (void) fv; }
    virtual void onCollectionEnd(const Content &fv) { (void) fv; }
    virtual void onStructStart(const Content &fv) { (void) fv; }
    virtual void onStructEnd(const Content &fv) { (void) fv; }
    virtual ModificationStatus doModify(FieldValue &) { return ModificationStatus::NOT_MODIFIED; };

    // Scratchpad to store pass on weight.
    int getWeight() const { return _weight; }

    int _weight;
    std::vector<uint32_t>   _arrayIndexStack;
    fieldvalue::VariableMap _variables;
};

}