You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xap-commits@incubator.apache.org by jm...@apache.org on 2007/02/20 06:03:06 UTC

svn commit: r509431 - in /incubator/xap/trunk/codebase/src/xap/data: bridge/ controller/ datasource/

Author: jmargaris
Date: Mon Feb 19 22:03:05 2007
New Revision: 509431

URL: http://svn.apache.org/viewvc?view=rev&rev=509431
Log:
better documentation and some simplification

Modified:
    incubator/xap/trunk/codebase/src/xap/data/bridge/DataSourceBridge.js
    incubator/xap/trunk/codebase/src/xap/data/bridge/ObjectDataSourceBridge.js
    incubator/xap/trunk/codebase/src/xap/data/bridge/SimpleDocumentDataSourceBridge.js
    incubator/xap/trunk/codebase/src/xap/data/controller/Binding.js
    incubator/xap/trunk/codebase/src/xap/data/controller/Iterator.js
    incubator/xap/trunk/codebase/src/xap/data/datasource/AbstractDataSource.js
    incubator/xap/trunk/codebase/src/xap/data/datasource/ObjectDataSource.js
    incubator/xap/trunk/codebase/src/xap/data/datasource/QueryRecord.js
    incubator/xap/trunk/codebase/src/xap/data/datasource/SimpleDocumentDataSource.js

Modified: incubator/xap/trunk/codebase/src/xap/data/bridge/DataSourceBridge.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/data/bridge/DataSourceBridge.js?view=diff&rev=509431&r1=509430&r2=509431
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/data/bridge/DataSourceBridge.js (original)
+++ incubator/xap/trunk/codebase/src/xap/data/bridge/DataSourceBridge.js Mon Feb 19 22:03:05 2007
@@ -89,9 +89,7 @@
 // Protected Methods.
 //-----------------------------------------------------------------------
 /**
- * Calls initialize() on the data source
- * and adds the data source to the dataSourceContainer if the initialize
- * call was successfull.
+ * Adds the data source to the dataSourceContainer after checking for a valid ID.
  * @throws InitializationException
  */
 xap.data.bridge.DataSourceBridge.prototype.initializeDataSource = function () {
@@ -101,8 +99,6 @@
 	if (!id || xap.xml.dom.XapElement.isGeneratedId(id)){
 		throw new xap.util.Exception("Data source did not have an id: "+ this.getElement().toXml());
 	}
-
-	this._dataSource.initialize(id, this.getSession(), this.getElement());
 	this.getDataSourceContainer().put(id, this._dataSource);
 };
 /**

Modified: incubator/xap/trunk/codebase/src/xap/data/bridge/ObjectDataSourceBridge.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/data/bridge/ObjectDataSourceBridge.js?view=diff&rev=509431&r1=509430&r2=509431
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/data/bridge/ObjectDataSourceBridge.js (original)
+++ incubator/xap/trunk/codebase/src/xap/data/bridge/ObjectDataSourceBridge.js Mon Feb 19 22:03:05 2007
@@ -34,7 +34,7 @@
 	
 //protected DataSource
 xap.data.bridge.ObjectDataSourceBridge.prototype.createDataSource = function () {
-	return new xap.data.datasource.ObjectDataSource();
+	return new xap.data.datasource.ObjectDataSource(this.getSession());
 };
 
 xap.data.bridge.ObjectDataSourceBridge.prototype.initializeDataSource = function () {

Modified: incubator/xap/trunk/codebase/src/xap/data/bridge/SimpleDocumentDataSourceBridge.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/data/bridge/SimpleDocumentDataSourceBridge.js?view=diff&rev=509431&r1=509430&r2=509431
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/data/bridge/SimpleDocumentDataSourceBridge.js (original)
+++ incubator/xap/trunk/codebase/src/xap/data/bridge/SimpleDocumentDataSourceBridge.js Mon Feb 19 22:03:05 2007
@@ -40,7 +40,7 @@
 	
 //protected DataSource
 xap.data.bridge.SimpleDocumentDataSourceBridge.prototype.createDataSource = function () {
-	return new xap.data.datasource.SimpleDocumentDataSource();
+	return new xap.data.datasource.SimpleDocumentDataSource(this.getSession());
 };
 
 xap.data.bridge.SimpleDocumentDataSourceBridge.prototype.initializeDataSource = function () {

Modified: incubator/xap/trunk/codebase/src/xap/data/controller/Binding.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/data/controller/Binding.js?view=diff&rev=509431&r1=509430&r2=509431
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/data/controller/Binding.js (original)
+++ incubator/xap/trunk/codebase/src/xap/data/controller/Binding.js Mon Feb 19 22:03:05 2007
@@ -336,26 +336,3 @@
 	}
 };
 
-/**
- * This method and isDataRetrievalListener
- * will be used by the data source to determine
- * which sort of result set to expect
- * Their return values will be NOT'd in
- * the Iterator class's implementation.
- * @return false
-**/
-xap.data.controller.Binding.prototype.isDataSetRetrievalListener = function () {
-	return false;
-};
-/**
- * This method and isDataSetRetrievalListener
- * will be used by the data source to determine
- * which sort of result set to expect
- * Their return values will be NOT'd in
- * the Iterator class's implementation.
- * @return true
-**/
-xap.data.controller.Binding.prototype.isDataRetrievalListener = function () {
-	return true;
-};
-

Modified: incubator/xap/trunk/codebase/src/xap/data/controller/Iterator.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/data/controller/Iterator.js?view=diff&rev=509431&r1=509430&r2=509431
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/data/controller/Iterator.js (original)
+++ incubator/xap/trunk/codebase/src/xap/data/controller/Iterator.js Mon Feb 19 22:03:05 2007
@@ -64,6 +64,8 @@
     this._parentLocation.setLocationListener(this);
     this._name = name;
     this._session = session;
+    
+    this._iterating = false;
     /*xap.data.controller.ElementLocation*/
     var iteratorLocation = new xap.data.controller.ElementLocation(this._iteratorElement);
     iteratorLocation.setLocationListener(this);
