// file : odb/semantics/relational/elements.hxx // copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC // license : GNU GPL v3; see accompanying LICENSE file #ifndef ODB_SEMANTICS_RELATIONAL_ELEMENTS_HXX #define ODB_SEMANTICS_RELATIONAL_ELEMENTS_HXX #include #include #include #include #include #include #include #include #include #include #include namespace semantics { namespace relational { using namespace cutl; using std::string; using container::pointer_iterator; using compiler::context; typedef unsigned long long version; // // extern string const xmlns; // // class node; class edge; typedef container::graph graph; // // class edge: public context { public: template bool is_a () const { return dynamic_cast (this) != 0; } public: virtual ~edge () {} }; // // class node: public context { // Return name of the node. // public: virtual string kind () const = 0; public: template bool is_a () const { return dynamic_cast (this) != 0; } public: virtual ~node () {} // XML serialization. // virtual void serialize (xml::serializer&) const = 0; // Sink functions that allow extensions in the form of one-way // edges. // void add_edge_right (edge&) {} void remove_edge_right (edge&) {} }; // // class alters: public edge { public: node& base () const {return *base_;} node& modifier () const {return *modifier_;} public: alters () : base_ (0), modifier_ (0) {} void set_left_node (node& m) { assert (modifier_ == 0); modifier_ = &m; } void set_right_node (node& b) { assert (base_ == 0); base_ = &b; } void clear_left_node (node& m) { assert (modifier_ == &m); modifier_ = 0; } void clear_right_node (node& b) { assert (base_ == &b); base_ = 0; } protected: node* base_; node* modifier_; }; // // template class scope; template class nameable; // // template class names: public edge { public: typedef N name_type; typedef relational::scope scope_type; typedef relational::nameable nameable_type; name_type const& name () const { return name_; } scope_type& scope () const { return *scope_; } nameable_type& nameable () const { return *nameable_; } public: names (name_type const& name): name_ (name) {} void set_left_node (scope_type& n) { scope_ = &n; } void set_right_node (nameable_type& n) { nameable_ = &n; } void clear_left_node (scope_type& n) { assert (scope_ == &n); scope_ = 0; } void clear_right_node (nameable_type& n) { assert (nameable_ == &n); nameable_ = 0; } protected: name_type name_; scope_type* scope_; nameable_type* nameable_; }; typedef names unames; typedef names qnames; // // template class nameable: public virtual node { public: typedef N name_type; typedef relational::names names_type; typedef relational::scope scope_type; name_type const& name () const {return named_->name ();} scope_type& scope () const {return named ().scope ();} names_type& named () const {return *named_;} string const& id () const {return id_;} public: // Id identifies the C++ node (e.g., a class or a data member) that // this model node corresponds to. The ids are not necessarily unique // (e.g., there can be a foreign key and an index with the same id that // correspond to a container member). However, in any given scope, the // {id,typeid} must be unique. This becomes important when we try to // find correspondance between nodes during model diff'ing. // nameable (string const& id): id_ (id), named_ (0) {} virtual nameable& clone (scope_type&, graph&) const = 0; // Virtual because we call it via nameable interface (e.g., in copy). // virtual void add_edge_right (names_type& e) { assert (named_ == 0); named_ = &e; } virtual void remove_edge_right (names_type& e) { assert (named_ == &e); named_ = 0; } using node::add_edge_right; using node::remove_edge_right; protected: nameable (nameable const&, graph& g); nameable (xml::parser&, graph& g); void serialize_attributes (xml::serializer&) const; public: typedef void (*parser_func) (xml::parser&, scope_type&, graph&); typedef std::map parser_map; static parser_map parser_map_; template static void parser_impl (xml::parser&, scope_type&, graph&); private: string id_; names_type* named_; }; typedef nameable unameable; typedef nameable qnameable; // // struct duplicate_name { template duplicate_name (relational::scope&, relational::nameable& orig, relational::nameable& dup); node& scope; node& orig; node& dup; string name; }; template class scope: public virtual node { protected: typedef N name_type; typedef relational::names names_type; typedef relational::nameable nameable_type; typedef std::list names_list; typedef std::map names_map; typedef std::map names_iterator_map; public: typedef pointer_iterator names_iterator; typedef pointer_iterator names_const_iterator; public: // Iteration. // names_iterator names_begin () { return names_.begin (); } names_iterator names_end () { return names_.end (); } names_const_iterator names_begin () const { return names_.begin (); } names_const_iterator names_end () const { return names_.end (); } bool names_empty () const { return names_.empty (); } // Find (this scope only). // template T* find (name_type const&); names_iterator find (name_type const&); names_const_iterator find (name_type const&) const; names_iterator find (names_type const&); names_const_iterator find (names_type const&) const; // Lookup in this and all altered scopes until we find what we are // looking for or hit a stop node of type S (e.g., drop_*). // template T* lookup (name_type const&); public: scope* base () const { return alters_ != 0 ? &dynamic_cast (alters_->base ()) : 0; } public: scope () : first_key_ (names_.end ()), first_drop_column_ (names_.end ()), alters_ (0) {} // Virtual because we call it via scope interface (e.g., in copy). // virtual void add_edge_left (alters& a) { assert (alters_ == 0); alters_ = &a; } virtual void remove_edge_left (alters& a) { assert (alters_ == &a); alters_ = 0; } virtual void add_edge_left (names_type&); virtual void remove_edge_left (names_type&); protected: scope (scope const&, scope* base, graph&); scope (xml::parser&, scope* base, graph&); void serialize_content (xml::serializer&) const; protected: names_list names_; names_map names_map_; names_iterator_map iterator_map_; typename names_list::iterator first_key_; typename names_list::iterator first_drop_column_; alters* alters_; }; template <> void scope:: add_edge_left (names_type&); template <> void scope:: remove_edge_left (names_type&); typedef scope uscope; typedef scope qscope; } } #include #endif // ODB_SEMANTICS_RELATIONAL_ELEMENTS_HXX