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
105
106
107
108
109
110
111
112
113
114
|
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "referencefieldvalue.h"
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/util/stringfmt.h>
#include <cassert>
#include <ostream>
using vespalib::IllegalArgumentException;
using vespalib::make_string;
namespace document {
ReferenceFieldValue::ReferenceFieldValue()
: FieldValue(Type::REFERENCE),
_dataType(nullptr),
_documentId()
{
}
ReferenceFieldValue::ReferenceFieldValue(const ReferenceDataType& dataType)
: FieldValue(Type::REFERENCE),
_dataType(&dataType),
_documentId()
{
}
ReferenceFieldValue::ReferenceFieldValue(const ReferenceDataType& dataType, const DocumentId& documentId)
: FieldValue(Type::REFERENCE),
_dataType(&dataType),
_documentId(documentId)
{
requireIdOfMatchingType(_documentId, _dataType->getTargetType());
}
ReferenceFieldValue::~ReferenceFieldValue() = default;
void ReferenceFieldValue::requireIdOfMatchingType(
const DocumentId& id, const DocumentType& type)
{
if (id.getDocType() != type.getName()) {
throw IllegalArgumentException(
make_string("Can't assign document ID '%s' (of type '%s') to "
"reference of document type '%s'",
id.toString().c_str(),
vespalib::string(id.getDocType()).c_str(),
type.getName().c_str()),
VESPA_STRLOC);
}
}
FieldValue& ReferenceFieldValue::assign(const FieldValue& rhs) {
const auto* refValueRhs(dynamic_cast<const ReferenceFieldValue*>(&rhs));
if (refValueRhs == nullptr) {
throw IllegalArgumentException(
make_string("Can't assign field value of type %s to "
"a ReferenceFieldValue",
rhs.getDataType()->getName().c_str()),
VESPA_STRLOC);
}
if (refValueRhs == this) {
return *this;
}
_documentId = refValueRhs->_documentId;
_dataType = refValueRhs->_dataType;
return *this;
}
void ReferenceFieldValue::setDeserializedDocumentId(const DocumentId& id) {
assert(_dataType != nullptr);
requireIdOfMatchingType(id, _dataType->getTargetType());
_documentId = id;
// Pre-cache GID to ensure it's not attempted lazily initialized later in a racing manner.
(void) _documentId.getGlobalId();
}
ReferenceFieldValue* ReferenceFieldValue::clone() const {
assert(_dataType != nullptr);
if (hasValidDocumentId()) {
return new ReferenceFieldValue(*_dataType, _documentId);
} else {
return new ReferenceFieldValue(*_dataType);
}
}
int ReferenceFieldValue::compare(const FieldValue& rhs) const {
const int parentCompare = FieldValue::compare(rhs);
if (parentCompare != 0) {
return parentCompare;
}
// Type equality is checked by the parent.
const auto& refValueRhs(dynamic_cast<const ReferenceFieldValue&>(rhs));
// TODO PERF: DocumentId does currently _not_ expose any methods that
// cheaply allow an ordering to be established. Only (in)equality operators.
// IdString::operator== is already implemented in the same way as this, so
// don't put this code in your inner loops, kids!
return _documentId.toString().compare(refValueRhs._documentId.toString());
}
void ReferenceFieldValue::print(std::ostream& os, bool verbose, const std::string& indent) const {
(void) verbose;
assert(_dataType != nullptr);
os << indent << "ReferenceFieldValue(" << *_dataType << ", DocumentId(" << _documentId << "))";
}
void ReferenceFieldValue::accept(FieldValueVisitor& visitor) {
visitor.visit(*this);
}
void ReferenceFieldValue::accept(ConstFieldValueVisitor& visitor) const {
visitor.visit(*this);
}
} // document
|