@@ -123,85 +125,8 @@
         }
     }
 };
-Xap.setupClassAsSubclassOf("xap.data.controller.Iterator", "Object");
-/**
-	* @private
- * The select string
- */
-xap.data.controller.Iterator.prototype._select = null;
-/**
-	* @private
- * The name of this iterator.
- */
-xap.data.controller.Iterator.prototype._name = null;
-/**
- * @private
- * {xap.xml.dom.XapElement}
- * The <iterator> tag itself
- */
-xap.data.controller.Iterator.prototype._iteratorElement = null;
-/**
- * The parent of the <iterator> tag. We really also need to remember
- * something about the position of the iterator? Maybe we don't replace the
- * iterator until we do the first iteration, and when we iterate we just
- * find our own tag, remove it and then start adding the iterated items
- * in the position we were in. (Similar to include tag)
- * {xap.xml.dom.XapElement}	 
- * @private
- * 
- */
-xap.data.controller.Iterator.prototype._parentElement = null;
-/**
- * @private
- * {xap.data.controller.ElementLocation}
-	**/
-xap.data.controller.Iterator.prototype._parentLocation = null;
-/**
- * @private
- * {xap.xml.dom.XapElement}	
- **/
-xap.data.controller.Iterator.prototype._iteratorPlaceHolderElement = null;
-/**
- * @
-	private xap.data.controller.BindingType
-**/
-xap.data.controller.Iterator.prototype._bindingType = xap.data.controller.BindingType.ONE_TIME;
-
 
 /**
- * @private 
- * {xap.session.ClientSession }
-**/
-xap.data.controller.Iterator.prototype._session = null;
-/**
- * @private
- * {DataSet}
- * The current data set we are iterating over
- */
-xap.data.controller.Iterator.prototype._dataSet = null;
-/**
-* @private
-* {ContextStack}
-**/
-xap.data.controller.Iterator.prototype._contextStack = null;
-/**
-* @private
-* {Object}
-**/
-xap.data.controller.Iterator.prototype._context = null;
-/**
-* Listener on this iterator.
-* @private
-* {LocationListener}
-**/
-xap.data.controller.Iterator.prototype._locationListener; 
-// This needs to be set to true while iterating
-// over a data set so that clean up logic can run without
-/**
- * @private boolean
-**/
-xap.data.controller.Iterator.prototype._iterating = false;
-/**
  * Returns the name of this iterator.
  * 
  * @return The name.
@@ -601,29 +526,6 @@
 xap.data.controller.Iterator.prototype.remove = function () {
     this.invalidate();
 };
-/**
- * This method and isDataRetrievalListener
- * will be used by the data source to determine
- * which sort of result set to expect
- * Their return values will be NOT'd in
- * the <code>Binding</code> class's implementation.
- * @return true
-**/
-xap.data.controller.Iterator.prototype.isDataSetRetrievalListener = function () {
-    return true;
-};
-/**
- * This method and isDataSetRetrievalListener
- * will be used by the data source to determine
- * which sort of result set to expect
- * Their return values will be NOT'd in
- * the <code>Binding</code> class's implementation.
- * @return false
-**/
-xap.data.controller.Iterator.prototype.isDataRetrievalListener = function () {
-    return false;
-};
-
 
 	
 //-----------------------------------------------------------------------

