Line data Source code
1 : /**
2 : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023-2024 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_DB_SPDBFIELD_H_
25 : #define STAPPLER_DB_SPDBFIELD_H_
26 :
27 : #include "SPDbBackendInterface.h"
28 : #include "SPDbQueryList.h"
29 :
30 : namespace STAPPLER_VERSIONIZED stappler::db {
31 :
32 : template <typename F, typename V>
33 : struct FieldOption;
34 :
35 : enum class Type {
36 : None,
37 : Integer, // 64-bit signed integer
38 : Float, // 64-bit float
39 : Boolean, // true/false
40 : Text, // simple text
41 : Bytes, // binary data
42 : Data, // raw Value
43 : Extra, // raw binary object
44 : Object, // linked object (one-to-one connection or endpoint for many-to-one)
45 : Set, // linked set of objects (one-to-many)
46 : Array, // set of raw Value
47 : File,
48 : Image,
49 : View, // immutable predicate-based reference set of objects
50 : FullTextView, // full-text search resource
51 : Virtual,
52 :
53 : Custom
54 : };
55 :
56 : enum class Flags : uint32_t {
57 : /** empty flag */
58 : None = 0,
59 :
60 : Required = 1 << 0, /** field is required to create a new object, this field can not be removed from object */
61 : Protected = 1 << 1, /** field does not appear in client's direct output */
62 : ReadOnly = 1 << 2, /** field can not be modified by client's edit request */
63 :
64 : Reference = 1 << 3, /** object or set stored by reference */
65 : Unique = 1 << 4, /** field or array should contain only unique values */
66 : // deprecated: AutoNamed = 1 << 5, /** field will be automatically filled with new UUID */
67 : AutoCTime = 1 << 6, /** Property will be automatically set to object creation time */
68 : AutoMTime = 1 << 7, /** Property will be automatically update to modification time */
69 : AutoUser = 1 << 8, /** Property will be automatically set to current user (if available) */
70 : Indexed = 1 << 9, /** Create index, that allows select queries on that field */
71 : Admin = 1 << 10, /** Field can be accessed by administrative queries only */
72 : ForceInclude = 1 << 11, /** field will be internally included in all queries (useful for access control) */
73 : ForceExclude = 1 << 12, /** field will be excluded, if not requested directly */
74 : Composed = 1 << 13, /** propagate modification events from objects in that field (for object and set fields) */
75 : Compressed = 1 << 14, /** Try to compress data field with lz-hc (incompatible with pg-cbor) */
76 : Enum = 1 << 15, /** Value is enumeration with fixed (or low-distributed) number of values (enables more effective index in MDB) */
77 : PatternIndexed = (1 << 9) | (1 << 16), /** Create index, that allows select queries with textual patterns (also enables normal index) */
78 : TrigramIndexed = (1 << 9) | (1 << 17), /** enable trigram index on this field (also enables normal index) */
79 : };
80 :
81 : SP_DEFINE_ENUM_AS_MASK(Flags)
82 :
83 2475 : inline bool checkIfComparationIsValid(Type t, Comparation c, Flags f) {
84 2475 : switch (t) {
85 2000 : case Type::Integer:
86 : case Type::Object:
87 2000 : switch (c) {
88 0 : case Comparation::Includes:
89 : case Comparation::Prefix:
90 : case Comparation::Suffix:
91 : case Comparation::WordPart:
92 0 : return false;
93 : break;
94 2000 : default:
95 2000 : return true;
96 : break;
97 : }
98 : break;
99 0 : case Type::Float:
100 0 : switch (c) {
101 0 : case Comparation::Includes:
102 : case Comparation::In:
103 : case Comparation::NotIn:
104 : case Comparation::Prefix:
105 : case Comparation::Suffix:
106 : case Comparation::WordPart:
107 0 : return false;
108 : break;
109 0 : default:
110 0 : return true;
111 : break;
112 : }
113 : break;
114 200 : case Type::Bytes:
115 : case Type::Boolean:
116 200 : switch (c) {
117 200 : case Comparation::Equal:
118 : case Comparation::NotEqual:
119 : case Comparation::IsNull:
120 : case Comparation::IsNotNull:
121 200 : return true;
122 : break;
123 0 : default:
124 0 : return false;
125 : break;
126 : }
127 : break;
128 0 : case Type::Data:
129 : case Type::Extra:
130 : case Type::FullTextView:
131 0 : switch (c) {
132 0 : case Comparation::IsNull:
133 : case Comparation::IsNotNull:
134 0 : return true;
135 : break;
136 0 : default:
137 0 : return false;
138 : break;
139 : }
140 : break;
141 275 : case Type::Text:
142 275 : switch (c) {
143 275 : case Comparation::Equal:
144 : case Comparation::NotEqual:
145 : case Comparation::IsNull:
146 : case Comparation::IsNotNull:
147 : case Comparation::In:
148 : case Comparation::NotIn:
149 275 : return true;
150 : break;
151 0 : case Comparation::Prefix:
152 : case Comparation::Suffix:
153 : case Comparation::WordPart:
154 0 : return ((f & Flags::PatternIndexed) != Flags::None) || ((f & Flags::TrigramIndexed) != Flags::None);
155 : break;
156 0 : default:
157 0 : return false;
158 : break;
159 : }
160 : break;
161 0 : default:
162 0 : return false;
163 : break;
164 : }
165 : return false;
166 : }
167 :
168 : enum class Transform {
169 : None,
170 :
171 : // Text
172 : Text,
173 : Identifier,
174 : Alias,
175 : Url,
176 : Email,
177 : Number,
178 : Hexadecimial,
179 : Base64,
180 :
181 : // Bytes
182 : Uuid,
183 : PublicKey,
184 :
185 : // Extra
186 : Array, // handle extra field as array
187 :
188 : Password, // deprecated
189 : };
190 :
191 : enum class ValidationLevel {
192 : NamesAndTypes,
193 : Slots,
194 : Full,
195 : };
196 :
197 : enum class Linkage {
198 : Auto,
199 : Manual,
200 : None,
201 : };
202 :
203 : using MinLength = stappler::ValueWrapper<size_t, class MinLengthTag>; // min utf8 length for string
204 : using MaxLength = stappler::ValueWrapper<size_t, class MaxLengthTag>; // max utf8 length for string
205 : using PasswordSalt = stappler::ValueWrapper<StringView, class PasswordSaltTag>; // hashing salt for password
206 : using ForeignLink = stappler::ValueWrapper<StringView, class ForeignLinkTag>; // name for foreign linked field
207 : using Documentation = stappler::ValueWrapper<StringView, class DocumentationTag>; // tag for field documentation text
208 :
209 : // policy for images, that do not match bounds
210 : enum class ImagePolicy {
211 : Resize, // resize to match bounds
212 : Reject, // reject input field
213 : };
214 :
215 : // max size for files
216 : using MaxFileSize = stappler::ValueWrapper<size_t, class MaxFileSizeTag>;
217 :
218 : struct MaxImageSize {
219 : size_t width = 128;
220 : size_t height = 128;
221 : ImagePolicy policy = ImagePolicy::Resize;
222 :
223 400 : MaxImageSize(): width(128), height(128), policy(ImagePolicy::Resize) { }
224 525 : MaxImageSize(size_t w, size_t h, ImagePolicy p = ImagePolicy::Resize)
225 525 : : width(w), height(h), policy(p) { }
226 : };
227 :
228 : struct MinImageSize {
229 : size_t width = 0;
230 : size_t height = 0;
231 : ImagePolicy policy = ImagePolicy::Reject;
232 :
233 525 : MinImageSize(): width(0), height(0), policy(ImagePolicy::Reject) { }
234 : MinImageSize(size_t w, size_t h, ImagePolicy p = ImagePolicy::Reject)
235 : : width(w), height(h), policy(p) { }
236 : };
237 :
238 : struct Thumbnail {
239 : size_t width;
240 : size_t height;
241 : String name;
242 :
243 300 : Thumbnail(String && name, size_t w, size_t h)
244 300 : : width(w), height(h), name(std::move(name)) { }
245 : };
246 :
247 : // what to do if object is removed
248 : enum class RemovePolicy {
249 : Cascade, // remove object in set or field
250 : Restrict, // reject request, if object or set is not empty
251 : Reference, // no linkage action, object is reference
252 : StrongReference, // only for Set: no linkage action, objects will be owned
253 : Null, // set object to null
254 : };
255 :
256 : // old-fashion filter fn (use WriteFilterFn instead)
257 : using FilterFn = Function<bool(const Scheme &, Value &)>;
258 :
259 : // function to deduce default value from object data
260 : using DefaultFn = Function<Value(const Value &)>;
261 :
262 : // function to modify out value of object's field to return it to users
263 : using ReadFilterFn = Function<bool(const Scheme &, const Value &obj, Value &value)>;
264 :
265 : // function to modify input value of object's field to write it into storage
266 : using WriteFilterFn = Function<bool(const Scheme &, const Value &patch, Value &value, bool isCreate)>;
267 :
268 : // function to replace previous value of field with another
269 : using ReplaceFilterFn = Function<bool(const Scheme &, const Value &obj, const Value &oldValue, Value &newValue)>;
270 :
271 : // function to deduce root object ids list from object of external scheme
272 : // Used by:
273 : // - View field: to deduce id of root object id from external objects
274 : // - AutoField: to deduce id of object with auto field from external objects
275 : using ViewLinkageFn = Function<Vector<uint64_t>(const Scheme &targetScheme, const Scheme &objScheme, const Value &obj)>;
276 :
277 : // function to deduce view data from object of external scheme
278 : using ViewFn = Function<bool(const Scheme &objScheme, const Value &obj)>;
279 :
280 : // function to extract fulltext search data from object
281 : using FullTextViewFn = Function<FullTextVector(const Scheme &objScheme, const Value &obj)>;
282 :
283 : // function to prepare fulltext query from input string
284 : using FullTextQueryFn = Function<FullTextQuery(const Value &searchData)>;
285 :
286 : using VirtualReadFn = Function<Value(const Scheme &objScheme, const Value &)>;
287 :
288 : using VirtualWriteFn = Function<bool(const Scheme &objScheme, const Value &, Value &)>;
289 :
290 : struct AutoFieldScheme : AllocBase {
291 : using ReqVec = Vector<String>;
292 :
293 : const Scheme &scheme;
294 : ReqVec requiresForAuto; // fields, that should be updated to trigger auto field update
295 :
296 : ViewLinkageFn linkage;
297 : ReqVec requiresForLinking;
298 :
299 : AutoFieldScheme(const Scheme &, ReqVec && = ReqVec(), ViewLinkageFn && = nullptr, ReqVec && = ReqVec());
300 : AutoFieldScheme(const Scheme &, ReqVec &&, ReqVec &&);
301 : };
302 :
303 : struct AutoFieldDef {
304 : Vector<AutoFieldScheme> schemes;
305 : DefaultFn defaultFn;
306 : Vector<String> requireFields; // fields to acquire from field's scheme object when defaultFn is called
307 : };
308 :
309 : // definition for scheme's unique constraints
310 : struct UniqueConstraintDef {
311 : StringView name;
312 : Vector<StringView> fields;
313 : };
314 :
315 : struct CustomFieldInfo {
316 : bool isIndexable = false;
317 : String typeName;
318 :
319 : Function<Value(const FieldCustom &, const ResultCursor &, size_t field)> readFromStorage;
320 : Function<bool(const FieldCustom &, QueryInterface &, StringStream &, const Value &)> writeToStorage;
321 :
322 : Function<String(const FieldCustom &)> getIndexName;
323 : Function<String(const FieldCustom &)> getIndexDefinition;
324 :
325 : Function<bool(const FieldCustom &, Comparation)> isComparationAllowed;
326 :
327 : Function<void(const FieldCustom &, const Scheme &,
328 : stappler::sql::Query<db::Binder, Interface>::WhereContinue &,
329 : Operator, const StringView &, Comparation, const Value &, const Value &)> writeQuery;
330 :
331 : Function<void(const FieldCustom &, const Scheme &,
332 : stappler::sql::Query<db::Binder, Interface>::SelectFrom &,
333 : Comparation cmp, const Value &val, const Value &)> writeFrom;
334 : };
335 :
336 : struct FieldCustom;
337 :
338 : class Field : public AllocBase {
339 : public:
340 : template <typename ... Args> static Field Data(String && name, Args && ... args);
341 : template <typename ... Args> static Field Integer(String && name, Args && ... args);
342 : template <typename ... Args> static Field Float(String && name, Args && ... args);
343 : template <typename ... Args> static Field Boolean(String && name, Args && ... args);
344 : template <typename ... Args> static Field Text(String && name, Args && ... args);
345 : template <typename ... Args> static Field Bytes(String &&name, Args && ... args);
346 : template <typename ... Args> static Field Password(String && name, Args && ... args);
347 : template <typename ... Args> static Field Extra(String &&name, Args && ... args);
348 : template <typename ... Args> static Field Extra(String &&name, stappler::InitializerList<Field> &&, Args && ... args);
349 : template <typename ... Args> static Field File(String &&name, Args && ... args);
350 : template <typename ... Args> static Field Image(String &&name, Args && ... args);
351 : template <typename ... Args> static Field Object(String &&name, Args && ... args);
352 : template <typename ... Args> static Field Set(String && name, Args && ... args);
353 : template <typename ... Args> static Field Array(String && name, Args && ... args);
354 : template <typename ... Args> static Field View(String && name, Args && ... args);
355 : template <typename ... Args> static Field FullTextView(String && name, Args && ... args);
356 : template <typename ... Args> static Field Virtual(String && name, Args && ... args);
357 : template <typename ... Args> static Field Custom(FieldCustom *);
358 :
359 : struct Slot : public AllocBase {
360 : public:
361 0 : virtual ~Slot() { }
362 :
363 : template <typename F, typename T>
364 7802 : static void setOptions(F &f, T && t) {
365 7802 : FieldOption<F, typename std::remove_reference<T>::type>::assign(f, std::forward<T>(t));
366 7801 : }
367 :
368 : template <typename F, typename T, typename ... Args>
369 1806 : static void setOptions(F &f, T && t, Args && ... args) {
370 1806 : setOptions(f, std::forward<T>(t));
371 1806 : setOptions(f, std::forward<Args>(args)...);
372 1806 : }
373 :
374 : template <typename F>
375 2025 : static void init(F &f) { };
376 :
377 : template <typename F, typename ... Args>
378 5868 : static void init(F &f, Args && ... args) {
379 5868 : setOptions(f, std::forward<Args>(args)...);
380 5868 : };
381 :
382 7947 : Slot(String && n, Type t) : name(n), type(t) { }
383 :
384 292825 : StringView getName() const { return name; }
385 414875 : bool hasFlag(Flags f) const { return ((flags & f) != Flags::None); }
386 1120222 : Type getType() const { return type; }
387 : bool isProtected() const;
388 10200 : Transform getTransform() const { return transform; }
389 :
390 65750 : virtual bool isSimpleLayout() const { return type == Type::Integer || type == Type::Float ||
391 60175 : type == Type::Boolean || type == Type::Text || type == Type::Bytes ||
392 149225 : type == Type::Data || type == Type::Extra || type == Type::Virtual; }
393 :
394 34225 : virtual bool isDataLayout() const { return type == Type::Data || type == Type::Extra; }
395 :
396 4375 : bool isIndexed() const { return hasFlag(Flags::Indexed) || transform == Transform::Alias || type == Type::Object; }
397 136000 : bool isFile() const { return type == Type::File || type == Type::Image; }
398 :
399 : virtual bool hasDefault() const;
400 : virtual Value getDefault(const Value &patch) const;
401 :
402 : virtual bool transformValue(const Scheme &, const Value &, Value &, bool isCreate) const;
403 : virtual void hash(StringStream &stream, ValidationLevel l) const;
404 :
405 : Value def;
406 : String name;
407 : String documentation;
408 : Flags flags = Flags::None;
409 : Type type = Type::None;
410 : Transform transform = Transform::None;
411 : DefaultFn defaultFn;
412 :
413 : ReadFilterFn readFilterFn;
414 : WriteFilterFn writeFilterFn;
415 : ReplaceFilterFn replaceFilterFn;
416 :
417 : AutoFieldDef autoField;
418 :
419 : size_t inputSizeHint = 0;
420 :
421 : const Scheme *owner = nullptr;
422 : const Field::Slot *root = nullptr;
423 : };
424 :
425 292625 : StringView getName() const { return slot->getName(); }
426 1120097 : Type getType() const { return slot->getType(); }
427 2475 : Flags getFlags() const { return slot->flags; }
428 10200 : Transform getTransform() const { return slot->getTransform(); }
429 250 : Value getDefault(const Value &patch) const { return slot->getDefault(patch); }
430 :
431 335425 : bool hasFlag(Flags f) const { return slot->hasFlag(f); }
432 45525 : bool hasDefault() const { return slot->hasDefault(); }
433 :
434 37375 : bool isProtected() const { return slot->isProtected(); }
435 105775 : bool isSimpleLayout() const { return slot->isSimpleLayout(); }
436 34225 : bool isDataLayout() const { return slot->isDataLayout(); }
437 4375 : bool isIndexed() const { return slot->isIndexed(); }
438 136000 : bool isFile() const { return slot->isFile(); }
439 : bool isReference() const;
440 :
441 : const Scheme * getForeignScheme() const;
442 :
443 0 : void hash(StringStream &stream, ValidationLevel l) const { slot->hash(stream, l); }
444 :
445 : bool transform(const Scheme &, int64_t, Value &, bool isCreate = false) const;
446 : bool transform(const Scheme &, const Value &, Value &, bool isCreate = false) const;
447 :
448 500 : explicit operator bool () const { return slot != nullptr; }
449 :
450 : template <typename SlotType = Slot>
451 69272 : auto getSlot() const -> const SlotType * { return static_cast<const SlotType *>(slot); }
452 :
453 : Value getTypeDesc() const;
454 :
455 7971 : Field(const Slot *s) : slot(s) { }
456 :
457 : Field(const Field & s) = default;
458 : Field &operator=(const Field & s) = default;
459 :
460 : Field(Field && s) = default;
461 : Field &operator=(Field && s) = default;
462 :
463 : protected:
464 : const Slot *slot;
465 : };
466 :
467 :
468 : struct FieldText : Field::Slot {
469 0 : virtual ~FieldText() { }
470 :
471 : template <typename ... Args>
472 2148 : FieldText(String && n, Type t, Args && ... args) : Field::Slot(std::move(n), t) {
473 2148 : init<FieldText, Args...>(*this, std::forward<Args>(args)...);
474 2148 : }
475 :
476 : virtual bool transformValue(const Scheme &, const Value &, Value &, bool isCreate) const override;
477 : virtual void hash(StringStream &stream, ValidationLevel l) const override;
478 :
479 : size_t minLength = config::FIELD_TEXT_DEFAULT_MIN_SIZE, maxLength = config::FIELD_TEXT_DEFAULT_MAX_SIZE;
480 : };
481 :
482 : struct FieldPassword : Field::Slot {
483 0 : virtual ~FieldPassword() { }
484 :
485 : template <typename ... Args>
486 77 : FieldPassword(String && n, Args && ... args) : Field::Slot(std::move(n), Type::Bytes) {
487 77 : init<FieldPassword, Args...>(*this, std::forward<Args>(args)...);
488 77 : transform = Transform::Password;
489 77 : }
490 :
491 : virtual bool transformValue(const Scheme &, const Value &, Value &, bool isCreate) const override;
492 : virtual void hash(StringStream &stream, ValidationLevel l) const override;
493 :
494 : size_t minLength = config::FIELD_TEXT_DEFAULT_MIN_SIZE, maxLength = config::FIELD_TEXT_DEFAULT_MAX_SIZE;
495 : StringView salt = config::FIELD_PASSWORD_DEFAULT_SALT;
496 : };
497 :
498 : struct FieldExtra : Field::Slot {
499 0 : virtual ~FieldExtra() { }
500 :
501 : template <typename ... Args>
502 325 : FieldExtra(String && n, Args && ... args) : Field::Slot(std::move(n), Type::Extra) {
503 325 : init<FieldExtra, Args...>(*this, std::forward<Args>(args)...);
504 325 : }
505 :
506 : virtual bool hasDefault() const override;
507 : virtual Value getDefault(const Value &) const override;
508 :
509 : virtual bool transformValue(const Scheme &, const Value &, Value &, bool isCreate) const override;
510 : virtual void hash(StringStream &stream, ValidationLevel l) const override;
511 :
512 : Map<String, Field> fields;
513 : };
514 :
515 : struct FieldFile : Field::Slot {
516 0 : virtual ~FieldFile() { }
517 :
518 : template <typename ... Args>
519 125 : FieldFile(String && n, Args && ... args) : Field::Slot(std::move(n), Type::File) {
520 125 : init<FieldFile, Args...>(*this, std::forward<Args>(args)...);
521 125 : }
522 :
523 : virtual void hash(StringStream &stream, ValidationLevel l) const override;
524 :
525 : size_t maxSize = config::FIELD_FILE_DEFAULT_MAX_SIZE;
526 : Vector<String> allowedTypes;
527 : };
528 :
529 : struct FieldImage : Field::Slot {
530 0 : virtual ~FieldImage() { }
531 :
532 : template <typename ... Args>
533 400 : FieldImage(String && n, Args && ... args) : Field::Slot(std::move(n), Type::Image) {
534 400 : init<FieldImage, Args...>(*this, std::forward<Args>(args)...);
535 400 : }
536 :
537 : virtual void hash(StringStream &stream, ValidationLevel l) const override;
538 :
539 : size_t maxSize = config::FIELD_FILE_DEFAULT_MAX_SIZE;
540 : Vector<String> allowedTypes;
541 : MaxImageSize maxImageSize;
542 : MinImageSize minImageSize;
543 : Vector<Thumbnail> thumbnails;
544 : bool primary = true;
545 : };
546 :
547 : struct FieldObject : Field::Slot {
548 0 : virtual ~FieldObject() { }
549 :
550 : template <typename ... Args>
551 625 : FieldObject(String && n, Type t, Args && ... args) : Field::Slot(std::move(n), t) {
552 625 : init<FieldObject, Args...>(*this, std::forward<Args>(args)...);
553 625 : if (t == Type::Set && (stappler::toInt(flags) & stappler::toInt(Flags::Reference))) {
554 100 : if (onRemove != RemovePolicy::Reference && onRemove != RemovePolicy::StrongReference) {
555 0 : onRemove = RemovePolicy::Reference;
556 : }
557 : }
558 625 : if (t == Type::Set && (onRemove == RemovePolicy::Reference || onRemove == RemovePolicy::StrongReference)) {
559 100 : flags |= Flags::Reference;
560 : }
561 625 : }
562 :
563 : virtual bool transformValue(const Scheme &, const Value &, Value &, bool isCreate) const override;
564 : virtual void hash(StringStream &stream, ValidationLevel l) const override;
565 :
566 : const Scheme *scheme = nullptr;
567 : RemovePolicy onRemove = RemovePolicy::Null;
568 : Linkage linkage = Linkage::Auto;
569 : StringView link;
570 : };
571 :
572 : struct FieldArray : Field::Slot {
573 0 : virtual ~FieldArray() { }
574 :
575 : template <typename ... Args>
576 150 : FieldArray(String && n, Args && ... args) : Field::Slot(std::move(n), Type::Array), tfield(new FieldText("", Type::Text)) {
577 150 : init<FieldArray, Args...>(*this, std::forward<Args>(args)...);
578 150 : }
579 :
580 : virtual bool transformValue(const Scheme &, const Value &, Value &, bool isCreate) const override;
581 : virtual void hash(StringStream &stream, ValidationLevel l) const override;
582 :
583 : Field tfield;
584 : };
585 :
586 : struct FieldView : Field::Slot {
587 : enum DeltaOptions {
588 : Delta
589 : };
590 :
591 0 : virtual ~FieldView() { }
592 :
593 : template <typename ... Args>
594 100 : FieldView(String && n, Args && ... args) : Field::Slot(std::move(n), Type::View) {
595 100 : init<FieldView, Args...>(*this, std::forward<Args>(args)...);
596 100 : }
597 :
598 0 : virtual bool transformValue(const Scheme &, const Value &, Value &, bool isCreate) const override { return false; }
599 :
600 : const Scheme *scheme = nullptr;
601 : Vector<String> requireFields;
602 : ViewLinkageFn linkage;
603 : ViewFn viewFn;
604 : bool delta = false;
605 : };
606 :
607 : struct FieldFullTextView : Field::Slot {
608 0 : virtual ~FieldFullTextView() { }
609 :
610 : template <typename ... Args>
611 100 : FieldFullTextView(String && n, Args && ... args) : Field::Slot(std::move(n), Type::FullTextView) {
612 100 : init<FieldFullTextView, Args...>(*this, std::forward<Args>(args)...);
613 100 : }
614 :
615 0 : virtual bool transformValue(const Scheme &, const Value &, Value &, bool isCreate) const override { return false; }
616 :
617 : FullTextQuery parseQuery(const Value &) const;
618 :
619 : Vector<String> requireFields;
620 : FullTextViewFn viewFn;
621 : FullTextQueryFn queryFn;
622 :
623 : search::Normalization normalization = search::Normalization::Default;
624 : const search::Configuration *searchConfiguration = nullptr;
625 : };
626 :
627 : struct FieldCustom : Field::Slot {
628 0 : virtual ~FieldCustom() { }
629 :
630 : template <typename ... Args>
631 375 : FieldCustom(String && n, Args && ... args) : Field::Slot(std::move(n), Type::Custom) {
632 375 : init<FieldCustom, Args...>(*this, std::forward<Args>(args)...);
633 375 : }
634 :
635 : virtual StringView getDriverTypeName() const = 0;
636 : };
637 :
638 : struct FieldVirtual : Field::Slot {
639 0 : virtual ~FieldVirtual() { }
640 :
641 : template <typename ... Args>
642 50 : FieldVirtual(String && n, Args && ... args) : Field::Slot(std::move(n), Type::Virtual) {
643 50 : init<FieldVirtual, Args...>(*this, std::forward<Args>(args)...);
644 50 : }
645 :
646 0 : virtual void hash(StringStream &stream, ValidationLevel l) const override { }
647 : virtual bool transformValue(const Scheme &, const Value &, Value &, bool isCreate) const override;
648 :
649 : Vector<String> requireFields;
650 : VirtualReadFn readFn;
651 : VirtualWriteFn writeFn;
652 : };
653 :
654 500 : template <typename ... Args> Field Field::Data(String && name, Args && ... args) {
655 500 : auto newSlot = new Field::Slot(std::move(name), Type::Data);
656 500 : Slot::init<Field::Slot>(*newSlot, std::forward<Args>(args)...);
657 500 : newSlot->inputSizeHint = config::FIELD_EXTRA_DEFAULT_HINT_SIZE;
658 500 : return Field(newSlot);
659 : }
660 :
661 2497 : template <typename ... Args> Field Field::Integer(String && name, Args && ... args) {
662 2497 : auto newSlot = new Field::Slot(std::move(name), Type::Integer);
663 2496 : Slot::init<Field::Slot>(*newSlot, std::forward<Args>(args)...);
664 2497 : return Field(newSlot);
665 : }
666 :
667 100 : template <typename ... Args> Field Field::Float(String && name, Args && ... args) {
668 100 : auto newSlot = new Field::Slot(std::move(name), Type::Float);
669 100 : Slot::init<Field::Slot>(*newSlot, std::forward<Args>(args)...);
670 100 : return Field(newSlot);
671 : }
672 :
673 321 : template <typename ... Args> Field Field::Boolean(String && name, Args && ... args) {
674 321 : auto newSlot = new Field::Slot(std::move(name), Type::Boolean);
675 321 : Slot::init<Field::Slot>(*newSlot, std::forward<Args>(args)...);
676 321 : return Field(newSlot);
677 : }
678 :
679 1848 : template <typename ... Args> Field Field::Text(String && name, Args && ... args) {
680 1848 : return Field(new FieldText(std::move(name), Type::Text, std::forward<Args>(args)...));
681 : }
682 :
683 150 : template <typename ... Args> Field Field::Bytes(String &&name, Args && ... args) {
684 150 : return Field(new FieldText(std::move(name), Type::Bytes, std::forward<Args>(args)...));
685 : }
686 :
687 77 : template <typename ... Args> Field Field::Password(String && name, Args && ... args) {
688 77 : return Field(new FieldPassword(std::move(name), std::forward<Args>(args)...));
689 : }
690 :
691 325 : template <typename ... Args> Field Field::Extra(String &&name, Args && ... args) {
692 325 : auto newSlot = new FieldExtra(std::move(name), std::forward<Args>(args)...);
693 325 : newSlot->inputSizeHint = config::FIELD_EXTRA_DEFAULT_HINT_SIZE;
694 325 : return Field(newSlot);
695 : }
696 :
697 : template <typename ... Args> Field Field::Extra(String &&name, stappler::InitializerList<Field> &&f, Args && ... args) {
698 : auto newSlot = new FieldExtra(std::move(name), move(f), std::forward<Args>(args)...);
699 : newSlot->inputSizeHint = config::FIELD_EXTRA_DEFAULT_HINT_SIZE;
700 : return Field(newSlot);
701 : }
702 :
703 125 : template <typename ... Args> Field Field::File(String &&name, Args && ... args) {
704 125 : return Field(new FieldFile(std::move(name), std::forward<Args>(args)...));
705 : }
706 :
707 400 : template <typename ... Args> Field Field::Image(String &&name, Args && ... args) {
708 400 : return Field(new FieldImage(std::move(name), std::forward<Args>(args)...));
709 : }
710 :
711 300 : template <typename ... Args> Field Field::Object(String &&name, Args && ... args) {
712 300 : return Field(new FieldObject(std::move(name), Type::Object, std::forward<Args>(args)...));
713 : }
714 :
715 325 : template <typename ... Args> Field Field::Set(String && name, Args && ... args) {
716 325 : return Field(new FieldObject(std::move(name), Type::Set, std::forward<Args>(args)...));
717 : }
718 :
719 150 : template <typename ... Args> Field Field::Array(String && name, Args && ... args) {
720 150 : return Field(new FieldArray(std::move(name), std::forward<Args>(args)...));
721 : }
722 :
723 100 : template <typename ... Args> Field Field::View(String && name, Args && ... args) {
724 100 : return Field(new FieldView(std::move(name), std::forward<Args>(args)...));
725 : }
726 :
727 100 : template <typename ... Args> Field Field::FullTextView(String && name, Args && ... args) {
728 100 : return Field(new FieldFullTextView(std::move(name), std::forward<Args>(args)...));
729 : }
730 :
731 50 : template <typename ... Args> Field Field::Virtual(String && name, Args && ... args) {
732 50 : return Field(new FieldVirtual(std::move(name), std::forward<Args>(args)...));
733 : }
734 :
735 375 : template <typename ... Args> Field Field::Custom(FieldCustom *custom) {
736 375 : return Field(custom);
737 : }
738 :
739 : template <typename F> struct FieldOption<F, Flags> {
740 3173 : static inline void assign(F & f, Flags flags) { f.flags |= flags; }
741 : };
742 :
743 : template <typename F> struct FieldOption<F, FilterFn> {
744 : static inline void assign(F & f, const FilterFn &fn) {
745 : f.writeFilterFn = WriteFilterFn([fn] (const Scheme &scheme, const Value &patch, Value &value, bool isCreate) -> bool {
746 : return fn(scheme, value);
747 : });
748 : }
749 : };
750 :
751 : template <typename F> struct FieldOption<F, WriteFilterFn> {
752 25 : static inline void assign(F & f, const WriteFilterFn &fn) { f.writeFilterFn = fn; }
753 : };
754 :
755 : template <typename F> struct FieldOption<F, ReadFilterFn> {
756 25 : static inline void assign(F & f, const ReadFilterFn &fn) { f.readFilterFn = fn; }
757 : };
758 :
759 : template <typename F> struct FieldOption<F, ReplaceFilterFn> {
760 : static inline void assign(F & f, const ReplaceFilterFn &fn) { f.replaceFilterFn = fn; }
761 : };
762 :
763 : template <typename F> struct FieldOption<F, DefaultFn> {
764 75 : static inline void assign(F & f, const DefaultFn &fn) { f.defaultFn = fn; }
765 : };
766 :
767 : template <typename F> struct FieldOption<F, Function<Value()>> {
768 : static inline void assign(F & f, const Function<Value()> &fn) {
769 : f.defaultFn = DefaultFn([fn] (const Value &) -> Value { return fn(); });
770 : }
771 : };
772 :
773 : template <typename F> struct FieldOption<F, Transform> {
774 600 : static inline void assign(F & f, Transform t) { f.transform = t; }
775 : };
776 :
777 : template <typename F> struct FieldOption<F, Documentation> {
778 : static inline void assign(F & f, Documentation && doc) { f.documentation = doc.get(); }
779 : };
780 :
781 : template <typename F> struct FieldOption<F, MinLength> {
782 402 : static inline void assign(F & f, MinLength l) { f.minLength = l.get(); }
783 : };
784 :
785 : template <typename F> struct FieldOption<F, MaxLength> {
786 277 : static inline void assign(F & f, MaxLength l) { f.maxLength = l.get(); }
787 : };
788 :
789 : template <typename F> struct FieldOption<F, Value> {
790 225 : static inline void assign(F & f, Value && v) { f.def = std::move(v); }
791 : };
792 :
793 : template <typename F> struct FieldOption<F, PasswordSalt> {
794 75 : static inline void assign(F & f, PasswordSalt && s) { f.salt = s.get().pdup(f.name.get_allocator()); }
795 : };
796 :
797 : template <typename F> struct FieldOption<F, ForeignLink> {
798 100 : static inline void assign(F & f, ForeignLink && s) { f.link = s.get().pdup(f.name.get_allocator()); f.linkage = Linkage::Manual; }
799 : };
800 :
801 : template <typename F> struct FieldOption<F, Vector<Field>> {
802 325 : static inline void assign(F & f, Vector<Field> && s) {
803 1100 : for (auto &it : s) {
804 775 : const_cast<Field::Slot *>(it.getSlot())->root = &f;
805 775 : f.fields.emplace(it.getName().str<Interface>(), it);
806 : }
807 325 : }
808 : };
809 :
810 : template <typename F> struct FieldOption<F, AutoFieldDef> {
811 75 : static inline void assign(F & f, AutoFieldDef &&def) {
812 75 : f.autoField = std::move(def);
813 75 : }
814 : };
815 :
816 : template <typename F> struct FieldOption<F, std::initializer_list<Field>> {
817 : static inline void assign(F & f, std::initializer_list<Field> && s) {
818 : for (auto &it : s) {
819 : const_cast<Field::Slot *>(it.getSlot())->root = &f;
820 : f.fields.emplace(it.getName().str<Interface>(), it);
821 : }
822 : }
823 : };
824 :
825 : template <typename F> struct FieldOption<F, MaxFileSize> {
826 125 : static inline void assign(F & f, MaxFileSize l) { f.maxSize = l.get(); }
827 : };
828 :
829 : template <typename F> struct FieldOption<F, Vector<String>> {
830 : static inline void assign(F & f, Vector<String> && l) { f.allowedTypes = std::move(l); }
831 : };
832 :
833 : template <typename F> struct FieldOption<F, MaxImageSize> {
834 400 : static inline void assign(F & f, MaxImageSize && s) { f.maxImageSize = std::move(s); }
835 : };
836 :
837 : template <typename F> struct FieldOption<F, MinImageSize> {
838 : static inline void assign(F & f, MinImageSize && s) { f.minImageSize = std::move(s); }
839 : };
840 :
841 : template <typename F> struct FieldOption<F, Vector<Thumbnail>> {
842 100 : static inline void assign(F & f, Vector<Thumbnail> && s) { f.thumbnails = std::move(s); }
843 : };
844 :
845 : template <typename F> struct FieldOption<F, RemovePolicy> {
846 200 : static inline void assign(F & f, RemovePolicy p) {
847 200 : f.onRemove = p;
848 200 : if (p == RemovePolicy::Reference || p == RemovePolicy::StrongReference) {
849 125 : f.flags |= Flags::Reference;
850 : }
851 200 : }
852 : };
853 :
854 : template <typename F> struct FieldOption<F, Linkage> {
855 100 : static inline void assign(F & f, Linkage p) { f.linkage = p; }
856 : };
857 :
858 : template <typename F> struct FieldOption<F, const Scheme *> {
859 : static inline void assign(F & f, const Scheme *s) { f.scheme = s; }
860 : };
861 : template <typename F> struct FieldOption<F, Scheme> {
862 725 : static inline void assign(F & f, const Scheme &s) { f.scheme = &s; }
863 : };
864 : template <typename F> struct FieldOption<F, const Scheme> {
865 : static inline void assign(F & f, const Scheme &s) { f.scheme = &s; }
866 : };
867 : template <typename F> struct FieldOption<F, Field> {
868 100 : static inline void assign(F & f, Field && s) { f.tfield = s; }
869 : };
870 :
871 : template <> struct FieldOption<FieldArray, Type> {
872 50 : static inline void assign(FieldArray & f, Type type) {
873 50 : switch (type) {
874 25 : case Type::Integer: f.tfield = Field::Integer("value"); break;
875 0 : case Type::Float: f.tfield = Field::Float("value"); break;
876 0 : case Type::Boolean: f.tfield = Field::Boolean("value"); break;
877 25 : case Type::Text: f.tfield = Field::Text("value"); break;
878 0 : case Type::Bytes: f.tfield = Field::Bytes("value"); break;
879 0 : case Type::Data: f.tfield = Field::Data("value"); break;
880 0 : case Type::Extra: f.tfield = Field::Extra("value"); break;
881 0 : default:
882 0 : break;
883 : }
884 50 : }
885 : };
886 :
887 : // view options
888 :
889 : template <> struct FieldOption<FieldView, Vector<String>> {
890 50 : static inline void assign(FieldView & f, Vector<String> && s) {
891 50 : f.requireFields = std::move(s);
892 50 : }
893 : };
894 :
895 : template <> struct FieldOption<FieldFullTextView, Vector<String>> {
896 100 : static inline void assign(FieldFullTextView & f, Vector<String> && s) {
897 100 : f.requireFields = std::move(s);
898 100 : }
899 : };
900 :
901 : template <> struct FieldOption<FieldFullTextView, search::Configuration *> {
902 : static inline void assign(FieldFullTextView & f, const search::Configuration *s) {
903 : f.searchConfiguration = s;
904 : }
905 : };
906 :
907 : template <> struct FieldOption<FieldFullTextView, search::Configuration> {
908 100 : static inline void assign(FieldFullTextView & f, const search::Configuration &s) {
909 100 : f.searchConfiguration = &s;
910 100 : }
911 : };
912 :
913 : template <typename F> struct FieldOption<F, ViewLinkageFn> {
914 : static inline void assign(F & f, ViewLinkageFn && s) {
915 : f.linkage = std::move(s);
916 : }
917 : };
918 :
919 : template <typename F> struct FieldOption<F, ViewFn> {
920 100 : static inline void assign(F & f, ViewFn && s) {
921 100 : f.viewFn = std::move(s);
922 100 : }
923 : };
924 :
925 : template <typename F> struct FieldOption<F, FullTextViewFn> {
926 100 : static inline void assign(F & f, FullTextViewFn && s) {
927 100 : f.viewFn = std::move(s);
928 100 : }
929 : };
930 :
931 : template <typename F> struct FieldOption<F, FullTextQueryFn> {
932 : static inline void assign(F & f, FullTextQueryFn && s) {
933 : f.queryFn = std::move(s);
934 : }
935 : };
936 :
937 : template <typename F> struct FieldOption<F, FieldView::DeltaOptions> {
938 50 : static inline void assign(F & f, FieldView::DeltaOptions d) {
939 50 : if (d == FieldView::Delta) { f.delta = true; } else { f.delta = false; }
940 50 : }
941 : };
942 :
943 : // virtual options
944 :
945 : template <> struct FieldOption<FieldVirtual, Vector<String>> {
946 50 : static inline void assign(FieldVirtual & f, Vector<String> && s) {
947 50 : f.requireFields = std::move(s);
948 50 : }
949 : };
950 :
951 : template <> struct FieldOption<FieldVirtual, VirtualReadFn> {
952 50 : static inline void assign(FieldVirtual & f, VirtualReadFn && r) {
953 50 : f.readFn = std::move(r);
954 50 : }
955 : };
956 :
957 : template <> struct FieldOption<FieldVirtual, VirtualWriteFn> {
958 25 : static inline void assign(FieldVirtual & f, VirtualWriteFn && r) {
959 25 : f.writeFn = std::move(r);
960 25 : }
961 : };
962 :
963 : }
964 :
965 : #endif /* STAPPLER_DB_SPDBFIELD_H_ */
|