/* * Smart GWT (GWT for SmartClient) * Copyright 2008 and beyond, Isomorphic Software, Inc. * * Smart GWT is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * as published by the Free Software Foundation. Smart GWT is also * available under typical commercial license terms - see * http://smartclient.com/license * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package com.smartgwt.client.data; import com.smartgwt.client.event.*; import com.smartgwt.client.core.*; import com.smartgwt.client.types.*; import com.smartgwt.client.data.*; import com.smartgwt.client.data.events.*; import com.smartgwt.client.rpc.*; import com.smartgwt.client.widgets.*; import com.smartgwt.client.widgets.events.*; import com.smartgwt.client.widgets.form.*; import com.smartgwt.client.widgets.form.validator.*; import com.smartgwt.client.widgets.form.fields.*; import com.smartgwt.client.widgets.tile.*; import com.smartgwt.client.widgets.tile.events.*; import com.smartgwt.client.widgets.grid.*; import com.smartgwt.client.widgets.grid.events.*; import com.smartgwt.client.widgets.chart.*; import com.smartgwt.client.widgets.layout.*; import com.smartgwt.client.widgets.layout.events.*; import com.smartgwt.client.widgets.menu.*; import com.smartgwt.client.widgets.tab.*; import com.smartgwt.client.widgets.toolbar.*; import com.smartgwt.client.widgets.tree.*; import com.smartgwt.client.widgets.tree.events.*; import com.smartgwt.client.widgets.viewer.*; import com.smartgwt.client.widgets.calendar.*; import com.smartgwt.client.widgets.calendar.events.*; import com.smartgwt.client.widgets.cube.*; import java.util.Date; import java.util.List; import java.util.Map; import java.util.HashMap; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.user.client.Element; import com.smartgwt.client.util.*; import com.google.gwt.event.shared.*; import com.google.gwt.event.shared.HasHandlers; /** * The RestDataSource implements the 4 core DataSource operations using a simple protocol of * XML or JSON requests and responses sent over HTTP, which can be easily fulfilled by any HTTP * server technology. * <P> * RestDataSource is named for the * <a href='http://www.google.com/search?hl=en&q=REST+HTTP' * onclick="window.open('http://www.google.com/search?hl=en&q=REST+HTTP');return false;">REST</a> (REpresentational State * Transfer) pattern, which in brief says that simple messages passed over HTTP is a sufficient * protocol for many web applications, without the need for further protocols such as WSDL or * SOAP. * <P> * A RestDataSource is used just like a normal DataSource. RestDataSources are pre-configured, * using the general-purpose databinding facilities of DataSources, to expect a particular * format for responses and to send requests in a specific format. These request and * response formats represent Isomorphic's recommended best practices for binding Smart GWT * to backends which do not already support a similar, pre-existing request and response * format and where the Smart GWT Java Server cannot be used. * <P> * If you have a pre-existing REST or WSDL service which is difficult to change, consider * adapting Smart GWT to the existing service instead, by starting with a normal * {@link com.smartgwt.client.data.DataSource} and using the * {@link com.smartgwt.client.docs.ClientDataIntegration client-side data integration} facilities to create a * mapping between Smart GWT's {@link com.smartgwt.client.data.DSRequest} and {@link com.smartgwt.client.data.DSResponse} * objects and the message * formats of your existing services. * <P> * RestDataSource is typically used with PHP, Ruby, Python, Perl or custom server technologies, * and represents an alternative to installing the Smart GWT Server in a Java technology * stack, or using {@link com.smartgwt.client.docs.WsdlBinding WSDL-based binding} with .NET or other WSDL-capable * technologies. Note that Smart GWT Server also provides built-in support for the REST * protocol via its RESTHandler servlet; this is primarily to allow non-Smart GWT clients * to make use of DataSource operations. If you particularly wished to do so, you could use * RestDataSource to make a Smart GWT app talk to the Smart GWT Server using REST rather * than the proprietary wire format normally used when communicating with Smart GWT Server * (this is how we are able to write automated tests for the RESTHandler servlet). However, * doing this provides no benefit, imposes a number of inconveniences, and makes a handful * of server-based features less useful * ({@link com.smartgwt.client.docs.serverds.DataSourceField#viewRequiresAuthentication field-level declarative security}, * for * example), so we strongly recommend that you do <em>not</em> do this; it is only mentioned * here for completeness while we are discussing REST. * <P> * The request and response formats used by the RestDataSource allow for many of the available * features of Smart GWT's databinding system to be used, including data paging, searching & * sorting, {@link com.smartgwt.client.data.DSRequest#getOldValues long transactions}, * {@link com.smartgwt.client.data.ResultSet automatic cache sync}, {@link com.smartgwt.client.docs.Relogin relogin} and * {@link com.smartgwt.client.rpc.RPCManager#startQueue queuing}. However, advanced * features such as {@link com.smartgwt.client.docs.Upload uploading / binary fields} and * {@link com.smartgwt.client.widgets.grid.ListGrid#exportData export} aren't available with RestDataSource and need to be * re-implemented as needed. Most, though not all, {@link com.smartgwt.client.docs.IscServer server-based features} * are still available when using RestDataSource, as long as you are also using the RESTHandler * servlet that is part of Smart GWT Server. However, as noted above, this approach is not * recommended; if you are using Isomorphic technology both client- and server-side, it makes * more sense to use the proprietary wire format. * <P> * <span style="font-weight:bold;font-size:16px;">Examples</span> * <p> * <b>XML formatted responses:</b> * <P> * RestDataSource expects a response like the following in response to a "fetch" request: * <pre> * <response> * <status>0</status> * <startRow>0</startRow> * <endRow>76</endRow> * <totalRows>546</totalRows> * <data> * <record> * <field1>value</field1> * <field2>value</field2> * </record> * <record> * <field1>value</field1> * <field2>value</field2> * </record> * <i>... 76 total records ... </i> * </data> * </response> * </pre> * The <status> element indicates whether the fetch operation was successful * (see {@link com.smartgwt.client.docs.StatusCodes}). * <P> * The <data> element contains a list of record nodes, each of which represents a record * returned by the server. The optional <startRow>, <endRow> and <totalRows> * elements are needed only if data paging is in use, and populate the * {@link com.smartgwt.client.data.DSResponse#getStartRow startRow}, {@link com.smartgwt.client.data.DSResponse#getEndRow * endRow} and * {@link com.smartgwt.client.data.DSResponse#getTotalRows totalRows} properties of the {@link * com.smartgwt.client.data.DSResponse}. * <P> * Note: for a more compact format, simple field values may be specified on record * nodes directly as attributes - in this case a record element might be structured like this: * <pre> * <record field1="value" field2="value" /> * </pre> * <p> * Note that a RestDataSource will bypass browser caching of all responses by default. See * {@link com.smartgwt.client.data.DataSource#getPreventHTTPCaching preventHTTPCaching}. * <p> * Successful "add" or "update" request responses are similar in format - in this case the data * element would be expected to contain a single record object containing the details of the * record, as saved on the server. * <P> * The response from a "remove" operation would again include status and data elements, but in * this case, only the primary key field value(s) of the removed record would be expected to be * present under the data element. * <p> * If a validation failure occurred on the server, the response would * have status set to {@link com.smartgwt.client.rpc.RPCResponse#STATUS_VALIDATION_ERROR STATUS_VALIDATION_ERROR} * [<code>-4</code>], * and any validation errors could be included as per-field sub-elements of an "errors" * element. For a validation error, the response is not expected to contain any * <data> element. * <P> * A response showing a validation error might look like this: * <pre> * <response> * <status>-4</status> * <errors> * <field1> * <errorMessage>A validation error occurred for this field</errorMessage> * </field1> * </errors> * </response> * </pre> * <P> * An unrecoverable error, such as an unexpected server failure, can be flagged by setting * <status> to -1 and setting <data> to an error message. In this case the * <errors> element is not used (it's specific to validation errors). An unrecoverable * error causes all response processing to be skipped and {@link com.smartgwt.client.rpc.RPCManager#handleError * RPCManager.handleError} to be * invoked, which by default will show the provided error message as an alert using * {@link com.smartgwt.client.util.isc#warn isc.warn}. * <p> * <b>JSON formatted responses:</b> * <P> * JSON format responses are expected to contain the same data / meta-data as XMLresponses, * encapsulated a simple object with a <code>"response"</code> attribute.<br> * The response to a "fetch" request would therefore have this format:<br> * <pre> * { * response:{ * status:0, * startRow:0, * endRow:76, * totalRows:546, * data:[ * {field1:"value", field2:"value"}, * {field1:"value", field2:"value"}, * <i>... 76 total records ...</i> * ] * } * } * </pre> * The structure successful for "add", "update" and "remove" responses would be similar, though * the data array would be expected to contain only a single object, representing the values as * saved. This allows the server to return values such as an auto-generated sequence * primaryKey, a last modified timestamp, or similar server-generated field values. * <P> * For a remove, only the value for the primaryKey field[s] would be required. * <p> * For a validation error, the <code>status</code> attribute would be set to * {@link com.smartgwt.client.rpc.RPCResponse#STATUS_VALIDATION_ERROR STATUS_VALIDATION_ERROR} [<code>-4</code>], and * errors would * be specified in the <code>errors</code> attribute of the response. For example: * <pre> * { response: * { status:-4, * errors: * { field1:{errorMessage:"A validation error on field1"}, * field2:{errorMessage:"A validation error on field2"} * } * } * } * </pre> * An array of errors may also be returned for a single field, like this: * <pre> * { response: * { status:-4, * errors: * { field1:[ * {errorMessage:"First error on field1"}, * {errorMessage:"Second error on field1"} * ] * } * } * } * </pre> * <P> * As with the XML format above, an unrecoverable error is indicated by setting the * <code>status</code> attribute to -1 and the <code>data</code> property to the error message. * <P> * <b>Server inbound data formats</b> * <P> * The format of data sent to the server is determined by the {@link * com.smartgwt.client.data.OperationBinding#getDataProtocol dataProtocol} * specified for the operation. Request data is sent as parameters if the format is * specified as <code>"getParams"</code> or <code>"postParams"</code>. * <P> * In this case, the parameters sent to the server will consist of the DSRequest's data, and any * parameters explicitly specified on the DSRequest object (as {@link com.smartgwt.client.rpc.RPCRequest#getParams * params}.<br> * If {@link com.smartgwt.client.data.RestDataSource#getSendMetaData sendMetaData} is true, the DSRequest meta * data properties will also be present as parameters, prefixed with * {@link com.smartgwt.client.data.RestDataSource#getMetaDataPrefix metaDataPrefix}. * <P> * Example URL constructed with the metaDataPrefix set to <code>"_"</code> (the default): * <p> * <code> *    <i>[dataURL]</i>?field1=value1&_operationType=fetch&_startRow=0&_endRow=50&_sortBy=-field2&_dataSource=dsName * </code> * <p> * In this case the server would be able to separate the request's data from the meta data * via the <code>"_"</code> prefix. * <P> * If data is sent to the server via the <code>"postMessage"</code> dataProtocol, the data will * be serialized as an XML or JSON message according to the <code>dataFormat</code> setting. * Both XML and JSON messages will contain request metadata such as startRow and endRow, and * will appear exactly as though the subset of the {@link com.smartgwt.client.data.DSRequest} that is meaningful to the * server had been passed to {@link com.smartgwt.client.data.DataSource#xmlSerialize DataSource.xmlSerialize} or {@link * com.smartgwt.client.util.JSON#encode JSON.encode} * respectively. * <P> * An example of an XML message might look like this: * <pre> * <request> * <data> * <countryCode>US</countryCode> * <countryName>Edited Value</countryName> * <capital>Edited Value</capital> * <continent>Edited Value</continent> * </data> * <dataSource>countryDS</dataSource> * <operationType>update</operationType> * </request> * </pre> * An example of an XML message for a fetch operation passing simple criteria: * <pre> * <request> * <data> * <continent>North America</continent> * </data> * <dataSource>countryDS</dataSource> * <operationType>fetch</operationType> * <startRow>0</startRow> * <endRow>75</endRow> * <componentId>worldGrid</componentId> * <textMatchStyle>exact</textMatchStyle> * </request> * </pre> * And an example of an XML message for a fetch operation passing AdvancedCriteria: * <pre> * <request> * <data> * <_constructor>AdvancedCriteria</_constructor> * <operator>or</operator> * <criteria> * <criterion> * <fieldName>continent</fieldName> * <operator>equals</continent> * <value>North America</value> * </criterion> * <criterion> * <operator>and</operator> * <criteria> * <criterion> * <fieldName>continent</fieldName> * <operator>equals</operator> * <value>Europe</value> * </criterion> * <criterion> * <fieldName>population</fieldName> * <operator>greaterThan</operator> * <value>50000000</value> * </criterion> * </criteria> * </criterion> * </criteria> * </data> * <dataSource>countryDS</dataSource> * <operationType>fetch</operationType> * <startRow>0</startRow> * <endRow>75</endRow> * <componentId>worldGrid</componentId> * </request> * </pre> * JSON messages are just the plain JSON form of the structures shown in the above XML * examples. To show the last of the three XML examples in JSON form: * <pre> * { * data: { * _constructor: "AdvancedCriteria", * operator: "or", * criteria: [ * { fieldName: "continent", operator: "equals", value: "North America }, * { operator: "and", criteria: [ * { fieldName: "continent", operator: "equals", value: "Europe" }, * { fieldName: "population", operator: "greaterThan", value: 50000000 } * ] } * ] * } * dataSource: "countryDS", * operationType: "fetch", * startRow: 0, * endRow: 75, * componentId: "worldGrid" * } * </pre> * The {@link com.smartgwt.client.data.RestDataSource#getOperationBindings default OperationBindings} for a RestDataSource * specify dataProtocol as "getParams" for the fetch operation, and "postParams" for update, * add and remove operations. * <P> * <b>Date, time and datetime values</b> * <P> * Date, time and datetime values must be communicated using XML Schema format, as in the * following examples:<br> * <code>  <dateField>2007-04-22</dateField></code><br> * <code>  <timeField>11:07:13</timeField></code><br> * <code>  <dateTimeField>2007-04-22T11:07:13</dateTimeField></code> * <P> * And the equivalent in JSON:<br> * <code>  dateField: "2007-04-22"<br> * <code>  timeField: "11:07:13"<br> * <code>  dateTimeField: "2007-04-22T11:07:13"</code> * <P> * Both RestDataSource on the client-side and the RESTHandler servlet on the server side * automatically handle encoding and decoding temporal values using these formats. * <P> * Fields of type "date" and "time" are considered to hold logical date and time values, as * discussed in the {@link com.smartgwt.client.docs.DateFormatAndStorage date and time handling article}, and are * not affected by timezones. Fields of type "datetime" will be converted to UTC on the * client side by RestDataSource, and will be sent back down to the client as UTC by the * server-side RESTHandler. We recommend that your own REST client and/or server code do the * same thing (ie, transmit all datetime values in both directions as UTC). * <P> * <b>RestDataSource queuing support</b> * <P> * RestDataSource supports {@link com.smartgwt.client.rpc.RPCManager#startQueue queuing} of DSRequests. This allows * you to send multiple requests to the server in a single HTTP turnaround, thus minimizing * network traffic and allowing the server to treat multiple requests as a single transaction, * if the server is able to do so (in Power Edition and above, the Smart GWT Server * transparently supports grouping multiple REST requests in a queue into a single database * transaction when using one of the built-in DataSource types). * <P> * If you want to use queuing with RestDataSource, you must use the "postMessage" dataProtocol * with either XML or JSON dataFormat. Message format is similar to the non-queued examples * shown earlier: it is simply extended to cope with the idea of multiple DSRequests * encapsulated in the message. * <P> * An example of the XML message sent from RestDataSource to the server for two update requests * combined into a queue, using XML dataFormat: * <pre> * <transaction> * <operations> * <request> * <data> * <pk>1</pk> * <countryName>Edited Value</countryName> * <capital>Edited Value</capital> * <continent>Edited Value</continent> * </data> * <dataSource>countryDS</dataSource> * <operationType>update</operationType> * </request> * <request> * <data> * <pk>2</pk> * <capital>Edited Value</capital> * <population>123456</population> * </data> * <dataSource>countryDS</dataSource> * <operationType>update</operationType> * </request> * </operations> * <transaction> * </pre> * And the same message in JSON format: * <pre> * { * transaction: { * operations: [{ * dataSource:"countryDS", * operationType:"update", * data: { * pk: 1 * countryName: "Edited Value", * capital: "Edited Value", * continent: "Edited Value" * } * }, { * dataSource:"countryDS", * operationType:"update", * data: { * pk: 2, * capital: "Edited Value", * popuilation: 123456 * } * }] * } * } * </pre> * RestDataSource expects the response to a queue of requests to be a queue of responses in * the same order as the original requests. Again, the message format is very similar to the * unqueued REST format, it just has an outer container construct. Note also that the * individual DSResponses in a queued response have an extra property, * <code>queueStatus</code>. This allows each individual response to determine whether the * queue as a whole succeeded. For example, if the first update succeeded but the second * failed validation, the first response would have a <code>status</code> of 0, but a * <code>queueStatus</code> of -1, while the second response would have both properties set * to -1. * <P> * The update queue example given above would expect a response like this (in XML): * <pre> * <responses> * <response> * <status>0</status> * <queueStatus>0</queueStatus> * <data> * <record> * <countryName>Edited Value</countryName> * <gdp>1700.0</gdp> * <continent>Edited Value</continent> * <capital>Edited Value</capital> * <pk>1</pk> * </record> * </data> * </response> * <response> * <status>0</status> * <queueStatus>0</queueStatus> * <data> * <record> * <countryName>United States</countryName> * <gdp>7247700.0</gdp> * <continent>North America</continent> * <independence>1776-07-04</independence> * <capital>Washington DC</capital> * <pk>2</pk> * <population>123456</population> * </record> * </data> * </response> * </responses> * </pre> * And in JSON: * <pre> * [ * { * response: { * queueStatus: 0, * status: 0, * data: [{ * countryName: "Edited Value", * gdp: 1700.0, * continent":"Edited Value", * capital: "Edited Value", * pk: 1 * }] * } * }, * { * response: { * queueStatus: 0, * status: 0, * data: [{ * countryName:"United States", * gdp: 7247700.0, * continent":"North America, * independence: Date.parseServerDate(1776,6,4), * capital: "Washington DC", * pk: 2, * population: 123456 * }] * } * } * ] * </pre> * <b>Hierarchical (Tree) data:</b> * <P> * To create a hierarchical DataSource, in the DataSource's <code>fields</code> array, a field * must be specified as the parent id field - the field which will contain a pointer to the * id of each node's parent. * This can be achieved by setting the {@link com.smartgwt.client.data.DataSourceField#getForeignKey foreignKey} and the * {@link com.smartgwt.client.data.DataSourceField#getRootValue rootValue} attributes on the field definition. For example: * <pre> * RestDataSource.create({ * ID:"supplyItem", * fields : [ * {name:"itemId", type:"sequence", primaryKey:true}, * {name:"parentId", type:"integer", foreignKey:"supplyItem.itemId", rootValue:0}, * ... * ] * }); * </pre> * Tree Data is then treated on the server as a flat list of records linked by parent id. * <P> * Tree data is typically displayed using a dataBound {@link com.smartgwt.client.widgets.tree.TreeGrid} component. * TreeGrids * automatically create a ResultTree data object, which requests data directly * from the DataSource. ResultTrees load data on demand, only requesting currently visible * (open) nodes from the server. This is handled by including a specified value for the parent * id field in the request criteria.<br> * To implement a standard load-on-demand tree RestDataSource back end, you should therefore * simply return the set of nodes that match the criteria passed in. * For example, if your DataSource was defined as the "supplyItem" code snippet above, * a fetch request for all children of a node with <code>itemId</code> set to <code>12</code> * would have <code>"parentId"</code> set to <code>12</code> in the request criteria. * A valid response would then contain all the records that matched this criteria. For example: * <pre> * <response> * <status>0</status> * <data> * <record> * <itemId>15</itemId> * <parentId>12</parentId> * </record> * <record> * <itemId>16</itemId> * <parentId>12</parentId> * </record> * </data> * </response> * </pre> * The structure of responses for Add, Update and Delete type requests will be the * same regardless of whether the data is hierarchical. However you should be aware that * the underlying data storage may need to be managed slightly differently in some cases. * <P> * Specifically, Add and Update operations may change the structure of the tree by returning a * new parent id field value for the modified node. Depending on how your data is stored you * may need to include special back-end logic to handle this. * <P> * Also, if a user deletes a folder within a databound tree, any children of that folder will * also be dropped from the tree, and can be removed from the back-end data storage. * <P> * Note: For a general overview of binding components to Tree structured data, see * {@link com.smartgwt.client.docs.TreeDataBinding Tree Databinding}. */ public class RestDataSource extends DataSource { public static RestDataSource getOrCreateRef(JavaScriptObject jsObj) { if(jsObj == null) return null; BaseClass obj = BaseClass.getRef(jsObj); if(obj != null) { return (RestDataSource) obj; } else { return new RestDataSource(jsObj); } } public RestDataSource(){ scClassName = "RestDataSource"; } public RestDataSource(JavaScriptObject jsObj){ super(jsObj); } public native JavaScriptObject create()/*-{ var config = this.@com.smartgwt.client.core.BaseClass::getConfig()(); var scClassName = this.@com.smartgwt.client.core.BaseClass::scClassName; return $wnd.isc[scClassName].create(config); }-*/; // ********************* Properties / Attributes *********************** /** * Custom dataURL for add type operations * * @param addDataURL addDataURL Default value is null * @throws IllegalStateException this property cannot be changed after the underlying component has been created */ public void setAddDataURL(String addDataURL) throws IllegalStateException { setAttribute("addDataURL", addDataURL, false); } /** * Custom dataURL for add type operations * * * @return String */ public String getAddDataURL() { return getAttributeAsString("addDataURL"); } /** * Default URL to contact to fulfill all DSRequests. RestDataSources also allow per-operationType dataURLs to be set via * <ul> <li>{@link com.smartgwt.client.data.RestDataSource#getFetchDataURL fetchDataURL}</li> <li>{@link * com.smartgwt.client.data.RestDataSource#getAddDataURL addDataURL}</li> <li>{@link * com.smartgwt.client.data.RestDataSource#getUpdateDataURL updateDataURL}</li> <li>{@link * com.smartgwt.client.data.RestDataSource#getRemoveDataURL removeDataURL}</li> </ul> * * @param dataURL dataURL Default value is null * @throws IllegalStateException this property cannot be changed after the underlying component has been created */ public void setDataURL(String dataURL) throws IllegalStateException { setAttribute("dataURL", dataURL, false); } /** * Default URL to contact to fulfill all DSRequests. RestDataSources also allow per-operationType dataURLs to be set via * <ul> <li>{@link com.smartgwt.client.data.RestDataSource#getFetchDataURL fetchDataURL}</li> <li>{@link * com.smartgwt.client.data.RestDataSource#getAddDataURL addDataURL}</li> <li>{@link * com.smartgwt.client.data.RestDataSource#getUpdateDataURL updateDataURL}</li> <li>{@link * com.smartgwt.client.data.RestDataSource#getRemoveDataURL removeDataURL}</li> </ul> * * * @return String */ public String getDataURL() { return getAttributeAsString("dataURL"); } /** * Custom dataURL for fetch type operations * * @param fetchDataURL fetchDataURL Default value is null * @throws IllegalStateException this property cannot be changed after the underlying component has been created */ public void setFetchDataURL(String fetchDataURL) throws IllegalStateException { setAttribute("fetchDataURL", fetchDataURL, false); } /** * Custom dataURL for fetch type operations * * * @return String */ public String getFetchDataURL() { return getAttributeAsString("fetchDataURL"); } /** * <code>recordXPath</code> mapping to the data node of json returned by the server. * Applies if this.dataFormat is set to <code>"json"</code><br> * The default value will pick up data from a response structured as follows:<br> * <pre> * {response: * {status:0, * data:[ * {field1:"value", field2:"value"}, * {field1:"value", field2:"value"} * ] * } * </pre> * * @param jsonRecordXPath jsonRecordXPath Default value is "/response/data" * @throws IllegalStateException this property cannot be changed after the underlying component has been created */ public void setJsonRecordXPath(String jsonRecordXPath) throws IllegalStateException { setAttribute("jsonRecordXPath", jsonRecordXPath, false); } /** * <code>recordXPath</code> mapping to the data node of json returned by the server. * Applies if this.dataFormat is set to <code>"json"</code><br> * The default value will pick up data from a response structured as follows:<br> * <pre> * {response: * {status:0, * data:[ * {field1:"value", field2:"value"}, * {field1:"value", field2:"value"} * ] * } * </pre> * * * @return String */ public String getJsonRecordXPath() { return getAttributeAsString("jsonRecordXPath"); } /** * If {@link com.smartgwt.client.data.RestDataSource#getSendMetaData sendMetaData} is true, this attribute is used to * specify the prefix to apply to 'meta data' properties when assembling parameters to send to the server. Applies to * operations where OperationBinding.dataProtocol is set to <code>"getParams"</code> or <code>"postParams"</code> only. * * @param metaDataPrefix metaDataPrefix Default value is "_" * @throws IllegalStateException this property cannot be changed after the underlying component has been created */ public void setMetaDataPrefix(String metaDataPrefix) throws IllegalStateException { setAttribute("metaDataPrefix", metaDataPrefix, false); } /** * If {@link com.smartgwt.client.data.RestDataSource#getSendMetaData sendMetaData} is true, this attribute is used to * specify the prefix to apply to 'meta data' properties when assembling parameters to send to the server. Applies to * operations where OperationBinding.dataProtocol is set to <code>"getParams"</code> or <code>"postParams"</code> only. * * * @return String */ public String getMetaDataPrefix() { return getAttributeAsString("metaDataPrefix"); } /** * When using dataFormat:"json" and dataProtocol:"postMessage" should we use the {@link * com.smartgwt.client.util.JSONEncoder#getPrettyPrint prettyPrint} feature to enable indented, highly readable JSON * messages. <P> True by default because the bandwidth involved is generally negligible and the benefits for * troubleshooting are key. * * @param prettyPrintJSON prettyPrintJSON Default value is true * @throws IllegalStateException this property cannot be changed after the underlying component has been created */ public void setPrettyPrintJSON(Boolean prettyPrintJSON) throws IllegalStateException { setAttribute("prettyPrintJSON", prettyPrintJSON, false); } /** * When using dataFormat:"json" and dataProtocol:"postMessage" should we use the {@link * com.smartgwt.client.util.JSONEncoder#getPrettyPrint prettyPrint} feature to enable indented, highly readable JSON * messages. <P> True by default because the bandwidth involved is generally negligible and the benefits for * troubleshooting are key. * * * @return Boolean */ public Boolean getPrettyPrintJSON() { return getAttributeAsBoolean("prettyPrintJSON"); } /** * For RestDataSources, by default, either the {@link com.smartgwt.client.data.RestDataSource#getXmlRecordXPath * xmlRecordXPath} or {@link com.smartgwt.client.data.RestDataSource#getJsonRecordXPath jsonRecordXPath} is used based on * the {@link com.smartgwt.client.data.RestDataSource#getDataFormat dataFormat} setting. <P> Note that you can also apply * record xpath binding via {@link com.smartgwt.client.data.OperationBinding#getRecordXPath recordXPath}. * * @param recordXPath recordXPath Default value is null */ public void setRecordXPath(String recordXPath) { setAttribute("recordXPath", recordXPath, true); } /** * For RestDataSources, by default, either the {@link com.smartgwt.client.data.RestDataSource#getXmlRecordXPath * xmlRecordXPath} or {@link com.smartgwt.client.data.RestDataSource#getJsonRecordXPath jsonRecordXPath} is used based on * the {@link com.smartgwt.client.data.RestDataSource#getDataFormat dataFormat} setting. <P> Note that you can also apply * record xpath binding via {@link com.smartgwt.client.data.OperationBinding#getRecordXPath recordXPath}. * * * @return String */ public String getRecordXPath() { return getAttributeAsString("recordXPath"); } /** * Custom dataURL for remove type operations * * @param removeDataURL removeDataURL Default value is null * @throws IllegalStateException this property cannot be changed after the underlying component has been created */ public void setRemoveDataURL(String removeDataURL) throws IllegalStateException { setAttribute("removeDataURL", removeDataURL, false); } /** * Custom dataURL for remove type operations * * * @return String */ public String getRemoveDataURL() { return getAttributeAsString("removeDataURL"); } /** * Should operation meta data be included when assembling parameters to send to the server? If true, meta data parameters * will be prefixed with the {@link com.smartgwt.client.data.RestDataSource#getMetaDataPrefix metaDataPrefix}.<br> Applies * to operations where OperationBinding.dataProtocol is set to <code>"getParams"</code> or <code>"postParams"</code> only. * * @param sendMetaData sendMetaData Default value is true * @throws IllegalStateException this property cannot be changed after the underlying component has been created */ public void setSendMetaData(Boolean sendMetaData) throws IllegalStateException { setAttribute("sendMetaData", sendMetaData, false); } /** * Should operation meta data be included when assembling parameters to send to the server? If true, meta data parameters * will be prefixed with the {@link com.smartgwt.client.data.RestDataSource#getMetaDataPrefix metaDataPrefix}.<br> Applies * to operations where OperationBinding.dataProtocol is set to <code>"getParams"</code> or <code>"postParams"</code> only. * * * @return Boolean */ public Boolean getSendMetaData() { return getAttributeAsBoolean("sendMetaData"); } /** * Custom dataURL for update type operations * * @param updateDataURL updateDataURL Default value is null * @throws IllegalStateException this property cannot be changed after the underlying component has been created */ public void setUpdateDataURL(String updateDataURL) throws IllegalStateException { setAttribute("updateDataURL", updateDataURL, false); } /** * Custom dataURL for update type operations * * * @return String */ public String getUpdateDataURL() { return getAttributeAsString("updateDataURL"); } /** * <code>recordXPath</code> mapping to the data node of XML returned by the server. * Applies if this.dataFormat is set to <code>"xml"</code>.<br> * The default value will pick up data from a response structured as follows:<br> * <pre> * <response> * <status>0</status> * <data> * <record> * <field1>value</field1> * <field2>value</field2> * </record> * <record> * <field1>value</field1> * <field2>value</field2> * </record> * </data> * </response> * </pre> * * @param xmlRecordXPath xmlRecordXPath Default value is "/response/data/*" * @throws IllegalStateException this property cannot be changed after the underlying component has been created */ public void setXmlRecordXPath(String xmlRecordXPath) throws IllegalStateException { setAttribute("xmlRecordXPath", xmlRecordXPath, false); } /** * <code>recordXPath</code> mapping to the data node of XML returned by the server. * Applies if this.dataFormat is set to <code>"xml"</code>.<br> * The default value will pick up data from a response structured as follows:<br> * <pre> * <response> * <status>0</status> * <data> * <record> * <field1>value</field1> * <field2>value</field2> * </record> * <record> * <field1>value</field1> * <field2>value</field2> * </record> * </data> * </response> * </pre> * * * @return String */ public String getXmlRecordXPath() { return getAttributeAsString("xmlRecordXPath"); } // ********************* Methods *********************** // ********************* Static Methods *********************** // *********************************************************** }