Modified: incubator/xap/trunk/codebase/src/xap/data/datasource/AbstractDataSource.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/data/datasource/AbstractDataSource.js?view=diff&rev=509431&r1=509430&r2=509431
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/data/datasource/AbstractDataSource.js (original)
+++ incubator/xap/trunk/codebase/src/xap/data/datasource/AbstractDataSource.js Mon Feb 19 22:03:05 2007
@@ -27,91 +27,127 @@
 Xap.require("xap.data.datasource.QueryRecord") ;
 
 /**
-* An ease-of-use base class for DataSource implementations. 
-* 
-* <br><br>
-* 
-* This class persists bound queries (i.e. queries whose binding type != 
-* BindingType.ONE_WAY) so that they can be later requeried when the data 
-* changes.
-* 
-* <br><br>
-* 
-* This base class can also keep track of any queries that need to be postponed 
-* and executed later if the data is being retrieved at the time of the original
-* query.  It is up to the subclasses to take advantage of this functionality.
-* If subclasses add postponed queries, it is their responsibility to execute or
-* clean them up later (the queries are automatically cleaned up after the 
-* execution).
-* 
-* @author Igor Kaplansky
-* @author James Margaris
-*/
-xap.data.datasource.AbstractDataSource = function () {
+ * @fileoverview 
+ * Implements the base class for all data sources.
+ */
+ 
+
+/** 
+ * Creates a new AbstractDataSource.
+ * 
+ * @class AbstractDataSource is the base class for all data sources. Data sources
+ * are typically declared in XML rather than instantiated in code.
+ * Data source methods can be called from XML as in the following example that
+ * loads a document data source with new data.
+ * 
+ * <code><pre>
+ * &lt;button text="Switch data source url" 
+ * 	onCommand="dataSource:myDataSource.loadSourceFromServer('myPage.xml')" /&gt;
+ * </pre></code>
+ *
+ * @constructor
+ * @param {xap.session.ClientSession} session The client session this data source belongs to.
+ * 
+ * @see xap.data.datasource.SimpleDocumentDataSource
+ * @see xap.data.datasource.ObjectDataSource
+ */
+xap.data.datasource.AbstractDataSource = function( session ) {
+	/** @private */
+	this._clientSession = session;
+	/** @private */
 	this._boundQueries = [];
+	/** @private */
 	this._postponedQueries = [];
+	/** @private */
 	this._asynchronousDataSourceListeners = [];
+	/** @private */
 	this._dataChangeListeners = [];
 }
 
 
-/**
- * @see DataSource#initialize(String, ClientSession, Element)
- * <p/>
- * Subclasses have to call <code>super.initialize(String,ClientSession,
- * Element)</code> if they override this method.
- *
- *
- * @public
- * @param id{String}
- * @param session{ClientSession}
- * @param dataSourceElement{XapElement}
- * @return {void}
- * @throws InitializationException
- **/
-xap.data.datasource.AbstractDataSource.prototype.initialize = function (id, session, dataSourceElement) {
-	this._id = id;
-	this._clientSession = session;
-	this._dataSourceElement = dataSourceElement;
-}
-
 
+/**
+ * Cleans up the data source.
+ * 
+ * @private
+ */
 xap.data.datasource.AbstractDataSource.prototype.destroy = function () {
 	this._boundQueries =[];
 	this._postponedQueries = [];
 	this._asynchronousDataSourceListeners = [];
 	this._dataChangeListeners = [];
 }
+
+
 /**
- * @see DataSource#getDataSet(String, DataSetRetrievalListener)
- * @public
- * @param query{String}
- * @param listener{DataRetrievalListener}
- * @param ctx a context (optional)
- * @throws DataAccessException, MalformedQueryException,UnsupportedBindingTypeException 
- * @return {void}
+ * Attempts to run the query against the data source, calling the listener when the 
+ * query is completed.
+ * 
+ * @param {String} query A query string the datasource understands.
+ * @param listener A listener with a dataSetRetrieved() method to call back when the data is available.
+ * @param {xap.data.controller.ContextFrame} context An optional ContextFrame for nested iteration.
+ * 
+ * @see xap.data.controller.Iterator#dataSetRetrieved <code>xap.data.controller.Iterator.dataSetRetrieved()</code> for an example listener.
  **/
 xap.data.datasource.AbstractDataSource.prototype.getDataSet = function (query, listener,context) {
-	this.handleGenericQuery(query, context, listener);
+	//cases to cover here:
+	//if the listener is ONE_TIME and the source isn't available we need to save the postponed query
+	//if the listener is not ONE_TIME we need to save it as a bound query
+	//if the source is currently available we need to run the query
+	
+	
+	//if the listener is not ONE_TIME we need to save it for later
+	if (listener && listener.getBindingType() != xap.data.controller.BindingType.ONE_TIME) {
+		var queryRecord = new xap.data.datasource.QueryRecord(query, context, listener, true);
+		this._boundQueries.push(queryRecord);
+	}
+	//else if it IS ONE_TIME and we don't have a source yet we need to save the query
+	//for later
+	else if(!this.getSource()){
+		this.addPostponedQuery( query, context, listener, true );
+	}
+	
+	if (this.getSource()){
+		this.handleQuery(query, context, listener, true);
+	}
 };
+
+
 /**
- * @see xap.data.datasource.DataSource#getDataSet
- * @public
- * @return {void}
- * @param query{String}
- * @param listener{DataRetrievalListener}
- * @param context{ContextFrame}
- * @throws DataAccessException, MalformedQueryException, UnsupportedBindingTypeException 
+ * Atempts to run the query against the data source, calling the listener when the 
+ * query is completed.
+ * 
+ * @param {String} query A query string the datasource understands.
+ * @param listener A listener with a dataRetrieved() method to call back when the data is available.
+ * @param {xap.data.controller.ContextFrame} context An optional ContextFrame for nested iteration.
+ * 
+ * @see xap.data.controller.Binding#dataRetrieved <code>xap.data.controller.Binding.dataRetrieved()</code>
  **/
 xap.data.datasource.AbstractDataSource.prototype.getData = function (query, listener, context) {
-	this.handleGenericQuery(query, context, listener);
+	//if the listener is not ONE_TIME we need to save it for later
+	if (listener && listener.getBindingType() != xap.data.controller.BindingType.ONE_TIME) {
+		var queryRecord = new xap.data.datasource.QueryRecord(query, context, listener, false);
+		this._boundQueries.push(queryRecord);
+	}
+	//else if it IS ONE_TIME and we don't have a source yet we need to save the query
+	//for later
+	else if(!this.getSource()){
+		this.addPostponedQuery( query, context, listener, false );
+	}
+	
+	if (this.getSource()){
+		this.handleQuery(query, context, listener, false);
+	}
 }
 
 /**
- * @see DataSource#removeListener(RetrievalListener)
- * @public
- * @param listener{RetrievalListener}
- * @return {void}
+ * Removes a listener that was registered in a call to <code>getData()</code> or
+ * <code>getDataSet()</code>.
+ * 
+ * @param listener The listener to remove.
+ * 
+ * @see #getData
+ * @see #getDataSet
  **/
 xap.data.datasource.AbstractDataSource.prototype.removeListener = function (listener) {
 	for (var i = 0; i < this._boundQueries.length; i++) {
@@ -129,52 +165,86 @@
 		}
 	}
 };
+
 /**
- * @param l{DataChangeListener}
+ * Adds a data change listener to the data source that will have 
+ * <code>onDataChanged()</code> called whenever the data in this data source changes,
+ * with this data source as the argument. The data change listener is used for notification
+ * purposes only, queries should be run against the data source with a call to
+ * <code>getData()</code> or <code>getDataSet()</code>
+ * 
+ * @param l The listener with the <code>onDataChanged()</code> method to add.
+ * 
+ * @see #removeDataChangeListener
+ * @see #getData
+ * @see #getDataSet
+ * 
  **/
 xap.data.datasource.AbstractDataSource.prototype.addDataChangeListener = function (l) {
 	if (! xap.util.ArrayHelper.contains(this._dataChangeListeners,l)) {
 		this._dataChangeListeners.push(l);
 	}
 };
+
 /**
- * @public
- * @param l{DataChangeListener}
- * @return {void}
+ * Removes a data change listener from the data source that was added via a call
+ * to <code>addDataChangeListener()</code>.
+ * 
+ * @param l The listener to remove.
+ *
+ * @see #addDataChangeListener
  **/
 xap.data.datasource.AbstractDataSource.prototype.removeDataChangeListener = function (l) {
 	xap.util.ArrayHelper.removeElement(this._dataChangeListeners,l);
 };
