summaryrefslogtreecommitdiffstats
path: root/client/clientapi.h
blob: b035708a50a7dbabc884c072397197079053ef52 (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
#pragma once

#include <QString>
#include <QSet>

namespace ClientAPI {

template<class T>
class Set {

};

template<class T>
class TreeSet : public Set<T> {

};

class DomainObject {

};

/*
 * Resource and domain object specific
 * FIXME: should we hardcode the requirement that the domain adapter is a subclass for the domain object?
 * * how do we allow copying of domain objects?
 * ** dummy domain object that is a wrapper?
 * ** domain adapter has an accessor for the domain object to hide subclassing
 */
class DomainAdapter : public DomainObject {
    // virtual void setFoo(const QString &value)
    // {
    //     mBuffer.setFoo(value);
    // }

    // virtual QString foo() const
    // {
    //     return mBuffer.foo();
    // }

    // MessageBuffer mBuffer;
};


/**
 * A query that matches a set of objects
 */
class Query
{
public:
    QSet<QString> resources() const { return QSet<QString>(); }
};

/**
 * Interface for the store facade
 */
template<class DomainType>
class StoreFacade {
public:
    virtual void create(const DomainType &domainObject) = 0;
    virtual void modify(const DomainType &domainObject) = 0;
    virtual void remove(const DomainType &domainObject) = 0;
    virtual void load(const Query &query) = 0;
};


class ResourceImpl {

};

/**
 * Actual implementation of the store facade that is provided by the resource plugin.
 *
 * It knows the buffer type used by the resource as well as the actual store used.
 * 
 * A resource must provide this facade for each domain type it knows.
 * => is reimplemented a lot
 * 
 * This interface should be executed in a thread so we can synchronously retrieve data from the store.
 */
template<class DomainType>
class StoreFacadeImpl : public StoreFacade<DomainType> {
public:
    void create(const DomainType &domainObject) {
        //FIXME here we would need to cast to DomainAdapter
        //Do actual work
    }

    void modify(const DomainType &domainObject) {
        //Do actual work
    }

    void remove(const DomainType &domainObject) {
        //Do actual work
    }

    Set<DomainType> load(Query) {
        Set<DomainType> resultSet;

        //retrieve results from store and fill into result set

        resultSet << 

        return resultSet;
    }

private:
    ResourceImpl resource;
};

/**
 * Facade factory that returns a store facade implementation, by loading a plugin and providing the relevant implementation.
 */
class FacadeFactory {
public:
    template<class DomainType>
    static StoreFacade<DomainType> getFacade(const QString &resource)
    {
        if (resource == "resourceX") {
            return StoreFacadeImpl<DomainType>();
        }
        return StoreFacadeImpl<DomainType>();
    }
};

/**
 * Store interface used in the client API
 */
class Store {
public:
    template <class DomainType>
    static Set<DomainType> load(Query)
    {
        //Query all resources and aggregate results
        //Query tells us in which resources we're interested
        Set<DomainType> resultSet;

        //FIXME this should run in a thread.
        //The result set is immediately returned and a "promise"/"resultprovider",
        //is passed to the actual query. The resultset is threadsafe so the query thread can safely move data
        //via the promise to the mainthread.
        for(auto resource, query.resources()) {
            auto facade = FacadeFactory::getFacade(resource);
            resultSet += facade.load<DomainType>(query);
        }
        return resultSet;
    }

    //Future load(id); => Set with single value

    template <class DomainType>
    static TreeSet<DomainType> loadTree(Query)
    {

    }

    //Sync methods for modifications
    template <class DomainType>
    static void create(const DomainType &domainObject) {
        auto facade = FacadeFactory::getFacade(domainObject.resource());
        facade.create(domainObject);
    }

    template <class DomainType>
    static void modify(const DomainType &domainObject) {
        auto facade = FacadeFactory::getFacade(domainObject.resource());
        facade.modify(domainObject);
    }

    template <class DomainType>
    static void remove(const DomainType &domainObject) {
        auto facade = FacadeFactory::getFacade(domainObject.resource());
        facade.remove(domainObject);
    }
};

}