dmfs / contentpal Goto Github PK
View Code? Open in Web Editor NEWA friend to help with Android ContentProvider operations.
License: Apache License 2.0
A friend to help with Android ContentProvider operations.
License: Apache License 2.0
It's known that some devices cause problems when trying to get all columns of a calendar table by passing null
as the projection. We need to provide defaults for regular apps and for sync-adapters.
which allows to make a specific data vlaue the super primary value of its kind.
As per the fresh naming agreed for these kind of delegating base class it can be renamed to DelegatingTable
and also some methods are not final currently.
It's well known that some devices fail when trying to get all columns by passing null
as the projection. ContactsPal should provide defaults for normal apps and sync-adapters.
At present it's not possible to add a contact to a group which was inserted earlier in the same transaction.
When passing an Iterable<Iterable<…>>
it is impossible to ensure the right constructor is called.
Sometimes the use case doesn't justify the boilerplate code required to create and close a ContentProviderClient
in order to use a BasicOperationsQueue
. This is especially true if you just want to execute a single OperationsBatch
.
What we need is another simple OperationsQueue
which just executes every OperationsBatch
instantly using ContentResolver.applyBatch(…). This is also useful when using assert operations, because the lazyness of BasicOperationsQueue
makes it unsuitable for assert operations. You wouldn't know which OperationsBatch actually caused an error and some operations might have been executed, while everything after the erroneous batch would be "lost".
The CountedTest
shows a probably better way to mock this stuff.
The code below is repeated at multiple places, we can create a Predicate
delegating class for it:
new AllOf(predicate, new EqArg(CalendarContract.Events.CALENDAR_ID, mCalendarRow.values().charData(CalendarContract.Calendars._ID).value("-1")))
uriParams
are only decorated in insertOperation
but SyncParams
should be applied in all other cases as well.
In order to read the user's profile, as a developer I need a View
to access it.
#76 Adds a couple of useful utilities to test ContentPal and implementations based on ContentPal like ContactsPal and CalendarPal. In order to make these utilities available to these implementations we need a separate contentpal-testing
module which can be imported as a test dependency.
In general there are two obvious ways:
create a contentpal-testing
module which depends on contentpal
and add it as a testCompile
dependency to contentpal
. Though this creates a circular reference which needs to be resolved (possibly be limiting the dependency on a specific source set or something like this). The Android Gradle plugin doesn't seem to be able to resolve this automatically (unlike the Java plugin).
outsource the contentpal
interfaces to a module like contentpal-interfaces
and create a contentpal-testing
module which depends on this module. This works well as long as the test utilities don't use any contentpal
classes (which they probably shouldn't do anyway).
In order to create custom contact Groups, as a developer I need a Table and specialized
RowData` to create entries.
As a developer I want to be able to insert new contacts even easier like so
new RawContactInsertBatch<>(
AccountScoped(account, new RawContacts()),
new DisplayNameData("John Doe"),
new Primary(new Typed(ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE, new PhoneData("123"))),
new Custom("personal", new EmailData("[email protected]")))));
new NoteData("A note"),
new WorkPostal(
new StreetData("Some street"),
new PostcodeData("0000"),
new CityData("Some City"),
new CountryData("Some country")));
The only thing which needs to be provided to insert a new RawContact is the table and the data, hence we can reduce this to a single batch.
Can be useful in tests.
In order to add to the user's profile, as a developer I need a Table
to write to the profile table.
As a developer I want to read the data rows of a RawContact in a convenient manner, e.g. by declaring a RowSet like so
RowSet<Data> dataRows = new RawContactDataRows(dataView, new RowUriReference<RawContacts>(rawContactUri));
which represents the set of all data rows of the given RawContact.
When executing another (update, delete or assert) operation on a specific row which was inserted before, ResultTransactionContext
fails to return the correct RowUriReference.
Caused by: java.lang.IllegalArgumentException: Unable to resolve virtual RowReference org.dmfs.android.contentpal.references.VirtualRowReference@ae1645f
at org.dmfs.android.contentpal.transactions.contexts.EmptyTransactionContext.resolved(EmptyTransactionContext.java:44)
at org.dmfs.android.contentpal.transactions.contexts.Quick.resolved(Quick.java:50)
at org.dmfs.android.contentpal.operations.Put.contentOperationBuilder(Put.java:68)
at org.dmfs.android.contentpal.transactions.BaseTransaction.with(BaseTransaction.java:105)
at org.dmfs.android.contentpal.queues.BasicOperationsQueue.enqueue(BasicOperationsQueue.java:57)
For testing purposes it can be useful to have a Predicate
which takes RowData
and matches all rows which contain the given RowData
.
Usage:
new QueryRowSet(dataTable, new RowDataPredicate(rowData));
This would return all rows which contain the given rowData.
The question is, is that even possible at all? RowData
is added to a ContentProviderOperation.Builder
and requires a TransactionContext
to do so. We could certainly subclass the Builder so it builds the actual predicate instead and provide an EmptyTransactionContext
but that means you can not select by ids of virtual rows (because you need the TransactionContext
). In most cases that's not an issue but in some edge cases it is.
One use case: Assert operations based on the relation of two rows.
As a developer I want to be able to read the data rows of multiple RawContacts in a convenient manner, e.g. by declaring an Iterable
like so:
Iterable<RowSet<Data>> rawContacts = new BulkRawContactDataRows(dataView, new AccountEq(account));
Where rawContact
would iterate RowSets
of all RawContacts in the given account.
See https://developer.android.com/reference/android/content/ContentProviderOperation.Builder.html#withExpectedCount(int). Not sure about the name.
In order to create custom contact Aggregations, as a developer I need a Table
and specialized RowData
to create entries.
also NoneOf(…)
can easily be expressed as new Not(new AnyOf(…))
.
upgrade iterators and optional dependencies to 1.8 (introduce a shared Gradle property).
also replace all Collections.<>emptyList()
with EmptyIterable
s which had been added recently.
Abstract base class for Predicate
s which only need to compose a Predicate
in the constructor.
In order to access the CalendarProvider, as a developer I want a "CalendaPal" which provides abstractions for calendar and event tables.
Sometimes it might make sense to have a "Compare & Swap"-like operation like so:
public final class AssertAndPut<T> extends DelegatingOperationsBatch
{
public AssertAndPut(RowSnapshot<T> row, RowData<T> assertion, RowData<T> values)
{
super(
new Assert(row, assertion),
new Put(row, values)
);
}
}
In order to access the OpenTasks ContentProvider, as a developer I want an OpenTasksPal which provides abstractions for the OpenTasksContract.
In order to reference virtual rows in a query predicate the query needs access to the TransactionContext
. This will allow to query tables scoped to "virtual rows" which have just been committed earlier.
It may be useful in some places.
In order to make use of optimistic updates, as a developer I want support for Assert operations.
We need several Hamcrest Matchers which help testing Operations etc.
In order to get nice code coverage reports we should integrate codecov.io.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.