+
+
 /**
- * @protected
- * @return {void}
- **/
+ * Fires the <code>onDataChanged()</code> on each data change listener.
+ * 
+ * @private
+ */
 xap.data.datasource.AbstractDataSource.prototype.fireDataChanged = function () {
 	for (var i = 0; i < this._dataChangeListeners.length; i++) {
 		this._dataChangeListeners[i].onDataChanged(this);
 	}
 };
+
+
 /**
- * @public
- * @param l{AsynchronousDataSourceListener}
- * @return {void}
+ * Adds an asynchronous data source listener to the data source that will have 
+ * <code>onDataRequestCompleted</code> or <code>onDataRequestFailed</code> called whenever an asynchronous
+ * load of data completes successfully or fails, with this data source as the argument and
+ * an accompanying exception with <code>onDataRequestFailed</code> only.
+ * 
+ * @param l The listener with the <code>onDataRequestCompleted()</code> and
+ * <code>onDataRequestFailed</code> methods to add.
+ * 
+ * @see #removeAsynchronousDataSourceListener
+ * @see #loadSourceFromServer
+ * 
  **/
 xap.data.datasource.AbstractDataSource.prototype.addAsynchronousDataSourceListener = function (l) {
 	if (!xap.util.ArrayHelper.contains(this._asynchronousDataSourceListeners,l)) {
 		this._asynchronousDataSourceListeners.push(l);
 	}
 };
+
 /**
- * @public
- * @return {void}
- * @param l{AsynchronousDataSourceListener}
+ * Removes an asynchronous data source listener from the data source that was added via a call
+ * to <code>addAsynchronousDataSourceListener()</code>.
+ * 
+ * @param l The listener to remove.
+ *
+ * @see #addAsynchronousDataSourceListener
  **/
 xap.data.datasource.AbstractDataSource.prototype.removeAsynchronousDataSourceListener = function (l) {
 	xap.util.ArrayHelper.removeElement(this._asynchronousDataSourceListeners,l);
 };
+
 /**
- * @protected
- * @return {void}
+ * @private
+ * Fires onDataRequestCompleted() to each asynch listener.
  **/
 xap.data.datasource.AbstractDataSource.prototype.fireOnDataRetrieveSucess = function () {
 	/*for (int*/
@@ -182,10 +252,10 @@
 		this._asynchronousDataSourceListeners[i].onDataRequestCompleted(this);
 	}
 };
+
 /**
- * @protected
- * @param failureCause{Exception}
- * @return {void}
+ * @private
+ * Fires onDataRequestFailed() to each asynch listener.
  **/
 xap.data.datasource.AbstractDataSource.prototype.fireOnDataRetrieveFailure = function (failureCause) {
 	/*for (int*/
@@ -195,88 +265,90 @@
 };
 
 /**
- * @param container{Container}
- * @param name{String}
+ * Called when the data source is removed from the data source container, performing cleanup.
+ * 
+ * @param {xap.session.Container} container The container the source was removed from.
+ * @param {String} name The name the data source was registered under in the container.
  **/
 xap.data.datasource.AbstractDataSource.prototype.removedFromContainer = function (container, name) {
 	this.destroy();
 };
 	
-//-----------------------------------------------------------------------
-// Public Methods.
-//-----------------------------------------------------------------------
+
 /**
- * Requeries all bound queries notifying cached RetrievalListeners 
- * with the new data.
- * 
- * @throws DataAccessException
- * @throws MalformedQueryException
+ * Re-runs any queries bound to the data source. This method should be called 
+ * after the source object is changed or modified.
  */
-/**
- * @public
- * @return {synchronized}
- * @throws DataAccessException, MalformedQueryException
- **/
 xap.data.datasource.AbstractDataSource.prototype.refresh = function () {
 	this.fireDataChanged();
-	this.requeryAll();
+	this.executeQueries(this._boundQueries);
+	this.executeQueries(this._postponedQueries);
+	this._postponedQueries = [];
 };
+	
+	
 			
-//----------------------------------------------------------------------
-// Protected Abstract Methods.
-//-----------------------------------------------------------------------
-/**
- * Subclasses are responsible for implementing this method.  The query 
- * details are obviously subclass specific. It is also up to the subclass
- * whether to execute the query asynchronously or not.
- * 
- * @param query The query to execute
- * @param context The context for executing the query
- * @param listener The listener to notify with the results of the query
- * @throws DataAccessException
- * @throws MalformedQueryException
- * @protected
- * @param query{String}
- * @param context{ContextFrame} 
- * @param listener{DataRetrievalListener}
- * @throws DataAccessException, MalformedQueryException;
+/**
+ * @private
+ * 
+ * Runs a data query and calls the listener, we assume the source is valid at this point
+ * as it was checked earlier.
+ * 
+ * @param {String} query The query to execute
+ * @param {xap.data.controller.ContextFrame} context An optional ContextFrame for nested iteration.
+ * @param listener A listener with a dataRetrieved() method to call back when the data is available.
  **/
 xap.data.datasource.AbstractDataSource.prototype.handleDataQuery = function (query, context, listener) {
+	var rawData =  this.executeQuery(query, context) ;
+	listener.dataRetrieved(query, rawData, context);
 };
