summaryrefslogtreecommitdiff
path: root/src/syncevo/ConfigTree.h
blob: 4cc51f6a40f9554d7e5ffb2cf407795ffd13a27f (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
/*
 * Copyright (C) 2008-2009 Patrick Ohly <patrick.ohly@gmx.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) version 3.
 *
 * This library 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.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#ifndef INCL_EVOLUTION_CONFIG_TREE
# define INCL_EVOLUTION_CONFIG_TREE

#include <boost/shared_ptr.hpp>
#include <map>
#include <list>
#include <string>

#include <syncevo/declarations.h>
SE_BEGIN_CXX

class ConfigNode;

/**
 * This class organizes the access to config nodes in a tree. Nodes
 * are identified by a relative path name, using a slash / as
 * separator between levels. Each node can have user-visible and
 * hidden properties. The two sets might be stored in the same
 * ConfigNode, i.e. properties should have unique names per node. For
 * each path there's also a second, separate namespace of key/value
 * pairs. The intented use for that is saving state by sync sources
 * close to, but without interfering with their configuration and the
 * state maintained by the client library itself.
 *
 * A ConfigNode can list all its properties while the tree lists nodes
 * at a specific level and creates nodes.
 *
 * This model is similar to the Funambol C++ DeviceManagementTree.
 * Besides being implemented differently, it also provides additional
 * functionality:
 * - the same node can be opened more than once; in the client library
 *   the content of multiple instances is not synchronized and changes
 *   can get lost
 * - nodes and the whole tree can be explicitly flushed
 * - it distinguishes between user visible configuration options and
 *   hidden read/write properties attached to the same path
 * - in addition to these visible or hidden properties under well-known
 *   names there can be nodes attached to each path which can
 *   be used for arbitrary key/value pairs; different "other" nodes can
 *   be selected via an additional string
 * - temporarily override values without saving them (see FilterConfigNode
 *   decorator)
 * - improved access to properties inside nodes (iterating, deleting)
 */
class ConfigTree {
 public:
    /** frees all resources *without* flushing changed nodes */
    virtual ~ConfigTree() {}

    /** ensure that all changes are saved persistently */
    virtual void flush() = 0;

    /** tell all nodes to reload from background storage, discarding in-memory changes */
    virtual void reload() = 0;

    /**
     * Remove all configuration nodes below and including a certain
     * path and (if based on files) directories created for them, if
     * empty after file removal.
     *
     * The nodes must not be in use for this to work.
     */
    virtual void remove(const std::string &path) = 0;

    /** a string identifying the root of the configuration - exact meaning varies */
    virtual std::string getRootPath() const = 0;

    /**
     * Selects which node attached to a path name is to be used.
     * This is similar in concept to multiple data forks in a file.
     */
    enum PropertyType {
        visible,   /**< visible configuration properties */
        hidden,    /**< hidden read/write properties */
        other,     /**< additional node selected via otherID */
        server,    /**< yet another additional node, similar to other */
    };

    /**
     * Open the specified node. Opening it multiple
     * times will return the same instance, so the content
     * is always synchronized.
     *
     * @param path      a relative path with / as separator
     * @param type      selects which fork of that path is to be opened
     *                  (visible, hidden, change tracking, server)
     * @param otherId   an additional string to be attached to the 'other' or 'server'
     *                  node's name (allows having multiple different such
     *                  nodes); an empty string is allowed
     */
    virtual boost::shared_ptr<ConfigNode> open(const std::string &path,
                                               PropertyType type,
                                               const std::string &otherId = std::string("")) = 0;

    /**
     * Use the specified node, with type determined
     * by caller. The reason for adding the instance is
     * twofold:
     * - ensure that flush() is called on the node
     *   as part of flushing the tree
     * - an existing instance is reused and shared between
     *   different users of the tree
     *
     * @param path       a relative or absolute path, may be outside of normal tree
     * @param node       default instance if not opened before, discarded if a
     *                   node was registered or opened under the given path before
     */
    virtual boost::shared_ptr<ConfigNode> add(const std::string &path,
                                              const boost::shared_ptr<ConfigNode> &node) = 0;

    /**
     * returns names of all existing nodes beneath the given path
     */
    virtual std::list<std::string> getChildren(const std::string &path) = 0;
};


SE_END_CXX
#endif