ResultSets are an implementation of the com.smartgwt.client.data.List interface that automatically fetches
DataSource records when items are requested from the List. ResultSets provide robust,
customizable, high-performance cache management for ListGrids and other built-in Smart GWT
components, and can be used as cache managers by custom components.

ResultSets manage data paging, that is, loading records in batches as the user navigates
the data set. A ResultSet will switch to using client-side sorting and filtering when
possible to improve responsiveness and reduce server load. ResultSets also participate in
automatic cache synchronization, observing operations on DataSources and automatically
updating their caches.

Creation

A ResultSet can be passed to any component that expects a List, and the List APIs can be
called directly on the ResultSet as long as the caller is able to deal with asynchronous
loading; see getRange().

Generally ResultSets do not need to be created directly, but are created by DataBound
components as an automatic consequence of calling
DataBound Component Methods.
For example, the ListGrid.fetchData() causes ListGrid.data to become an
automatically created ResultSet object. Automatically created ResultSets
can be customized via properties on ListGrids such as ListGrid.dataPageSize and
ListGrid.dataProperties. All ResultSets for a given
DataSource may also be
customized via setting DataSource.resultSetClass to the
name of a ResultSet
subclass in which
defaults have been changed.

A ResultSet defaults to using data paging, setting DSRequest.startRow and
DSRequest.endRow in issued dsRequests. Server code may always
return more rows than
the ResultSet requests and the ResultSet will correctly integrate those rows based on
DSResponse.startRow/endRow.
Hence the server can always avoid paging mode by simply returning all matching rows.

Directly created ResultSets are typically used by custom components, or as a means of
managing datasets that will be used by several components.

When created directly rather than via a dataBoundComponent, a newly created ResultSet will
not issue it's first "fetch" DSRequest until data is accessed (for example, via
get()).

Paging and total dataset length

When using data paging, the server communicates the total number of records that match the
current search criteria by setting DSResponse.totalRows. The
ResultSet will then
return this number from getLength(), and ListGrids and other
components will show a scrollbar that allows the user to jump to the end of the dataset
directly.

However, the ResultSet does not require that the server calculate the true length of the
dataset, which can be costly for an extremely large, searchable dataset. Instead, the
server may simply advertise a totalRows value that is one page larger
than the last row loaded. This results in a UI sometimes called "progressive loading",
where the user may load more rows by scrolling past the end of the currently loaded rows,
but is not allowed to skip to the end of the dataset.

No client-side settings are required to enable this mode - it is entirely server-driven.
However, it is usually coupled with disabling sorting,
since
server-side sorting would also force the server to traverse the entire dataset. Note
also the progressiveLoading flag, which can be applied
at a DataSource, operation, request, component or ResultSet level; if you are using the
built-in server-side DataSource implementations with Pro or better, this tells Smart GWT
Server to use its pre-built progressive loading mode for that DataSource, operation,
request, component or ResultSet.

Client-side Sorting and Filtering

If a ResultSet obtains a full cache for the current set of filter criteria, it will
automatically switch to client-side sorting, and will also use client-side filtering
if the filter criteria are later changed but appear to be more restrictive than the
criteria in use when the ResultSet obtained a full cache.

The useClientSorting and
useClientFiltering flags can be used to disable
client-side sorting and filtering respectively if these behaviors don't match server-based
sorting and filtering. However, because client-side sorting and filtering radically improve
responsiveness and reduce server load, it is better to customize the ResultSet so that it
can match server-side sorting and filtering behaviors.

Sorting behavior is primarily customized via the "sort normalizer" passed to
sortByProperty(), either via direct calls on a standalone
ResultSet, or via
ListGridField.sortNormalizer() for a
ListGrid-managed ResultSet.

By default, client-side filtering interprets the criteria passed to
setCriteria() as a set of field values that records must match
(similarly to the built-in SQL/Hibernate connectors built into the Smart GWT Server).
Custom client-side filtering logic can be implemented by overriding
applyFilter(). Overriding
compareCriteria() allows you to control when the ResultSet
uses client-side vs server-side filtering, and the ResultSet has two default
criteria policies built-in.

Modifying ResultSets