+
 /**
- * Subclasses are responsible for implementing this method.  The query 
- * details are obviously subclass specific. It is also up to the subclass
- * whether to execute the query asynchronously or not.
- * 
- * @param query The query to execute
- * @param context The context for executing the query
- * @param listener The listener to notify with the results of the query
- * @throws DataAccessException
- * @throws MalformedQueryException
- * @protected
- * @param query{String}
- * @param context{ContextFrame}
- * @param listener{DataSetRetrievalListener  }
- * @throws DataAccessException, MalformedQueryException
+ * @private
+ * 
+ * Runs a data query and calls the listener, we assume the source is valid at this point
+ * as it was checked earlier.
+ * 
+ * @param {String} query The query to execute
+ * @param {xap.data.controller.ContextFrame} context An optional ContextFrame for nested iteration.
+ * @param listener A listener with a dataSetRetrieved() method to call back when the data is available.
  **/
 xap.data.datasource.AbstractDataSource.prototype.handleDataSetQuery = function (query, context, listener) {
+	var theData = this.executeQuery(query, context) ;
+	var dataset = xap.data.datasource.AbstractDataSet.getDataSet(query, this, theData);		
+	listener.dataSetRetrieved(query, dataset, context);
 };
 
 
 /**
- * Subclass should override to implement asynch loading of data source that comes
- * in a response body
+ * Runs a query against the data source with the given optional context. We assume the source
+ * is valid and was checked earlier. This base class implementation does nothing, subclasses
+ * should override it to run the query and return the resulting object.
+ * 
+ * @param {String} queryString The string representing the query to run.
+ * @param {xap.data.controller.ContextFrame} An optional context object for nested iteration.
+ * @return The result of the query.
  */
