#pragma once #include #include #include #include #include class TypeRegistry; class GeneratorRuleFactory; class GeneratorRule; class DimensionGenerator; class JExpressionMemory; class DimensionFactory; class Dimension; /* * 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* fromJson(Framework::JSON::JSONValue* zJson) const = 0; virtual Framework::JSON::JSONValue* toJson(T* zObject) const = 0; virtual Framework::JSON::Validator::JSONValidator* getValidator() const = 0; }; /* * 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* fromJson(Framework::JSON::JSONObject* zJson) const = 0; virtual Framework::JSON::JSONObject* toJson(S* zObject) const = 0; virtual Framework::JSON::Validator::JSONValidator* getValidator( Framework::JSON::Validator::ObjectValidationBuilder< Framework::JSON::Validator::JSONValidator>* builder) const = 0; virtual Framework::Text getTypeToken() const = 0; }; template class SubTypeFactoryRef : public Framework::ReferenceCounter { private: Framework::Text typetoken; std::function fromJsonFunc; std::function toJsonFunc; std::function*)> getValidatorFunc; Framework::ReferenceCounter* factory; public: SubTypeFactoryRef(Framework::Text typetoken, std::function fromJsonFunc, std::function toJsonFunc, std::function*)> getValidatorFunc, Framework::ReferenceCounter* factory) : ReferenceCounter(), typetoken(typetoken), fromJsonFunc(fromJsonFunc), toJsonFunc(toJsonFunc), getValidatorFunc(getValidatorFunc), factory(factory) {} ~SubTypeFactoryRef() { factory->release(); } T* fromJson(Framework::JSON::JSONObject* zJson) const { return fromJsonFunc(zJson); } Framework::JSON::JSONObject* toJSON(T* zObject) const { return toJsonFunc(zObject); } Framework::JSON::Validator::JSONValidator* getValidator( Framework::JSON::Validator::ObjectValidationBuilder< Framework::JSON::Validator::JSONValidator>* builder) const { return getValidatorFunc(builder); } const Framework::Text& getTypetoken() const { return typetoken; } }; template class PolymorphTypeFactory : public TypeFactory { private: Framework::RCArray> factories; public: PolymorphTypeFactory() : TypeFactory() {} T* fromJson(Framework::JSON::JSONValue* zJson) const override { for (SubTypeFactoryRef* factory : factories) { if (zJson->asObject() ->zValue("type") ->asString() ->getString() .istGleich(factory->getTypetoken())) { return factory->fromJson(zJson->asObject()); } } return 0; } Framework::JSON::JSONValue* toJson(T* zObject) const override { for (SubTypeFactoryRef* factory : factories) { Framework::JSON::JSONObject* result = factory->toJSON(zObject); if (result) { result->addValue("type", new Framework::JSON::JSONString(factory->getTypetoken())); return result; } } return 0; } Framework::JSON::Validator::JSONValidator* getValidator() const override { auto validator = Framework::JSON::Validator::JSONValidator::buildForOneOf() ->typeSpecifiedByAttribute("type"); for (SubTypeFactoryRef* factory : factories) { validator = validator->addAcceptedType(factory->getValidator( Framework::JSON::Validator::JSONValidator::buildForObject() ->withRequiredString("type") ->withExactMatch(factory->getTypetoken()) ->finishString())); } return validator->finishOneOf(); } template::value>> void addFactory(SubTypeFactory* factory) { factories.add(new SubTypeFactoryRef( factory->getTypeToken(), [factory](Framework::JSON::JSONObject* zJson) { S* value = factory->fromJson(zJson); if (value) { return dynamic_cast(factory->fromJson(zJson)); } return (T*)0; }, [factory](T* zObject) { S* value = dynamic_cast(zObject); if (value) { return factory->toJson(value); } return (Framework::JSON::JSONObject*)0; }, [factory](Framework::JSON::Validator::ObjectValidationBuilder< Framework::JSON::Validator::JSONValidator>* builder) { return factory->getValidator(builder); }, dynamic_cast(factory))); } }; class TypeFatoryRef : public Framework::ReferenceCounter { private: std::function fromJsonFunc; std::function toJsonFunc; std::function getValidatorFunc; Framework::ReferenceCounter* factory; public: TypeFatoryRef( std::function fromJsonFunc, std::function toJsonFunc, std::function getValidatorFunc, Framework::ReferenceCounter* factory) : ReferenceCounter(), fromJsonFunc(fromJsonFunc), toJsonFunc(toJsonFunc), getValidatorFunc(getValidatorFunc), factory(factory) {} ~TypeFatoryRef() { factory->release(); } void* fromJson(Framework::JSON::JSONValue* zJson) const { return fromJsonFunc(zJson); } Framework::JSON::JSONValue* toJSON(void* zObject) const { return toJsonFunc(zObject); } Framework::JSON::Validator::JSONValidator* getValidator() const { return getValidatorFunc(); } template TypeFactory* zFactory() const { return (TypeFactory*)(factory); } }; class GeneratorRuleFactory : public virtual Framework::ReferenceCounter { public: GeneratorRuleFactory(); virtual GeneratorRule* createRule( Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory) = 0; virtual Framework::JSON::Validator::JSONValidator* getValidator() = 0; }; class DimensionFactory : public virtual Framework::ReferenceCounter { private: int dimensionId; public: DimensionFactory(int dimensionId); virtual ~DimensionFactory() = default; virtual Dimension* createDimension() = 0; int getDimensionId() const; }; class DimensionGeneratorFactory : public virtual Framework::ReferenceCounter { private: Framework::Text name; int dimensionId; public: DimensionGeneratorFactory(Framework::Text name, int dimensionId); virtual DimensionGenerator* createDimensionGenerator( int worldSeed, Framework::JSON::JSONValue* config) = 0; virtual Framework::JSON::Validator::JSONValidator* getConfigValidator() = 0; virtual Framework::JSON::JSONValue* getDefaultConfig() = 0; Framework::Text getName() const; int getDimensionId() const; }; class TypeRegistry : public Framework::ReferenceCounter { private: Framework::RCArray generatorRules; Framework::RCArray dimensionGenerators; Framework::RCArray dimensionFactories; Framework::RCTrie parsableTypes; public: TypeRegistry(); void registerGeneratorRuleFactory(GeneratorRuleFactory* factory); GeneratorRule* createGeneratorRule( Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory); Framework::JSON::Validator::JSONValidator* getGeneratorRuleValidator(); void registerDimensionGeneratorFactory(DimensionGeneratorFactory* factory); DimensionGenerator* createDimensionGenerator( Framework::JSON::JSONValue* zConfig, int worldSeed); Framework::JSON::Validator::JSONValidator* getDimensionGeneratorValidator(); const Framework::RCArray& getDimensionGeneratorFactories() const; void registerDimension(DimensionFactory* factory); Dimension* createDimension(int id); 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()); } PolymorphTypeFactory* polymorphFactory = dynamic_cast*>( typeFactoryRef->zFactory()); if (!polymorphFactory) { 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) { throw Framework::Text("Type already registered: ") + typeId; } typeFactoryRef = new TypeFatoryRef( [factory](Framework::JSON::JSONValue* zJson) { return factory->fromJson(zJson); }, [factory](void* zObject) { return factory->toJson((T*)zObject); }, [factory]() { return factory->getValidator(); }, factory); parsableTypes.set(typeId, typeId.getLength(), typeFactoryRef); } template T* fromJson(Framework::JSON::JSONValue* zJson) const { Framework::Text typeId = typeid(T).name(); TypeFatoryRef* typeFactoryRef = parsableTypes.z(typeId, typeId.getLength()); if (!typeFactoryRef) { throw Framework::Text("Type not registered: ") + typeId; } return (T*)(typeFactoryRef->fromJson(zJson)); } template Framework::JSON::JSONValue* toJson(T* zObject) const { Framework::Text typeId = typeid(T).name(); TypeFatoryRef* typeFactoryRef = parsableTypes.z(typeId, typeId.getLength()); if (!typeFactoryRef) { throw Framework::Text("Type not registered: ") + typeId; } return typeFactoryRef->toJSON(zObject); } template Framework::JSON::Validator::JSONValidator* getValidator() const { Framework::Text typeId = typeid(T).name(); TypeFatoryRef* typeFactoryRef = parsableTypes.z(typeId, typeId.getLength()); if (!typeFactoryRef) { throw Framework::Text("Type not registered: ") + typeId; } return typeFactoryRef->getValidator(); } 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) { invalidPart->printInvalidInfo(); } return result; } };