com.isomorphic.datasource
Class DSRequest

java.lang.Object
  |
  +--com.isomorphic.datasource.DSRequest

public class DSRequest
extends java.lang.Object

Server-side representation of a DataSource request initiated by a client-side DataBoundComponent or programmatically by custom client-side JavaScript.

When databound components need to load or persist data, they make Ajax background requests to the server. Those requests are decoded into DSRequest Java objects by SmartClient's server-side Java libraries.

You obtain a DSRequest obtain by either:

If you are integrating SmartClient with a pre-existing Java data store, you can call various getters on the DSRequest, such as getCriteria(), to retrieve request parameters that you can then use with your pre-existing data store. For example, when working with an ORM (Object Relational Mapping) system, a typical way of processing an "update" DSRequest is to:

  1. use DSRequest.getCriteria() to retrieve the primary key for the object being updated, and fetch that object from your ORM system
  2. use DSRequest.getValues() in combination with DataTools.setProperties() to apply new properties to the object, based on the Java Beans naming convention
  3. store the modified object using your ORM system

Built-in connectors: SQL, Hibernate

The SmartClient Server can also automatically process DSRequests from DataSources with serverType="sql" or serverType="hibernate". In this case, you can call execute() to cause the default behavior to occur, which will return a DSResponse populated with data supplied by Hibernate or SQL.

By modifying the DSRequest before you call execute() and by modifying the DSResponse you receive, you can combine SmartClient's built-in SQL support with custom processing.

For example, if you have a SQL table of records that are specific to each user, and there is a column containing the user's id, you could use setFieldValue() to ensure the DSRequest always contains the user's id. This would ensure that fetch, add, update and remove operations are always restricted to the user's own data.

See Also:
RPCManager, DSResponse

Field Summary
static long ENDROW_UNSET
          If endRow is set to this constant, then there is no set bound for the number of records the server should return for the current request.
 
Constructor Summary
DSRequest(java.lang.String dataSourceName, java.lang.String operationType)
          Creates an empty DSRequest bound to the named datasource with the specified operationType.
 
Method Summary
 void addToTemplateContext(java.lang.String name, java.lang.Object value)
          If you're using the Velocity-based SQL Templating, you can make additional Java objects available to the the template context by calling this method.
 DSResponse execute()
          Executes this DSRequest and returns a DSResponse.
 java.util.Map getCriteria()
          This is a convenience method - it is useful for when you know there can only be one set of criteria.
 java.util.List getCriteriaSets()
          Returns the criteria for this operation as a set of key-value pairs where the keys are field names and the values are field values.
 DataSource getDataSource()
          Returns an instance of class DataSource for this DSRequest.
 java.lang.String getDataSourceName()
          Returns the dataSourceName for this DSRequest.
 long getEndRow()
          Returns the index of the last requested record.
 java.lang.Object getFieldValue(java.lang.Object fieldName)
          Returns the value for a particular fieldName.
 java.util.Map getOldValues()
          This is a convenience method - it is useful for when you know there can only be one set of oldValues.
 java.util.List getOldValueSets()
          For an "update" or "remove" operation, returns the complete original record as it was delivered to the client, as a set of key-value pairs where the keys are field names and the values are field values.
 java.lang.String getOperationId()
          Optional operationId passed by the client.
 java.lang.String getOperationType()
          Returns the type of this DataSource operation.
 java.util.List getSortByFields()
          The sortBy specification is only valid for the fetch operation since it specifies the sort order for the returned data.
 long getStartRow()
          When components that are capable or showing multiple records at once are bound to datasources with large datasets, it becomes important to only send those records that are currently visible in the component (or can become visible with a typical user action).
 ISCFileItem getUploadedFile(java.lang.String fieldName)
           
 java.util.Map getValues()
          This is a convenience method - it is useful for when you know there can only be one set of values.
 java.util.List getValueSets()
          Returns the values for this operation as a set of key-value pairs where the keys are field names and the values are field values.
 boolean isPaged()
          Returns true if the current request has is requestinga partial set of data using startRow/endRow parameters.
 void setCriteria(java.lang.Object criteria)
          Sets the criteria for this DSRequest.
 void setEndRow(long endRow)
          Sets the index of the last requested record.
 void setFieldValue(java.lang.Object fieldName, java.lang.Object value)
          Sets the value for a particular fieldName.
 void setOperationType(java.lang.String operationType)
          Sets the operation type.
 void setStartRow(long startRow)
          Sets the index of the first requested record.
 void setValues(java.lang.Object values)
          Sets the values for this DSRequest.
 ErrorReport validate()
          Performs validation on the values in this DSRequest.
 

