Perform the action
, usually on a worker thread associated with this
notifier.
Perform the action
, usually on a worker thread associated with this
notifier. Results may be posted back to the calling thread, viz.
the conventions documented in org.positronicnet.notifications.Actions.
ContentQuery whose conditions match those declared for the Scope.
ContentQuery whose conditions match those declared for the Scope.
Notifier which can be used to fetch, or to receive updates on, the number of records matching the scope's conditions.
Notifier which can be used to fetch, or to receive updates on, the number of records matching the scope's conditions. One usage pattern:
Bugs.count ! AddWatcher( this ) { bugCount => if (bugCount == 0) { startActivity( new Intent( this, classOf[ CelebrationActivity ]) Bugs ! StopWatcher( this ) finish } }
The onChangeTo
method in
PositronicActivityHelpers can simplify this
a bit... but I digress.
Note that count
is supported only if it is supported by the underlying
ContentRepository; e.g., by databases, but
not by ContentProviders.
As for recordsQuery
, but returns a notifier of the count of
records matching the extra conditions.
As for recordsQuery
, but returns a notifier of the count of
records matching the extra conditions.
AppFacility associated with the content source.
AppFacility associated with the content source.
Synchronously fetch the value being monitored by this Notifier
.
Synchronously fetch the value being monitored by this Notifier
.
Fetch and construct the records from a ContentQuery on this record manager's ContentRepository.
Fetch and construct the records from a ContentQuery on this record manager's ContentRepository.
This is largely an internal method. It's made available mostly for the sake of ORM extensions, to be implemented as traits mixed into RecordManager subclasses, on the model of SoftDelete.
Find the record with the given id
, if it exists, running the
query on the current thread, and returning it as the value.
Find the record with the given id
, if it exists, running the
query on the current thread, and returning it as the value.
XXX should only find it if it matches conditions of the scope, as per Rails.
ContentQuery whose conditions match those for the records in scope.
ContentQuery whose conditions
match those for the records in scope. Ordinarily the same
as baseQuery
, but some RecordManagers
may add extra conditions to, e.g., make soft-deleted records
invisible from an ordinary fetch.
Support for "cascading deletes", when the parent record in a many-to-one association is gone.
Support for "cascading deletes", when the parent record in a many-to-one association is gone.
This is largely an internal method. It's made available mostly for the sake of ORM extensions, to be implemented as traits mixed into RecordManager subclasses, on the model of SoftDelete.
org.positronicnet.notications.Notifier for whether this Scope has any deleted records within it:
org.positronicnet.notications.Notifier for whether this Scope has any deleted records within it:
myList.items.hasDeleted ! Fetch{ hasDeleted => { if ( hasDeleted ) myList.items ! Undelete else toast( R.string.undeletes_exhausted ) }}
Upcasting a raw Long to an ID; sometimes useful in cases where serializing "baked" record Ids is really awkward, as in the extras to a pending intent.
Upcasting a raw Long to an ID; sometimes useful in cases where serializing "baked" record Ids is really awkward, as in the extras to a pending intent...
Produce a modified subscope which supplies at most a given number of records.
Produce a modified subscope which supplies at most a given
number of records. The string supplied is used directly in a SQL limit
clause.
May not be supported by all repositories; in particular, it is
not supported by ContentProviders.
Produce a modified subscope which supplies at most a given number of records.
Produce a modified subscope which supplies at most a given
number of records. The string supplied is used directly in a SQL limit
clause.
May not be supported by all repositories; in particular, it is
not supported by ContentProviders.
Declare that the field named fieldName
in our
org.positronic.orm.ManagedRecord subclass T
is to be mapped to the persistent storage columnName
.
Declare that the field named fieldName
in our
org.positronic.orm.ManagedRecord subclass T
is to be mapped to the persistent storage columnName
.
If the primaryKey
argument is set true, this field and
column will be treated as the record's primary key; this
currently must be a Long
.
For Database mapping, when using a RecordManager, it is rarely necessary to call this explicitly; so long as you're following the usual naming conventions, the ORM will figure out what's going on without being told. Those conventions are:
_id
will be mapped to a field named id
,
and will be treated as the primary key.like_this
will be mapped to a
camel-cased field likeThis
.However, a BaseRecordManager will not map any columns by default, and requires you to map everything explicitly.
Produce a new object (to be populated with mapped data from a query).
Produce a new object (to be populated with mapped data from a query).
Default is to use a niladic constructor if one exists. Failing that, if there is one constructor, and defaults for all its arguments, we'll use that.
Note that if you override this, you might want to provide a niladic
constructor anyway on the class itself, or strange and unuseuful things
will happen when attempting to serialize and deserialize our
RecordIds, e.g., when putting them into the
extras of an android Intent
.
The Notifier to which the delegator forwards, well.
The Notifier to which the delegator forwards, well... everything here.
As hasDeleted
, but notifies for the number of deleted records.
As hasDeleted
, but notifies for the number of deleted records.
Perform the action
, synchronously on the calling thread.
Perform the action
, synchronously on the calling thread.
Produce a modified subscope which supplies records in a particular order.
Produce a modified subscope which supplies records in a particular
order. The string supplied is used directly in a SQL order
clause (or passed to the underlying ContentProvider
, if
appropriate).
Declare a mapping, as with mapField
, for a field to be
designated as the primary key.
Declare a mapping, as with mapField
, for a field to be
designated as the primary key.
Returns a notifier for a subset of the records covered by this
scope, matching extra conditions, which can be changed later by sending
a Requery
message.
Returns a notifier for a subset of the records covered by this
scope, matching extra conditions, which can be changed later by sending
a Requery
message.
This can be used, for example, as the source for an IndexedSeqSourceAdapter, which displays the rows matching the user's "current search condition", whatever it may be, and changes when the condition changes, but without having to rewire the IndexedSeqSourceAdapter, perhaps something like so:
val matchingBugs = Bugs.recordsQuery( "" ){ pattern => Bugs.where( "tag_line like ?", pattern ) } // ... later ... matchingBugs ! Requery( "newpattern" )
The Requery
will cause any declared watchers of matchingBugs
to be notified of the new query result.
Produce a restricted subscope containing only records
matching an extra SQL condition, possibly including
?
placeholders which can get filled in by the supplied
ContentValue arguments, if
any.
Produce a restricted subscope containing only records
matching an extra SQL condition, possibly including
?
placeholders which can get filled in by the supplied
ContentValue arguments, if
any. Example:
val recentBugs = Bugs.where( "state != ? and create_date > ?", "closed", System.currentTimeMillis - 3*86400*1000 )
Note that the columns are named using internal SQL column names, not the Java mapped versions.
(Note for the future: we could consider changing this by
allowing syntax like "{createDate}>?"
, where the string
in curly-braces would be a Java field name to be mapped to
the SQL equivalent. But that's not there yet.)
Produce a restricted subscope containing only records where particular fields have particular values.
Produce a restricted subscope containing only records
where particular fields have particular values.
The argument is a set of
(String,[[org.positronicnet.content.ContentValue]])
pairs,
often entered using ->
notation, like so:
Bugs.whereEq( "status"->"done", "ownerId"->joe.id )
Note that columns can be designated by either the names
of the columns in the underlying tables, or the names of the
Scala val
s in the classes that they get mapped to.
Mixin for record managers, to implement "soft deletion". (Written as a first-draft ORM extension, largely to make sure I wasn't painting myself into a corner where such things are impossible, so API here is subject to change.) See the "todo list" sample app for a usage example.
With this scheme, items that the user deletes aren't really deleted immediately. Instead, they get marked with an
is_deleted
flag, which puts them in limbo from which they can be recalled with anundelete
.Whenever we're doing a soft deletion, similar items that already were in limbo do in fact go away.
To activate the basic machinery for a record type, make sure the table corresponding to the records has an
is_deleted
column (you don't have to map it), and mixSoftDelete[T]
into the record manager.This gets you something pretty aggressive about expunging prior
is_deleted
records --- anything in the table that already wasis_deleted
gets the axe. To control that, you can mix SoftDeleteScope into derived scopes (e.g. a HasMany).Also, if you have a many-to-one relation, and the parent records are subject to soft deletion, the child records might want to know about it. You can use the ParentSoftDeleteListener trait to look for that...