Records cannot be directly added or removed from a ResultSet via com.smartgwt.client.data.List
APIs such as removeAt(), since this would break the consistency of
server and client row numbering needed for data paging, and also
create some issues with automatic cache synchronization.

To create a locally modifiable cache of Records from a DataSource, you
can use DataSource.fetchData() to retrieve a List of Records which
can
be modified directly, or you can create a client-only DataSource from
the retrieved data to share a modifiable cache between several
DataBoundComponents.

Updates and Automatic Cache Synchronization

Once a ResultSet has retrieved data or has been initialized with data, the ResultSet will observe any
successful "update", "add" or "remove" dsRequests against their DataSource, regardless of the
component that initiated them. A ResultSet with a full cache for the current filter criteria will
integrate updates into the cache automatically.

Updated rows that no longer match the current filter criteria will be removed
automatically. To prevent this, you can set neverDropUpdatedRows.
Added rows will similarly be added to the cache only if they match current filter criteria.

Note that the client-side filtering described above is also used to determine whether
updated or added rows should be in the cache. If any aspect of automated cache update is
ever incorrect, dropCacheOnUpdate can be set for the
ResultSet or DSResponse.invalidateCache can be set for an
individual dsResponse.

If automatic cache synchronization isn't working, troubleshoot the problem using the steps
suggested in the FAQ.

Regarding operationIds and how they affect caching,
take into account that cache sync is based on the fetch used - any add or update operation
uses a fetch to retrieve updated data, and the operationId of that fetch can be set via
cacheSyncOperation.
If the operationId of the cache is different from the operationId of the cache update data,
it won't be used to update the cache, since the fields included and other aspects of the
data are allowed to be different across different operationIds. This allows to maintain
distinct caches on a per component basis, so when two components are using separate
operationIds they are assumed to have distinct caches, because updates performed with
one operationId will not affect the cache obtained via another operationId.
Also, take into account that operationId must be unique per DataSource, across all
operationTypes for that DataSource.

Data Paging with partial cache

When in paging mode with a partial cache, a ResultSet relies on server side sorting, setting
DSRequest.sortBy to the current sort field and direction. In order
for the cache to
remain coherent, row numbering must continue to agree between server and client as new
fetches are issued, otherwise, duplicate rows or missing rows may occur.

If concurrent modifications by other users are allowed, generally the server should set
DSResponse.invalidateCache to clear the cache when
concurrent modification is
detected.

In paging mode with a partial cache, any successful "update" or "add" operation may cause
client and server row numbering to become out of sync. This happens because the update
may affect the sort order, and client and server cannot be guaranteed to match for sets of
records that have equivalent values for the sort field.

For this reason, after an "add" or "update" operation with a partial cache, the ResultSet
will automatically mark cache for invalidation the next time a fetch operation is performed.
Alternatively, if updatePartialCache is set to false,
the ResultSet will
simply invalidate cache immediately in this circumstance.

Returns a list of the currently visible data, that is, all rows that match the current
criteria, with null entries or loading markers for
rows that are not yet loaded or in the process of loading, respectively.

When a successful Add, Update or Remove type operation fires on this ResultSet's dataSource, if data is unset, should we integrate the submitted data values (from the
request) into our data-set? This attribute will be passed to DataSource#getUpdatedData
as the useDataFromRequest parameter.

When a successful Add, Update or Remove type operation fires on this ResultSet's dataSource, if data is unset, should we integrate the submitted data values (from the
request) into our data-set? This attribute will be passed to DataSource#getUpdatedData
as the useDataFromRequest parameter.

Will changing the criteria for this resultSet require fetching new data from the server, or can the new criteria be
satisfied from data already cached on the client? Second textMatchStyle parameter determines whether a
change of text-match style will require a server fetch - for example if filter is being changed between an exact match
(from e.g: ListGrid.fetchData()) and a substring match (from e.g: ListGrid.filterData()). This method can be used to determine whether ListGrid.fetchData() or ListGrid.filterData()
would cause a server side fetch when passed a certain set of criteria.

