use of com.ichi2.libanki.Models in project AnkiChinaAndroid by ankichinateam.
the class ContentProviderTest method setUp.
/**
* Initially create one note for each model.
*/
@Before
public void setUp() throws Exception {
Log.i(AnkiDroidApp.TAG, "setUp()");
mCreatedNotes = new ArrayList<>();
final Collection col = getCol();
// We have parameterized the "schedVersion" variable, if we are on an emulator
// (so it is safe) we will try to run with multiple scheduler versions
tearDown = false;
if (InstrumentedTest.isEmulator()) {
col.changeSchedulerVer(schedVersion);
} else {
if (schedVersion == 1) {
assumeThat(col.getSched().getName(), is("std"));
} else {
assumeThat(col.getSched().getName(), is("std2"));
}
}
tearDown = true;
// Do not teardown if setup was aborted
// Add a new basic model that we use for testing purposes (existing models could potentially be corrupted)
Model model = StdModels.basicModel.add(col, BASIC_MODEL_NAME);
mModelId = model.getLong("id");
ArrayList<String> fields = Models.fieldNames(model);
// Use the names of the fields as test values for the notes which will be added
mDummyFields = fields.toArray(new String[0]);
// create test decks and add one note for every deck
mNumDecksBeforeTest = col.getDecks().count();
for (String fullName : TEST_DECKS) {
String[] path = Decks.path(fullName);
String partialName = "";
/* Looping over all parents of full name. Adding them to
* mTestDeckIds ensures the deck parents decks get deleted
* too at tear-down.
*/
for (String s : path) {
partialName += s;
/* If parent already exists, don't add the deck, so
* that we are sure it won't get deleted at
* set-down, */
if (col.getDecks().byName(partialName) != null) {
continue;
}
long did = col.getDecks().id(partialName);
mTestDeckIds.add(did);
mCreatedNotes.add(setupNewNote(col, mModelId, did, mDummyFields, TEST_TAG));
partialName += "::";
}
}
// Add a note to the default deck as well so that testQueryNextCard() works
mCreatedNotes.add(setupNewNote(col, mModelId, 1, mDummyFields, TEST_TAG));
}
use of com.ichi2.libanki.Models in project AnkiChinaAndroid by ankichinateam.
the class CardContentProvider method addModelToCursor.
private void addModelToCursor(Long modelId, Models models, MatrixCursor rv, String[] columns) {
Model jsonObject = models.get(modelId);
MatrixCursor.RowBuilder rb = rv.newRow();
try {
for (String column : columns) {
if (column.equals(FlashCardsContract.Model._ID)) {
rb.add(modelId);
} else if (column.equals(FlashCardsContract.Model.NAME)) {
rb.add(jsonObject.getString("name"));
} else if (column.equals(FlashCardsContract.Model.FIELD_NAMES)) {
JSONArray flds = jsonObject.getJSONArray("flds");
String[] allFlds = new String[flds.length()];
for (int idx = 0; idx < flds.length(); idx++) {
allFlds[idx] = flds.getJSONObject(idx).optString("name", "");
}
rb.add(Utils.joinFields(allFlds));
} else if (column.equals(FlashCardsContract.Model.NUM_CARDS)) {
rb.add(jsonObject.getJSONArray("tmpls").length());
} else if (column.equals(FlashCardsContract.Model.CSS)) {
rb.add(jsonObject.getString("css"));
} else if (column.equals(FlashCardsContract.Model.DECK_ID)) {
// #6378 - Anki Desktop changed schema temporarily to allow null
rb.add(jsonObject.optLong("did", Consts.DEFAULT_DECK_ID));
} else if (column.equals(FlashCardsContract.Model.SORT_FIELD_INDEX)) {
rb.add(jsonObject.getLong("sortf"));
} else if (column.equals(FlashCardsContract.Model.TYPE)) {
rb.add(jsonObject.getLong("type"));
} else if (column.equals(FlashCardsContract.Model.LATEX_POST)) {
rb.add(jsonObject.getString("latexPost"));
} else if (column.equals(FlashCardsContract.Model.LATEX_PRE)) {
rb.add(jsonObject.getString("latexPre"));
} else if (column.equals(FlashCardsContract.Model.NOTE_COUNT)) {
rb.add(models.useCount(jsonObject));
} else {
throw new UnsupportedOperationException("Column \"" + column + "\" is unknown");
}
}
} catch (JSONException e) {
Timber.e(e, "Error parsing JSONArray");
throw new IllegalArgumentException("Model " + modelId + " is malformed", e);
}
}
use of com.ichi2.libanki.Models in project AnkiChinaAndroid by ankichinateam.
the class NoteService method updateJsonNoteFromMultimediaNote.
/**
* Updates the JsonNote field values from MultimediaEditableNote When both notes are using the same Model, it updaes
* the destination field values with source values. If models are different it throws an Exception
*
* @param noteSrc
* @param editorNoteDst
*/
public static void updateJsonNoteFromMultimediaNote(final IMultimediaEditableNote noteSrc, final Note editorNoteDst) {
if (noteSrc instanceof MultimediaEditableNote) {
MultimediaEditableNote mmNote = (MultimediaEditableNote) noteSrc;
if (mmNote.getModelId() != editorNoteDst.getMid()) {
throw new RuntimeException("Source and Destination Note ID do not match.");
}
int totalFields = mmNote.getNumberOfFields();
for (int i = 0; i < totalFields; i++) {
editorNoteDst.values()[i] = mmNote.getField(i).getFormattedValue();
}
}
}
use of com.ichi2.libanki.Models in project AnkiChinaAndroid by ankichinateam.
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 = new HashMap<>();
for (JSONObject m : mCol.getModels().all()) {
JSONArray flds = m.getJSONArray("flds");
for (int fi = 0; fi < flds.length(); ++fi) {
JSONObject f = flds.getJSONObject(fi);
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().getDatabase().query("select id, mid, flds from notes where mid in " + Utils.ids2str(new LinkedList<>(mods.keySet())) + " and flds like ? escape '\\'", new String[] { "%" + 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.libanki.Models in project AnkiChinaAndroid by ankichinateam.
the class Collection method basicCheck.
/**
* DB maintenance *********************************************************** ************************************
*/
/*
* Basic integrity check for syncing. True if ok.
*/
public boolean basicCheck() {
// cards without notes
if (mDb.queryScalar("select 1 from cards where nid not in (select id from notes) limit 1") > 0) {
return false;
}
boolean badNotes = mDb.queryScalar("select 1 from notes where id not in (select distinct nid from cards) " + "or mid not in " + Utils.ids2str(getModels().ids()) + " limit 1") > 0;
// notes without cards or models
if (badNotes) {
return false;
}
// invalid ords
for (JSONObject m : getModels().all()) {
// ignore clozes
if (m.getInt("type") != Consts.MODEL_STD) {
continue;
}
// Make a list of valid ords for this model
JSONArray tmpls = m.getJSONArray("tmpls");
boolean badOrd = mDb.queryScalar("select 1 from cards where (ord < 0 or ord >= ?) and nid in ( " + "select id from notes where mid = ?) limit 1", tmpls.length(), m.getLong("id")) > 0;
if (badOrd) {
return false;
}
}
return true;
}
Aggregations