Field Detail

ENDROW_UNSET

public static final long ENDROW_UNSET
If endRow is set to this constant, then there is no set bound for the number of records the server should return for the current request.
See Also:
getEndRow()
Constructor Detail

DSRequest

public DSRequest(java.lang.String dataSourceName,
                 java.lang.String operationType)
Creates an empty DSRequest bound to the named datasource with the specified operationType. Depending on the operation you're performing you'll need to call some other setters on the returned instance before calling execute().
Parameters:
dataSourceName - name of the datasource for this request
operationType - operationType for this request
Method Detail

getOperationType

public java.lang.String getOperationType()
Returns the type of this DataSource operation.
Returns:
One of: "fetch", "add", "remove", "update" or "custom".

setOperationType

public void setOperationType(java.lang.String operationType)
Sets the operation type. Valid values are one of: "fetch", "add", "remove", "update" or "custom".
Parameters:
operationType - the operation type - see above for valid values.

getOperationId

public java.lang.String getOperationId()
Optional operationId passed by the client.

The operationId is a means for client-side DataBound Components to request variants of the basic DataSource operations that the server may support, such as normal fetch operations vs fetch operations that use a single parameter and do full-text search. See the Client Reference for DSRequest.operationId for more information.

Returns:
the operationId

getCriteria

public java.util.Map getCriteria()
This is a convenience method - it is useful for when you know there can only be one set of criteria. This is always the case for operationType "fetch" and can also be the case for remove and update operations if you e.g. never call removeSelectedData() on a component that allows multi-record selection.

If you call this method on a DSRequest that contains multiple criteria sets, a warning is logged and the first criteria set in the list is returned by this method.

See also getCriteriaSets() for a description on the meaning of criteria by operationType.

Returns:
the criteria for this DSRequest if there is only one, or the first one in the list if there is more than one.
See Also:
getCriteria()

getCriteriaSets

public java.util.List getCriteriaSets()
Returns the criteria for this operation as a set of key-value pairs where the keys are field names and the values are field values. The meaning of criteria varies by operationType.

If the operationType is "fetch", then the criteria specifies the search criteria.

If the operationType is "remove" or "update" then the criteria the primary key/value pairs for the record to be updated or deleted. This set of fields is derived directly from the field specification in the dataSource for this operation - all fields marked as {primaryKey: true} are considered primary keys and their field names and values will be sent as part of the criteria in this case.

Note: this signature returns a List of criteria sets (Maps). This is the generic case and the recommended API because it captures interactions like removing multiple records. If there is only one set of criteria, then you will get a List with one Map.

Returns:
List of criteria sets for this request
See Also:
getCriteria(), getValueSets()

setCriteria

public void setCriteria(java.lang.Object criteria)
Sets the criteria for this DSRequest. You may pass either a Map or a List of Maps, but note that criteria has slightly different meanings for different operations, so be sure to read the API for getCriteriaSets() on this method for a description of what's required.
Parameters:
criteria - Map or List of Maps: the criteria to use for this DSRequest
See Also:
getCriteriaSets()

getUploadedFile

public ISCFileItem getUploadedFile(java.lang.String fieldName)
                            throws java.lang.Exception
Parameters:
fileName - Form field of type 'binary'.
Returns:
ISCFileItem containing uploaded file for specified field, or null if no file was uploaded for the specified field.

getValues

public java.util.Map getValues()
This is a convenience method - it is useful for when you know there can only be one set of values. If your UI and your custom logic does not allow a user to add, update, or remove more than one record at a time, then this is a safe assumption.

