← Back to Stormify Documentation

PagedList

Facet-based lazy paginated list view of entities of type T, a UI-model façade over the shared PagedQueryCore engine.

A PagedList implements kotlin.collections.AbstractList, so it behaves as a normal List<T> while loading pages on demand from the database. Filtering and sorting are defined through Facet objects set up at configuration time. The list caches the current page and the total size, and supports a "selected" entity that always appears first.

When to use PagedList

PagedList is intended for UI consumers — desktop/embedded grids (ZK, Compose, Swing, JavaFX) where a single long-lived list instance drives a view. It is not appropriate for stateless server-side request handling: its per-column filter/sort state is mutable and shared, and its cached page / size / selected entity have no meaning across independent REST requests.

For REST/stateless server use, use PagedQuery — configure once at startup, call execute(spec) per request.

A list is created by a Stormify instance and works on it: stormify.pagedList<T>(), or pagedList<T>() on the instance of the enclosing transaction or the default instance; from Java, stormify.pagedList(T.class).

Usage

val list = stormify.pagedList<Company>()
list.addFacet("name") // text filter + sort
list.addFacet("contactPerson.firstName",
"contactPerson.lastName") // OR filter via FK
list.addSqlFacet("SUM(amount)", Facet.Type.NUMERIC)

list.getFacet(0).filter = "Acme"
list.getFacet(1).sort = SortState.ASCENDING

val company = list[0] // triggers page load
val total = list.size // triggers COUNT query

Parameters

classType

The KClass of the entity type

Type Parameters

T

The entity type

Properties

Link copied to clipboard
Link copied to clipboard

The columns defined on this list. Columns are added via addFacet or addSqlFacet and define what can be filtered and sorted.

Link copied to clipboard

Input parser for this list. Overrides Stormify.inputParser.

Link copied to clipboard

Whether the query should return only distinct results.

Link copied to clipboard

Direction of the primary key in the generated ORDER BY. The key orders the rows when no facet sorts, and closes every ORDER BY as the tie-breaker after the facet sorts. Default SortState.ASCENDING.

Link copied to clipboard

The page size — the number of elements loaded into memory at a time. Default is 15.

Link copied to clipboard
var selected: T?

Sets the selected entity, which will appear first in the list.

Link copied to clipboard
open override val size: Int

Total number of rows that match the current filters and constraints. The first access issues a COUNT(*) (or COUNT(*) FROM (SELECT DISTINCT ...) if isDistinct) query and caches the result for reuse.

Functions

Link copied to clipboard
fun addFacet(vararg fieldPaths: String): Facet

Adds a column with one or more field paths. The column type is auto-detected from the field's Kotlin type. Multiple paths use OR logic for filtering.

fun addFacet(vararg paths: ScalarPath): Facet

Adds a column using type-safe KSP-generated path objects.

fun addFacet(enumValues: Map<String, Any>, vararg fieldPaths: String): Facet

Adds an ENUM column with a custom display-name-to-DB-value map. Use this when the field is not a Kotlin enum but logically represents one (e.g., a status integer column with human-readable labels), or to override the auto-built map for a real enum field. The Map first argument distinguishes this overload from the scalar-typed variants at compile time.

fun addFacet(enumValues: Map<String, Any>, vararg paths: ScalarPath): Facet

Enum-column variant using typed paths — same rules as the Map + String overload.

fun addFacet(type: Facet.Type, vararg fieldPaths: String): Facet

