#pragma once #include #include #include #include #include #include class TypeRegistry; #define JSONObjectValidationBuilder \ Framework::JSON::Validator::ObjectValidationBuilder< \ Framework::JSON::Validator::JSONValidator> /* * Used to convert an object of type T to a JSONValue and vice versa. * Can be registered at the TypeRegistry to be used by the JSON system */ template class TypeFactory : public Framework::ReferenceCounter { public: TypeFactory() : ReferenceCounter(){}; virtual T* createValue(Framework::JSON::JSONObject* zJson) const = 0; virtual void fromJson(T* zResult, Framework::JSON::JSONObject* zJson) const = 0; virtual void toJson(T* zObject, Framework::JSON::JSONObject* zResult) const = 0; virtual JSONObjectValidationBuilder* addToValidator( JSONObjectValidationBuilder* builder) const = 0; virtual Framework::JSON::Validator::JSONValidator* getValidator() const { return addToValidator( Framework::JSON::Validator::JSONValidator::buildForObject()) ->finishObject(); }; }; /* * Used to convert an object of type S witch inherits from type T to a * JSONValue and vice versa. Can be registered at the TypeRegistry to be * used by the JSON */ template::value>> class SubTypeFactory : public Framework::ReferenceCounter { public: SubTypeFactory() : ReferenceCounter(){}; virtual S* createValue(Framework::JSON::JSONObject* zJson) const = 0; virtual void fromJson(S* zResult, Framework::JSON::JSONObject* zJson) const = 0; virtual void toJson(S* zObject, Framework::JSON::JSONObject* zResult) const = 0; virtual JSONObjectValidationBuilder* addToValidator( JSONObjectValidationBuilder* builder) const = 0; virtual Framework::JSON::Validator::JSONValidator* getValidator() const { return addToValidator( Framework::JSON::Validator::JSONValidator::buildForObject()) ->finishObject(); }; virtual Framework::Text getTypeToken() const = 0; }; template class SubTypeFactoryRef : public Framework::ReferenceCounter { private: Framework::Text typetoken; std::function createJValueFunc; std::function fromJsonFunc; std::function toJsonFunc; std::function getValidatorFunc; Framework::ReferenceCounter* factory; public: SubTypeFactoryRef(Framework::Text typetoken, std::function createJValueFunc, std::function fromJsonFunc, std::function toJsonFunc, std::function getValidatorFunc, Framework::ReferenceCounter* factory) : ReferenceCounter(), createJValueFunc(createJValueFunc), typetoken(typetoken), fromJsonFunc(fromJsonFunc), toJsonFunc(toJsonFunc), getValidatorFunc(getValidatorFunc), factory(factory) {} ~SubTypeFactoryRef() { factory->release(); } T* createValue(Framework::JSON::JSONObject* zJson) const { return createJValueFunc(zJson); } void fromJson(T* zResult, Framework::JSON::JSONObject* zJson) const { fromJsonFunc(zResult, zJson); } void toJSON(T* zObject, Framework::JSON::JSONObject* zResult) const { toJsonFunc(zObject, zResult); } JSONObjectValidationBuilder* addToValidator( JSONObjectValidationBuilder* builder) const { return getValidatorFunc(builder); } const Framework::Text& getTypetoken() const { return typetoken; } }; template class PolymorphTypeFactory : public TypeFactory { private: Framework::RCArray> factories; Framework::RCArray typeNames; static thread_local bool insideGetValidator; public: PolymorphTypeFactory() : TypeFactory() {} T* createValue(Framework::JSON::JSONObject* zJson) const override { for (SubTypeFactoryRef* factory : factories) { if (zJson->asObject() ->zValue("type") ->asString() ->getString() .istGleich(factory->getTypetoken())) { return factory->createValue(zJson->asObject()); } } return 0; } void fromJson(T* zResult, Framework::JSON::JSONObject* zJson) const override { for (SubTypeFactoryRef* factory : factories) { if (zJson->asObject() ->zValue("type") ->asString() ->getString() .istGleich(factory->getTypetoken())) { factory->fromJson(zResult, zJson->asObject()); } } } void toJson(T* zObject, Framework::JSON::JSONObject* zResult) const override { auto name = typeNames.begin(); for (SubTypeFactoryRef* factory : factories) { if (name->istGleich(typeid(*zObject).name())) { factory->toJSON(zObject, zResult); zResult->addValue("type", new Framework::JSON::JSONString(factory->getTypetoken())); return; } name++; } } JSONObjectValidationBuilder* addToValidator( JSONObjectValidationBuilder* builder) const override { Framework::Logging::error() << "Can not add polymorph json validator to an object " "validation builder"; throw "Can not add polymorph json " "validator to an object " "validation builder"; } Framework::JSON::Validator::JSONValidator* getValidator() const override { Framework::JSON::Validator::JSONValidator* result; if (!insideGetValidator) { insideGetValidator = true; auto validator = Framework::JSON::Validator::JSONValidator::buildForOneOf() ->typeSpecifiedByAttribute("type"); for (SubTypeFactoryRef* factory : factories) { validator = validator->addAcceptedType( factory ->addToValidator( Framework::JSON::Validator::JSONValidator:: buildForObject() ->withRequiredString("type") ->withExactMatch(factory->getTypetoken()) ->finishString() ->setObjectReferenceId( ((Framework::Text("_type_") += typeid(T).name()) += "_") += factory->getTypetoken())) ->finishObject()); } result = validator->finishOneOf(); insideGetValidator = false; } else { auto validator = Framework::JSON::Validator::JSONValidator::buildForOneOf() ->typeSpecifiedByAttribute("type"); for (SubTypeFactoryRef* factory : factories) { validator = validator->addAcceptedType(Framework::JSON:: Validator::JSONValidator::buildForObjectReference( ((Framework::Text("_type_") += typeid(T).name()) += "_") += factory->getTypetoken())); } result = validator->finishOneOf(); } return result; } template::value>> void addFactory(SubTypeFactory* factory) { factories.add(new SubTypeFactoryRef( factory->getTypeToken(), [factory](Framework::JSON::JSONObject* zJson) { S* value = factory->createValue(zJson); if (value) { return dynamic_cast(value); } return (T*)0; }, [factory](T* zResult, Framework::JSON::JSONObject* zJson) { factory->fromJson(dynamic_cast(zResult), zJson); }, [factory](T* zObject, Framework::JSON::JSONObject* zResult) { factory->toJson(dynamic_cast(zObject), zResult); }, [factory](JSONObjectValidationBuilder* builder) { return factory->addToValidator(builder); }, dynamic_cast(factory))); typeNames.add(new Framework::Text(typeid(S).name())); } }; template thread_local bool PolymorphTypeFactory::insideGetValidator = false; class TypeFatoryRef : public Framework::ReferenceCounter { private: std::function createValueFunc; std::function fromJsonFunc; std::function toJsonFunc; std::function getValidatorFunc; std::function addToValidatorFunc; Framework::ReferenceCounter* factory; public: TypeFatoryRef( std::function createValueFunc, std::function fromJsonFunc, std::function toJsonFunc, std::function getValidatorFunc, std::function addToValidatorFunc, Framework::ReferenceCounter* factory) : ReferenceCounter(), createValueFunc(createValueFunc), fromJsonFunc(fromJsonFunc), toJsonFunc(toJsonFunc), getValidatorFunc(getValidatorFunc), addToValidatorFunc(addToValidatorFunc), factory(factory) {} ~TypeFatoryRef() { factory->release(); } void* createValue(Framework::JSON::JSONObject* zJson) const { return createValueFunc(zJson); } void fromJson(void* zResult, Framework::JSON::JSONObject* zJson) const { return fromJsonFunc(zResult, zJson); } void toJSON(void* zObject, Framework::JSON::JSONObject* zResult) const { return toJsonFunc(zObject, zResult); } Framework::JSON::Validator::JSONValidator* getValidator() const { return getValidatorFunc(); } JSONObjectValidationBuilder* addToValidator( JSONObjectValidationBuilder* builder) const { return addToValidatorFunc(builder); } template TypeFactory* zFactory() const { return (TypeFactory*)(factory); } }; class TypeRegistry : public Framework::ReferenceCounter { private: Framework::RCTrie parsableTypes; Framework::RCArray parsableTypeNames; public: TypeRegistry(); template::value>> void registerSubType(SubTypeFactory* factory) { Framework::Text typeId = typeid(T).name(); TypeFatoryRef* typeFactoryRef = parsableTypes.z(typeId, typeId.getLength()); if (!typeFactoryRef) { PolymorphTypeFactory* polymorphFactory = new PolymorphTypeFactory(); registerType(polymorphFactory); typeFactoryRef = parsableTypes.z(typeId, typeId.getLength()); parsableTypeNames.add(new Framework::Text(typeId)); } PolymorphTypeFactory* polymorphFactory = dynamic_cast*>( typeFactoryRef->zFactory()); if (!polymorphFactory) { Framework::Logging::error() << Framework::Text("Type not registered as Polymorphic type: ") + typeId; throw Framework::Text("Type not registered as Polymorphic type: ") + typeId; } polymorphFactory->template addFactory(factory); } template void registerType(TypeFactory* factory) { Framework::Text typeId = typeid(T).name(); TypeFatoryRef* typeFactoryRef = parsableTypes.z(typeId, typeId.getLength()); if (typeFactoryRef) { Framework::Logging::error() << Framework::Text("Type already registered: ") + typeId; throw Framework::Text("Type already registered: ") + typeId; } typeFactoryRef = new TypeFatoryRef( [factory](Framework::JSON::JSONObject* zJson) { return (void*)factory->createValue(zJson); }, [factory](void* zResult, Framework::JSON::JSONObject* zJson) { factory->fromJson((T*)zResult, zJson); }, [factory](void* zObject, Framework::JSON::JSONObject* zResult) { factory->toJson((T*)zObject, zResult); }, [factory]() { return factory->getValidator(); }, [factory](JSONObjectValidationBuilder* builder) { return factory->addToValidator(builder); }, factory); parsableTypes.set(typeId, typeId.getLength(), typeFactoryRef); parsableTypeNames.add(new Framework::Text(typeId)); } template T* fromJson(Framework::JSON::JSONValue* zJson) const { Framework::Text typeId = typeid(T).name(); TypeFatoryRef* typeFactoryRef = parsableTypes.z(typeId, typeId.getLength()); if (!typeFactoryRef) { Framework::Logging::error() << Framework::Text("Type not registered: ") + typeId; throw Framework::Text("Type not registered: ") + typeId; } T* result = (T*)(typeFactoryRef->createValue(zJson->asObject())); (typeFactoryRef->fromJson(result, zJson->asObject())); return result; } template Framework::JSON::JSONValue* toJson(T* zObject) const { Framework::Text typeId = typeid(T).name(); TypeFatoryRef* typeFactoryRef = parsableTypes.z(typeId, typeId.getLength()); if (!typeFactoryRef) { Framework::Logging::error() << Framework::Text("Type not registered: ") + typeId; throw Framework::Text("Type not registered: ") + typeId; } Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject(); typeFactoryRef->toJSON(zObject, result); return result; } template Framework::JSON::Validator::JSONValidator* getValidator() const { Framework::Text typeId = typeid(T).name(); TypeFatoryRef* typeFactoryRef = parsableTypes.z(typeId, typeId.getLength()); if (!typeFactoryRef) { Framework::Logging::error() << Framework::Text("Type not registered: ") + typeId; throw Framework::Text("Type not registered: ") + typeId; } return typeFactoryRef->getValidator(); } template JSONObjectValidationBuilder* addToValidator( JSONObjectValidationBuilder* builder) const { Framework::Text typeId = typeid(T).name(); TypeFatoryRef* typeFactoryRef = parsableTypes.z(typeId, typeId.getLength()); if (!typeFactoryRef) { Framework::Logging::error() << Framework::Text("Type not registered: ") + typeId; throw Framework::Text("Type not registered: ") + typeId; } return typeFactoryRef->addToValidator(builder); } template Framework::JSON::JSONValue* getValidParts( Framework::JSON::JSONValue* zJson) const { Framework::RCArray invalidParts; Framework::JSON::Validator::JSONValidator* validator = getValidator(); Framework::JSON::JSONValue* result = validator->getValidParts(zJson, &invalidParts); for (Framework::JSON::Validator::JSONValidationResult* invalidPart : invalidParts) { Framework::Logging::error() << invalidPart->getInvalidInfo(); } return result; } void writeSyntaxInfo(Framework::Text folderPath) const; };