Will changing the criteria for this resultSet require fetching new data from the server, or can the new criteria be
satisfied from data already cached on the client? Second textMatchStyle parameter determines whether a
change of text-match style will require a server fetch - for example if filter is being changed between an exact match
(from e.g: ListGrid.fetchData()) and a substring match (from e.g: ListGrid.filterData()). This method can be used to determine whether ListGrid.fetchData() or ListGrid.filterData()
would cause a server side fetch when passed a certain set of criteria.

asSGWTComponent

Returns the existing SGWT ResultSet, or creates and returns one if none exist,
associated with the supplied JavaScriptObject. If
the supplied object is not a SmartClient ResultSet, a warning will be logged and null
returned; otherwise the SGWT ResultSet will be returned.

Parameters:

jsObj - SmartClient ResultSet whose wrapper is wanted

Returns:

wrapping SGWT ResultSet or null

ensureCreated

public void ensureCreated()
throws java.lang.IllegalStateException

Ensures that the underlying SmartClient ResultSet object is created for this ResultSet
instance. If the SmartClient object has already been created, then calling this method
amounts to a no-op. Otherwise, the isc.ResultSet.create() function is
executed to create the SmartClient ResultSet object wrapped by this instance.

This method is required to be called for standalone usage of a ResultSet. In addition,
it can only be called after all initial configuration (dataSource,
allRows if being used, etc.) has been set.

Throws:

java.lang.IllegalStateException - if no dataSource has been set

getPaletteDefaults

public java.util.Map getPaletteDefaults()

This method returns a Map of config properties suitable for use as the "defaults"
attribute of a PaletteNode. Use it when you need to
work with PaletteNodes indirectly, such when setting up
TileRecords that will be used in a
TilePalette. See
the dev tools overview for examples of how to
assemble and acquire a suitable defaults object when you are creating a PaletteNode
indirectly

setInitialData

This data will be treated exactly as though it were the data returned from
the ResultSet's first server fetch.

By default, initialData will be considered a complete response (all
rows that match the Criteria which the ResultSet was initialized with).

Set initialLength to treat initialData as a partial
response, equivalent to receiving a DSResponse with startRow:0,
endRow:initialData.length and totalRows:initialLength. Normal data paging will then occur if
data is requested for row indices not filled via initialData.

Note : This is an advanced setting

Parameters:

initialData - initialData Default value is null

Throws:

java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

setInitialSort

Initial multi property sort specification for this ResultSet's data. If a ResultSet is being
explicitly created and seeded with setInitialData(Record[]), this method may be used
to notify the ResultSet that the data is already sorted such that a call to RecordList.setSort(SortSpecifier...) will
not require a new fetch unless additional data beyond the ends of the specified initialData are required.

Parameters:

sortSpecifiers - Initial sort specification

setAllRows

If the complete set of records for a resultSet is available when the resultSet is created, it can be made available to
the resultSet via this property at initialization time. This data will then be considered cached meaning sorting and
filtering can occur on the client (no need for server fetch). This cached data can be dropped via a call to invalidateCache().

Note : This is an advanced setting

Parameters:

allRows - allRows Default value is null

Throws:

java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

setResultSize

public void setResultSize(int resultSize)

How many rows to retrieve at once.

Applicable only with fetchMode: "paged". When a paged ResultSet is
asked for rows that have not yet been loaded, it will fetch adjacent rows that are likely to be required soon, in
batches of this size.

Note : This is an advanced setting

Parameters:

resultSize - resultSize Default value is 75

getResultSize

public int getResultSize()

How many rows to retrieve at once.

Applicable only with fetchMode: "paged". When a paged ResultSet is
asked for rows that have not yet been loaded, it will fetch adjacent rows that are likely to be required soon, in
batches of this size.

Returns:

int

setFetchDelay

public void setFetchDelay(int fetchDelay)

Delay in milliseconds before fetching rows.

When a get() or getRange() call asked for rows that haven't been loaded,
the ResultSet will wait before actually triggering the request. If, during the delay, more get() or getRange() calls
are made for missing rows, the final fetch to the server will reflect the most recently requested rows.

The intent
of this delay is to avoid triggering many unnecessary fetches during drag-scrolling and similar user interactions.

Note : This is an advanced setting

Parameters:

fetchDelay - fetchDelay Default value is 0

getFetchDelay

public int getFetchDelay()

Delay in milliseconds before fetching rows.

