diff options
Diffstat (limited to 'client/clientapi.h')
-rw-r--r-- | client/clientapi.h | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/client/clientapi.h b/client/clientapi.h new file mode 100644 index 0000000..b035708 --- /dev/null +++ b/client/clientapi.h | |||
@@ -0,0 +1,176 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <QString> | ||
4 | #include <QSet> | ||
5 | |||
6 | namespace ClientAPI { | ||
7 | |||
8 | template<class T> | ||
9 | class Set { | ||
10 | |||
11 | }; | ||
12 | |||
13 | template<class T> | ||
14 | class TreeSet : public Set<T> { | ||
15 | |||
16 | }; | ||
17 | |||
18 | class DomainObject { | ||
19 | |||
20 | }; | ||
21 | |||
22 | /* | ||
23 | * Resource and domain object specific | ||
24 | * FIXME: should we hardcode the requirement that the domain adapter is a subclass for the domain object? | ||
25 | * * how do we allow copying of domain objects? | ||
26 | * ** dummy domain object that is a wrapper? | ||
27 | * ** domain adapter has an accessor for the domain object to hide subclassing | ||
28 | */ | ||
29 | class DomainAdapter : public DomainObject { | ||
30 | // virtual void setFoo(const QString &value) | ||
31 | // { | ||
32 | // mBuffer.setFoo(value); | ||
33 | // } | ||
34 | |||
35 | // virtual QString foo() const | ||
36 | // { | ||
37 | // return mBuffer.foo(); | ||
38 | // } | ||
39 | |||
40 | // MessageBuffer mBuffer; | ||
41 | }; | ||
42 | |||
43 | |||
44 | /** | ||
45 | * A query that matches a set of objects | ||
46 | */ | ||
47 | class Query | ||
48 | { | ||
49 | public: | ||
50 | QSet<QString> resources() const { return QSet<QString>(); } | ||
51 | }; | ||
52 | |||
53 | /** | ||
54 | * Interface for the store facade | ||
55 | */ | ||
56 | template<class DomainType> | ||
57 | class StoreFacade { | ||
58 | public: | ||
59 | virtual void create(const DomainType &domainObject) = 0; | ||
60 | virtual void modify(const DomainType &domainObject) = 0; | ||
61 | virtual void remove(const DomainType &domainObject) = 0; | ||
62 | virtual void load(const Query &query) = 0; | ||
63 | }; | ||
64 | |||
65 | |||
66 | class ResourceImpl { | ||
67 | |||
68 | }; | ||
69 | |||
70 | /** | ||
71 | * Actual implementation of the store facade that is provided by the resource plugin. | ||
72 | * | ||
73 | * It knows the buffer type used by the resource as well as the actual store used. | ||
74 | * | ||
75 | * A resource must provide this facade for each domain type it knows. | ||
76 | * => is reimplemented a lot | ||
77 | * | ||
78 | * This interface should be executed in a thread so we can synchronously retrieve data from the store. | ||
79 | */ | ||
80 | template<class DomainType> | ||
81 | class StoreFacadeImpl : public StoreFacade<DomainType> { | ||
82 | public: | ||
83 | void create(const DomainType &domainObject) { | ||
84 | //FIXME here we would need to cast to DomainAdapter | ||
85 | //Do actual work | ||
86 | } | ||
87 | |||
88 | void modify(const DomainType &domainObject) { | ||
89 | //Do actual work | ||
90 | } | ||
91 | |||
92 | void remove(const DomainType &domainObject) { | ||
93 | //Do actual work | ||
94 | } | ||
95 | |||
96 | Set<DomainType> load(Query) { | ||
97 | Set<DomainType> resultSet; | ||
98 | |||
99 | //retrieve results from store and fill into result set | ||
100 | |||
101 | resultSet << | ||
102 | |||
103 | return resultSet; | ||
104 | } | ||
105 | |||
106 | private: | ||
107 | ResourceImpl resource; | ||
108 | }; | ||
109 | |||
110 | /** | ||
111 | * Facade factory that returns a store facade implementation, by loading a plugin and providing the relevant implementation. | ||
112 | */ | ||
113 | class FacadeFactory { | ||
114 | public: | ||
115 | template<class DomainType> | ||
116 | static StoreFacade<DomainType> getFacade(const QString &resource) | ||
117 | { | ||
118 | if (resource == "resourceX") { | ||
119 | return StoreFacadeImpl<DomainType>(); | ||
120 | } | ||
121 | return StoreFacadeImpl<DomainType>(); | ||
122 | } | ||
123 | }; | ||
124 | |||
125 | /** | ||
126 | * Store interface used in the client API | ||
127 | */ | ||
128 | class Store { | ||
129 | public: | ||
130 | template <class DomainType> | ||
131 | static Set<DomainType> load(Query) | ||
132 | { | ||
133 | //Query all resources and aggregate results | ||
134 | //Query tells us in which resources we're interested | ||
135 | Set<DomainType> resultSet; | ||
136 | |||
137 | //FIXME this should run in a thread. | ||
138 | //The result set is immediately returned and a "promise"/"resultprovider", | ||
139 | //is passed to the actual query. The resultset is threadsafe so the query thread can safely move data | ||
140 | //via the promise to the mainthread. | ||
141 | for(auto resource, query.resources()) { | ||
142 | auto facade = FacadeFactory::getFacade(resource); | ||
143 | resultSet += facade.load<DomainType>(query); | ||
144 | } | ||
145 | return resultSet; | ||
146 | } | ||
147 | |||
148 | //Future load(id); => Set with single value | ||
149 | |||
150 | template <class DomainType> | ||
151 | static TreeSet<DomainType> loadTree(Query) | ||
152 | { | ||
153 | |||
154 | } | ||
155 | |||
156 | //Sync methods for modifications | ||
157 | template <class DomainType> | ||
158 | static void create(const DomainType &domainObject) { | ||
159 | auto facade = FacadeFactory::getFacade(domainObject.resource()); | ||
160 | facade.create(domainObject); | ||
161 | } | ||
162 | |||
163 | template <class DomainType> | ||
164 | static void modify(const DomainType &domainObject) { | ||
165 | auto facade = FacadeFactory::getFacade(domainObject.resource()); | ||
166 | facade.modify(domainObject); | ||
167 | } | ||
168 | |||
169 | template <class DomainType> | ||
170 | static void remove(const DomainType &domainObject) { | ||
171 | auto facade = FacadeFactory::getFacade(domainObject.resource()); | ||
172 | facade.remove(domainObject); | ||
173 | } | ||
174 | }; | ||
175 | |||
176 | } | ||