LCOV - code coverage report
Current view: top level - core/db - SPDbField.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 201 247 81.4 %
Date: 2024-05-12 00:16:13 Functions: 267 298 89.6 %

          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_ */

Generated by: LCOV version 1.14