summaryrefslogtreecommitdiffstats
path: root/src/uscxml/plugins/DataModelImpl.h
blob: afb41bca276d28dcd36bbe5f4f0cc2d1dd4c3178 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/**
 *  @file
 *  @author     2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
 *  @copyright  Simplified BSD
 *
 *  @cond
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the FreeBSD license as published by the FreeBSD
 *  project.
 *
 *  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.
 *
 *  You should have received a copy of the FreeBSD license along with this
 *  program. If not, see <http://www.opensource.org/licenses/bsd-license>.
 *  @endcond
 */

#ifndef DATAMODELIMPL_H_5A33C087
#define DATAMODELIMPL_H_5A33C087

#include "uscxml/Common.h"
#include "uscxml/plugins/Invoker.h"
#include "uscxml/plugins/IOProcessor.h"
#include "uscxml/interpreter/Logging.h"

namespace XERCESC_NS {
class DOMDocument;
class DOMNode;
}

#include <list>
#include <string>
#include <memory>

namespace uscxml {

class InterpreterImpl;
class DataModelImpl;

/**
 * @ingroup datamodel
 * @ingroup callback
 * Callbacks available for every data-model.
 */
class USCXML_API DataModelCallbacks {
public:
	virtual ~DataModelCallbacks() {} ///< silence virtual destructor warning from swig
	virtual const std::string& getName() = 0;
	virtual const std::string& getSessionId() = 0;
	virtual const std::map<std::string, IOProcessor>& getIOProcessors() = 0;
	virtual bool isInState(const std::string& stateId) = 0;
#ifndef NO_XERCESC
	virtual XERCESC_NS::DOMDocument* getDocument() const = 0;
#endif
	virtual const std::map<std::string, Invoker>& getInvokers() = 0;
	virtual Logger getLogger() = 0;
};

class USCXML_API DataModelExtension {
public:
	DataModelExtension() : dm(NULL) {}
	virtual ~DataModelExtension() {}
	virtual std::string provides() = 0;
	virtual Data invoke(const std::string& member, const Data& params) = 0;
	virtual Data getValueOf(const std::string& member) = 0;
	virtual void setValueOf(const std::string& member, const Data& data) = 0;
	DataModelImpl* dm;
};

/**
 * @ingroup datamodel
 * @ingroup abstract
 * Abstract base class for all data-model implementations.
 */
class USCXML_API DataModelImpl {
public:
	virtual ~DataModelImpl() {}

	/**
	 * The Factory wants to instantiate a new instance.
	 * This functions calls the constructor and returns a shared_ptr to the respective
	 * object. Note that this function can not contain actual initialization code as we
	 * could no longer inherit the class. Therefore, this function calls the setup()
	 * method which can be extended by an child class to actually get the object ready.
	 * The only other time that the constructor is called directly is for the prototype
	 * object in the Factory.
	 *
	 * @param callbacks The callbacks available to the datamodel
	 * @return A shared pointer with an initialized instance
	 */
	virtual std::shared_ptr<DataModelImpl> create(DataModelCallbacks* callbacks) = 0;

protected:
	/**
	 * This function will initialize the object.
	 * We cannot initialize an instance of a datamodel from the default constructors as
	 * it would be called for the prototype objects in the factory as well. And we can
	 * neither initialize an instance in create() as it is invoke in the prototype and
	 * cannot be overridden by an inheriting class. Thus, we have to call this setup()
	 * function on the instance created by create() so that inheriting classes won't have
	 * to copy all the code in create() and can rely on the base class' initialization
	 * of the datamodel runtime environment and merely extend it.
	 *
	 * @TODO: We may want to introduce two-stage constructors for other prototype types in
	 * the factory as well.
	 */
	virtual void setup() = 0;

public:
	/**
	 * Return a list of names to be matched by the `datamodel` attribute in SCXML.
	 */
	virtual std::list<std::string> getNames() = 0;

	/**
	 * Determine whether a given string constitutes valid syntax in the
	 * data-model's language. This is only used to identify InterpreterIssues
	 * but may be useful to implement isLegalDataValue() as well.
	 * @param expr A string, supposedly containing an expression of the data-model.
	 * @return Whether expr is in L(DM).
	 */
	virtual bool isValidSyntax(const std::string& expr) {
		return true; // overwrite when datamodel supports it
	}

