aboutsummaryrefslogtreecommitdiffstats
path: root/document/src/vespa/document/datatype/structdatatype.h
blob: 73170bbd4f6b3326e8af413a056aa33514490ddc (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
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
/**
 * \class document::StructDataType
 * \ingroup datatype
 *
 * \brief A data type describing what can be contained in a struct field value.
 *
 * Describes what can be stored in a struct.
 */
#pragma once

#include "structureddatatype.h"
#include <vespa/vespalib/stllike/hash_map.h>

namespace document {

class StructDataType final : public StructuredDataType {
public:
    using UP = std::unique_ptr<StructDataType>;
    using SP = std::shared_ptr<StructDataType>;

    StructDataType(vespalib::stringref name);
    StructDataType(vespalib::stringref name, int32_t id);
    StructDataType(const StructDataType & rhs); // TODO avoid using this
    StructDataType & operator=(const StructDataType & rhs) = delete;
    ~StructDataType();

    /**
     * @throws vespalib::IllegalArgumentException if field conflicts with
     *                                            already existing field.
     */
    void addField(const Field& field);

    /**
     * Similar to addField(field), but does not throw exceptions on errors.
     * Fields that can be added are, and the other ones are skipped. Skipped
     * fields will logs a warning informing about the conflict.
     *
     * This is typically called from DocumentType::inherit() to add the fields
     * that does not conflict with existing fields.
     */
    void addInheritedField(const Field& field);

    // Implementation of StructuredDataType
    std::unique_ptr<FieldValue> createFieldValue() const override;
    void print(std::ostream&, bool verbose, const std::string& indent) const override;
    uint32_t getFieldCount() const noexcept override { return _idFieldMap.size(); }

    const Field& getField(vespalib::stringref name) const override;

    /**
     * Retrieves a field based on its ID. To determine which ID to use, we also
     * need the document serialization version.
     */
    const Field& getField(int32_t fieldId) const override;

    bool hasField(vespalib::stringref name) const noexcept override;
    bool hasField(int32_t fieldId) const noexcept override;
    bool hasField(const Field& f) const noexcept {
        return hasField(f.getId());
    }

    Field::Set getFieldSet() const override;
private:
    using StringFieldMap = vespalib::hash_map<vespalib::string, Field::SP>;
    using IntFieldMap = vespalib::hash_map<int32_t, Field::SP>;
    StringFieldMap    _nameFieldMap;
    IntFieldMap       _idFieldMap;

    /** @return "" if not conflicting. Error message otherwise. */
    vespalib::string containsConflictingField(const Field& field) const;
};

}