/* Copyright (C) 2014 Erik Ogenvik This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef PROVIDERS_H_ #define PROVIDERS_H_ #include "Predicates.h" #include "../LocatedEntity.h" #include #include #include class OutfitProperty; class TypeNode; class BBoxProperty; namespace EntityFilter { class Predicate; struct QueryContext { LocatedEntity& entity; std::map memory; //This field can be used by client code to specify entity for "self.*" query LocatedEntity* self_entity; }; class TypedProvider { public: virtual ~TypedProvider() = default; /** * @brief Gets the type of the pointer provided by this instance, if that can be determined. * * This will only return a valid value if * 1) An Element containing a pointer will always be returned. * 2) The exact same type always will be returned. * @return Null, or a type info instance defining the type returned as a pointer Element. */ virtual const std::type_info* getType() const = 0; }; template class Consumer : public TypedProvider { public: ~Consumer() override = default; virtual void value(Atlas::Message::Element& value, const T& parent_value) const = 0; const std::type_info* getType() const override; }; template const std::type_info* Consumer::getType() const { return nullptr; } template class ProviderBase { public: explicit ProviderBase(Consumer* consumer); virtual ~ProviderBase(); protected: Consumer* m_consumer; }; template inline ProviderBase::ProviderBase(Consumer* consumer) : m_consumer(consumer) { } template inline ProviderBase::~ProviderBase() { delete m_consumer; } template class ConsumingProviderBase : public ProviderBase, public Consumer { public: explicit ConsumingProviderBase(Consumer* consumer); ~ConsumingProviderBase() override = default;; const std::type_info* getType() const override; }; template inline ConsumingProviderBase::ConsumingProviderBase(Consumer* consumer) : ProviderBase(consumer) { } template inline const std::type_info* ConsumingProviderBase::getType() const { if (this->m_consumer) { return this->m_consumer->getType(); } return nullptr; } template class NamedAttributeProviderBase : public ProviderBase { public: NamedAttributeProviderBase(Consumer* consumer, std::string attribute_name); protected: const std::string m_attribute_name; }; template inline NamedAttributeProviderBase::NamedAttributeProviderBase(Consumer* consumer, std::string attribute_name) : ProviderBase(consumer), m_attribute_name(std::move(attribute_name)) { } template class ConsumingNamedAttributeProviderBase : public NamedAttributeProviderBase, public Consumer { public: ConsumingNamedAttributeProviderBase(Consumer* consumer, const std::string& attribute_name); ~ConsumingNamedAttributeProviderBase() override = default;; const std::type_info* getType() const override; }; template inline ConsumingNamedAttributeProviderBase::ConsumingNamedAttributeProviderBase(Consumer* consumer, const std::string& attribute_name) : NamedAttributeProviderBase(consumer, attribute_name) { } template inline const std::type_info* ConsumingNamedAttributeProviderBase::getType() const { if (this->m_consumer) { return this->m_consumer->getType(); } return nullptr; } class FixedElementProvider : public Consumer { public: explicit FixedElementProvider(const Atlas::Message::Element& element); void value(Atlas::Message::Element& value, const QueryContext& context) const override; const Atlas::Message::Element m_element; }; class FixedTypeNodeProvider : public ConsumingProviderBase { public: FixedTypeNodeProvider(Consumer* consumer, const TypeNode& type); void value(Atlas::Message::Element& value, const QueryContext& context) const override; const std::type_info* getType() const override; const TypeNode& m_type; }; class MemoryProvider: public ConsumingProviderBase{ public: explicit MemoryProvider(Consumer* consumer); void value(Atlas::Message::Element& value, const QueryContext&) const override; }; class EntityProvider : public ConsumingProviderBase { public: explicit EntityProvider(Consumer* consumer); void value(Atlas::Message::Element& value, const QueryContext& context) const override; const std::type_info* getType() const override; }; class SelfEntityProvider : public ConsumingProviderBase { public: explicit SelfEntityProvider(Consumer* consumer); void value(Atlas::Message::Element& value, const QueryContext& context) const override; const std::type_info* getType() const override; }; class EntityTypeProvider : public ConsumingProviderBase { public: explicit EntityTypeProvider(Consumer* consumer); void value(Atlas::Message::Element& value, const LocatedEntity& entity) const override; const std::type_info* getType() const override; }; //Provides integer ID of an entity class EntityIdProvider : public Consumer{ public: void value(Atlas::Message::Element& value, const LocatedEntity& entity) const override; }; class TypeNodeProvider : public Consumer { public: explicit TypeNodeProvider(const std::string& attribute_name); void value(Atlas::Message::Element& value, const TypeNode& type) const override; const std::string m_attribute_name; }; class OutfitEntityProvider : public ConsumingNamedAttributeProviderBase { public: OutfitEntityProvider(Consumer* consumer, const std::string& attribute_name); void value(Atlas::Message::Element& value, const OutfitProperty& prop) const override; }; class BBoxProvider : public ConsumingProviderBase { public: enum class Measurement { HEIGHT, WIDTH, DEPTH, VOLUME, AREA }; BBoxProvider(Consumer* consumer, Measurement measurement); void value(Atlas::Message::Element& value, const BBoxProperty& prop) const override; protected: Measurement m_measurement; }; template class PropertyProvider : public ConsumingNamedAttributeProviderBase { public: PropertyProvider(Consumer* consumer, const std::string& attribute_name); virtual ~PropertyProvider() = default; virtual void value(Atlas::Message::Element& value, const LocatedEntity& entity) const; }; template inline PropertyProvider::PropertyProvider(Consumer* consumer, const std::string& attribute_name) : ConsumingNamedAttributeProviderBase(consumer, attribute_name) { } template inline void PropertyProvider::value(Atlas::Message::Element& value, const LocatedEntity& entity) const { const TProperty* prop = entity.getPropertyClass(this->m_attribute_name); if (!prop) { return; } if (this->m_consumer) { this->m_consumer->value(value, *prop); } else { value = (void*)prop; } } class SoftPropertyProvider : public ConsumingNamedAttributeProviderBase { public: SoftPropertyProvider(Consumer* consumer, const std::string& attribute_name); void value(Atlas::Message::Element& value, const LocatedEntity& entity) const override; }; class MapProvider : public ConsumingNamedAttributeProviderBase { public: MapProvider(Consumer* consumer, const std::string& attribute_name); void value(Atlas::Message::Element& value, const Atlas::Message::Element& parent_element) const override; }; class EntityRefProvider : public ConsumingNamedAttributeProviderBase { public: EntityRefProvider(Consumer* consumer, const std::string& attribute_name); void value(Atlas::Message::Element& value, const LocatedEntity& entity) const override; const std::type_info* getType() const override; }; ///\brief This class retrieves a pointer to the m_contains property of a given entity class ContainsProvider : public Consumer { public: void value(Atlas::Message::Element& value, const LocatedEntity& entity) const override; const std::type_info* getType() const override; }; ///\brief This class uses container Consumer to retrieve a container and condition Predicate ///to check whether there exists an entity within the container that matches the given condition class ContainsRecursiveFunctionProvider : public Consumer { public: ContainsRecursiveFunctionProvider(Consumer* container, Predicate* condition); void value(Atlas::Message::Element& value, const QueryContext& context) const override; private: ///\brief Condition used to match entities within the container Predicate* m_condition; ///\brief A Consumer which must return LocatedEntitySet* i.e. entity.contains Consumer* m_consumer; bool checkContainer(LocatedEntitySet* container) const; }; class ProviderFactory { public: struct Segment { std::string delimiter; std::string attribute; }; typedef std::list SegmentsList; virtual ~ProviderFactory() = default; virtual Consumer* createProviders(SegmentsList segments) const; protected: FixedTypeNodeProvider* createFixedTypeNodeProvider(SegmentsList segments) const; EntityProvider* createEntityProvider(SegmentsList segments) const; SelfEntityProvider* createSelfEntityProvider(SegmentsList segments) const; OutfitEntityProvider* createOutfitEntityProvider(SegmentsList segments) const; BBoxProvider* createBBoxProvider(SegmentsList segments) const; Consumer* createPropertyProvider(SegmentsList segments) const; MapProvider* createMapProvider(SegmentsList segments) const; TypeNodeProvider* createTypeNodeProvider(SegmentsList segments) const; }; class MindProviderFactory: public ProviderFactory{ public: ~MindProviderFactory() override = default; Consumer* createProviders(SegmentsList segments) const override; protected: MemoryProvider* createMemoryProvider(SegmentsList segments) const; }; } #endif /* PROVIDERS_H_ */