Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Org.eclipse.higgins.js.pds.client"

(getAttributes(agent, domain, audience, attributes, where, onReady))
(URI getConnectionTemplate(string domain))
Line 138: Line 138:
  
 
Return:
 
Return:
* http://<servername>/<pdsuser>/template/domain
+
* http://<servername>/sys/template/domain
  
 
===string getLocalAtt (URI attribute)===
 
===string getLocalAtt (URI attribute)===

Revision as of 18:52, 14 September 2011

{{#eclipseproject:technology.higgins|eclipse_custom_style.css}}

Files

Design Notes for API additions to this component

Objective

Create a general purpose API that JavaScript programs executed by HBX can use to get and set attributes about the user.

getAttributes(agent, domain, audience, attributes, where, onReady)

Enables a JavaScript app to request attributes (e.g user's email address, gender, etc.) about the user. It searches the person graph to find the requested attributes. If it finds multiple, ambiguous values for one or more attributes, it returns nothing (and the "where' parameter must be used to refine the query).

  • The goal of this rather high-level API is to shield the developer from the complexities of the multi-contextual, multi-person persona data model.
  • Depending on how the calling JavaScript is written, information about the user may remain local (i.e. within the browser and/or on the user's machine) or it may be transmitted to some external web service. The identity of the calling application and the identity of the "domain" are parameters to this call.
  • FUTURE: By setting the value of the authorities = the JavaScript developer's domain (i.e. the "issuer" id of the context associated with this JavaScript) it will only read attributes from this context.
  • FUTURE: If the attribute release is not part of (i) an explicit pre-existing connection/relationship with the domain or (ii) an implicit relationship (e.g. form filling when the user is viewing the page) then a UI should be implemented informing the user as to the identity of the agent, the identity of domain (the "next hop" destination if any) and the set of requested (required/optional) attributes and allowing them to give consent to this attribute disclosure.

Parameters:

agent
String identifier of the software agent (e.g. JavaScript program) that is getting the attributes and forwarding them to the domain
domain
String identifier of ultimate attribute data consumer as far as this is known.
audience
FUTURE (ignored for now) - String. Must match either the agent or the domain parameter value or be nil. If not nil, then indicates whether to encrypt tokens for the agent or the domain.
attributes
Set of (attribute, optional, authorities) tuples where: attribute is a URI indicating the attribute type; the attribute may have one or more role params attached (e.g. ?r=Buyer); optional is a boolean (if true then this attribute is desired but not required). authorities will be used in the future; it must be nil for now. it is a list of domains that are considered by the caller as authoritative WRT this attribute and thus must be used as the source of the attribute, if this list is nil then self asserted values are acceptable. The value of a member of authorities is matched against the issuer of the containing context of the entity.
where 
A set of (attribute, value-expression) tuples where: attribute is the attribute URI of the form <namespace>#localAtt and namespace is the URL of a page (or a set of pages with a consistent schema). if the entire site uses the same schema then the site domain will suffice;value-expression (for now) may be an exact value (e.g. "Alice") or may be a regex that the value must match. In the short term the so-called "regex" is just a string of one or more characters followed by an asterisk (e.g. 2*, or 25*)--meaning that the value of the attribute must start with these characters (e.g. values "290" and "250" will match "2*" and "250" (only) will match "25*")
tokenTypes
A list of token types that are understood by RP. At present this must be a JSon document
onReady
Represents name of a JS event listener. If the value of 'onready' is an empty string, then it executes an synchronous query, otherwise it does an asynchronous query. The result will be passed as a parameter to the function onReady

Returns:

  • A set of zero or more tokens (JSON documents at present). Each token encodes multiple (attribute, value(s)) tuples where:
    • Attribute is the attribute URI (note: this will be one of the attribute URIs passed in to this method)
    • Value(s) are the value(s) of the attribute (may be nil, if no values could be found). Each value may be literal or object typed.

Implementation

We start with an empty list called rt of (attribute, value, ambiguous) tuples where attribute is the long (URI) form of the attribute; value is the value of the attribute or nil; ambiguous is a boolean that indicates that there were multiple alternative values found (and thus a nil value is returned).

(1) We try to pull values within the context of context

  • context := getConnectionContext(domain) // e.g. http://azigo.com/ptrevithick/staples.com
  • person := context concatenated with "#me" // e.g. http://azigo.com/ptrevithick/staples.com#me
  • If context exists and person has at least one attribute then
    • template := getTemplate(context); // e.g. http://azigo.com/ptrevithick/template/staples.com
    • Loop: For every triple t in attributes[]:
      • If (t.authority is not nil) then continue looping // t.authority is always nil at present
      • att := getLocalAtt(t.attribute) // e.g. "bFirstName"
      • role[] := getRole(t.attribute) // e.g. "Buyer"
      • class := getNamespace(t.attribute) // e.g. http://staples.com/Office-supplies-StaplesCheckoutFlow
      • rule := getRule(template, class, att)
      • person := context + "#me"
      • value := pullEvalRule(rule, person, role[]) // pull within the scope of person
      • If value is not nil then
        • Insert new tuple (t.attribute, value, false) into rt
        • Remove tuple t from the list
      • EndIf
    • End Loop

(2) We now pull (read) values without any context-scope restriction. We are careful that we pull logically self-consistent manner. That is, we do not pull inter-related attributes from different entities (e.g. person nodes). For example we would never pull a vcard:street from a v:adr object and the vcard:postal-code from another v:adr object.

  • person := rootPerson // root node in root context
  • Loop: For every person p reachable (traversing through Proxy objects as needed) from h:correlation links from root
    • context := get containing context of p
    • Loop: For every tuple t in attributes[]
      • att := t.attribute
      • If rt has a tuple whose value is (att, <don't care>, true) then continue looping // we already found too many values for this attribute on some person, so there is no point finding yet more values
      • authority := t.authority
      • If authority doesn't match context.issuer then break out of this loop and the outer loop
      • rule := getRule(att)
      • value := pullEvalRule(rule, person, role[])
      • If value is not nil then
        • If rt contains a tuple whose attribute matches t.attribute and that has a non-nil value then
          • Replace the value of value in that tuple with nil
          • Set the value of ambiguous in that tuple to true
        • Else
          • Add a new tuple (t.attribute, value, false) to rt
        • EndIf
      • EndIf
    • EndLoop
  • EndLoop

(3) Convert rt into JSON and return

getSuggestions(attribute, onready)

This method is only needed for interactive form filling use cases.

Note: For privacy reasons this method may only be called by highly trusted JavaScript.

Parameters:

attribute
attribute URI of the form <namespace>#<localAtt>
onready
represents event listener (name of the JS function). if value of 'onready' is empty string, BX does a synchronous request, otherwise BX does an asynchronous request, the result will be passed like parameter to function 'onready'.


JS Example of asynchronous request:

 function onSuggestions(res){
 	//...
 };
 //...
 bx.getSuggestions(attribute, 'onSuggestions');

JS Example of synchronous request:

 res = bx.getSuggestions(attribute, );

setAttribute(agent, domain, attributes[])

Takes a set of attribute/value pairs. Some of these pairs are used to update existing attributes within the connection-specific context. Update means replacing the existing values of the same attribute (if they exist) or adding them if they do not. All other attributes/values are unaffected. Other pairs are used to add new person attributes (and even add new contexts to hold them) external to the connection-specific context. In the add case existing attribute values are not deleted. Whether we update or add depends on what's found when we lookup the mapping rule for the attribute within the pair. Mapping rules may or may not have non-nil roles (e.g. Buyer, Recipient, etc.). If the attribute's mapping rule has role=nil then

Parameters:

agent
ignored
domain
domain of the party providing the attribute value
attributes
And array of (attribute,value) pairs. The attribute is a URI of the form <namespace>#<localAtt>. For scraping <namespace> is the URL of the page being scraped (with query parameters removed). The value is a literal or object value.

Implementation:

(1) Phase I

(2) Phase II

  • Compare newPeople to existing people and see if they are redundant. If so remove them and any dangling h:correlation link to them.

Private Functions

URI getConnectionContext(string domain)

Return:

  • http://<servername>/<pdsuser>/domain

URI getConnectionTemplate(string domain)

Return:

  • http://<servername>/sys/template/domain

string getLocalAtt (URI attribute)

Return everything to the right of the #. (e.g. if the input was http://staples.com/office/supplies/StaplescheckoutFlow#bFirstName then return "bFirstName").

URI getNamespace (URI attribute)

Return all but the # and beyond. (e.g. if the input was http://staples.com/office/supplies/StaplescheckoutFlow#bFirstName then return http://staples.com/office/supplies/StaplescheckoutFlow).

string getRule(URI template, URI class, string localAtt)

Find a matching mapping rule in the class entity class within this template. Look through all the values of spin:rule attribute (or sub-attribute, e.g. map:nameRule) of the entity class such that the attribute map:predicate matches localAtt (e.g. bFirstName). For example here is a match:

     map:nameRule
             [ rdf:type map:rolePathLiteral ;
               map:mappedAtt <http://www.w3.org/2006/vcard/ns#given-name> ;
               map:path <http://www.w3.org/2006/vcard/ns#n> ;
               map:predicate :bFirstName ;
               map:role p:Buyer
             ] ;

The above rule includes the optional role attribute.

URI getTemplate (URI context)

Returns value of template attribute of context

pullEvalRule (string rule, URI person, role[])

We evaluate the rule in "pull" mode (we're pulling values from the PDS) and from person person. Within the rule string there is the name of the rule to fire, and a set of parameter/values and there may be additional role values. We call dispatch functions by name.

  • mappingRule := getRuleName(rule) // e.g. "rolePathLiteral"
  • If mappingRule == "rolePathLiteral" then
    • value := pullRolePathLiteral(rule, person, role[])
    • return value
  • If (mappingRule == ... ) then ...

pullRolePathLiteral(rule, person, role[])

Pull value within scope of person (or if role!=nil) from another person node linked from person.

  • r[] := getRoleParam(rule) plus values (if any) from role[] // merge role array from role in rule + role[] param
  • path := getPathParam(rule)
  • mappedAtt := getMappedAtt(rule)
  • If role is not nil then
    • If person has all role(s) r[] then p := person // person must match all roles
    • Else
      • p := find person linked via h:correlation from person of role(s) == r[]
      • if p == nil then return nil
    • EndIf
  • p := person
  • EndIf
  • EndIf
  • obj := value of path attribute of entity
  • If obj is nil Return nil
  • Return the value ofmappedAtt attribute of obj

URI pushEvalRule (string rule, URI context, value)

We evaluate the rule in "push" mode (we're pushing values in to the PDS). Within the rule string there is the name of the rule to fire, and a set of parameter/values. We call dispatch functions by name.

  • mappingRule := getRuleName(rule) // e.g. "rolePathLiteral"
  • If (mappingRule == "rolePathLiteral") Then
    • newPerson := pushRolePathLiteral(context, rule, value)
    • return newPerson
  • EndIf
  • If (mappingRule == ... ) Then ...

URI pushRolePathLiteral(URI context, string rule, value)

Push value into PDS.

  • role := getRoleParam(rule)
  • path := getPathParam(rule)
  • mappedAtt := getMappedAtt(rule)
  • If role == nil then
    • If path exists from :me
      • Then follow it
      • Else build it
    • Replace the value of mappedAtt with new value
  • Else
    • Find a person from :me one hop out along h:correlation links who has role value of role
    • If it isn't there then build a new context and create it (and remember to return it)
    • If it is there then walk path/mappedAtt
  • EndIf

Back to the top