If you call this method on a DSRequest that contains multiple value sets, a warning is logged and the first value set in the list is returned by this method.

As a convenience, this method returns the criteria for if this DSRequest is of type fetch or remove.

See also getValueSets() for a description on the meaning of criteria by operationType.

Returns:
the values for this DSRequest if there is only one, or the first one in the list if there is more than one.
See Also:
getValueSets(), getCriteriaSets()

getValueSets

public java.util.List getValueSets()
Returns the values for this operation as a set of key-value pairs where the keys are field names and the values are field values. The meaning of values varies by operationType.

If the operationType is "add" then the values are interpreted as a complete record to add. Note that a complete record at this stage may be missing primary keys that are expected to be auto-generated by the persistence layer.

If the operationType is "update", then the values represent the new values for the records matching the criteria specified on this request.

As a convenience, this method returns the criteria for if this DSRequest is of type fetch or remove.

Note: this signagure returns a List of value sets (Maps). This is the generic case and the recommended API because it captures interactions like adding multiple records at once. If there is only one set of values, then you will get a List with one Map.

Returns:
List of value sets for this request.
See Also:
getValues(), getCriteriaSets()

setValues

public void setValues(java.lang.Object values)
Sets the values for this DSRequest. You may pass either a Map or a List of Maps. The List type is typically used for a DataSource.OP_ADD operation with multiple records.
Parameters:
values - Map or List of Maps - the values to use for this DSRequest

getOldValues

public java.util.Map getOldValues()
This is a convenience method - it is useful for when you know there can only be one set of oldValues. If your UI and your custom logic does not allow a user to add, update, or remove more than one record at a time, then this is a safe assumption.

If you call this method on a DSRequest that contains multiple value sets, a warning is logged and the first value set in the list is returned by this method.

See also getOldValueSets() for a description on the meaning of criteria by operationType.

Returns:
the oldValues for this DSRequest if there is only one, or the first one in the list if there is more than one.

getOldValueSets

public java.util.List getOldValueSets()
For an "update" or "remove" operation, returns the complete original record as it was delivered to the client, as a set of key-value pairs where the keys are field names and the values are field values.

The server can compare the oldValues to the most recent stored values in order to detect that the user was looking at stale values when the user submitted changes (NOTE: this means of detecting concurrent edit is sometimes called "long transactions").

Note that client logic must be written to pass oldValues. SmartClient DataBound Components do so automatically, but manually submitted DSRequests may not.

Note: this signagure returns a List of value sets (Maps). This is the generic case and the recommended API because it captures interactions like updating multiple records at once. If there is only one set of values, then you will get a List with one Map.

Returns:
List of value sets for this request.
See Also:
getOldValues()

getSortByFields

public java.util.List getSortByFields()
The sortBy specification is only valid for the fetch operation since it specifies the sort order for the returned data.

This method signature is the generic method that returns all fields for which a sort has been requested. If the list contains more than one entry, then that means the data should be sorted by the first field in the list, then within that first sort data should be sorted by the next field in the list and so on. So the second sortBy field can only affect data that has the same value for the first sortBy field.

The returned value is a List of Strings that are the names of the fields to sort by. If the String is prefixed by a - then that specifies descending order. Otherwise it's a request for an ascending sort on that field.

A concrete example of when a sortBy is sent by an ISC databound component: Let's say you have a ListGrid that has a partially loaded dataset (the dataset is too large to be on the client at once, so you're only showing, say, the first 100 rows). If you now click on one of the columns to sort by that column, the ListGrid will send a DSRequest to the server with a sortBy fieldName of the field that was clicked on. Since not all data is present on the client, the grid can't do the sort client-side (and still continue to display the first 100 matches to the curent filter criteria).

Returns:
set of fields to sort by

isPaged

public boolean isPaged()
Returns true if the current request has is requestinga partial set of data using startRow/endRow parameters. Specifically, this method returns true if startRow is non-zero or endRow has a value other than DSRequest.ENDROW_UNSET.
See Also:
getStartRow(), getEndRow(), ENDROW_UNSET