-xap.data.datasource.AbstractDataSource.prototype.responseToDataSource = function(response){
-	
+xap.data.datasource.AbstractDataSource.prototype.executeQuery =function(queryString , context){
+
 }
+
 /**
- * This should be overridden by subclasses to handle the asynchronous loading
- * of data.
- * @param a{String}, 
- * @param response{HttpResponse}
- **/
-xap.data.datasource.AbstractDataSource.prototype.requestCompleted = function (a, response) {
+ * Subclasses should override this method to support asynchronous loading of data.
+ * 
+ * @param {XMLHttpRequest} response A completed request object with data that should be converted
+ * into data for the data source.
+ * @return The content of the XMLHttpRequest object parsed into an object suitable to the source object
+ * of the data source.
+ */
+xap.data.datasource.AbstractDataSource.prototype.responseToDataSource = function(response){}
+
+
+/**
+ * @private
+ * Callback method for asynchronous data loading.
+ */
+xap.data.datasource.AbstractDataSource.prototype.requestCompleted = function (url, response) {
 	try{
 		var dataSource = this.responseToDataSource( response );
 		this.setSource( dataSource );
@@ -286,224 +358,124 @@
     	//this sucess message. But we probably want them
     	//to be able to get the new source their listener
    		this.fireOnDataRetrieveSucess();
-    	this.executePostponedQueries();
+    	this.refresh();
 	}
 	catch(e){
-		this.getClientSession().handleException(e);
+		this.getSession().handleException(e);
 		this.fireOnDataRetrieveFailure(e);
-	}
-    finally {
-        this.clearPostponedQueries();
-    }    
+	} 
 };
+
 /**
- * This should be overridden by subclasses to handle the asynchronous loading
- * of data.
- * @param a{String}
- * @param e{NetServiceException}
- **/
+ * @private
+ * Callback method for asynchronous data loading.
+ */
 xap.data.datasource.AbstractDataSource.prototype.requestFailed = function (a, e) {
-	try {
-		this.getClientSession().handleException(e);
-		this.fireOnDataRetrieveFailure(e);
-	}
-	finally {
-		this.clearPostponedQueries();
-	}
-
+	this.getSession().handleException(e);
+	this.fireOnDataRetrieveFailure(e);
 };
 
 
 /**
- * @return the ClientSession this DataSource is associated with
+ * Returns the ClientSession object this data source belongs to.
+ * @return {xap.session.ClientSession} The ClientSession.
  */
-/**
- * @protected
- * @return {ClientSession}
- **/
-xap.data.datasource.AbstractDataSource.prototype.getClientSession = function () {
+xap.data.datasource.AbstractDataSource.prototype.getSession = function () {
 	return this._clientSession;
 };
 
 
 /**
- * @return the source object of the DataSource
- * @protected
- * @return {Object}
- **/
+ * Returns the object that serves as the source of this data source.
+ * @return The object that serves as the source of this data source.
+ */
 xap.data.datasource.AbstractDataSource.prototype.getSource = function () {
 	return this._source;
 };
+
 /**
- * Asynchronously loads the source object using NetService
  * 
- * @param sourceUrl The url to the resource that is expected to return the
- * source object for this DataSource
- * @protected
- * @param sourceUri{String}
- * @return {void}
+ * 
+ * Asynchronously loads a source object from a server URL. When the loading is complete
+ * the data source will refresh and any bindings will re-resolve.
+ * 
+ * @param sourceUrl The url to the resource that will serve as the data source backing object.
  **/
 xap.data.datasource.AbstractDataSource.prototype.loadSourceFromServer = function (sourceUrl) {
+	//IMPORTANT change this to retrieve?
+	
 	/*ClientSession*/
-	var session = this.getClientSession();
+	var session = this.getSession();
 	/*RequestService*/
 	var netService = session.getRequestService();
 	netService.retrieveAsynchronously(sourceUrl, this);
 };
+
 /**
- * Sets the source object for this DataSource
+ * Sets the source object for this DataSource. This will automatically call
+ * <code>refresh()</code> after the source is set.
  * 
- * @param sourceObject The new source object
- * @protected
- * @param sourceObject{Object}
- * @return {void}
+ * @param sourceObject The new source object for the data source.
+ * @see #refresh
  **/
 xap.data.datasource.AbstractDataSource.prototype.setSource = function (sourceObject) {
 	this._source = sourceObject;
+	
+	//TODO make conditional in some cases??
+	this.refresh();
 };
 
 
 
 /**
- * Adds a postponed query to this DataSource. This method can be used to
- * cache queries for later execution (for example if the source object is
- * loaded asynchronously, postponed queries can be executed when the object
- * finishes loading). Subclasses are responsible for clearing the posponed
- * query queue after the queries are executed.
- * 
- * @param query
- * @param context
- * @param listener
- *
- * @protected
- * @return {void}
- * @param query{String}
- * @param context{ContextFrame}
- * @param listener{RetrievalListener  }
+ * @private
+ * Adds a postponed query to this DataSource. A postponed query is a query
+ * that is postponed because the data is not yet available. Note that
+ * bound queries (ONE_WAY) should never be postponed as they run every time anyway.
  **/
-xap.data.datasource.AbstractDataSource.prototype.addPostponedQuery = function (query, context, listener) {
-	var queryRecord = new xap.data.datasource.QueryRecord(query, context, listener);
+xap.data.datasource.AbstractDataSource.prototype.addPostponedQuery = function (query, context, listener, isDataSetQuery) {
+	var queryRecord = new xap.data.datasource.QueryRecord(query, context, listener, isDataSetQuery);
 	this._postponedQueries.push(queryRecord);
 }
 /**
- * Executes all posponed queries in order they came in.
- * At the end of this method the postponed query vector is cleared 
- * regardless of queries' execution result.
- *
- * @protected
- * @synchronized
+ * @private
+ * Runs all the queries in a given array of queries.
  **/
-xap.data.datasource.AbstractDataSource.prototype.executePostponedQueries = function () {
-	try {
-		for (var i = 0; i < this._postponedQueries.length; i++) {
-			/*QueryRecord*/
-			var rec = this._postponedQueries[i];
-			try {
-				this.handleQuery(rec.getQuery(), rec.getContext(), rec.getListener());
-			}
-			catch (e) { 
-				
-				//TODO instead of logging just throw this?
-				this.getLog().exception(e);
-			}
+xap.data.datasource.AbstractDataSource.prototype.executeQueries= function( queries ) {
+	for (var i = 0; i < queries.length; i++) {
+		/*QueryRecord*/
+		var rec = queries[i];
+		try {
+			this.handleQuery(rec.getQuery(), rec.getContext(), rec.getListener(), rec.isDataSetQuery());
+		}
+		catch (e) { 
+			//TODO instead of logging just throw this?
+			this.getLog().error("Error executing databound query:" + rec.getQuery(), e);
 		}
-	}
-	finally {
-		this.clearPostponedQueries();
 	}
 }
 
-
 /**
- * Clears the posponed query vector. 
- *
- * @protected
- * @return {void}
- **/
-xap.data.datasource.AbstractDataSource.prototype.clearPostponedQueries = function () {
-	this._postponedQueries = [];
-}
-
-/**
- * @return the static Log instance
- *
- * @protected
- * @return {Log}
+ * Returns the logger used to log DataSource issues.
+ * @returns {xap.log.Logger} The logger used to log DataSource issues.
  **/
 xap.data.datasource.AbstractDataSource.prototype.getLog = function () {
 	return xap.log.Logger.getLogger("DataSource");
 };
 	
-//-----------------------------------------------------------------------
-// Private Methods.
-//-----------------------------------------------------------------------
-/**
- * This method persists queries whose binding type != ONE_TIME). 
- * It then delegates the call to a subclass whose responsibility is to 
- * process the query in a way it sees fit (i.e. the query could be 
- * executed synchronously or asynchronously).
- * 
- * @param context The context for executing the query
- * @param query The query to execute
- * @param listener The listener to notify after the query finishes
- * 
- * @throws DataAccessException
- * @throws MalformedQueryException
- * @throws UnsupportedBindingTypeException
- *
+
+/**
  * @private
- * @return {void}
- * @param query{String}
- * @param context{ContextFrame}
- * @param listener{RetrievalListener  }
- * @throws DataAccessException, MalformedQueryException,UnsupportedBindingTypeException
- **/
-xap.data.datasource.AbstractDataSource.prototype.handleGenericQuery = function (query, context, listener) {
-	// take care of caching queries for later executions when the data
-	// changes
-	if (listener && listener.getBindingType() != xap.data.controller.BindingType.ONE_TIME) {
-		var queryRecord = new xap.data.datasource.QueryRecord(query, context, listener);
-		this._boundQueries.push(queryRecord);
+ * Delegates to either <code>handleDataSetQuery</code> or <code>handleDataQuery</code>
+ * that subclasses should have implemented.
+ */
+xap.data.datasource.AbstractDataSource.prototype.handleQuery = function (query, queryContext, listener, isDataSetQuery) {
+	this.getLog().trace("Executing query:" + query);
+	if (isDataSetQuery){
+		this.handleDataSetQuery(query, queryContext, listener);
 	}
-	this.handleQuery(query, context, listener);
-};
-/**
- * A helper method for calling appropriate handleX methods
- * @private * 
- * @param query
- * @param queryContextFrame
- * @param listener
- * @throws DataAccessException
- * @throws MalformedQueryException
- *
- * @param query{String}
- * @param queryContext{ContextFrame}
- * @param listener{RetrievalListener  }
- **/
-xap.data.datasource.AbstractDataSource.prototype.handleQuery = function (query, queryContext, listener) {
-	if (listener.isDataRetrievalListener()) {
-		
+	else{
 		this.handleDataQuery(query, queryContext, listener);
-	} else {
-		if (listener.isDataSetRetrievalListener()) {	
-			this.handleDataSetQuery(query, queryContext, listener);
-		}
-	}
-};
-/**
- * Requeries all bound queries (binding type != xap.data.controller.BindingType.ONE_TIME)
- * @throws DataAccessException
- * @throws MalformedQueryException
- * @private
- * @return {void}
- * @throws DataAccessException, MalformedQueryException  
- **/
-xap.data.datasource.AbstractDataSource.prototype.requeryAll = function () {
-	for (var i = 0; i < this._boundQueries.length; i++) {
-		/*QueryRecord*/
-		var rec = this._boundQueries[i];
-		
-		this.handleQuery(rec.getQuery(), rec.getContext(), rec.getListener());
 	}
 };
 

Modified: incubator/xap/trunk/codebase/src/xap/data/datasource/ObjectDataSource.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/data/datasource/ObjectDataSource.js?view=diff&rev=509431&r1=509430&r2=509431
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/data/datasource/ObjectDataSource.js (original)
+++ incubator/xap/trunk/codebase/src/xap/data/datasource/ObjectDataSource.js Mon Feb 19 22:03:05 2007
@@ -25,34 +25,53 @@
 Xap.require("google.xpath");
 
 
+/**
+ * @fileoverview 
+ * Implements a JavaScript object-based data source.
+ */
+ 
 
-xap.data.datasource.ObjectDataSource = function() {
-	xap.data.datasource.AbstractDataSource.call(this) ;
+/** 
+ * Creates a new ObjectDataSource.
+ * 
+ * @class ObjectDataSource is a data source that runs JavaScript queries
+ * against a backing object. This object can be set using  
+ * <code>setSource()</code> or loaded from a server-side URL that return JSON.
+ * 
+ * @constructor
+ * @param {xap.session.ClientSession} session The client session this data source belongs to.
+ * 
+ * @see xap.data.datasource.SimpleDocumentDataSource
+ * @see xap.data.datasource.AbstractDataSource
+ */
+xap.data.datasource.ObjectDataSource = function( session ) {
+	xap.data.datasource.AbstractDataSource.call(this, session) ;
 };
 
+//SETUP SUBCLASS does this but we need this for doc to pick it up correctly
+xap.data.datasource.ObjectDataSource.prototype = new xap.data.datasource.AbstractDataSource();
+
 Xap.setupClassAsSubclassOf("xap.data.datasource.ObjectDataSource", "xap.data.datasource.AbstractDataSource");
 
 
 /**
- * Sets the source to be a document.
+ * Converts the response object into a datasource
+ * assume the response content is JSON that can be run through <code>eval</code>
+ * to return an object. 
+ * This overrides the no-op version in <code>xap.data.datasource.AbstractDataSource</code>.
+ * 
+ * @param {XMLHttpRequest} response A completed request object with data that should be converted
+ * into data for the data source.
+ * @return The content of the XMLHttpRequest object parsed into an object suitable to the source object
+ * of the data source.
  */
-xap.data.datasource.ObjectDataSource.prototype.setSource = function( object ) {
-	this.superclass.setSource.call(this, object );
-	
-	//TODO this should be conditional?
-	this.refresh();
-	
-        
-};
-
-
-
 xap.data.datasource.ObjectDataSource.prototype.responseToDataSource = function(response){
 	var result = dj_eval( '(' + response.responseText + ')');
 	return result ;
 }
 
 /**
+ * @private
  * Mozilla supports an eval() on object itself but IE does not. This normalizes the behavior
  * against both browsers. Note that by doing this to run a string against an object you have to
  * do something like 'this.employees' not just 'employees'
@@ -66,44 +85,14 @@
 	return object._eval(evalText);
 }
 
-//TODO move this to a base class?
-xap.data.datasource.ObjectDataSource.prototype.handleDataQuery = function(query, context, listener) {
-	
-	if (!this.getSource()){
-		if (listener.getBindingType() == xap.data.controller.BindingType.ONE_TIME){
-			this.addPostponedQuery( query, context, listener );
-		}
-	}
-	else{
-		var rawData =  this.executeQuery(context, query) ;
-		listener.dataRetrieved(query, rawData, context);
-	}
-};
-
-//TODO move this to a base class?
-xap.data.datasource.ObjectDataSource.prototype.handleDataSetQuery = function(query, context, listener) {
-	
-	if (!this.getSource()){		
-		if (listener.getBindingType() == xap.data.controller.BindingType.ONE_TIME){
-			this.addPostponedQuery( query, context, listener );
-		}
-		
-	}
-	else{
-		theData = this.executeQuery(context, query) ;
-		var dataset = xap.data.datasource.AbstractDataSet.getDataSet(query, this, theData);		
-		listener.dataSetRetrieved(query, dataset, context);
-	}
-};
-
-
-
 /**
- * Execute query against a DOM
- * @see  handleDataQuery
- * @see  handleDataSetQuery
-**/ 
-xap.data.datasource.ObjectDataSource.prototype.executeQuery =function(context ,queryString){
+ * Executes the JavaScript query against the source object or context object if it is defined.
+ * This overrides the no-op version in <code>xap.data.datasource.AbstractDataSource</code>.
+ * 
+ * @param {String} queryString A JavaScript string that can be run against an object.
+ * @param {xap.data.controller.ContextFrame} context An optional ContextFrame for nested iteration.
+ */
+xap.data.datasource.ObjectDataSource.prototype.executeQuery =function(queryString , context){
 	
 	var contextObject = this.getSource();
 	if (context){
@@ -111,6 +100,5 @@
 	}
 	
 	//eval query string relative to context object
-	
 	return this.evalOnObject(queryString,contextObject);
 }

Modified: incubator/xap/trunk/codebase/src/xap/data/datasource/QueryRecord.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/data/datasource/QueryRecord.js?view=diff&rev=509431&r1=509430&r2=509431
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/data/datasource/QueryRecord.js (original)
+++ incubator/xap/trunk/codebase/src/xap/data/datasource/QueryRecord.js Mon Feb 19 22:03:05 2007
@@ -27,24 +27,17 @@
  * and all the listeners that get notified after the execution. Only one
  * QueryRecord is created for a given query.
  */
-xap.data.datasource.QueryRecord = function(){
-	/*private String*/
-	this._query =  null;
-	/*private Context*/
-	this._context =  null;
-	/*private RetrievalListener*/
-	this._listener =  null;
-}
-
+ 
 /**
  * @param query{String}
  * @param context{Context}
  * @param listener{RetrievalListener  }
 **/
-xap.data.datasource.QueryRecord = function( query, context, listener ) {
+xap.data.datasource.QueryRecord = function( query, context, listener, isDataSetQuery ) {
 	this._query = query;
 	this._context = context;
 	this._listener = listener;
+	this._isDataSetQuery = isDataSetQuery;
 }
 /**
  * @return {String}
@@ -66,4 +59,10 @@
 xap.data.datasource.QueryRecord.prototype.getListener = function() {
 	return this._listener;
 }
+
+xap.data.datasource.QueryRecord.prototype.isDataSetQuery = function() {
+	return this._isDataSetQuery;
+}
+
+
    

Modified: incubator/xap/trunk/codebase/src/xap/data/datasource/SimpleDocumentDataSource.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/data/datasource/SimpleDocumentDataSource.js?view=diff&rev=509431&r1=509430&r2=509431
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/data/datasource/SimpleDocumentDataSource.js (original)
+++ incubator/xap/trunk/codebase/src/xap/data/datasource/SimpleDocumentDataSource.js Mon Feb 19 22:03:05 2007
@@ -25,18 +25,41 @@
 Xap.require("google.xpath");
 
 
-
-xap.data.datasource.SimpleDocumentDataSource = function() {
-	xap.data.datasource.AbstractDataSource.call(this) ;
+/**
+ * @fileoverview 
+ * Implements an XML document-based data source.
+ */
+ 
+
+/** 
+ * Creates a new SimpleDocumentDataSource.
+ * 
+ * @class SimpleDocumentDataSource is a data source that runs XPath queries
+ * against a backing XML Document. This document can be set using  
+ * <code>setSource()</code> or loaded from a server-side URL that return XML.
+ * 
+ * @constructor
+ * @param {xap.session.ClientSession} session The client session this data source belongs to.
+ * 
+ * @see xap.data.datasource.ObjectDataSource
+ * @see xap.data.datasource.AbstractDataSource
+ */
+xap.data.datasource.SimpleDocumentDataSource = function( session ) {
+	xap.data.datasource.AbstractDataSource.call(this, session) ;
 };
+
+//SETUP SUBCLASS does this but we need this for doc to pick it up correctly
+xap.data.datasource.SimpleDocumentDataSource.prototype = new xap.data.datasource.AbstractDataSource();
 
 Xap.setupClassAsSubclassOf("xap.data.datasource.SimpleDocumentDataSource", "xap.data.datasource.AbstractDataSource");
 
 
-//TODO take a name and register the document as a name?
 
 /**
- * Sets the source to be a document.
+ * Sets the source and throws and exception if the source is not an XML document.
+ * This will automatically call
+ * <code>refresh()</code> after the source is set.
+ * @param {xap.xml.dom.Document} document The document to serve as the new source.
  */
 xap.data.datasource.SimpleDocumentDataSource.prototype.setSource = function( document ) {
 	if (! document instanceof xap.xml.dom.Document){
@@ -45,79 +68,35 @@
 		throw new xap.util.Exception("Source for a document source must be a document");
 	}
 	this.superclass.setSource.call(this, document );
-	
-	//TODO this should be conditional if they set refreshOnStructureChange to true
-	this.refresh();
-	
-        
 };
 
 
-
+/**
+ * Converts the response object into a datasource
+ * assume the response content is XML taht can be parsed into a document. 
+ * This overrides the no-op version in <code>xap.data.datasource.AbstractDataSource</code>.
+ * 
+ * @param {XMLHttpRequest} response A completed request object with data that should be converted
+ * into data for the data source.
+ * @return The content of the XMLHttpRequest object parsed into an object suitable to the source object
+ * of the data source.
+ */
 xap.data.datasource.SimpleDocumentDataSource.prototype.responseToDataSource = function(response){
 	var parser = xap.xml.ParserFactory.getParser();
 	var doc = parser.parse( response.responseText );
 	return doc;
 }
 
-/**
- * @see AbstractDataSource#handleDataQuery( String, Context, 
- *										  DataRetrievalListener )
- *
- * @protected
- * @param query{String}
- * @param context{Context} 
- * @param listener{DataRetrievalListener}
- * @throws DataAccessException, MalformedQueryException   
- * @return {void}
-**/
-xap.data.datasource.SimpleDocumentDataSource.prototype.handleDataQuery = function(query, context, listener) {
-	
-	if (!this.getSource()){
-		if (listener.getBindingType() == xap.data.controller.BindingType.ONE_TIME){
-			this.addPostponedQuery( query, context, listener );
-		}
-	}
-	else{
-		var rawData =  this.executeQuery(context, query) ;
-		listener.dataRetrieved(query, rawData, context);
-	}
-};
-
-/**
- * @see AbstractDataSource#handleDataSetQuery( String, Context, 	 *											 DataSetRetrievalListener )
- *
- * @protected
- * @return {void}
- *
- * @param query{String}
- * @param context{Context}
- * @param listener{DataSetRetrievalListener  }
- * @throws DataAccessException, MalformedQueryException  
-**/
-xap.data.datasource.SimpleDocumentDataSource.prototype.handleDataSetQuery = function(query, context, listener) {
-	
-	if (!this.getSource()){		
-		if (listener.getBindingType() == xap.data.controller.BindingType.ONE_TIME){
-			this.addPostponedQuery( query, context, listener );
-		}
-		
-	}
-	else{
-		theData = this.executeQuery(context, query) ;
-		var dataset = xap.data.datasource.AbstractDataSet.getDataSet(query, this, theData);		
-		listener.dataSetRetrieved(query, dataset, context);
-	}
-};
-
 
 
 /**
- * Execute query against a DOM
- * @see  handleDataQuery
- * @see  handleDataSetQuery
-**/ 
-xap.data.datasource.SimpleDocumentDataSource.prototype.executeQuery =function(context ,queryString){
+ * Executes the XPath query against the source document or context object if it is defined.
+ * This overrides the no-op version in <code>xap.data.datasource.AbstractDataSource</code>.
+ * 
+ * @param {String} queryString An XPath string that can be run against an object.
+ * @param {xap.data.controller.ContextFrame} context An optional ContextFrame for nested iteration.
+ */
+xap.data.datasource.SimpleDocumentDataSource.prototype.executeQuery =function(queryString ,context){
 	
 	var contextObject = this.getSource();
 	if (context){