When a get() or getRange() call asked for rows that haven't been loaded,
the ResultSet will wait before actually triggering the request. If, during the delay, more get() or getRange() calls
are made for missing rows, the final fetch to the server will reflect the most recently requested rows.

The intent
of this delay is to avoid triggering many unnecessary fetches during drag-scrolling and similar user interactions.

Note: any field values in the criteria explicitly specified as null will be passed to the server. By default the server then returns only records whose value is null for that field. This differs from certain higher level methods such as ListGrid.fetchData() which prune null criteria fields before performing a fetch operation.

setUseClientFiltering

Whether to filter data locally when all DataSource records have been loaded (that is, criteria is blank and cache is
complete).

This may need to be disabled if client-side filtering differs from server-side filtering in a way that
affects functionality or is surprising.

This setting is distinct from fetchMode:"local", which
explicitly loads all available DataSource records up front.

See ResultSet#applyFilter for default filtering behavior.

NOTE: even with
useClientFiltering false, client-side filtering will be used during cache sync to determine if an updated or added row
matches the current criteria. To avoid relying on client-side filtering in this case, either: - avoid returning
update data when the updated row doesn't match the current filter - set dropCacheOnUpdate

Note : This is an advanced setting

Parameters:

useClientFiltering - useClientFiltering Default value is true

getUseClientFiltering

public java.lang.Boolean getUseClientFiltering()

Whether to filter data locally when all DataSource records have been loaded (that is, criteria is blank and cache is
complete).

This may need to be disabled if client-side filtering differs from server-side filtering in a way that
affects functionality or is surprising.

This setting is distinct from fetchMode:"local", which
explicitly loads all available DataSource records up front.

See ResultSet#applyFilter for default filtering behavior.

NOTE: even with
useClientFiltering false, client-side filtering will be used during cache sync to determine if an updated or added row
matches the current criteria. To avoid relying on client-side filtering in this case, either: - avoid returning
update data when the updated row doesn't match the current filter - set dropCacheOnUpdate

Returns:

Boolean

setUpdateCacheFromRequest

When a successful Add, Update or Remove type operation fires on this ResultSet's dataSource, if data is unset, should we integrate the submitted data values (from the
request) into our data-set? This attribute will be passed to DataSource#getUpdatedData
as the useDataFromRequest parameter.

Note : This is an advanced setting

Parameters:

updateCacheFromRequest - updateCacheFromRequest Default value is true

Throws:

java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getUpdateCacheFromRequest

public java.lang.Boolean getUpdateCacheFromRequest()

When a successful Add, Update or Remove type operation fires on this ResultSet's dataSource, if data is unset, should we integrate the submitted data values (from the
request) into our data-set? This attribute will be passed to DataSource#getUpdatedData
as the useDataFromRequest parameter.

setDropCacheOnUpdate

Whether to discard all cached rows when a modification operation (add, update, remove) occurs on the ResultSet's
DataSource.

A ResultSet that has a complete cache for the current filter criteria can potentially incorporate a
newly created or updated row based on the data that the server returns when a modification operation completes. However
this is not always possible for ResultSets that show some types of joins, or when the server cannot easily return update
data. In this case set dropCacheOnUpdate to cause the cache to be discarded when an update occurs.

dropCacheOnUpdate can be set either directly on a ResultSet, or on a DataSource in order to affect all
ResultSets on that DataSource.

Note : This is an advanced setting

Parameters:

dropCacheOnUpdate - dropCacheOnUpdate Default value is false

Throws:

java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getDropCacheOnUpdate

public java.lang.Boolean getDropCacheOnUpdate()

Whether to discard all cached rows when a modification operation (add, update, remove) occurs on the ResultSet's
DataSource.

A ResultSet that has a complete cache for the current filter criteria can potentially incorporate a
newly created or updated row based on the data that the server returns when a modification operation completes. However
this is not always possible for ResultSets that show some types of joins, or when the server cannot easily return update
data. In this case set dropCacheOnUpdate to cause the cache to be discarded when an update occurs.

dropCacheOnUpdate can be set either directly on a ResultSet, or on a DataSource in order to affect all
ResultSets on that DataSource.

setUpdatePartialCache

