use of com.orgzly.org.OrgProperties in project orgzly-android by orgzly.
the class NotesClient method update.
/**
* Updates note by its ID.
*/
public static int update(Context context, Note note) {
ContentValues values = new ContentValues();
toContentValues(values, note);
Uri noteUri = ProviderContract.Notes.ContentUri.notesId(note.getId());
Uri uri = noteUri.buildUpon().appendQueryParameter("bookId", String.valueOf(note.getPosition().getBookId())).build();
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
/* Update note. */
ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());
/* Delete all note's properties. */
ops.add(ContentProviderOperation.newDelete(ProviderContract.NoteProperties.ContentUri.notesIdProperties(note.getId())).build());
/* Add each of the note's property. */
int i = 0;
OrgProperties properties = note.getHead().getProperties();
for (String name : properties.keySet()) {
String value = properties.get(name);
values = new ContentValues();
values.put(ProviderContract.NoteProperties.Param.NOTE_ID, note.getId());
values.put(ProviderContract.NoteProperties.Param.NAME, name);
values.put(ProviderContract.NoteProperties.Param.VALUE, value);
values.put(ProviderContract.NoteProperties.Param.POSITION, i++);
ops.add(ContentProviderOperation.newInsert(ProviderContract.NoteProperties.ContentUri.notesProperties()).withValues(values).build());
}
ContentProviderResult[] result;
try {
result = context.getContentResolver().applyBatch(ProviderContract.AUTHORITY, ops);
} catch (RemoteException | OperationApplicationException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return result[0].count;
}
use of com.orgzly.org.OrgProperties in project orgzly-android by orgzly.
the class Shelf method syncCreatedAtTimeWithProperty.
/**
* Syncs created-at time and property, using lower value if both exist.
*/
public void syncCreatedAtTimeWithProperty() throws IOException {
boolean useCreatedAtProperty = AppPreferences.createdAt(mContext);
String createdAtPropName = AppPreferences.createdAtProperty(mContext);
if (!useCreatedAtProperty) {
return;
}
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
// If new property is added to the note below, book has to be marked as modified.
Set<Long> bookIds = new HashSet<>();
/*
* Get all notes.
* This is slow and only notes that have either created-at time or created-at property
* are actually needed. But since this syncing (triggered on preference change) is done
* so rarely, we don't bother.
*/
try (Cursor cursor = mContext.getContentResolver().query(ProviderContract.Notes.ContentUri.notes(), null, null, null, null)) {
if (cursor != null) {
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
/* Get current heading string. */
Note note = NotesClient.fromCursor(cursor);
/* Skip root node. */
if (note.getPosition().getLevel() == 0) {
continue;
}
long dbCreatedAt = note.getCreatedAt();
OrgProperties properties = NotesClient.getNoteProperties(mContext, NotesClient.idFromCursor(cursor));
String dbPropValue = properties.get(createdAtPropName);
OrgDateTime dbPropertyValue = OrgDateTime.doParse(dbPropValue);
// Compare dbCreatedAt and dbPropertyValue
if (dbCreatedAt > 0 && dbPropertyValue == null) {
addOpUpdateProperty(ops, note, createdAtPropName, dbCreatedAt, dbPropValue, bookIds);
} else if (dbCreatedAt > 0 && dbPropertyValue != null) {
// Use older created-at
if (dbPropertyValue.getCalendar().getTimeInMillis() < dbCreatedAt) {
addOpUpdateCreatedAt(ops, note, dbPropertyValue, note.getCreatedAt());
} else {
addOpUpdateProperty(ops, note, createdAtPropName, dbCreatedAt, dbPropValue, bookIds);
}
// Or prefer property and set created-at time?
// addOpUpdateCreatedAt(ops, note.getId(), dbPropertyValue, note.getCreatedAt());
} else if (dbCreatedAt == 0 && dbPropertyValue != null) {
addOpUpdateCreatedAt(ops, note, dbPropertyValue, note.getCreatedAt());
}
// else: Neither created-at time nor property are set
}
}
}
long time = System.currentTimeMillis();
for (long bookId : bookIds) {
BooksClient.setModifiedTime(mContext, bookId, time);
}
/*
* Apply batch.
*/
try {
mContext.getContentResolver().applyBatch(ProviderContract.AUTHORITY, ops);
} catch (RemoteException | OperationApplicationException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
notifyDataChanged(mContext);
syncOnNoteUpdate();
}
use of com.orgzly.org.OrgProperties in project orgzly-android by orgzly.
the class Provider method loadBookFromReader.
private Uri loadBookFromReader(final String bookName, final String repoUrl, final String rookUrl, final String rookRevision, final long rookMtime, final String format, final Reader inReader, final String usedEncoding, final String detectedEncoding, final String selectedEncoding) throws IOException {
long startedAt = System.currentTimeMillis();
Uri uri;
/* Gets a writable database. This will trigger its creation if it doesn't already exist. */
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
/* Create book if it doesn't already exist. */
uri = getOrInsertBook(db, bookName);
final long bookId = ContentUris.parseId(uri);
/* Delete all notes from book. TODO: Delete all other references to this book ID */
db.delete(DbNote.TABLE, DbNote.BOOK_ID + "=" + bookId, null);
final Map<String, Long> propNameDbIds = new HashMap<>();
{
Cursor cursor = db.query(DbPropertyName.TABLE, new String[] { DbPropertyName._ID, DbPropertyName.NAME }, null, null, null, null, null);
try {
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
propNameDbIds.put(cursor.getString(1), cursor.getLong(0));
}
} finally {
cursor.close();
}
}
final Map<String, Long> propValueDbIds = new HashMap<>();
{
Cursor cursor = db.query(DbPropertyValue.TABLE, new String[] { DbPropertyValue._ID, DbPropertyValue.VALUE }, null, null, null, null, null);
try {
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
propValueDbIds.put(cursor.getString(1), cursor.getLong(0));
}
} finally {
cursor.close();
}
}
/*
* Maps node's lft to database id.
* Used to update parent id and insert ancestors.
* Not using SparseArray as speed is preferred over memory here.
*/
@SuppressLint("UseSparseArrays") final HashMap<Long, Long> lft2id = new HashMap<>();
/* Set of ids for which parent is already set. */
final Set<Long> notesWithParentSet = new HashSet<>();
boolean useCreatedAtProperty = AppPreferences.createdAt(getContext());
String createdAtProperty = AppPreferences.createdAtProperty(getContext());
/* Open reader. */
Reader reader = new BufferedReader(inReader);
try {
/*
* Create and run parser.
* When multiple formats are supported, decide which parser to use here.
*/
new OrgParser.Builder().setInput(reader).setTodoKeywords(AppPreferences.todoKeywordsSet(getContext())).setDoneKeywords(AppPreferences.doneKeywordsSet(getContext())).setListener(new OrgNestedSetParserListener() {
@Override
public void onNode(OrgNodeInSet node) throws IOException {
BookSizeValidator.validate(node);
/* Insert note with book id at specific position. */
NotePosition position = new NotePosition();
position.setBookId(bookId);
position.setLft(node.getLft());
position.setRgt(node.getRgt());
position.setLevel(node.getLevel());
position.setDescendantsCount(node.getDescendantsCount());
ContentValues values = new ContentValues();
// Update ContentValues
DbNote.toContentValues(values, position);
if (useCreatedAtProperty) {
DbNote.toContentValues(values, node.getHead().getProperties(), createdAtProperty);
}
DbNote.toContentValues(db, values, node.getHead());
long noteId = db.insertOrThrow(DbNote.TABLE, null, values);
/* Insert note's properties. */
int pos = 1;
OrgProperties noteProperties = node.getHead().getProperties();
for (String propName : noteProperties.keySet()) {
String propValue = noteProperties.get(propName);
Long nameId = propNameDbIds.get(propName);
if (nameId == null) {
nameId = DbPropertyName.getOrInsert(db, propName);
propNameDbIds.put(propName, nameId);
}
Long valueId = propValueDbIds.get(propValue);
if (valueId == null) {
valueId = DbPropertyValue.getOrInsert(db, propValue);
propValueDbIds.put(propValue, valueId);
}
long propertyId = DbProperty.getOrInsert(db, nameId, valueId);
DbNoteProperty.getOrInsert(db, noteId, pos++, propertyId);
}
/*
* Update parent ID and insert ancestors.
* Going through all descendants - nodes between lft and rgt.
*
* lft: 1 2 3 4 5 6
* L2 l1 r2 R2
*/
lft2id.put(node.getLft(), noteId);
for (long index = node.getLft() + 1; index < node.getRgt(); index++) {
Long descendantId = lft2id.get(index);
if (descendantId != null) {
if (!notesWithParentSet.contains(descendantId)) {
values = new ContentValues();
values.put(DbNote.PARENT_ID, noteId);
db.update(DbNote.TABLE, values, DbNote._ID + " = " + descendantId, null);
notesWithParentSet.add(descendantId);
}
values = new ContentValues();
values.put(DbNoteAncestor.NOTE_ID, descendantId);
values.put(DbNoteAncestor.ANCESTOR_NOTE_ID, noteId);
values.put(DbNoteAncestor.BOOK_ID, bookId);
db.insert(DbNoteAncestor.TABLE, null, values);
}
}
}
@Override
public void onFile(OrgFile file) throws IOException {
BookSizeValidator.validate(file);
ContentValues values = new ContentValues();
BooksClient.toContentValues(values, file.getSettings());
/* Set preface. TODO: Move to and rename OrgFileSettings */
values.put(DbBook.PREFACE, file.getPreface());
values.put(DbBook.USED_ENCODING, usedEncoding);
values.put(DbBook.DETECTED_ENCODING, detectedEncoding);
values.put(DbBook.SELECTED_ENCODING, selectedEncoding);
db.update(DbBook.TABLE, values, DbBook._ID + "=" + bookId, null);
}
}).build().parse();
} finally {
reader.close();
}
if (BuildConfig.LOG_DEBUG)
LogUtils.d(TAG, bookName + ": Parsing done in " + (System.currentTimeMillis() - startedAt) + " ms");
if (rookUrl != null) {
updateOrInsertBookLink(db, bookId, repoUrl, rookUrl);
updateOrInsertBookSync(db, bookId, repoUrl, rookUrl, rookRevision, rookMtime);
}
/* Mark book as complete. */
ContentValues values = new ContentValues();
values.put(DbBook.IS_DUMMY, 0);
db.update(DbBook.TABLE, values, DbBook._ID + "=" + bookId, null);
return uri;
}
use of com.orgzly.org.OrgProperties in project orgzly-android by orgzly.
the class NoteFragment method updateViewsFromNote.
/**
* Note -> Views
*/
private void updateViewsFromNote() {
OrgHead head = mNote.getHead();
setStateView(head.getState());
setPriorityView(head.getPriority());
/* Title. */
mTitleView.setText(head.getTitle());
/* Tags. */
if (head.hasTags()) {
mTagsView.setText(TextUtils.join(" ", head.getTags()));
} else {
mTagsView.setText(null);
}
/* Times. */
updateTimestampView(TimeType.SCHEDULED, mScheduledButton, head.getScheduled());
updateTimestampView(TimeType.DEADLINE, mDeadlineButton, head.getDeadline());
updateTimestampView(TimeType.CLOSED, mClosedButton, head.getClosed());
/* Properties. */
propertyList.removeAllViews();
if (head.hasProperties()) {
OrgProperties properties = head.getProperties();
for (String name : properties.keySet()) {
String value = properties.get(name);
addPropertyToList(name, value);
}
}
/* Content. */
bodyEdit.setText(head.getContent());
bodyView.setText(OrgFormatter.INSTANCE.parse(head.getContent(), getContext()));
}
use of com.orgzly.org.OrgProperties in project orgzly-android by orgzly.
the class NotesClient method forEachBookNote.
public static void forEachBookNote(Context context, String bookName, NotesClientInterface notesClientInterface) {
Cursor cursor = NotesClient.getCursorForBook(context, bookName);
try {
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
Note note = NotesClient.fromCursor(cursor);
OrgProperties propertiesFromCursor = getNoteProperties(context, note.getId());
note.getHead().setProperties(propertiesFromCursor);
notesClientInterface.onNote(note);
}
} finally {
cursor.close();
}
}
Aggregations