- From: Richard Tibbett via cvs-syncmail <cvsmail@w3.org>
- Date: Thu, 22 Oct 2009 10:42:43 +0000
- To: public-dap-commits@w3.org
Update of /sources/public/2009/dap/contacts In directory hutz:/tmp/cvs-serv16409/contacts Modified Files: Overview.html Log Message: Updated the Contacts API in line with discussion on the mailing list: http://lists.w3.org/Archives/Public/public-device-apis/2009Oct/0161.html Index: Overview.html =================================================================== RCS file: /sources/public/2009/dap/contacts/Overview.html,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- Overview.html 5 Oct 2009 17:14:03 -0000 1.6 +++ Overview.html 22 Oct 2009 10:42:41 -0000 1.7 @@ -20,34 +20,178 @@ <section id='abstract'> This specification defines an API that provides access to the device's address book. </section> - + + <section id='conformance'> + <p> + This specification defines conformance criteria that apply to a single product: + <dfn>user agents</dfn> that implement the interfaces that it contains. + </p> + </section> + <section> <h2>Introduction</h2> + <p> + The Contacts API defines a high-level interface to Address Book information, such as names, addresses and contact details. The API itself is agnostic of any underlying address book sources. + </p> + + <p class='issue'> + There is a significant case for making this API asynchronous due to the agnosticity of implementation. There is no reason why the underlying implementation cannot interface with e.g. cloud based address book sources, in which the need for request/response calls denotes a need for asynchronous implementation. + </p> + <p> Rather than each application having its own address book for its own purposes (email, phone, driving directions) it is more practical for the user to have a single address book which multiple applications share. That is what this specification exposes. </p> + <p> The requirements for this set of interfaces are listed in the Device API Requirements document [[DAP-REQS]]. </p> + + <section> + <h2>Simple Usage Examples</h2> + + <p>The following code extracts illustrate how to search, add and remove contacts information:</p> + + <div class='example'> + + <p>Example of a simple Address Book search.</p> + + <pre> // Simple address book search for 'Bob' + var contacts = navigator.device.addressbook.find({givenName:'Bob'});</pre> + + <p class='note'> + Contact.getFullName() is not currently searchable in this model. Is this a problem? + </p> + </div> + + <div class='example'> + + <p>Adding a new contact to the Address Book.</p> + + <pre> // Add a new contact to the Address Book + navigator.device.addressbook.add( {givenName: 'Bob', + familyName: 'Smith', + phone: '+440000000000'} );</pre> + + <p class='issue'> + Should we specify mandatory required attributes when adding a new contact? + </p> + + <p class='issue'> + Should we be throwing exceptions if any attributes are incorrectly formed? + </p> + + </div> + + <div class='example'> + + <p>Removing an existing contact from the Address Book.</p> + + <pre> // Search address book for 'Mike' + var contacts = navigator.device.addressbook.find({givenName:'Mike'}); + + if(contacts.length>0) { + // Remove first 'Mike' + navigator.device.addressbook.remove(contacts[0]); + }</pre> + </div> + + <div class='example'> + + <p>Editing an existing contact details.</p> + + <pre> // Search address book for surname 'Doe' + var contacts = navigator.device.addressbook.find({familyName:'Doe'}); + + if(contacts.length>0) { + // Edit first 'Doe' company name + contacts[0].companyName = 'BarFoo Company'; + // Add a new phone number to first 'Doe' + contacts[0].phones.push('+440000000001'); + + // Update first 'Doe' in Address Book + contacts[0].save(); + }</pre> + + </div> + + </section> + + <section> + <h2>Advanced Usage Examples</h2> + + <p>The following code extracts demonstrate more powerful contact searching scenarios.</p> + + <section> + <h2>Combinatorial Search Filters</h2> + + <div class='example'> + + <p>Searching for a contact based on a number of ANDed parameters.</p> + + <pre> // Address book search for contacts called 'Jane' who also work at 'FooBar Inc' + var contacts = navigator.device.addressbook.find( {givenName:'Jane', + companyName:'FooBar Inc'} );</pre> + </div> + + <div class='example'> + + <p>Searching for a contact based on a number of ORed parameters.</p> + + <pre> // Address book search for contacts called 'Jane' OR contacts that work at 'FooBar Inc' + var contacts = navigator.device.addressbook.find( [ {givenName:'Jane'}, + {companyName:'FooBar Inc'} ] );</pre> + </div> + + </section> + + <section> + <h2>Search Options</h2> + + <div class='example'> + <p>Example of a simple Address Book search with simple options.</p> + + <pre> // Simple address book search for 'Jane' and return only the first 5 matches + var contacts = navigator.device.addressbook.find( {givenName:'Jane'}, + {limit: 5} );</pre> + </div> + + <div class='example'> + + <p>Paginating Address Book search results.</p> + + <pre> // Address book search for contacts working at 'FooBar Inc' and + // return 5 matches starting at a results offset of 5 + var contacts = navigator.device.addressbook.find( {companyName:'FooBar Inc'}, + {limit: 5, page: 2} );</pre> + </div> + + </section> + + </section> + </section> - - <section id='conformance'> - <p> - This specification defines conformance criteria that apply to a single product: - <dfn>user agents</dfn> that implement the interfaces that it contains. - </p> - </section> - + + <section> + <h2>Security and Privacy Considerations</h2> + + <p class='note'> + TODO + </p> + </section> + + <section> + <h2>API Description</h2> + <section> - <h2>The <a>AddressBook</a> interface</h2> + <h2><a>AddressBook</a> interface</h2> <p> The <a>AddressBook</a> interface exposes an interface to a database collecting addresses, such that they may be created, found, read, updated, and deleted. </p> - <dl title='[NoInterfaceObject] interface AddressBook' class='idl'> + <dl title='interface AddressBook' class='idl'> <dt>void add ()</dt> <dd> Adds a contact to the address book. @@ -70,11 +214,29 @@ </dd> <dt>sequence<Contact> find ()</dt> <dd> - Uses a filter in order to find corresponding contacts in the address book. + Uses a single filter in order to find corresponding contacts in the address book. This method MUST be processed according to the <a href='#rules-for-processing-filter-combinations'>rules for processing filter combinations</a> and the <a href='#rules-for-applying-filter-options'>rules for applying filter options</a>. <dl class='parameters'> <dt>ContactFilter filter</dt> <dd> - The filter used in order to select which contacts are returned + The filter used in order to select which contacts are returned. + </dd> + <dt>[Optional] ContactFilterOptions options</dt> + <dd> + The options to apply to the output of this method. This parameter is OPTIONAL. + </dd> + </dl> + </dd> + <dt>sequence<Contact> find ()</dt> + <dd> + Uses multiple filters in order to find corresponding contacts in the address book. This method MUST be processed according to the <a href='#rules-for-processing-filter-combinations'>rules for processing filter combinations</a> and the <a href='#rules-for-applying-filter-options'>rules for applying filter options</a>. + <dl class='parameters'> + <dt>sequence<ContactFilter> filters</dt> + <dd> + The filters used in order to select which contacts are returned. + </dd> + <dt>[Optional] ContactFilterOptions options</dt> + <dd> + The options to apply to the output of this method. This parameter is OPTIONAL. </dd> </dl> </dd> @@ -82,7 +244,10 @@ </section> <section> - <h2>The <a>Contact</a> interface</h2> + <h2><a>Contact</a> interface</h2> + +<p class='note'>We need more discussion around the attributes that should be provided by the Contacts interface.</p> + <p> The <a>Contact</a> interface captures a single contact item. </p> @@ -101,9 +266,13 @@ The contact's nickname. </p> <p class='issue'> - Could there be several of this? + Could there be several nicknames? </p> </dd> + <dt>attribute sequence<DOMString> category</dt> + <dd> + The contact's categories (e.g. 'home', 'work', 'friends', 'family', etc). + </dd> <dt>attribute DOMString companyName</dt> <dd> The contact's company name. @@ -181,7 +350,7 @@ </section> <section> - <h2>The <a>Address</a> interface</h2> + <h2><a>Address</a> interface</h2> <p> The <a>Address</a> interface is used to describe a physical street address. </p> @@ -232,7 +401,7 @@ </section> <section> - <h2>The <a>PhoneNumber</a> interface</h2> + <h2><a>PhoneNumber</a> interface</h2> <p> The <a>PhoneNumber</a> interface describes a phone number. </p> @@ -249,7 +418,7 @@ </section> <section> - <h2>The <a>EmailAddress</a> interface</h2> + <h2><a>EmailAddress</a> interface</h2> <p> The <a>EmailAddress</a> interface describes an email address. </p> @@ -266,7 +435,7 @@ </section> <section> - <h2>The <a>URIAddress</a> interface</h2> + <h2><a>URIAddress</a> interface</h2> <p> The <a>URIAddress</a> interface describes a URI. </p> @@ -283,7 +452,7 @@ </section> <section> - <h2>The <a>IMHandle</a> interface</h2> + <h2><a>IMHandle</a> interface</h2> <p> The <a>IMHandle</a> interface describes an IM handle. </p> @@ -304,11 +473,12 @@ </section> <section> - <h2>The <a>ContactFilter</a> interface</h2> + <h2><a>ContactFilter</a> interface</h2> <p> The <a>ContactFilter</a> interface captures a filter that enables simple searches within the address book. Fields that are set to <code>null</code> are considered to match anything. </p> + <dl title='[NoInterfaceObject] interface ContactFilter' class='idl'> <dt>attribute DOMString givenName</dt> <dd> @@ -322,6 +492,10 @@ <dd> The nickname that is being looked for. </dd> + <dt>attribute DOMString category</dt> + <dd> + The category that is being looked for + </dd> <dt>attribute DOMString companyName</dt> <dd> The company name that is being looked for. @@ -380,7 +554,33 @@ </section> <section> - <h2>The ContactsException exception</h2> + <h2><a>ContactFilterOptions</a> interface</h2> + <p> + The <a>ContactFilterOptions</a> interface describes the options that can be applied to sorted, limit, group and order the resulting output of contact searching. + </p> + <dl title='[NoInterfaceObject] interface ContactFilterOptions' class='idl'> + <dt>attribute int limit</dt> + <dd> + <p>The maximum number of results to return from the contacts search.</p> + <p>DEFAULT = 200</p> + </dd> + <dt>attribute int page</dt> + <dd> + <p>The page number of the contacts search to return. If the requested page index does not exist, this parameter MUST be assigned the default value.</p> + <p>DEFAULT = 1</p> + </dd> + </dl> + + <p class='note'> + Should we add a sorting attribute to ContactFilterOptions? i.e. ability to 'ORDER BY name ASCENDING'. + </p> + <p class='note'> + Should we add a grouping attribute to ContactFilterOptions? i.e. ability to 'GROUP BY category'. + </p> + </section> + + <section> + <h2><a>ContactsException</a> exception</h2> <p> The <a>ContactsException</a> exception class encapsulates all errors in the manipulation of objects in the Contacts API. @@ -392,7 +592,159 @@ book, but it hasn't been added to one yet. </dd> </dl> + + <p class='note'> + If we add any asynchronicity to this API any exceptions should become 'errors' for sync+async usage. + </p> + <p class='note'> + Do we need further error codes and throws throughout the API? + </p> </section> + + </section> <!-- api description section --> + + <section> + <h2><a>Contact Search processing rules</a></h2> + + <p class='issue'> + In order to represent the relationship within and between ContactFilter objects, an SQL language representation is currently being used. Do we have any relevant logical language, references or logic conventions that could be used here instead? Would there be a better way to descibe the ContactFilter processing rules in this section? + </p> + + <p>The <a href="#addressbook-interface">AddressBook</a> interface allows <var title=''>filter</var> overloading to provide a means to <a href='#widl-AddressBook-find'>find()</a> contacts according to the input of a single <code>ContactFilter</code> object or a sequence of <code>ContactFilter</code> objects. + + <p>The premise of the contact search processing rules is that all fields within a single ContactFilter object represet logical AND unions and the links between multiple ContactFilter objects represent logical OR unions. + + <p>Some examples of this concept are as follows: + + <div class='example'> + <p>Single <code>ContactFilter</code> passing and processing. + + <pre> // Search for an existing contact in the Address Book + navigator.device.addressbook.find( {givenName: 'Bob', + familyName: 'Smith', + phone: '+440000000000'} );</pre> + + <p>The example above MUST be represented in SQL as: + + <pre>WHERE (givenName='Bob' AND familyName='Smith' AND phone='+440000000000') + </div> + + <div class='example'> + <p>Multiple <code>ContactFilter</code> passing and processing. + + <pre> // Search for an existing contact in the Address Book + navigator.device.addressbook.add( [ {givenName: 'Bob', + familyName: 'Smith'}, + {phone: '+440000000000'} ] );</pre> + + <p>The example above MUST be represented in SQL as: + + <pre>WHERE (givenName='Bob' AND familyName='Smith') OR (phone='+440000000000') + </div> + + <p><code>ContactFilterOptions</code> can optionally be used to apply filtering and sorting criteria to the result of the AddressBook find() method. + + <p class='note'> + Do we need to say something about whether contact search matching is loose or strict? Could this be added as a ContactFilterOptions attribute? + </p> + + <p>The <dfn id='rules-for-processing-filter-combinations'>rules for processing filter combinations</dfn> is always provided with one <var title="">input</var> parameter, and its behaviour depends on the type of <var title="">input</var>. The following algorithm demonstrates the conversion of a <a href='#widl-AddressBook-find'>find()</a> filter object to an SQL WHERE query.</p> + + <dl class=switch> + + <dt>If <var title="">input</var> is an Array object</dt> + + <dd> + <ol> + <li>Let <var title="">multiplefilters</var> be the <var title="">input</var> parameter being parsed.</li> + <li>Let <var title="">singlefilter</var> be the next index in <var title="">mutiplefilters</var>. If there are no more indices, go to step 6.</li> + <li>Let <var title="">contactfilter</var> be the result of processing <var title="">singlefilter</var> through <a href="#rules-for-processing-filter-combinations">rules for processing filter combinations</a>.</li> + <li>If <var title="">contactfilter</var> is not null, let <var title="">output</var> be the string value consisting of the characters in the previous value of <var title="">output</var> followed by the string ' OR ' and then followed by the string value of <var title="">contactfilter</var>.</li> + <li>Go to step 2.</li> + <li>Return <var title="">output</var>.</li> + </ol> + + </dd> + + <dt>If <var title="">input</var> is an Object object</dt> + + <dd> + <ol> + <li>Let <var title="">singlefilter</var> be the <var title="">input</var> parameter being parsed.</li> + <li>Let <var title="">output</var> be the string '('.</li> + <li>Let <var title="">item</var> be the next enumerable property in <var title="">singlefilter</var>. If there are no more enumerable properties, go to step 10.</li> + <li>If the value of <var title="">item</var> is null, go to step 3.</li> + <li>Let <var title="">output</var> be the string value consisting of the characters in the previous value of <var title="">output</var> followed by the string ' AND '.</li> + <li>Let <var title="">output</var> be the string value consisting of the characters in the previous value of <var title="">output</var> followed by the string value of <var title="">item</var> key.</li> + <li>Let <var title="">output</var> be the string value consisting of the characters in the previous value of <var title="">output</var> followed by the string ' = '.</li> + <li>Let <var title="">output</var> be the string value consisting of the characters in the previous value of <var title="">output</var> followed by the string value of <var title="">item</var> value.</li> + <li>Go to step 3.</li> + <li>Let <var title="">output</var> be the string value consisting of the characters in the previous value followed by the string ')'.</li> + <li>Return <var title="">output</var>.</li> + </ol> + </dd> + + <dt>If <var title="">input</var> is another native object type</dt> + + <dd><p>Return a null value.</dd> + + </dl> + + <p> </p> + + <p>The <a href="#addressbook-interface">AddressBook</a> interface also provides a means to apply predefined options to the resulting contacts that match the given <code>ContactFilter</code>. <code>ContactFilterOptions</code> are an optional <var title''>input</var> to the <a href="#addressbook-interface">AddressBook</a> <a href='#widl-AddressBook-find'>find()</a> method.</p> + + <p>The <dfn id='rules-for-applying-filter-options'>rules for applying filter options</dfn> are as given in the following algorithm. If the <var title=''>output</var> of this algorithm is not null, then the string value of <var title=''>output</var> MUST be concatenated with the <var title=''>output</var> parameter of <a href='#rules-for-processing-filter-combinations'>rules for processing filter combinations</a> and returned as a single string result. The following algorithm demonstrates the conversion of a passed <code>ContactFilterOptions</code> object to an SQL Pagination query.</p> + + <ol> + <li>Let <var title="">filteroptions</var> be the <var title="">input</var> parameter being parsed.</li> + <li>If <var title="">filteroptions</var> is not an Array object or an Object object, go to step 7.</li> + <li>Let <var title=''>limit</var> be the value of the limit property in <var title=''>filteroptions</var>. + <li>If <var title=''>limit</var> is null, is not a valid integer or it is a non-positive integer, go to step 7. + <li>Let <var title=''>output</var> be the string ' LIMIT ' followed by the value of the <var title=''>limit</var> property. + <li>Go to step 8.</li> + <li>Let <var title=''>output</var> be the string ' LIMIT ' followed by the DEFAULT value of the ContactFilterOptions <var title=''>limit</var> attribute. + + <li>Let <var title=''>page</var> be the value of the page property in <var title=''>filteroptions</var>. + <li>If <var title=''>page</var> is null, is not a valid integer or it is a non-positive integer, go to step 12. + <li>Let <var title=''>output</var> be the string ' OFFSET ' followed by the value of the <var title=''>page</var> property multiplied by <var title''>limit</var> (i.e., <var title=''>page</var> * <var title=''>limit</var>). + <li>Go to step 13.</li> + <li>Let <var title=''>output</var> be the string ' OFFSET ' followed by the DEFAULT value of the ContactFilterOptions <var title=''>page</var> attribute multiplied by <var title''>limit</var> (i.e., <var title=''>page</var> * <var title=''>limit</var>). + + <li>Return <var title="">output</var>.</li> + </ol> + + </section> + + <section> + <h2>Use Cases and Requirements</h2> + + <section> + <h2>Use Cases</h2> + <p class="note"> + todo: include the input use cases + </p> + </section> + + <section> + <h2>Requirements</h2> + + <ul> + <li><em title="must" class="rfc2119">must</em> enable listing all available address books on the device;</li> + <li><em title="must" class="rfc2119">must</em> enable listing all contacts in the address book(s);</li> + + <li><em title="must" class="rfc2119">must</em> enable reading the details for a contact;</li> + <li><em title="should" class="rfc2119">should</em> enable creating a new contact;</li> + <li><em title="should" class="rfc2119">should</em> enable updating a contact;</li> + <li><em title="should" class="rfc2119">should</em> enable deleting a contact;</li> + + <li><em title="should" class="rfc2119">should</em> enable filtering the list of contacts to search for a subset.</li> + </ul> + + + </section> + + </section> <section class='appendix'> <h2>Features for Future Consideration</h2>
Received on Thursday, 22 October 2009 10:42:45 UTC