If set to true, updated and added rows will be integrated into the client-side cache even if paging is enabled and cache
is partial. If updatePartialCache is false, the cache will be invalidated and new data fetched.

If
updatePartialCache is enabled and an "add" or "update" operation succeeds with a partial cache:

updated rows
will remain in their current position. No attempt will be made to sort them into a new position even if the sort field
was updated.

newly added rows will be added at either the end (first preference) or beginning of the dataset if
that part of the dataset is cached and was most recently requested. If not, the new row is added at the end of the most
recently requested contiguously cached range

The cache will then be dropped the next time rows are fetched, to
prevent problems with inconsistent row numbering between the server and client, which could otherwise lead to duplicate
rows or rows being skipped entirely.

Note : This is an advanced setting

Parameters:

updatePartialCache - updatePartialCache Default value is true

Throws:

java.lang.IllegalStateException - this property cannot be changed after the underlying component has been created

getUpdatePartialCache

public java.lang.Boolean getUpdatePartialCache()

If set to true, updated and added rows will be integrated into the client-side cache even if paging is enabled and cache
is partial. If updatePartialCache is false, the cache will be invalidated and new data fetched.

If
updatePartialCache is enabled and an "add" or "update" operation succeeds with a partial cache:

updated rows
will remain in their current position. No attempt will be made to sort them into a new position even if the sort field
was updated.

newly added rows will be added at either the end (first preference) or beginning of the dataset if
that part of the dataset is cached and was most recently requested. If not, the new row is added at the end of the most
recently requested contiguously cached range

The cache will then be dropped the next time rows are fetched, to
prevent problems with inconsistent row numbering between the server and client, which could otherwise lead to duplicate
rows or rows being skipped entirely.

getValueMap

Get a map of the form { item[idField] -> item[displayField] }, for all items in the list. If more than
one item has the same idProperty, the value for the later item in the list will clobber the value for the
earlier item.

If this method is called when the allMatchingRowsCached(), it
will trigger fetches, and will return a valueMap reflecting only the currently loaded rows.

getLength

public int getLength()

Return the total number of records that match the current filter criteria.

This length can only be known, even
approximately, when the first results are retrieved from the server. Before then, the ResultSet returns a large length
in order to encourage viewers to ask for rows. lengthIsKnown() can be called
to determine whether an actual length is known.

indexOf

Return the position in the list of the first instance of the specified object.

If pos is specified, starts looking
after that position.

Returns -1 if not found.

NOTE: ResultSet.indexOf() only inspects the current cache
of records, so it is only appropriate for temporary presentation purposes. For example, it would not be appropriate to
hold onto a record and attempt to use indexOf() to determine if it had been deleted.

indexOf

Return the position in the list of the first instance of the specified object.

If pos is specified, starts looking
after that position.

Returns -1 if not found.

NOTE: ResultSet.indexOf() only inspects the current cache
of records, so it is only appropriate for temporary presentation purposes. For example, it would not be appropriate to
hold onto a record and attempt to use indexOf() to determine if it had been deleted.

getRange

Return the items between position start and end, non-inclusive at the end, possibly containing markers for records that
haven't loaded yet.

Calling getRange for records that have not yet loaded will trigger an asynchronous fetch. The
returned data will contain the loading marker as a placeholder for records being fetched. If
any rows needed to be fetched, dataArrived() will fire when they arrive.

getAllVisibleRows

Returns a list of the currently visible data, that is, all rows that match the current
criteria, with null entries or loading markers for
rows that are not yet loaded or in the process of loading, respectively.

This method will not trigger a fetch to load more records. getAllVisibileRows() will return
null if lengthIsKnown() is false.

Records are returned in a new List but the Records within it are the same
instances that the ResultSet is holding onto. Hence it's safe to add or remove records from
the List without affecting the ResultSet but modifying the Records themselves is a direct
modification of the client-side cache.

Returns:

the records in the cache that match the current criteria, possibly null

usingFilteredData

public java.lang.Boolean usingFilteredData()

Determine whether the ResultSet is showing a filtered, proper subset of the cached rows.
This happens if client filtering is enabled. Rows may have been
loaded from the server when a more restrictive criteria is applied such that filtering could
be performed on the client side.

