1 #ifndef ERIS_TYPE_INFO_H
2 #define ERIS_TYPE_INFO_H
3 
4 #include <Eris/Types.h>
5 #include <Eris/TypeService.h>
6 
7 #include <sigc++/trackable.h>
8 
9 #include <map>
10 #include <string>
11 
12 namespace Atlas {
13     namespace Message {
14         class Element;
15         typedef std::map<std::string, Element> MapType;
16     }
17 }
18 
19 namespace Eris {
20 
21 /**
22 @brief The representation of an Atlas type (i.e a class or operation definition).
23 This class supports efficent inheritance queries, and traversal of the type hierarchy. Atlas types
24 have a unique ID, and types can be retrieved using this value. Where an Atlas::Objects instance,
25 or an Atlas::Message::Element representing an Atlas object is being examined, it is much more
26 efficent to use the 'getSafe' methods rather than extracting PARENTS[0] and calling findSafe.
27 This is because the getSafe methods may take advantage of integer type codes stored in the
28 object, which avoids a map lookup to locate the type.
29 
30 Note that the core Atlas::Objects heirarchy (as defined in the protocols/atlas/spec section of
31 CVS) is loaded from the 'atlas.xml' file at startup, and that other types are queried from the
32 server. In general, Eris will automatically delay processing operations and entities until the
33 necessary type data has become available, without intervention by the client. However, certain
34 routines may throw the 'OperationBlocked' exception, which must be forward to the Connection
35 instance for handling.
36 */
37 class TypeInfo : virtual public sigc::trackable
38 {
39 public:
40     /**
41      * @brief Test whether this type inherits (directly or indirectly) from the specific class. If this type is not bound, this may return false-negatives.
42      */
43     bool isA(TypeInfoPtr ti);
44 
45     /**
46      * @brief Check the bound flag for this node; if false then recursivley check parents until an authorative is found
47      */
48     inline bool isBound() const;
49 
50     /**
51      * @brief Test if there are child types of the type, which have not yet been retrieved from the server.
52      */
53     bool hasUnresolvedChildren() const;
54 
55     /**
56      * @brief Retrive all child types from the server.
57      * This will log an error and do nothing if no unresolved children exist.
58      */
59     void resolveChildren();
60 
61 // operators
62     /// efficent comparisom of types (uses type ids if possible)
63     bool operator==(const TypeInfo &x) const;
64 
65     /// efficent ordering of type (uses type ids if possible)
66     bool operator<(const TypeInfo &x) const;
67 
68 // accessors
69     /// the unique type name (matches the Atlas type)
70     const std::string& getName() const;
71 
72     /**
73      * @brief Gets the currently resolved child TypeInfo instances.
74      * @return A set of child TypeInfo instances.
75      */
76     const TypeInfoSet & getChildren() const;
77 
78     /**
79      * @brief Gets the currently resolved parent TypeInfo instances.
80      * @return A set of parent TypeInfo instances.
81      */
82     const TypeInfoSet & getParents() const;
83 
84     /**
85     @brief Gets the default attributes for this entity type.
86     Note that the map returned does not include inherited attributes.
87     @returns An element map of the default attributes for this type.
88     */
89     const Atlas::Message::MapType& getAttributes() const;
90 
91     /**
92      * @brief Gets the value of the named attribute.
93      * This method will search through both this instance and all of its parents for the attribute by the specified name. If no attribute can be found a null pointer will be returned.
94      * @param attributeName The name of the attribute to search for.
95      * @note This method won't throw an exception if the attribute isn't found.
96      * @return A pointer to an Element instance, or a null pointer if no attribute could be found.
97      */
98     const Atlas::Message::Element* getAttribute(const std::string& attributeName) const;
99 
100     /**
101      * @brief Emitted before an attribute changes.
102      * The first parameter is the name of the attribute, and the second is the actual attribute.
103      */
104     sigc::signal<void, const std::string&, const Atlas::Message::Element&> AttributeChanges;
105 
106 
107     /**
108      * @brief Sets an attribute.
109      * @param attributeName The name of the attribute.
110      * @param element The new value of the attribute.
111      */
112     void setAttribute(const std::string& attributeName, const Atlas::Message::Element& element);
113 
114 
115 protected:
116     friend class TypeService;
117     friend class TypeBoundRedispatch;
118 
119     /// forward constructor, when data is not available
120     TypeInfo(const std::string &id, TypeService*);
121 
122     /// full constructor, if an INFO has been received
123     TypeInfo(const Atlas::Objects::Root &atype, TypeService*);
124 
125     void validateBind();
126 
127     /// process the INFO data
128     void processTypeData(const Atlas::Objects::Root& atype);
129 
130     /**
131      * @brief Emitted when the type is bound, i.e there is an unbroken graph of TypeInfo instances through every ancestor to the root object.
132      */
133     sigc::signal<void> Bound;
134 
135 
136     /**
137      * @brief Called before the AttributeChanges signal is emitted.
138      * This call is made before an attribute is changed. It will emit the AttributeChanges event first, and then go through all of the children, calling itself on them as long as the children themselves doesn't have an attribute by the same name defined.
139      * @param attributeName The name of the attribute which is being changed.
140      * @param element The new attribute value.
141      */
142     void onAttributeChanges(const std::string& attributeName, const Atlas::Message::Element& element);
143 
144 private:
145     void addParent(TypeInfoPtr tp);
146     void addChild(TypeInfoPtr tp);
147 
148     /** Recursive add to this node and every descendant the specified ancestor */
149     void addAncestor(TypeInfoPtr tp);
150 
151     /**
152      * @brief Extracts default attributes from the supplied root object, and adds them to the m_attributes field.
153      * Note that inherited (i..e those that belong to the parent entity type) attributes won't be extracted.
154      * @param atype Root data for this entity type.
155      */
156     void extractDefaultAttributes(const Atlas::Objects::Root& atype);
157 
158     /** The TypeInfo nodes for types we inherit from directly */
159     TypeInfoSet m_parents;
160     /** TypeInfo nodes that inherit from us directly */
161     TypeInfoSet m_children;
162 
163     /** Every TypeInfo node we inherit from at all (must contain the root node, obviously) */
164     TypeInfoSet m_ancestors;
165 
166     bool m_bound;               ///< cache the 'bound-ness' of the node, see the isBound() implementation
167     const std::string m_name;	///< the Atlas unique typename
168     int m_atlasClassNo;         ///< if we registered an atlas factory, this is it's class
169 
170     StringSet m_unresolvedChildren;
171 
172     /** confidence-tracking - to facilitate clients displaying disappeared
173     entities, we estimate a confidence that they have not changed since they
174     disappeared. For the moment, that confidence is inversely proportional to
175     how frequently entities of that type move, which we count here. */
176     unsigned int m_moveCount;
177 
178     TypeService* m_typeService;
179 
180     /**
181      * @brief The default attributes specified for this entity type.
182      */
183     Atlas::Message::MapType m_attributes;
184 };
185 
getAttributes()186 inline const Atlas::Message::MapType& TypeInfo::getAttributes() const
187 {
188     return m_attributes;
189 }
190 
isBound()191 inline bool TypeInfo::isBound() const
192 {
193     return m_bound;
194 }
195 
getName()196 inline const std::string& TypeInfo::getName() const
197 {
198     return m_name;
199 }
200 
getChildren()201 inline const TypeInfoSet & TypeInfo::getChildren() const
202 {
203     return m_children;
204 }
205 
getParents()206 inline const TypeInfoSet & TypeInfo::getParents() const
207 {
208         return m_parents;
209 }
210 
211 
212 } // of Eris namespace
213 
214 #endif
215