Search in sources :

Example 1 with Models

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));
}
Also used : Model(com.ichi2.libanki.Model) Collection(com.ichi2.libanki.Collection) Before(org.junit.Before)

Example 2 with Models

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);
    }
}
Also used : Model(com.ichi2.libanki.Model) JSONArray(com.ichi2.utils.JSONArray) JSONException(com.ichi2.utils.JSONException) MatrixCursor(android.database.MatrixCursor)

Example 3 with Models

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();
        }
    }
}
Also used : MultimediaEditableNote(com.ichi2.anki.multimediacard.impl.MultimediaEditableNote) IMultimediaEditableNote(com.ichi2.anki.multimediacard.IMultimediaEditableNote)

Example 4 with Models

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);
}
Also used : Pattern(java.util.regex.Pattern) HashMap(java.util.HashMap) JSONArray(com.ichi2.utils.JSONArray) Cursor(android.database.Cursor) LinkedList(java.util.LinkedList) JSONObject(com.ichi2.utils.JSONObject)

Example 5 with Models

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;
}
Also used : JSONObject(com.ichi2.utils.JSONObject) JSONArray(com.ichi2.utils.JSONArray)

Aggregations

JSONObject (com.ichi2.utils.JSONObject)48 Model (com.ichi2.libanki.Model)28 JSONArray (com.ichi2.utils.JSONArray)26 Test (org.junit.Test)26 Collection (com.ichi2.libanki.Collection)25 RobolectricTest (com.ichi2.anki.RobolectricTest)16 Note (com.ichi2.libanki.Note)16 JSONException (com.ichi2.utils.JSONException)13 ArrayList (java.util.ArrayList)13 Card (com.ichi2.libanki.Card)11 Models (com.ichi2.libanki.Models)11 SuppressLint (android.annotation.SuppressLint)10 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)7 ModelManager (com.ichi2.libanki.ModelManager)7 File (java.io.File)6 HashMap (java.util.HashMap)6 List (java.util.List)6 Map (java.util.Map)6 ContentValues (android.content.ContentValues)5 NonNull (androidx.annotation.NonNull)5