Line data Source code
1 : /// IndiProperty.hpp
2 : ///
3 : /// @author Paul Grenz
4 : ///
5 : /// This class represents a list of INDI elements with additional information
6 : /// associated with it. All access is protected by a read-write lock.
7 : ///
8 : ////////////////////////////////////////////////////////////////////////////////
9 :
10 : #ifndef INDI_PROPERTY_HPP
11 : #define INDI_PROPERTY_HPP
12 : #pragma once
13 :
14 : #include <string>
15 : #include <map>
16 : #include <exception>
17 : #include "ReadWriteLock.hpp"
18 : #include "TimeStamp.hpp"
19 : #include "IndiElement.hpp"
20 :
21 : namespace pcf
22 : {
23 : class IndiProperty
24 : {
25 : public:
26 : enum Error
27 : {
28 : ErrNone = 0,
29 : ErrCouldntFindElement = -3,
30 : ErrElementAlreadyExists = -5,
31 : ErrIndexOutOfBounds = -6,
32 : ErrWrongElementType = -7,
33 : ErrUndefined = -9999
34 : };
35 :
36 : enum BLOBEnableType
37 : {
38 : UnknownBLOBEnable = 0,
39 : Also = 1,
40 : Only,
41 : Never
42 : };
43 :
44 : enum PropertyStateType
45 : {
46 : UnknownPropertyState = 0,
47 : Alert = 1,
48 : Busy,
49 : Ok,
50 : Idle
51 : };
52 :
53 : enum SwitchRuleType
54 : {
55 : UnknownSwitchRule = 0,
56 : AnyOfMany = 1,
57 : AtMostOne,
58 : OneOfMany
59 : };
60 :
61 : enum PropertyPermType
62 : {
63 : UnknownPropertyPerm = 0,
64 : ReadOnly = 1,
65 : ReadWrite,
66 : WriteOnly
67 : };
68 :
69 : // These are the types that a property can be.
70 : // The order and enumeration of this list is important.
71 : // Do not add or change enumerations here without adjusting
72 : // the indexing of the 'allowed attributes' list.
73 : enum Type
74 : {
75 : Unknown = 0,
76 : BLOB,
77 : Light,
78 : Number,
79 : Switch,
80 : Text,
81 : };
82 :
83 : public:
84 : class Excep : public std::exception
85 : {
86 : private:
87 : Excep() {}
88 :
89 : public:
90 0 : explicit Excep(const IndiProperty::Error &tCode ) : m_tCode( tCode ) {}
91 :
92 0 : ~Excep() throw() {}
93 : const IndiProperty::Error &getCode() const
94 : {
95 : return m_tCode;
96 : }
97 0 : virtual const char* what() const throw()
98 : {
99 0 : return IndiProperty::getErrorMsg( m_tCode ).c_str();
100 : }
101 : private:
102 : IndiProperty::Error m_tCode;
103 : };
104 :
105 : // Constructor/copy constructor/destructor.
106 : public:
107 : /// Constructor.
108 : IndiProperty();
109 : /// Constructor with a type. This will be used often.
110 : explicit IndiProperty( const Type &tType );
111 :
112 : /// Constructor with a type, device and name. This will be used often.
113 : IndiProperty( const Type &tType,
114 : const std::string &szDevice,
115 : const std::string &szName );
116 : /// Constructor with a type, device, name, state, and perm.
117 : IndiProperty( const Type &tType,
118 : const std::string &szDevice,
119 : const std::string &szName,
120 : const PropertyStateType &tState,
121 : const PropertyPermType &tPerm,
122 : const SwitchRuleType &tRule = UnknownSwitchRule );
123 : /// Copy constructor.
124 : IndiProperty( const IndiProperty &ipRhs );
125 : /// Destructor.
126 : virtual ~IndiProperty();
127 :
128 : // Operators.
129 : public:
130 : /// Assigns the internal data of this object from an existing one.
131 : const IndiProperty &operator= ( const IndiProperty &ipRhs );
132 : /// This is an alternate way of calling 'setBLOBEnable'.
133 : const BLOBEnableType &operator= ( const BLOBEnableType &tValue );
134 : /// Returns true if we have an exact match (value as well).
135 : bool operator== ( const IndiProperty &ipRhs ) const;
136 : // Return a reference to an element so it can be modified.
137 : const IndiElement &operator[] ( const std::string& szName ) const;
138 : IndiElement &operator[] ( const std::string& szName );
139 : // Return a reference to an element so it can be modified.
140 : const IndiElement &operator[] ( const unsigned int& uiIndex ) const;
141 : IndiElement &operator[] ( const unsigned int& uiIndex );
142 :
143 : // Methods.
144 : public:
145 : /// Reset this object.
146 : void clear();
147 : /// Compares one property with another instance. The values may not match,
148 : /// but the type must match, as must the device and name. The names of all
149 : /// the elements must match as well.
150 : bool compareProperty( const IndiProperty &ipComp ) const;
151 : /// Compares one element value contained in this class with another
152 : /// instance. The type must match, as must the device and name.
153 : /// The name of this element must match as well.
154 : bool compareValue( const IndiProperty &ipComp,
155 : const std::string &szElementName ) const;
156 : /// Compares all the element values contained in this class with another
157 : /// instance. The type must match, as must the device and name. The number
158 : /// and names of all the elements must match as well.
159 : bool compareValues( const IndiProperty &ipComp ) const;
160 : /// Returns a string with each attribute enumerated.
161 : std::string createString() const;
162 : /// Create a name for this property based on the device name and the
163 : /// property name. A '.' is used as the character to join them together.
164 : /// This key should be unique for all indi devices.
165 : std::string createUniqueKey() const;
166 :
167 : // A getter for blob enable.
168 : const BLOBEnableType &getBLOBEnable() const;
169 :
170 : // A getter for each attribute.
171 : const std::string &getDevice() const;
172 : const std::string &getGroup() const;
173 : const std::string &getLabel() const;
174 : const std::string &getMessage() const;
175 : const std::string &getName() const;
176 : const PropertyPermType &getPerm() const;
177 : const SwitchRuleType &getRule() const;
178 : const PropertyStateType &getState() const;
179 : const double &getTimeout() const;
180 : const pcf::TimeStamp &getTimeStamp() const;
181 : /// There is only a 'getter' for the type, since it can't be changed.
182 : const Type &getType() const;
183 : const std::string &getVersion() const;
184 : /// Compares one element value contained in this class with another
185 : /// instance. The type must match, as must the device and name.
186 : /// The name of this element must match as well, and the value must be a
187 : /// new, non-blank value.
188 : bool hasNewValue( const IndiProperty &ipComp,
189 : const std::string &szElementName ) const;
190 : const bool &isRequested() const;
191 :
192 : /// Returns the string type given the enumerated type.
193 : /// Throws exception if string is not found.
194 : static std::string convertTypeToString( const Type &tType );
195 : /// Returns the enumerated type given the tag.
196 : static Type convertStringToType( const std::string &szTag );
197 : /// Returns the string type given the enumerated type.
198 : static std::string getBLOBEnableString( const BLOBEnableType &tType );
199 : /// Returns the enumerated type given the string type.
200 : static BLOBEnableType getBLOBEnableType( const std::string &szType );
201 : /// Returns the string type given the enumerated type.
202 : static std::string getPropertyPermString( const PropertyPermType &tType );
203 : /// Returns the enumerated type given the string type.
204 : static PropertyPermType getPropertyPermType( const std::string &szType );
205 : /// Returns the string type given the enumerated type.
206 : static std::string getPropertyStateString( const PropertyStateType &tType );
207 : /// Returns the enumerated type given the string type.
208 : static PropertyStateType getPropertyStateType( const std::string &szType );
209 : /// Returns the string type given the enumerated type.
210 : static std::string getSwitchRuleString( const SwitchRuleType &tType );
211 : /// Returns the enumerated type given the string type.
212 : static SwitchRuleType getSwitchRuleType( const std::string &szType );
213 : /// Returns the message concerning the error.
214 : static std::string getErrorMsg( const int &nErr );
215 : /// Ensures that a name conforms to the INDI standard and can be used as
216 : /// an identifier. This means:
217 : /// 1) No ' ' - these will be converted to '_'
218 : /// 2) No '.' - these will be converted to '___'
219 : /// 3) No Unprintable chars - these will be converted to '_'
220 : static std::string scrubName( const std::string &szName );
221 :
222 : /// Returns the number of elements.
223 : unsigned int getNumElements() const;
224 :
225 : /// Returns true if this contains a valid BLOB-enable value.
226 : bool hasValidBLOBEnable() const;
227 : /// Returns true if this contains a non-empty 'device' attribute.
228 : bool hasValidDevice() const;
229 : /// Returns true if this contains a non-empty 'group' attribute.
230 : bool hasValidGroup() const;
231 : /// Returns true if this contains a non-empty 'label' attribute.
232 : bool hasValidLabel() const;
233 : /// Returns true if this contains a non-empty 'message' attribute.
234 : bool hasValidMessage() const;
235 : /// Returns true if this contains a non-empty 'name' attribute.
236 : bool hasValidName() const;
237 : /// Returns true if this contains a non-empty 'perm' attribute.
238 : bool hasValidPerm() const;
239 : /// Returns true if this contains a non-empty 'rule' attribute.
240 : bool hasValidRule() const;
241 : /// Returns true if this contains a non-empty 'state' attribute.
242 : bool hasValidState() const;
243 : /// Returns true if this contains a non-empty 'timeout' attribute.
244 : bool hasValidTimeout() const;
245 : /// Returns true if this contains a non-empty 'timestamp' attribute.
246 : bool hasValidTimeStamp() const;
247 : /// Returns true if this contains a non-empty 'version' attribute.
248 : bool hasValidVersion() const;
249 :
250 : /// All the attribute setters.
251 : void setBLOBEnable( const BLOBEnableType &tValue );
252 : void setDevice( const std::string &szValue );
253 : void setGroup( const std::string &szValue );
254 : void setLabel( const std::string &szValue );
255 : void setMessage( const std::string &szValue );
256 : void setName( const std::string &szValue );
257 : void setPerm( const PropertyPermType &tValue );
258 : void setRequested( const bool &oRequested );
259 : void setRule( const SwitchRuleType &tValue );
260 : void setState( const PropertyStateType &tValue );
261 : void setTimeout( const double &xValue );
262 : void setTimeStamp( const pcf::TimeStamp &tsValue );
263 : void setVersion( const std::string &szValue );
264 :
265 : // Element functions.
266 : public:
267 : // Return a reference to an element so it can be modified.
268 : const IndiElement &at( const std::string& szName ) const;
269 : IndiElement &at( const std::string& szName );
270 : // Return a reference to an element so it can be modified.
271 : const IndiElement &at( const unsigned int& uiIndex ) const;
272 : IndiElement &at( const unsigned int& uiIndex );
273 : /// Adds a new element.
274 : /// Throws if the element already exists.
275 : void add( const pcf::IndiElement &ieNew );
276 : /// Adds an element if it doesn't exist. If it does exist, this is a no-op.
277 : void addIfNoExist( const pcf::IndiElement &ieNew );
278 : /// Returns true if the element 'szElementName' exists, false otherwise.
279 : bool find( const std::string &szElementName ) const;
280 : /// Get the entire map of elements.
281 : const std::map<std::string, pcf::IndiElement> &getElements() const;
282 : /// Removes an element named 'szElementName'.
283 : /// Throws if the element doesn't exist.
284 : void remove( const std::string &szElementName );
285 : /// Set the entire map of elements.
286 : void setElements( const std::map<std::string, pcf::IndiElement> &mapElements );
287 : /// Updates the value of an element named 'szElementName'.
288 : /// Throws if the element doesn't exist.
289 : void update( const std::string &szElementName,
290 : const pcf::IndiElement &ieUpdate );
291 : /// Updates the value of an element, adds it if it doesn't exist.
292 : void update( const pcf::IndiElement &ieNew );
293 :
294 : // Members.
295 : private:
296 :
297 : std::string m_szDevice;
298 :
299 : std::string m_szGroup;
300 :
301 : std::string m_szLabel;
302 :
303 : std::string m_szMessage;
304 :
305 : std::string m_szName;
306 :
307 : PropertyPermType m_tPerm {UnknownPropertyPerm};
308 :
309 : SwitchRuleType m_tRule {UnknownSwitchRule};
310 :
311 : PropertyStateType m_tState {UnknownPropertyState};
312 :
313 : double m_xTimeout {0.0f};
314 :
315 : // This is a flag which can be used to show that this property
316 : // has been requested by a client. This is not managed automatically.
317 : bool m_oRequested {false};
318 :
319 : pcf::TimeStamp m_tsTimeStamp;
320 :
321 : std::string m_szVersion;
322 :
323 : /// This can also be the value.
324 : BLOBEnableType m_beValue {UnknownBLOBEnable};
325 :
326 : /// A dictionary of elements, indexable by name.
327 : std::map<std::string, pcf::IndiElement> m_mapElements;
328 :
329 : /// The type of this object. It cannot be changed.
330 : pcf::IndiProperty::Type m_tType {Unknown};
331 :
332 : // A read write lock to protect the internal data.
333 : mutable pcf::ReadWriteLock m_rwData;
334 :
335 : }; // class IndiProperty
336 :
337 : } // namespace pcf
338 :
339 : ////////////////////////////////////////////////////////////////////////////////
340 :
341 : #endif // INDI_PROPERTY_HPP
|