Core-Gadget - PubSub

Core-Gadget - PubSub

  <section title="Inter-Gadget Eventing" anchor="interGadgetEventing">       <t>The inter-gadget eventing feature, common known as "pub/sub", provides     for loosely-coupled and asynchronous inter-gadget communication based     on the <eref target="http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Introduction">     OpenAjax Hub 2.0</eref> specification.</t>       <t>The "pub/sub" feature provides:       <list style="symbols">         <t>An event hub, provided by the container and fully compliant          with OpenAjax Hub 2.0, that manages the subscription and publication          of events,</t>         <t>Methods for publishing and subscribing to events, and </t>         <t>Mechanisms for declaratively specifying metadata within         a gadget's XML definition relevant to publishing and subscribing          to events.</t>       </list>     </t>       <t>The process is straightforward:       <list style="symbols">         <t>First, a container that supports the "pub/sub" feature needs to          initialize the Hub and all default settings.</t>         <t>Second, a container can bootstrap and simplify the connection of          a gadget to the hub by registering an onLoad handler using the          gadgets.util.registerOnLoadHandler API. </t>         <t>Third, once the Hub is initialized by the container, individual gadget's         that declare support for the "pubsub-2" feature using either the          "Optional" or "Required" tag within the Gadget specifications          "ModulePrefs" can use the provided JavaScript APIs to publish          events to the hub using "topics", or use the JavaScript APIs to         subscribe to "topics" published by the Hub. When a gadget publishes         and event to the Hub using a specific topic, all gadget's connected          to that Hub and subscribed to the same topic will receive a copy          of the event.</t>       </list>     </t>       <t>A "topic" is a String value that conforms to the OpenAjax Hub 2.0      specification's <eref target="http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Topic_Names">Topic Name Rules</eref>.     All topic names prefixed with "org.opensocial." are reserved for use by     the OpenSocial specification. Developers MUST NOT use the "org.opensocial."     prefix when defining their own topics.</t>       <section title="Initializing the Hub within the Container" anchor="ContainerExample">         <t>The following example illustrates a non-normative example how a        container could provide support for this feature.</t>         <list style="numbers">         <t>Set default values:           <artwork type="code"> // Create a pubsub settings object gadgets.HubSettings = {};   // Set default HubClient constructor params object gadgets.HubSettings.params = {  HubClient: {     onSecurityAlert: function( alertSource, alertType ) {       alert( "Gadget stopped attempted security breach: " + alertType );       window.location.href = "about:blank"; // Forces container to see Frame Phish alert and probably close this gadget     },     scope: gadgetInstance   } };   // Set default onComplete function for HubClient.connect gadgets.HubSettings.onConnected = function( hub, suc, err ) { };             </artwork>         </t>         <t>     Register an onLoad handler     <t>An onLoad handler to actually create the HubClient and connect it         to the ManagedHub. Delaying the HubClient creation and         connection allows the gadget to override default values stored         in gadgets.HubSettings. For example, IframeHubClient         supports params properties such as seed, tokenLength and log,         which are not set by default; and a gadget might need to         override onSecurityAlert and/or scope, for which default values         are provided. More importantly, the onComplete function for         HubClient.connect usually sets up the gadget's subscriptions by         calling gadgets.Hub.subscribe, or if the connection fails         asynchronously, the onComplete function handles the error.</t>             <artwork type="code"> // Register an onLoad handler gadgets.util.registerOnLoadHandler( function() {   try {     // Create the HubClient.     gadgets.Hub = new OpenAjax.hub.IframeHubClient(  gadgets.HubSettings.params );       // Connect to the ManagedHub     gadgets.Hub.connect( gadgets.HubSettings.onConnect );     } catch(e) {     // TODO: error handling should be consistent with other OS gadget initialization error handling   } } );             </artwork>         </t>       </list>     </section>       <section title="Gadget Examples" anchor="GadgetExample">         <t>The following illustrates a non-normative example of a gadget that        subscribes to a topic published by the Hub.</t>         <t>Note that, by default, all of the necessary defaults parameters       on the underlying HubClient connected for the gadget were initialized       when the gadget was loaded. If the gadget developer wishes to override the        default parameters to the HubClient constructor, it can do so by        setting values on gadgets.HubSettings as illustrated in the example.</t>         <figure><artwork type="code">   &lt;Module&gt;     &lt;ModulePrefs title="Sample PubSub Subscriber" height="250"&gt;       &lt;Require feature="pubsub-2"&gt;         &lt;Param name="topics"&gt;&lt;![CDATA[            &lt;Topic title="Random Number"              name="org.apache.shindig.random-number"             description="Subscribes to random number generator."              type="number"             subscribe="true"/&gt;           ]]&gt;&lt;/Param&gt;       &lt;/Require&gt;     &lt;/ModulePrefs&gt;     &lt;Content type="html"&gt;&lt;![CDATA[       &lt;script&gt; var subId;   // Example of setting a parameter to the HubClient used by pubsub-2 feature. gadgets.HubSettings.params.HubClient.onSecurityAlert = function(alertSource, alertType) {   alert("SECURITY ERROR!");   window.location.href = "about:blank"; };   function callback(topic, data, subscriberData) {   document.getElementById("output").innerHTML =     "message : " + gadgets.util.escapeString(data + "") + "&lt;br/&gt;" +     "received at: " + (new Date()).toString(); }   function subscribe() {   subId = gadgets.Hub.subscribe("org.apache.shindig.random-number", callback); }   function unsubscribe() {   gadgets.Hub.unsubscribe(subId);   document.getElementById("output").innerHTML = ""; }       &lt;/script&gt;       &lt;div&gt;         &lt;input type="button" value="Subscribe" onclick="subscribe()"/&gt;         &lt;input type="button" value="Unsubscribe" onclick="unsubscribe()"/&gt;       &lt;/div&gt;       &lt;div id="output"&gt;&lt;/div&gt;     ]]>&lt;/Content&gt;   &lt;/Module&gt;    </artwork></figure>        <t>Similarly, below is a non-normative example of a gadget that       publishes events to the Hub:</t>        <figure><artwork>   &lt;Module&gt;     &lt;ModulePrefs title="Sample PubSub Publisher" height="250"&gt;       &lt;Require feature="pubsub-2"&gt;         &lt;Param name="topics"&gt;           &lt;![CDATA[              &lt;Topic title="Random Number"                name="org.apache.shindig.random-number"               description="Publishes a random number."                type="number"               publish="true" /&gt;         ]]>&lt;/Param&gt;       &lt;/Require&gt;     &lt;/ModulePrefs&gt;     &lt;Content type="html"&gt;&lt;![CDATA[       &lt;script&gt; function publish() {   var message = Math.random();   gadgets.Hub.publish("org.apache.shindig.random-number", message);   document.getElementById("output").innerHTML = message; }       &lt;/script&gt;       &lt;div&gt;         &lt;input type="button" value="Publish a random number" onclick="publish()"/&gt;       &lt;/div&gt;       &lt;div id="output">&lt;/div&gt;     ]]>&lt;/Content&gt;   &lt;/Module&gt;      </artwork></figure>       </section>       <section title="gadgets.Hub" anchor="gadgets.Hub">       <section title="Method Details">         <section title="publish" anchor="publish">           <t>publish(topic, payload)</t>           <t>Description: The publish method conforms to the semantics of the           OA Hub. The OAHub embraces the notion that pubsub is anonymous and           does not automatically include any information about the           identification of the publishing gadget with the message. The           following is an excerpt from their documentation.</t>           <t>Parameters:             <texttable align="left">               <ttcol>Name</ttcol>               <ttcol>Type</ttcol>               <ttcol>Description</ttcol>               <c>topic</c>               <c>String</c>               <c>A string that conforms to the rules defined above and by the               OA Hub to name the channel that the payload will be deliverd on.               Wildcards are NOT permitted.</c>               <c>payload</c>               <c>*</c>               <c>It is permissible to publish any object. The payload MUST               be serializable to JSON.</c>             </texttable>           </t>           <t>See the <eref target="http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Managed_Hub_APIs#OpenAjax.hub.Hub.prototype.publish">OpenAjax Hub 2.0 documentation</eref> for more information.</t>           <section title="subscribe" anchor="subscribe">             <t>subscribe(topic, callback [,scope [,onCompleteCallback [,subscriberData]]])</t>             <t>Description: The subscribe method is used to indicate to the             hub the topic from which the gadget is interested in receiving             information. When information is published on the topic, the hub             will invoke the callback method on the gadget. Since a gadget may             have multiple subscriptions on the same topic, the subscribe             method returns an opaque identifier that is used to uniquely             identify the subscription. This identifier is used to unsubscribe             to the topic. It is gadget developer's responsibility to manage             this identifier.</t>             <t>Parameters:               <texttable align="left">                 <ttcol>Name</ttcol>                 <ttcol>Type</ttcol>                 <ttcol>Description</ttcol>                 <c>topic</c>                 <c>String</c>                 <c>A string that conforms to the rules defined above and by the OA Hub                 to name the channel that the payload will be deliverd on. Wildcards                 MAY be used.</c>                 <c>callback</c>                 <c>String</c>                 <c>A callback function to be executed when the tab is selected. The                 callback function will not be called until after the existing                 callstack has completed execution.</c>                 <c>scope</c>                 <c>object</c>                 <c>When onData callback or onComplete callback is invoked, the                 JavaScript "this" keyword refers to this scope object. If no scope is                 provided, default is window.</c>                 <c>onCompleteCallback</c>                 <c>function</c>                 <c>Function invoked to tell the client application whether the                 subscribe operation succeeded or failed.</c>                 <c>subscriberData</c>                 <c>*</c>                 <c>Client application provides this data, which is handed back to the                 client application in the subscriberData parameter of the onData                 callback function.</c>               </texttable>             </t>             <t>Returns:               <texttable align="left">                 <ttcol>Type</ttcol>                 <ttcol>Description</ttcol>                 <c>String</c>                 <c>An opaque subscription identifier. This identifier is an arbitrary                 ID string that is unique within this Hub instance</c>               </texttable>             </t>             <t>See the <eref target="http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Managed_Hub_APIs#OpenAjax.hub.Hub.prototype.subscribe">OpenAjax Hub documentation</eref> for             more information</t>           </section>           <section title="unsubscribe" anchor="unsubscribe">             <t>unsubscribe(subscriptionId)</t>             <t>Description: This method is used to remove a subuscription for a             gadget from the hub. The unsubscribe function immediately throws an             exception if there is no subscription with the specified subscription             ID. Otherwise, unsubscribe immediately deactivates the subscription.             </t>             <t>Parameters:               <texttable align="left">                 <ttcol>Name</ttcol>                 <ttcol>Type</ttcol>                 <ttcol>Description</ttcol>                 <c>subscriptionId</c>                 <c>String</c>                 <c>The subscriptionId is the opaque string that is returned from the                     subscribe(...) method.</c>               </texttable>             </t>             <t>See the <eref target="http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Managed_Hub_APIs#OpenAjax.hub.Hub.prototype.unsubscribe">OpenAjax Hub documentation</eref> for             more information.</t>           </section>         </section>         <section title="Other Methods" anchor="OtherMethods">           <t>The 'gadgets.Hub' object is an instance of IframeHubClient and supports some additional methods.           Please see the <eref target="http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Managed_Hub_APIs#OpenAjax.hub.IframeHubClient">OpenAjax Hub documentation</eref> for more information.</t>         </section>       </section>     </section>       <section title="Wiring Metadata">         <t>As illustrated by the previous example gadgets, the "pub/sub" feature        provides a means of allowing gadget developers to declaratively describe       the topics their gadget's support directly within the feature declaration       within the "ModulePrefs" element.</t>         <figure><preamble>For example:</preamble>       <artwork>   &lt;Module&gt;     &lt;ModulePrefs title="Sample PubSub Publisher" height="250"&gt;       &lt;Require feature="pubsub-2"&gt;         &lt;Param name="topics"&gt;           &lt;![CDATA[              &lt;Topic title="Random Number"                name="org.apache.shindig.random-number"               description="Publishes a random number."                type="number"               publish="true" /&gt;         ]]>&lt;/Param&gt;       &lt;/Require&gt;     &lt;/ModulePrefs&gt;     ...   &lt;/Module&gt;       </artwork></figure>         <t>When gadgets use the &lt;Topic&gt; element, containers are able       to "wire" gadgets together either automatically or via a user interface       that allows a user to connect gadgets that publish events to a given       topic to gadgets that subscribe to those events.</t>         <t>The &lt;Topic&gt; element has the following attributes:</t>       <texttable align="left">           <ttcol>Attribute</ttcol>           <ttcol>Type</ttcol>           <ttcol>Usage</ttcol>           <ttcol>Description</ttcol>           <c>name</c>           <c>String</c>           <c>Required</c>           <c>           The dot-delimited topic name, e.g. "org.example.randomNumber". This           name follows the rules defined in the <eref target="http://www.openajax.org/member/wiki/OpenAjax_Metadata_1.0_Specification_Widget_Metadata#topic_element_name_attribute">OpenAjax Widget Metadata           specification</eref>. Developers of gadgets MAY allow the @name attribute to be ovveridden using user preference variables. See <xref target="usingVariablesForNameAttribute">Using Varuables for @name</xref></c>             <c>type</c>           <c>String</c>           <c>Optional</c>           <c>Type name for the event's payload data. When not specificed, any           type wil be allowed. See <xref target="EventDataTypes">Event Data Types</xref>.</c>             <c>title</c>           <c>String</c>           <c>Optional</c>           <c>Title for this type of event that is appropriate for a non-technical reader. When not specified, the value of the "name" attribute will be used.</c>             <c>publish</c>           <c>boolean</c>           <c>Optional</c>           <c>Indicates if the gadget publishes events on this topic. The default value is "false".</c>             <c>subscribe</c>           <c>boolean</c>           <c>Optional</c>           <c>Indicates if the gadget subscribes to events that are published on this topic. The default value is "false".</c>             <c>description</c>           <c>String</c>           <c>Optional</c>           <c>           The textual description of the gadget's publish or subscribe           endpoint.           This can be used as an indication of the gadget's behavior.           Consider a gadget that subscribes to a topic "com.example.address".           The description migh read, "When this gadget receives an event on the com.example.address           topic, it displays mass transit options within 10km of the address received as the event payload."</c>             <c>aboutUrl</c>           <c>String</c>           <c>Optional</c>           <c>           A URL pointing to a resource that provides more extensive           descriptive information than can be provided in the description           attribute.</c>       </texttable>         <section title="Using Variables for @name" anchor="usingVariablesForNameAttribute">         <t>In the absence of a specific standard for events within a given         domain, it is inevitable that different groups of developers,         working in different niches on similar problems, will use different         topic naming schemes for what is essentially the same event. While         some developers in a domain may eventually consolidate around a         standard set of topic names, it's also inevitable that installed         bases, legacy implementations, politics, requirement to integrate         with third party gadgets from other domains, schedule constraints         and other factors will ensure that once a topic space becomes         balkanized, it will remain that way for a long time.</t>         <t>It is important that the specification offer a mechanism that allows         developers to bridge simple mismatches between gadgets. It is         important that gadget developers use this mechanism where possible.         This will maximize the reusability of gadgets -- a major goal.</t>           <figure><preamble>The following is an example showing the use of          variable substituion in the definition of the @name attribute.</preamble>         <artwork xml:space="preserve">   &lt;Require feature="pubsub-2"&gt;     &lt;Param name="topics"&gt;&lt;![CDATA[        &lt;Topic title="Selected Location" name="__UP_location__"              description="The currently selected location" type="http://nsgs.gov/geo#Place"              publish="false" subscribe="true" aboutUrl="http://nsgs.gov"&gt;       &lt;/Topic&gt;       &lt;!-- etc. for other topics --&gt;     ]]&gt;&lt;/Param&gt;   &lt;/Require&gt;          </artwork></figure>       </section>         <section title="Event Data Types" anchor="EventDataTypes">         <t>The OpenAjax Hub has a predefined set of identifiers that are used          to indicate the data type. Tooling and runtime container code can use          this to infer information about the messages being published         as well as the parameters a gadget expects to receive when it         subscribes to a topic.</t>         <t>The data types provided by the OpenAjax Hub are "built in". These         are referred to as the OpenAjax common types, and they require no         namespace qualifier. When a type other than an OpenAjax common type         is used, it MUST contain a namesake qualifier. The namespace should         conform to reverse DNS rules. The namespace org.opensocial.* MUST NOT be         used and is reserved for types defined by this specification,          e.g. social data types.</t>           <texttable align="left">           <ttcol>Type Name</ttcol>           <ttcol>Comments</ttcol>           <c>string</c>           <c>ECMAScipt string</c>           <c>number</c>           <c>ECMAScipt number </c>           <c>boolean</c>           <c>ECMAScipt boolean </c>           <c>array</c>           <c>ECMAScipt array, e.g. [ 1, 1, 2, 3, 5, 8 ]. The element type/s are not specified when the generic "array" type is used.</c>           <c>object *</c>           <c>ECMAScipt object, e.g. { foo: "bar", baz: "boo" }. The specifics of the object are not specified when the generic "object" type is used.</c>           <c>null *</c>           <c>ECMAScipt null</c>           <c>length *</c>           <c>Any CSS length value <span style="color:red"> Howard 2009.11.10: CSS version?</span></c>           <c>color *</c>           <c>Any CSS color value</c>           <c>id</c>           <c>ID value - probably not useful for OpenSocial Gadgets, but might as well keep the two specs in sync</c>           <c>class *</c>           <c>zero of more CSS class names, separated by spaces</c>           <c>style *</c>           <c>a string that could be used as value for a 'style' attribute</c>           <c>url</c>           <c>A URL <span style="color:red"> Howard 2009.11.09: Do we want "uri" also?</span></c>           <c>html</c>           <c>A fragment of HTML markup.</c>           <c>countrycode *</c>           <c>A string that represents an [http://www.iso.org/iso/country_codes/iso_3166_code_lists.htm A3 ISO 3166 country code].</c>           <c>languagecode *</c>           <c>A string that represents an [http://www.loc.gov/standards/iso639-2/php/code_list.php ISO 639-2 language code].</c>           <c>email</c>           <c>A string that represents an e-mail address.</c>           <c>person</c>           <c>A string that holds a person's name.</c>           <c>postalcode</c>           <c>A string that represents a postal code.</c>           <c>phone</c>           <c>A string that represents a phone number.</c>           <c>date *</c>           <c>A string that represents a date. MUST be expressed using the "Date Time String Format" defined in the [http://www.ecmascript.org/docs/tc39-2009-043.pdf ECMAScript5 specification] using one of the date-only forms. For example: "2009-12-15"</c>           <c>time *</c>           <c>A string that represents a time of day. MUST be expressed using the "Date Time String Format" defined in the [http://www.ecmascript.org/docs/tc39-2009-043.pdf ECMAScript5 specification] using one of the time-only forms. For example: "18:45:00Z" or "10:26:24-05:00"</c>           <c>timestamp *</c>           <c>A string that represents a date and time of day. MUST be expressed using the "Date Time String Format" defined in the [http://www.ecmascript.org/docs/tc39-2009-043.pdf ECMAScript5 specification]. For example: "2009-12-15:18:45.000Z"</c>           <c>duration *</c>           <c>A string that represents a duration. MUST have format "PYYYY-DDDThh:mm:ss.fff". For example, "P0400-152T20:45:33.123" means "400 years, 152 days, 20 hours, 45 minutes, 33.123 seconds, while "P0003-000T01:56:22.000" means "3 years, 1 hour, 56 minutes and 22.000 seconds." (Must use this one variant defined in the ISO 8601 standard). </c>           <c>*</c>           <c>Asterisk, or missing type attribute, means "any datatype"</c>         </texttable>       </section>     </section>   </section>