KDE PIM/Akonadi Next/Client API
Loading:
- Set load(Query) => A query is executed and a reactive set is returned.
- TreeSet loadTree(Query) => Additionally to the query a tree structure is available in the reactive set, so support tree models.
- Future<Message> load(id)
Modifications:
- create(Message)
- modify(Message)
- delete(id)
Probably a template mechanism is used to define the message type:
- template <class T> T load(id)
Additionally to the wanted type the appropriate facade needs to be chosen based on the buffer type of the query result.
Interface Draft
class DomainObject { virtual void setFoo(QString); virtual QString foo() const; }; class MessageBuffer { }; class DomainAdapter : public DomainObject { virtual void setFoo(QString value) { mBuffer.setFoo(value); } virtual QString foo() const { return mBuffer.foo(); } MessageBuffer mBuffer; }; class FacadeFactory { StoreFacade getFacade(const QString &resource); } class Store { template <class DomainType> static Set<DomainType> load(Query); //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, const String &resource) { StoreFacade facade = } template <class Type> static void modify(const DomainType &domainObject) { } template <class Type> static void delete(const DomainType &domainObject) { } } //Translates between message type and domain object template <typename ResourceType> class StoreFacade { };
Store Facade
The store is always accessed through a store-type specific facade, which hides:
- store access (one store could use a database, and another one plain files)
- message type (flatbuffers, ...)
- Theoretically we could also include the index, which would allow us to have store specific indexes. However, that way we would require one query per store.
class StoreFacade { Message load(id); void store(Message); }
Message adaptor
A message adaptor interface is implemented for each domain type. This interface has a default implementation for each property like this:
virtual setFoo(value) { setProperty("foo", value); } virtual foo() { return property("foo"); }
setProperty()/property() must be implemented by every message, resulting in a generic key value store by default (inefficient to load since we have to load everything to load a single value). If the message implementation implements the individual properties it gets efficient loading of values. This way the domain objects can evolve without forcing n message schemas to be updated while we can stil guarantee that all properties work at least local only.