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