use of com.ichi2.utils.JSONArray in project Anki-Android by ankidroid.
the class Decks method select.
/**
* {@inheritDoc}
*/
@Override
public void select(long did) {
String name = mDecks.get(did).getString("name");
// current deck
mCol.set_config(CURRENT_DECK, did);
// and active decks (current + all children)
// Note: TreeMap is already sorted
TreeMap<String, Long> actv = children(did);
actv.put(name, did);
JSONArray activeDecks = new JSONArray();
for (Long n : actv.values()) {
activeDecks.put(n);
}
mCol.set_config(ACTIVE_DECKS, activeDecks);
}
use of com.ichi2.utils.JSONArray in project Anki-Android by ankidroid.
the class Finder method ordForMid.
/**
* Find duplicates
* ***********************************************************
* @param col The collection
* @param fields A map from some note type id to the ord of the field fieldName
* @param mid a note type id
* @param fieldName A name, assumed to be the name of a field of some note type
* @return The ord of the field fieldName in the note type whose id is mid. null if there is no such field. Save the information in fields
*/
public static Integer ordForMid(Collection col, Map<Long, Integer> fields, long mid, String fieldName) {
if (!fields.containsKey(mid)) {
JSONObject model = col.getModels().get(mid);
JSONArray flds = model.getJSONArray("flds");
for (int c = 0; c < flds.length(); c++) {
JSONObject f = flds.getJSONObject(c);
if (f.getString("name").equalsIgnoreCase(fieldName)) {
fields.put(mid, c);
return c;
}
}
fields.put(mid, null);
}
return fields.get(mid);
}
use of com.ichi2.utils.JSONArray in project Anki-Android by ankidroid.
the class Finder method _findField.
private String _findField(String field, String val) {
/*
* We need two expressions to query the cards: One that will use JAVA REGEX syntax and another
* that should use SQLITE LIKE clause syntax.
*/
String sqlVal = val.replace("%", // For SQLITE, we escape all % signs
"\\%").replace("*", // And then convert the * into non-escaped % signs
"%");
/*
* The following three lines make sure that only _ and * are valid wildcards.
* Any other characters are enclosed inside the \Q \E markers, which force
* all meta-characters in between them to lose their special meaning
*/
String javaVal = val.replace("_", "\\E.\\Q").replace("*", "\\E.*\\Q");
/*
* For the pattern, we use the javaVal expression that uses JAVA REGEX syntax
*/
Pattern pattern = Pattern.compile("\\Q" + javaVal + "\\E", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
// find models that have that field
Map<Long, Object[]> mods = HashUtil.HashMapInit(mCol.getModels().count());
for (JSONObject m : mCol.getModels().all()) {
JSONArray flds = m.getJSONArray("flds");
for (JSONObject f : flds.jsonObjectIterable()) {
String fieldName = f.getString("name");
fieldName = Normalizer.normalize(fieldName, Normalizer.Form.NFC);
if (fieldName.equalsIgnoreCase(field)) {
mods.put(m.getLong("id"), new Object[] { m, f.getInt("ord") });
}
}
}
if (mods.isEmpty()) {
// nothing has that field
return null;
}
LinkedList<Long> nids = new LinkedList<>();
try (Cursor cur = mCol.getDb().query("select id, mid, flds from notes where mid in " + Utils.ids2str(new LinkedList<>(mods.keySet())) + " and flds like ? escape '\\'", "%" + sqlVal + "%")) {
while (cur.moveToNext()) {
String[] flds = Utils.splitFields(cur.getString(2));
int ord = (Integer) mods.get(cur.getLong(1))[1];
String strg = flds[ord];
if (pattern.matcher(strg).matches()) {
nids.add(cur.getLong(0));
}
}
}
if (nids.isEmpty()) {
return "0";
}
return "n.id in " + Utils.ids2str(nids);
}
use of com.ichi2.utils.JSONArray in project Anki-Android by ankidroid.
the class Media method mediaChangesZip.
/*
* Media syncing: zips
* ***********************************************************
*/
/**
* Unlike python, our temp zip file will be on disk instead of in memory. This avoids storing
* potentially large files in memory which is not feasible with Android's limited heap space.
* <p>
* Notes:
* <p>
* - The maximum size of the changes zip is decided by the constant SYNC_ZIP_SIZE. If a media file exceeds this
* limit, only that file (in full) will be zipped to be sent to the server.
* <p>
* - This method will be repeatedly called from MediaSyncer until there are no more files (marked "dirty" in the DB)
* to send.
* <p>
* - Since AnkiDroid avoids scanning the media directory on every sync, it is possible for a file to be marked as a
* new addition but actually have been deleted (e.g., with a file manager). In this case we skip over the file
* and mark it as removed in the database. (This behaviour differs from the desktop client).
* <p>
*/
public Pair<File, List<String>> mediaChangesZip() {
File f = new File(mCol.getPath().replaceFirst("collection\\.anki2$", "tmpSyncToServer.zip"));
List<String> fnames = new ArrayList<>();
try (ZipOutputStream z = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
Cursor cur = mDb.query("select fname, csum from media where dirty=1 limit " + Consts.SYNC_MAX_FILES)) {
z.setMethod(ZipOutputStream.DEFLATED);
// meta is a list of (fname, zipname), where zipname of null is a deleted file
// NOTE: In python, meta is a list of tuples that then gets serialized into json and added
// to the zip as a string. In our version, we use JSON objects from the start to avoid the
// serialization step. Instead of a list of tuples, we use JSONArrays of JSONArrays.
JSONArray meta = new JSONArray();
int sz = 0;
byte[] buffer = new byte[2048];
for (int c = 0; cur.moveToNext(); c++) {
String fname = cur.getString(0);
String csum = cur.getString(1);
fnames.add(fname);
String normname = Utils.nfcNormalized(fname);
if (!TextUtils.isEmpty(csum)) {
try {
mCol.log("+media zip " + fname);
File file = new File(dir(), fname);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file), 2048);
z.putNextEntry(new ZipEntry(Integer.toString(c)));
int count = 0;
while ((count = bis.read(buffer, 0, 2048)) != -1) {
z.write(buffer, 0, count);
}
z.closeEntry();
bis.close();
meta.put(new JSONArray().put(normname).put(Integer.toString(c)));
sz += file.length();
} catch (FileNotFoundException e) {
Timber.w(e);
// A file has been marked as added but no longer exists in the media directory.
// Skip over it and mark it as removed in the db.
removeFile(fname);
}
} else {
mCol.log("-media zip " + fname);
meta.put(new JSONArray().put(normname).put(""));
}
if (sz >= Consts.SYNC_MAX_BYTES) {
break;
}
}
z.putNextEntry(new ZipEntry("_meta"));
z.write(Utils.jsonToString(meta).getBytes());
z.closeEntry();
// Don't leave lingering temp files if the VM terminates.
f.deleteOnExit();
return new Pair<>(f, fnames);
} catch (IOException e) {
Timber.e(e, "Failed to create media changes zip: ");
throw new RuntimeException(e);
}
}
use of com.ichi2.utils.JSONArray in project Anki-Android by ankidroid.
the class Model method parsedNodes.
/**
* @return A list of parsed nodes for each template's question. null in case of exception
*/
public List<ParsedNode> parsedNodes() {
JSONArray tmpls = getJSONArray("tmpls");
List<ParsedNode> nodes = new ArrayList<>(tmpls.length());
for (JSONObject tmpl : tmpls.jsonObjectIterable()) {
String format_question = tmpl.getString("qfmt");
ParsedNode node = null;
try {
node = ParsedNode.parse_inner(format_question);
} catch (TemplateError er) {
Timber.w(er);
}
nodes.add(node);
}
return nodes;
}
Aggregations