Adds a column with an explicit type override. Use this when the auto-detected type (based on the field's Kotlin type) is not what you want — for example, to treat a string zip-code column as numeric.

fun addFacet(type: Facet.Type, vararg paths: ScalarPath): Facet

Explicit-type variant of addFacet using typed paths.

Link copied to clipboard
fun addSqlFacet(expression: String, type: Facet.Type = Facet.Type.TEXT): Facet

Adds a raw/custom column backed by an arbitrary SQL expression.

fun addSqlFacet(expression: String, type: Facet.Type, converter: Converter): Facet

Adds a raw/custom column with a custom Converter. The converter receives the column expression and the user's filter value, and returns a SQL fragment while staging bind parameters via SqlArgsCollector.

Link copied to clipboard

Registers a TableRef for the root entity table. The ref's TableRef.alias resolves to the underlying DB table name, so raw SQL in setConstraints or in an addSqlFacet expression can safely reference the root without hardcoding the table name.

Registers a TableRef for a table reached through the given dotted path (e.g. "address", "company.hq"). The final segment must be an FK reference, not a scalar field. The associated JOIN is activated in every subsequent SQL build while the ref's TableRef.isActive is true.

Registers a TableRef from a KSP-generated typed ReferencePath.

Link copied to clipboard
fun constraints(query: String, vararg args: Any?): PagedList<T>
Link copied to clipboard

Fluent isDistinct: turns distinct mode on.

Link copied to clipboard
fun facet(vararg fieldPaths: String): PagedList<T>

Fluent addFacet: one facet over fieldPaths (dot notation), OR-combined when more than one.

fun facet(vararg paths: ScalarPath): PagedList<T>

Fluent addFacet: one facet over paths, OR-combined when more than one.

fun facet(enumValues: Map<String, Any>, vararg fieldPaths: String): PagedList<T>

Fluent addFacet for an ENUM facet, using dot-notation paths.

fun facet(enumValues: Map<String, Any>, vararg paths: ScalarPath): PagedList<T>

Fluent addFacet for an ENUM facet with a display-name-to-DB-value map.

fun facet(type: Facet.Type, vararg fieldPaths: String): PagedList<T>

Fluent addFacet with an explicit type, using dot-notation paths.

fun facet(type: Facet.Type, vararg paths: ScalarPath): PagedList<T>

Fluent addFacet with an explicit type.

Link copied to clipboard
fun facetByPath(fieldPath: String): Facet?

Returns the first facet that has fieldPath among its field paths (a facet with several paths matches any of them), or null when none does. SQL facets have no field paths and never match.

Typed-path variant of facetByPath.

Link copied to clipboard

Streams every row matching the current filter / sort / constraint state through action via a cursor — a single query that does not materialize the full result set. Use this for exports or bulk processing where paginating through the list's index-based iterator() would issue N / pageSize queries.

Link copied to clipboard
open operator override fun get(index: Int): T

Returns the row at index. If the row is not in the currently cached page, a new page is loaded around that index. Out-of-range indices propagate the underlying IndexOutOfBoundsException from the loaded page.

Link copied to clipboard

Returns a new PagedAggregator bound to this list. Each call returns a fresh aggregator so users can build multiple independent aggregation chains without interference.

Link copied to clipboard
fun getFacet(index: Int): Facet

Returns the column at the given index.

Link copied to clipboard
open override fun indexOf(element: T): Int

Searches for the element in the currently cached page. Returns the absolute index, or -1 if not found in the current page.

Link copied to clipboard
fun keySort(direction: SortState): PagedList<T>

Fluent keySort: sets the direction of the primary key in the ORDER BY.

Link copied to clipboard
fun refresh()

Forces the list to re-query the database on its next access.

Link copied to clipboard
fun reset()

Clears all column filters and sorting. Constraints are NOT cleared.

Link copied to clipboard

Re-applies a previously captured PagedListState. Keys present in state but missing from the current column set are silently ignored (the list's columns may have changed since the state was saved).

Link copied to clipboard

Captures the per-column filters / sorts / case-sensitivity flags plus the pageSize and isDistinct flag into a PagedListState. Intended for persisting a grid / picker screen's user state across navigation.

Link copied to clipboard
fun setConstraints(query: String, vararg args: Any?)

Sets a fixed constraint (WHERE clause) for this list. This constraint is always applied in addition to any column filters.

Link copied to clipboard
fun sort(fieldPath: String, direction: SortState): PagedList<T>

Dot-notation variant of sort.

fun sort(path: ScalarPath, direction: SortState): PagedList<T>

Sorts by path in the given direction. The sort is set on the facet that covers path (see facetByPath), whose Facet.sortPath becomes path, so a facet with several paths sorts by the requested one. When several facets are sorted, the ORDER BY follows the order in which they were sorted, whether through this method or through Facet.sort.