Skip to content

Commit 6e8fb2a

Browse files
authored
Merge migration branch
Keep original commit history
2 parents e82d368 + 7f5ffb0 commit 6e8fb2a

7 files changed

+1640
-0
lines changed

AsyncLocalStorageUtil.java

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.react.modules.storage;
9+
10+
import javax.annotation.Nullable;
11+
12+
import java.util.Arrays;
13+
import java.util.Iterator;
14+
15+
import android.content.ContentValues;
16+
import android.database.Cursor;
17+
import android.database.sqlite.SQLiteDatabase;
18+
import android.text.TextUtils;
19+
20+
import com.facebook.react.bridge.ReadableArray;
21+
22+
import org.json.JSONException;
23+
import org.json.JSONObject;
24+
25+
import static com.facebook.react.modules.storage.ReactDatabaseSupplier.KEY_COLUMN;
26+
import static com.facebook.react.modules.storage.ReactDatabaseSupplier.TABLE_CATALYST;
27+
import static com.facebook.react.modules.storage.ReactDatabaseSupplier.VALUE_COLUMN;
28+
29+
/**
30+
* Helper for database operations.
31+
*/
32+
public class AsyncLocalStorageUtil {
33+
34+
/**
35+
* Build the String required for an SQL select statement:
36+
* WHERE key IN (?, ?, ..., ?)
37+
* without 'WHERE' and with selectionCount '?'
38+
*/
39+
/* package */ static String buildKeySelection(int selectionCount) {
40+
String[] list = new String[selectionCount];
41+
Arrays.fill(list, "?");
42+
return KEY_COLUMN + " IN (" + TextUtils.join(", ", list) + ")";
43+
}
44+
45+
/**
46+
* Build the String[] arguments needed for an SQL selection, i.e.:
47+
* {a, b, c}
48+
* to be used in the SQL select statement: WHERE key in (?, ?, ?)
49+
*/
50+
/* package */ static String[] buildKeySelectionArgs(ReadableArray keys, int start, int count) {
51+
String[] selectionArgs = new String[count];
52+
for (int keyIndex = 0; keyIndex < count; keyIndex++) {
53+
selectionArgs[keyIndex] = keys.getString(start + keyIndex);
54+
}
55+
return selectionArgs;
56+
}
57+
58+
/**
59+
* Returns the value of the given key, or null if not found.
60+
*/
61+
public static @Nullable String getItemImpl(SQLiteDatabase db, String key) {
62+
String[] columns = {VALUE_COLUMN};
63+
String[] selectionArgs = {key};
64+
65+
Cursor cursor = db.query(
66+
TABLE_CATALYST,
67+
columns,
68+
KEY_COLUMN + "=?",
69+
selectionArgs,
70+
null,
71+
null,
72+
null);
73+
74+
try {
75+
if (!cursor.moveToFirst()) {
76+
return null;
77+
} else {
78+
return cursor.getString(0);
79+
}
80+
} finally {
81+
cursor.close();
82+
}
83+
}
84+
85+
/**
86+
* Sets the value for the key given, returns true if successful, false otherwise.
87+
*/
88+
/* package */ static boolean setItemImpl(SQLiteDatabase db, String key, String value) {
89+
ContentValues contentValues = new ContentValues();
90+
contentValues.put(KEY_COLUMN, key);
91+
contentValues.put(VALUE_COLUMN, value);
92+
93+
long inserted = db.insertWithOnConflict(
94+
TABLE_CATALYST,
95+
null,
96+
contentValues,
97+
SQLiteDatabase.CONFLICT_REPLACE);
98+
99+
return (-1 != inserted);
100+
}
101+
102+
/**
103+
* Does the actual merge of the (key, value) pair with the value stored in the database.
104+
* NB: This assumes that a database lock is already in effect!
105+
* @return the errorCode of the operation
106+
*/
107+
/* package */ static boolean mergeImpl(SQLiteDatabase db, String key, String value)
108+
throws JSONException {
109+
String oldValue = getItemImpl(db, key);
110+
String newValue;
111+
112+
if (oldValue == null) {
113+
newValue = value;
114+
} else {
115+
JSONObject oldJSON = new JSONObject(oldValue);
116+
JSONObject newJSON = new JSONObject(value);
117+
deepMergeInto(oldJSON, newJSON);
118+
newValue = oldJSON.toString();
119+
}
120+
121+
return setItemImpl(db, key, newValue);
122+
}
123+
124+
/**
125+
* Merges two {@link JSONObject}s. The newJSON object will be merged with the oldJSON object by
126+
* either overriding its values, or merging them (if the values of the same key in both objects
127+
* are of type {@link JSONObject}). oldJSON will contain the result of this merge.
128+
*/
129+
private static void deepMergeInto(JSONObject oldJSON, JSONObject newJSON)
130+
throws JSONException {
131+
Iterator<?> keys = newJSON.keys();
132+
while (keys.hasNext()) {
133+
String key = (String) keys.next();
134+
135+
JSONObject newJSONObject = newJSON.optJSONObject(key);
136+
JSONObject oldJSONObject = oldJSON.optJSONObject(key);
137+
if (newJSONObject != null && oldJSONObject != null) {
138+
deepMergeInto(oldJSONObject, newJSONObject);
139+
oldJSON.put(key, oldJSONObject);
140+
} else {
141+
oldJSON.put(key, newJSON.get(key));
142+
}
143+
}
144+
}
145+
}

0 commit comments

Comments
 (0)