This method returns false if data is not loaded yet.

Returns:

true if the ResultSet is showing a filtered subset of the cached rows,
false otherwise.

getAllCachedRows

Returns a list of all rows that have been cached. This is potentially a superset of all rows that are
available via getAllVisibleRows() if the ResultSet is using client-side filtering to
display a subset of loaded rows (see the ResultSet overview).

This method will not trigger a fetch to load more records. getAllCachedRows() will return
null if lengthIsKnown() is false.

Records are returned in a new List but the Records within it are the same
instances that the ResultSet is holding onto. Hence it's safe to add or remove records from
the List without affecting the ResultSet but modifying the Records themselves is a direct
modification of the client-side cache.

Returns:

the records in the cache, possibly null

lengthIsKnown

public java.lang.Boolean lengthIsKnown()

Whether the ResultSet actually knows how many records are available from the server. The ResultSet will not know how
many records are available when initially fetching and filtering data. Note that the value returned from getLength() will be an arbitrary, large value if the actual length is not known.

Returns:

whether length is known

rowIsLoaded

public java.lang.Boolean rowIsLoaded(int rowNum)

Whether the given row has been loaded.

Unlike get(), will not trigger a server fetch.

Parameters:

rowNum - row to check

Returns:

true whether if the given row has been loaded, false if it has not been loaded or is still in the
process of bring loaded

rangeIsLoaded

public java.lang.Boolean rangeIsLoaded(int startRow,
int endRow)

Whether the given range of rows has been loaded. Unlike getRange(), will not trigger a server fetch.

Parameters:

startRow - start position, inclusive

endRow - end position, exclusive

Returns:

true if all rows in the given range have been loaded, false if any rows in the range have not been
loaded or are still in the process of being loaded

findByKey

Attempt to find the record in the resultSet that has a primary key value that matches the passed in parameter value.
Only the locally cached data will be searched. Checks only loaded rows and will not trigger a fetch. Returns null if
there is no match, data is not loaded, or there is no 'dataSource'.

willFetchData

Will changing the criteria for this resultSet require fetching new data from the server, or can the new criteria be
satisfied from data already cached on the client? Second textMatchStyle parameter determines whether a
change of text-match style will require a server fetch - for example if filter is being changed between an exact match
(from e.g: ListGrid.fetchData()) and a substring match (from e.g: ListGrid.filterData()). This method can be used to determine whether ListGrid.fetchData() or ListGrid.filterData()
would cause a server side fetch when passed a certain set of criteria.

Parameters:

newCriteria - new criteria to test.

Returns:

true if server fetch would be required to satisfy new criteria.

willFetchData

Will changing the criteria for this resultSet require fetching new data from the server, or can the new criteria be
satisfied from data already cached on the client? Second textMatchStyle parameter determines whether a
change of text-match style will require a server fetch - for example if filter is being changed between an exact match
(from e.g: ListGrid.fetchData()) and a substring match (from e.g: ListGrid.filterData()). This method can be used to determine whether ListGrid.fetchData() or ListGrid.filterData()
would cause a server side fetch when passed a certain set of criteria.

Parameters:

newCriteria - new criteria to test.

textMatchStyle - New text match style. If not passed assumes textMatchStyle will not be modified.

Returns:

true if server fetch would be required to satisfy new criteria.

filterLocalData

public void filterLocalData()

Derive the current filtered set of data from the cache of all matching rows.

findAll

Note: JavaScript has no long type, so the long value becomes a JavaScript Number, which has a lesser range than Java long.
The range for integer numbers in Javascript is [-9007199254740992,9007199254740992] or [-Math.pow(2,53),Math.pow(2,53)].

findIndex

Note: JavaScript has no long type, so the long value becomes a JavaScript Number, which has a lesser range than Java long.
The range for integer numbers in Javascript is [-9007199254740992,9007199254740992] or [-Math.pow(2,53),Math.pow(2,53)].

Note: JavaScript has no long type, so the long value becomes a JavaScript Number, which has a lesser range than Java long.
The range for integer numbers in Javascript is [-9007199254740992,9007199254740992] or [-Math.pow(2,53),Math.pow(2,53)].