getStartRow

public long getStartRow()
When components that are capable or showing multiple records at once are bound to datasources with large datasets, it becomes important to only send those records that are currently visible in the component (or can become visible with a typical user action).

When multi-record capable components make requests to the server for data, they send the startRow and endRow parameters to indicate the slice of data they need to show to the user right now.

You can use the isPaged() method on this request to check if you need to respect startRow/endRow for this request.

Note that startRow and endRow are zero-based, so startRow: 0, endRow: 1 is a request for the first two records.

Returns:
index of the first requested record (using zero-based numbering)
See Also:
getEndRow(), isPaged()

setStartRow

public void setStartRow(long startRow)
Sets the index of the first requested record.

Note that startRow and endRow are zero-based, so startRow: 0, endRow: 1 is a request for the first two records.

Parameters:
startRow - the index of the first requested record (using zero-based numbering)

getEndRow

public long getEndRow()
Returns the index of the last requested record. See also the notes in getStartRow() for an example of when startRow/endRow are sent.

If getEndRow() returns DSRequest.ENDROW_UNSET (a negative value), that signifies a request for all records matching the current criteria.

Note that startRow and endRow are zero-based, so startRow: 0, endRow: 1 is a request for the first two records.

Returns:
index of the last requested record (using zero-based numbering)
See Also:
getStartRow(), ENDROW_UNSET

setEndRow

public void setEndRow(long endRow)
Sets the index of the last requested record.

Note that startRow and endRow are zero-based, so startRow: 0, endRow: 1 is a request for the first two records.

Parameters:
endRow - the index of the last requested record (using zero-based numbering)

getFieldValue

public java.lang.Object getFieldValue(java.lang.Object fieldName)
Returns the value for a particular fieldName. This method treats the DSRequest as a single record. If the valueSet contains a value for the requested fieldName, it is returned. If not, the criteria is checked for the requested fieldName. If a value exists there, it is returned. Otherwise null is returned.

This is a convenience method. For any given operation, a particular fieldName will usually appear in either the valueSet or criteria.

Parameters:
fieldName - the fieldName whose value you want to look up
Returns:
the value as found in valueSet or criteria

setFieldValue

public void setFieldValue(java.lang.Object fieldName,
                          java.lang.Object value)
Sets the value for a particular fieldName. This method treats the DSRequest as a single record. If a valueSet exists on this DSRequest, the value is added there, otherwise the value is added to the criteria.

This is a convenience method. For any given operation, a particular fieldName will usually appear in either the valueSet or criteria.

Parameters:
fieldName - the fieldName whose value you want to set
value - the value to set for the field (added to valueSet if it exists, otherwise to criteria)

getDataSourceName

public java.lang.String getDataSourceName()
Returns the dataSourceName for this DSRequest. This will be the same name you passed as the dataSource attribute to the databound component issuing this request.
Returns:
name of the datasource for this DSRequest

getDataSource

public DataSource getDataSource()
                         throws java.lang.Exception
Returns an instance of class DataSource for this DSRequest.
Returns:
dataSource instance for this DSRequest
See Also:
DataSource, getDataSourceName()

validate

public ErrorReport validate()
                     throws java.lang.Exception
Performs validation on the values in this DSRequest. The values provided as part of this DSRequest are tested against the validators defined on a per-field basis in the dataSource (.ds.xml file).

If validation is successful for all fields, this method returns null. Otherwise it returns an ErrorReport for the first record that encountered a validation error.

Returns:
ErrorReport or null if there were no errors.
See Also:
ErrorReport, ErrorMessage

execute

public DSResponse execute()
                   throws java.lang.Exception
Executes this DSRequest and returns a DSResponse. If an application is defined for this request, the execution is dispatched through that application. Otherwise, the execution is dispatched through the DataSource layer.

addToTemplateContext

public void addToTemplateContext(java.lang.String name,
                                 java.lang.Object value)
If you're using the Velocity-based SQL Templating, you can make additional Java objects available to the the template context by calling this method.
Parameters:
name - the name of the new object as it should appear in the Velocity namespace
value - arbitrary Java object