	/**
	 * Determine whether a given string constitutes a legal data value that can appear
	 * at the right-hand side of an assignment.
	 *
	 * @param expr A string, supposedly containing a legal data value.
	 * @return Whether expr is a legal data value.
	 */
	virtual bool isLegalDataValue(const std::string& expr) {
		return true; // overwrite when datamodel supports it
	}

	/**
	 * Set the given event as `_event` in the data-model's global scope.
	 * @param event The event as it was dequeued from either the internal or external queue.
	 */
	virtual void setEvent(const Event& event) = 0;

	/**
	 * Experimental extension to have dynamic content in string literals.
	 * This function was used to replace ${foo} expressions on the data-model,
	 * e.g. in text nodes. It will eventually make a reappearance I guess.
	 * @param content The string with tokens to replace.
	 * @return How many occurences where replaced.
	 */
	size_t replaceExpressions(std::string& content);

	/**
	 * Evaluate the given expression as something iterable and return its length.
	 * @param expr Anything that possibly evaluates to an enumerable object.
	 * @return The number of items in the enumerable object.
	 */
	virtual uint32_t getLength(const std::string& expr) = 0;

	/**
	 * Set a given item to the object at a given index for one iteration.
	 * @param item A variable or location to assign the current object to.
	 * @param array An expression evalating to an enumerable object.
	 * @param index A variable or location to set the current index at.
	 * @param iteration The current iteration index.
	 */
	virtual void setForeach(const std::string& item,
	                        const std::string& array,
	                        const std::string& index,
	                        uint32_t iteration) = 0;

	/**
	 * Return a string as an *unevaluated* Data object.
	 * @param content A string with a literal, eppression or compound data-structure in the data-model's language.
	 * @return An unevaluated structure representing the given compound or literal.
	 */
	virtual Data getAsData(const std::string& content) = 0;

	/**
	 * Return a string as an *evaluated* Data object.
	 * @param content A string with a literal, eppression or compound data-structure in the data-model's language.
	 * @return An evaluated structure representing the given compound or literal.
	 */
	virtual Data evalAsData(const std::string& content) = 0;

	/**
	 * Evaluating an expression
	 * We need an explicit 'eval' function for the LuaDataModel, see issue 118
	 * @param expr An expression in the data-model's language.
	 */
	virtual void eval(const std::string& content) {
		evalAsData(content);
	}

	/**
	 * Evaluate a given expression as a boolean.
	 * This function is a subset of evalAsData() but saves on creating and copying a Data object.
	 * @param expr An expression in the data-model's language.
	 * @return Whether the expression evaluates as `true`
	 */
	virtual bool evalAsBool(const std::string& expr) = 0;

	/**
	 * Determine whether a given variable / location is declared.
	 * @param expr The variable / location to check.
	 * @todo Is this still used?
	 */
	virtual bool isDeclared(const std::string& expr) = 0;

	/**
	 * Assign a data object to a location in the data-model.
	 * There are different occurences in the SCXML IRP tests, e.g.
	\verbatim
	test147:
	<data id="Var1" expr="0"/>

	test150:
	<data id="Var3">
	[1,2,3]
	</data>

	test277:
	<data id="Var1" expr="return"/>
	\endverbatim
	 * @param location A variable or locatio to assign to.
	 * @param data The Data object with the respective data.
	 * @param attr Additional attributes of the XML assign element.
	 */
	virtual void assign(const std::string& location,
	                    const Data& data,
	                    const std::map<std::string, std::string>& attr = std::map<std::string, std::string>()) = 0;

	/**
	 * Initialize a variable / location in the data-model with a given data object.
	 * This is, semantically, very close to assign() but does not assume the
	 * location to be declared first.
	 *
	 * @param location A variable or locatio to assign to.
	 * @param data The Data object with the respective data.
	 * @param attr Additional attributes of the XML data element.
	 */
	virtual void init(const std::string& location,
	                  const Data& data,
	                  const std::map<std::string, std::string>& attr = std::map<std::string, std::string>()) = 0;

	/**
	 * Register an extension to get data into and out of the data-model.
	 * @todo This is currently unsupported
	 */
	virtual void addExtension(DataModelExtension* ext);

protected:
	DataModelCallbacks* _callbacks;
};

}

#endif /* end of include guard: DATAMODELIMPL_H_5A33C087 */