Imported Upstream version 0.8~alpha1
[platform/upstream/syncevolution.git] / src / client-api / src / c++ / common / client / SQLKeyValueStore.cpp
1 /*
2  * Funambol is a mobile platform developed by Funambol, Inc. 
3  * Copyright (C) 2003 - 2007 Funambol, Inc.
4  * 
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU Affero General Public License version 3 as published by
7  * the Free Software Foundation with the addition of the following permission 
8  * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
9  * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE 
10  * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
11  * 
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
15  * details.
16  * 
17  * You should have received a copy of the GNU Affero General Public License 
18  * along with this program; if not, see http://www.gnu.org/licenses or write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20  * MA 02110-1301 USA.
21  * 
22  * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite 
23  * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
24  * 
25  * The interactive user interfaces in modified source and object code versions
26  * of this program must display Appropriate Legal Notices, as required under
27  * Section 5 of the GNU Affero General Public License version 3.
28  * 
29  * In accordance with Section 7(b) of the GNU Affero General Public License
30  * version 3, these Appropriate Legal Notices must retain the display of the
31  * "Powered by Funambol" logo. If the display of the logo is not reasonably 
32  * feasible for technical reasons, the Appropriate Legal Notices must display
33  * the words "Powered by Funambol".
34  */
35
36 #include "base/util/KeyValuePair.h"
37 #include "client/SQLKeyValueStore.h"
38
39 BEGIN_NAMESPACE
40
41 StringBuffer SQLKeyValueStore::sqlColKey() const
42 {
43     return "key";
44 }
45
46 StringBuffer SQLKeyValueStore::sqlColValue() const
47 {
48     return "value";
49 }
50
51 StringBuffer SQLKeyValueStore::sqlRemovePropertyString(const StringBuffer & key) const
52 {
53     StringBuffer sb("");
54     sb.append("DELETE FROM ").append(table).append(" WHERE ").append(sqlColKey()).append("='").append(key).append("' LIMIT 1");
55     return sb;
56 }
57
58 StringBuffer SQLKeyValueStore::sqlSetPropertyString(const StringBuffer & key, const StringBuffer & value) const
59 {
60     StringBuffer sb("");
61     sb.append("UPDATE ").append(table).append(" SET ").append(sqlColValue()).append("='").append(value).append("' WHERE ").append(sqlColKey()).append("='").append(key).append("' LIMIT 1");
62     return sb;
63 }
64
65 StringBuffer SQLKeyValueStore::sqlGetPropertyString(const StringBuffer & key) const
66 {
67     StringBuffer sb("");
68     sb.append("SELECT ").append(sqlColValue()).append(" FROM ").append(table).append(" WHERE ").append(sqlColKey()).append("='").append(key).append("' LIMIT 1");
69     return sb;
70 }
71
72 StringBuffer SQLKeyValueStore::sqlGetAllString() const
73 {
74     StringBuffer sb("");
75     sb.append("SELECT ").append(sqlColKey()).append(", ").append(sqlColValue()).append(" FROM ").append(table);
76     return sb;
77 }
78
79 SQLKeyValueStore::SQLKeyValueStore(const char * uri, const char * database, const char * table, const char * username, const char * password)
80 {
81     this->uri = new char[strlen(uri)];
82     strcpy(this->uri, uri);
83     
84     this->database = new char[strlen(database)];
85     strcpy(this->database, database);
86     
87     this->table = new char[strlen(table)];
88     strcpy(this->table, table);
89     
90     this->username = new char[strlen(username)];
91     strcpy(this->username, username);
92     
93     this->password = new char[strlen(password)];
94     strcpy(this->password, password);
95 }
96
97 SQLKeyValueStore::~SQLKeyValueStore()
98 {
99     if (uri)        delete uri;
100     if (database)   delete database;
101     if (table)      delete table;
102     if (username)   delete username;
103     if (password)   delete password;
104 }
105
106 /*
107  * Returns the value of the given property
108  *
109  *@param prop - the property name
110  *
111  *@return   A NULL StringBuffer in the returned implies that
112  *          the property was not set. Otherwise the value it was
113  *          set to is returned (which can be "", the empty string).
114  */
115 StringBuffer SQLKeyValueStore::readPropertyValue(const char *prop) const
116 {
117     StringBuffer sqlQuery = sqlGetPropertyString(StringBuffer(prop));
118     ArrayListEnumeration * en = query(sqlQuery);
119     
120     if (!en)
121         return StringBuffer(NULL);
122         
123     if (!en->hasMoreElement())
124     {
125         KeyValuePair * kvp = dynamic_cast<KeyValuePair*>(en->getNextElement());
126         delete en;
127         return kvp->getValue();
128     }
129     return StringBuffer(NULL);
130 }
131
132 /*
133  * Sets a property value.
134  *
135  * The value might be cached inside the implementation of this
136  * interface. To ensure that it is stored persistently and to do
137  * error checking, call save().
138  *
139  * @param prop      - the property name
140  * @param value     - the property value (zero terminated string)
141  *
142  * @return int 0 on success, an error code otherwise
143  */
144 int SQLKeyValueStore::setPropertyValue(const char *prop, const char *value)
145 {
146     KeyValuePair kvp(prop, "");
147     toSet.add(kvp);
148     return 0;
149 }
150
151  /**
152  * Remove a certain property 
153  *
154  * @param prop    the name of the property which is to be removed   
155  *
156  * @return int 0 on success, an error code otherwise
157  */
158 int SQLKeyValueStore::removeProperty(const char *prop)
159 {
160     KeyValuePair kvp(prop, "");
161     toDel.add(kvp);
162     return 0;
163 }
164  
165 /**
166  * Get all the properties that are currently defined.     
167  */
168 Enumeration& SQLKeyValueStore::getProperties() const
169 {
170     StringBuffer sqlQuery = sqlGetAllString();
171     Enumeration * en = query(sqlQuery);
172     return *en;
173 }
174
175 /**
176  * Ensure that all properties are stored persistently.
177  * If setting a property led to an error earlier, this
178  * call will indicate the failure.
179  *
180  * @return 0 - success, failure otherwise
181  */
182 int SQLKeyValueStore::save()
183 {
184     int numFail = 0;
185     
186     while (toDel.hasMoreElement())
187     {
188         KeyValuePair * kvp = (KeyValuePair*)toDel.getNextElement();
189         const char * prop = kvp->getKey();
190         StringBuffer sqlQuery = sqlRemovePropertyString(prop);
191         numFail += (execute(sqlQuery) ? 0 : 1);
192     }
193     toDel = ArrayListEnumeration();
194     
195     while (toSet.hasMoreElement())
196     {
197         KeyValuePair * kvp = (KeyValuePair*)toDel.getNextElement();
198         const char * prop  = kvp->getKey();
199         const char * value = kvp->getValue();
200         StringBuffer sqlQuery = sqlSetPropertyString(prop,value);
201         numFail += (execute(sqlQuery) ? 0 : 1);
202     }
203     toSet = ArrayListEnumeration();
204     
205     return numFail;
206 }
207
208
209 END_NAMESPACE
210