ClassFactory.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2018 to 2019 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. #ifndef DFPSR_PERSISTENT_CLASSFACTORY
  24. #define DFPSR_PERSISTENT_CLASSFACTORY
  25. #include "../api/stringAPI.h"
  26. #include "../collection/List.h"
  27. #include <memory>
  28. namespace dsr {
  29. class Persistent;
  30. // Reference method for creating a persistent class
  31. inline std::shared_ptr<Persistent> classConstructor() {
  32. return std::shared_ptr<Persistent>(); // Null
  33. }
  34. // Must be used in each class inheriting from Persistent (both directly and indirectly)
  35. #define PERSISTENT_DECLARATION(CLASS) \
  36. std::shared_ptr<StructureDefinition> getStructure() const override; \
  37. decltype(&classConstructor) getConstructor() const override; \
  38. explicit CLASS(const ReadableString &content);
  39. // Must be used in the implementation of each class inheriting from Persistent
  40. #define PERSISTENT_DEFINITION(CLASS) \
  41. std::shared_ptr<StructureDefinition> CLASS##Type; \
  42. std::shared_ptr<StructureDefinition> CLASS::getStructure() const { \
  43. if (CLASS##Type.get() == nullptr) { \
  44. CLASS##Type = std::make_shared<StructureDefinition>(U ## #CLASS); \
  45. this->declareAttributes(*(CLASS##Type)); \
  46. } \
  47. return CLASS##Type; \
  48. } \
  49. CLASS::CLASS(const ReadableString &content) { \
  50. this->assignValue(content); \
  51. } \
  52. std::shared_ptr<Persistent> CLASS##Constructor() { \
  53. return std::dynamic_pointer_cast<Persistent>(std::make_shared<CLASS>()); \
  54. } \
  55. decltype(&classConstructor) CLASS::getConstructor() const { \
  56. return &CLASS##Constructor; \
  57. }
  58. class PersistentAttribute {
  59. public:
  60. String name; // The name of the attribute
  61. public:
  62. PersistentAttribute() {}
  63. explicit PersistentAttribute(const String &name) : name(name) {}
  64. };
  65. class StructureDefinition {
  66. public:
  67. // The name of the class
  68. String name;
  69. // All attributes in the data structure, including attributes inherited from the parent class
  70. List<PersistentAttribute> attributes;
  71. public:
  72. StructureDefinition() {}
  73. explicit StructureDefinition(const String &name) : name(name) {}
  74. // TODO: Prevent adding the same name twice
  75. void declareAttribute(const String &name) {
  76. this->attributes.push(PersistentAttribute(name));
  77. }
  78. int length() {
  79. return this->attributes.length();
  80. }
  81. };
  82. class Persistent : public Printable {
  83. public:
  84. // Persistent attributes may not be write protected
  85. virtual Persistent* findAttribute(const ReadableString &name);
  86. virtual std::shared_ptr<StructureDefinition> getStructure() const;
  87. virtual decltype(&classConstructor) getConstructor() const = 0;
  88. // Call from the start of main, to allow constructing the class by name
  89. void registerPersistentClass();
  90. void setProperty(const ReadableString &key, const ReadableString &value);
  91. String getClassName() const;
  92. public:
  93. // Override for non-atomic collection types
  94. // Each child object will be constructed using Begin and End keywords directly inside of the parent
  95. // For atomic collections, direct parsing and generation of comma separated lists would be more compact
  96. // Attempt to add another persistent object
  97. // Return false if the child object was rejected
  98. // Make sure that connections that would create an infinite loop are rejected
  99. virtual bool addChild(std::shared_ptr<Persistent> child);
  100. virtual int getChildCount() const;
  101. virtual std::shared_ptr<Persistent> getChild(int index) const;
  102. public:
  103. // Override for new compound types
  104. // Override declareAttributes if your persistent structure has any variables to register as persistent
  105. // Use the MAKE_PERSISTENT macro with the attribute name for each persistent member
  106. // Each persistent attribute's type must also inherit from Persistent and start with the PERSISTENT_IMPL macro
  107. virtual void declareAttributes(StructureDefinition &target) const;
  108. public:
  109. // Override for new atomic types
  110. // Assign content from a string
  111. // Returns true on success and false if no assigment was made
  112. virtual bool assignValue(const ReadableString &content);
  113. // Save to a stream using any indentation
  114. virtual String& toStreamIndented(String& out, const ReadableString& indentation) const override;
  115. };
  116. // Save to a stream without indentation
  117. inline std::ostream& operator<< (std::ostream& out, const Persistent& p) {
  118. return p.toStream(out);
  119. }
  120. // Macro to be placed at the start of the global main function
  121. // The dsr namespace must be used to access registerPersistentClass
  122. #define REGISTER_PERSISTENT_CLASS(CLASS) \
  123. (CLASS().registerPersistentClass());
  124. // Create a single class instance without any content
  125. std::shared_ptr<Persistent> createPersistentClass(const String &type, bool mustExist = true);
  126. // Create a class instance from text
  127. std::shared_ptr<Persistent> createPersistentClassFromText(const ReadableString &text);
  128. }
  129. #endif