Projects‎ > ‎

Attribute Function

Overview

The Attribute within a Definition needs to be redesigned to address a number of issues:

  • Define how an Attribute argument required (true/false) relates to a given Function, and it's assigned Operation(s). Example: uniqueId is required for CREATE, READ, UPDATE, DELETE, PWDCHANGE, PWDRESET (not SEARCH)
  • Determine if "mode" is applicable anymore. Based on the Operation(s) a Function has specified.
  • If a Consumer Tier application requests an Attribute that is not defined in the Definition, an Attribute will be return with NO value and will have a State indicating NOTDEFINED in the Subject.
  • If a Consumer Tier application requests an Attribute that is defined in the Definition but does not exist in the Service, an Attribute will be returned with NO value and will have a State indicating NOTEXIST in the Service.

Function processing

The step for determining whether a Function is execute are:

  1. What is the Operation
  2. Is the Attribute required or not
  3. Did the Input contain the Attribute
  4. Does the Attribute have a value (non-null)
  5. Does the Function have usexisting set to true

Processing does not depend on the "mode"

CREATE

required=true Input has Attribute Attribute has value Length > 0 useexisting=true Run it
+ + + + +  
+ + + +   YES
+ + +
+ YES
+ + +     YES
+ +
x + YES
+ +
x
YES
+ +

+ YES
+ +       YES
+   x x + YES
+   x x   YES
+   x   + YES
+   x     YES
+     x + YES
+     x   YES
+       + YES
+         YES
required=true Input has Attribute Attribute has value Length > 0 useexisting=true Run it
  + + + +

+ + +   YES
  + +
+ YES
  + +     YES
  +   x +  
  +   x   YES
  +     +  
  +       YES
    x x +  
    x x    
    x   +  
    x      
      x +  
      x    
        +  
           

x = not a valid state

UPDATE

The UPDATE Operation does not use the concept of a required Attribute

required=true Input has Attribute Attribute has value Length > 0 useexisting=true Run it
  + + + +

+ + +   YES
  + +
+  
  + +     YES
  +   x + YES
  +   x   YES
  +     + YES
  +       YES
    x x +  
    x x    
    x   +  
    x      
      + +  
      +    
        +  
           

x = not a valid state

READ and SEARCH

For READ and SEARCH, the only factor is if the Input contains the Attribute.

required=true Input has Attribute Attribute has value Length > 0 useexisting=true Run it
  + + + + YES
  + + +   YES
  + +
+ YES
  + +     YES
  +   x + YES
  +   x   YES
  +

+ YES
  +       YES
    x x +  
    x x    
    x   +  
    x      
        +  
      + +  
           

x = not a valid state


Assumptions

  1. An Attribute will the required/optional XML Element Arguments as defined in the Reference Guide
  2. An Attribute can be be scoped to a specific Operation by adding it to an AttrGroup
    <AttrGroups>
       <AttrGroup id="person-search">
          <Attributes>
             <Attribute id="firstname"/>
             <Attribute id="lastname"/>
             <Attribute id="email"/>
             <Attribute id="fullname"/>
             <Attribute id="title"/>
          </Attributes>
       </AttrGroup>
       ...
    </AttrGrups>
    
  3. A Function,Operation will have no Properties unless they are explicitly set or they are inherited
    <Attribute id="foo">
       <Functions>
          <Function id="run" mode="toService" classname="...">
             <Properties> 
                <Property name="bar" value="xyz"/>
              </Properties>
             <Operations>
                <Operation type="create">
                   <Properties> 
                      <Property name="bar" value="123"/>
                   </Properties>
                </Operation>
             </Operations>
          </Function>
       </Functions>
    </Attribute>
    
  4. An Attribute, can have one or more Functions. All Functions are executed serially in-order. There is no dependency between Functions. Functions will only be applied to the the specified Operations
  5. If Function can apply to more then one Operation ... use multiple Operation elements
    <Attribute id="fullname">
       <Properties>
          <Property name="useexisting" value="true"/>
       </Properties>
       <Functions>
          <Function id="InConcat" classname="org.openptk.provision.definition.functions.ConcatStrings">
             <Arguments>
                <Argument name="arg1" type="attribute" value="firstname"/>
                <Argument name="arg2" type="literal"   value=" "/>
                <Argument name="arg3" type="attribute" value="lastname"/>
             </Arguments>
             <Operations>
                <Operation type="create">
                <Operation type="update">
             </Operations>
          </Function>
          <Function id="OutConcat" classname="org.openptk.provision.definition.functions.ConcatStrings">
             <Arguments>
                <Argument name="arg1" type="attribute" value="firstname"/>
                <Argument name="arg2" type="literal"   value=" "/>
                <Argument name="arg3" type="attribute" value="lastname"/>
             </Arguments>
             </Operations>
                <Operation type="read">
                <Operation type="search">
             </Operations>
          <Function>
       </Functions>
    </Attribute>
    

If the Function is placed/used in a given Operation, can the "mode" for that Function always be derived (if needed) based on the Operation.

Operation Mode
CREATE toService
READ toFramework
UPDATE toService
SEARCH toFramework

The other Operations do not apply: DELETE, PWDCHANGE, PWDRESET (they don't have a mode)


Use Case: uniqueId

Criteria:

  1. The uniqueId is used to identify specific record. It's is required for CREATE, READ, UPDATE, DELETE and the password operations PWDCHANGE and PWDRESET.
  2. For CREATE a Function is used to create the value, only when there is NO existing value provided in the Input. This Function applies to CREATE Operations with a mode that is "toService"

Release 1.x Design: uniqueid

<Attribute id="uniqueid" required="true">
   <Functions>
      <Function id="FirstInitialLastName" mode="toService" classname="org.openptk.provision.definition.functions.FirstInitialLastname">
         <Properties>
            <Property name="useexisting" value="true"/>
         </Properties>
         <Arguments>
            <Argument name="first"     type="attribute" value="firstname"/>
            <Argument name="last"      type="attribute" value="lastname"/>
            <Argument name="maxlength" type="literal"   value="8"/>
         </Arguments>
         <Operations>
            <Operation type="create"/>
         </Operations>
      </Function>
   </Functions>
</Attribute>

Scenario A: uniqueId

Determine, under which conditions, whether to "run" the Function or not.

  • The attribute "uniqueid" is an actual attribute in the back-end repository
  • It is required
  • This value can not be changed (no UPDATE operation)
Operation
(toService)
Input has
Attribute
Attribute
has Value
Run
Function
Behavior
CREATE + +   pass value through
  +
+ create the value
      + create the value (it is required)
<Attribute id="uniqueid" required="true">
   <Functions>
      <Function id="FirstInitialLastName" classname="org.openptk.provision.definition.functions.FirstInitialLastname">
         <Properties>
            <Property name="useexisting" value="true"/>
         </Properties>
         <Arguments>
            <Argument name="first"     type="attribute" value="firstname"/>
            <Argument name="last"      type="attribute" value="lastname"/>
            <Argument name="maxlength" type="literal"   value="8"/>
         </Arguments>
         <Operations>
            <Operation type="create"/>
         </Operations>
      </Function>
   </Functions>
</Attribute>

In the above example the Attribute XML Element argument required is set to true.

Scenario B: uniqueId

We need to leverage a Function or validation:

  • The attribute "uniqueid" is an actual attribute in the back-end repository
  • It is required
  • This value can not be changed (no UPDATE operation)
  • The value must be checked (via a Function) to make sure it is unique
Operation
(toService)
Input has
Attribute
Attribute
has Value
Run
Function
Behavior
CREATE + + + pass value through (first Function), run second
  +
+ create the value
      + create the value (it is required)
<Attribute id="uniqueid" required="true">
   <Functions>
      <Function id="FirstInitialLastName" classname="org.openptk.provision.definition.functions.FirstInitialLastname">
         <Properties>
            <Property name="useexisting" value="true"/>
         </Properties>
         <Arguments>
            <Argument name="first"     type="attribute" value="firstname"/>
            <Argument name="last"      type="attribute" value="lastname"/>
            <Argument name="maxlength" type="literal"   value="8"/>
         </Arguments>
         <Operations>
            <Operation type="create"/>
         </Operations>
      </Function>
      <Function id="CheckUniqueId" classname="org.openptk.provision.definition.functions.CheckUniqueId">
         <Arguments>
            <Argument name="uid" type="attribute" value="uniqueid"/>
         </Arguments>
         <Operations>
            <Operation type="create"/>
         </Operations>
      </Function>
   </Functions>
</Attribute>

In the above example the Attribute XML Element argument required is set to true. The second Function is always executed, it does not have the Property useexisting set to true.


Use Case: fullname

Criteria:

  1. This attribute is typically a value that contains the "firstname", "space", "lastname".
  2. The value could be explicitly provided as part of the Input. Or, it maybe derived using a Function that concatenates other attributes.
  3. Property useexisting:
    • true
      1. CREATE and UPDATE: the Function will NOT be executed if the Input contains the Attribute with a value
      2. READ and SEARCH: the Function will NOT be executed if the Result contains the Attribute (with or without a value)
    • false
      1. CREATE and UPDATE: the Function will ALWAYS be executed even if the Input contains the Attribute with a value
      2. READ and SEARCH: the Function will ALWAYS be executed even if the Result contains the Attribute (with or without a value)
  4. The value may or may not be actually stored in the back-end repository.
  5. If the value is NOT stored, then a Request (READ/SEARCH) for the attribute will need to "fetch" dependent Attributes and derive the value before returning to the Consumer Tier.

Release 1.x Design: fullname

<Attribute id="fullname" required="true">
   <Functions>
      <Function id="InConcat" mode="toService" classname="org.openptk.provision.definition.functions.ConcatStrings">
         <Properties>
            <Property name="useexisting" value="true"/>
         </Properties>
         <Arguments>
            <Argument name="arg1" type="attribute" value="firstname"/>
            <Argument name="arg2" type="literal"   value=" "/>
            <Argument name="arg3" type="attribute" value="lastname"/>
         </Arguments>
         <Operations>
            <Operation type="create"/>
            <Operation type="update"/>
         </Operations>
      </Function>
      <Function id="OutConcat" mode="toFramework" classname="org.openptk.provision.definition.functions.ConcatStrings">
         <Properties>
            <Property name="useexisting" value="true"/>
         </Properties>
         <Arguments>
            <Argument name="arg1" type="attribute" value="firstname"/>
            <Argument name="arg2" type="literal"   value=" "/>
            <Argument name="arg3" type="attribute" value="lastname"/>
         </Arguments>
         <Operations>
            <Operation type="read"/>
            <Operation type="search"/>
         </Operations>
      <Function>
   </Functions>
</Attribute>

Scenario A: fullname

  • The attribute "fullname" is an actual attribute in the back-end repository
  • It is NOT required
  • useexisting is true
  • For READ and SEARCH it is assumed that the Attribute is explicitly request (via the Input)
Operation
(toService)
Input has
Attribute
Attribute
has Value
Run
Function
Behavior
CREATE + +   pass value through
  +
+ create the value
        do nothing (not required)
UPDATE + +   pass value through
  +
+ create the value
        do nothing (not required)
Operation
(toFramework)
Result has
Attribute
Attribute
has Value
Run
Function
Behavior
READ + +   return actual value ... useexisting=true
  +     return actual value (will be empty) ... useexisting=true
      + create the value (see note 1)
SEARCH + +   return actual value ... useexisting=true
  +     return actual value (will be empty) ... useexisting=true
      + create the value (see note 1)

Notes:

  1. If the dependent Attributes (firstname and lastname) are NOT part of the Input/Request, the System will automatically "include" them in the Request before it is sent to the Service and then "remove" them before the Response is sent to the User
<Attribute id="fullname" required="true">
   <Functions>
      <Function id="InConcat" classname="org.openptk.provision.definition.functions.ConcatStrings">
         <Properties>
            <Property name="useexisting" value="true"/>
         </Properties>
         <Arguments>
            <Argument name="arg1" type="attribute" value="firstname"/>
            <Argument name="arg2" type="literal"   value=" "/>
            <Argument name="arg3" type="attribute" value="lastname"/>
         </Arguments>
         <Operations>
            <Operation type="create"/>
            <Operation type="update"/>
         </Operations>
      </Function>
      <Function id="OutConcat" classname="org.openptk.provision.definition.functions.ConcatStrings">
         <Properties>
            <Property name="useexisting" value="true"/>
         </Properties>
         <Arguments>
            <Argument name="arg1" type="attribute" value="firstname"/>
            <Argument name="arg2" type="literal"   value=" "/>
            <Argument name="arg3" type="attribute" value="lastname"/>
         </Arguments>
         <Operations>
            <Operation type="read"/>
            <Operation type="search"/>
         </Operations>
      <Function>
   </Functions>
</Attribute>

Use Case: lastcommafirst

Criteria:

  1. This attribute is a combination of the lastname a comma, a space, and the firstname
  2. It is NOT stored in the back-end repository
  3. It is primarily used by the SEARCH Operation and available to READ
  4. It needs to be created on-demand
  5. This really only applies to a mode of toFramework
  6. It has a dependency on the lastname and firstname attributes. These attributes may have to be inserted by the System (into the Request) and then removed (from the Response) if they are not also included with the Consumer Tier Input

Release 1.x Design: lastcommafirst

Note: This Attribute was not fully implemented / deployed

<Attribute id="lastcommafirst">
   <Functions>
      <Function id="OutputLastFirst" mode="toFramework" classname="org.openptk.provision.definition.functions.ConcatStrings">
         <Arguments>
            <Argument name="arg1" type="attribute" value="lastname"/>
            <Argument name="arg2" type="literal"   value=", "/>
            <Argument name="arg3" type="attribute" value="firstname"/>
         </Arguments>
         <Operations>
            <Operation type="read"/>
            <Operation type="search"/>
         </Operations>
      </Function>
   </Functions>
</Attribute>

Scenario A: lastcommafirst

  • The attribute "lastcommafirst" is not a real attribute in the back-end repository
  • Consider this a READ-ONLY attribute
Operation
(toFramework)
Result has
Attribute
Attribute
has Value
Run
Function
Behavior
READ     + create value (see note 1)
SEARCH     + create value (see note 1)

Notes:

  1. If the dependent Attributes (firstname and lastname) are NOT part of the Input/Request, the System will automatically "include" them in the Request before it is sent to the Service and then "remove" them before the Response is sent to the User
<Attribute id="lastcommafirst">
   <Functions>
      <Function id="OutputLastFirst" classname="org.openptk.provision.definition.functions.ConcatStrings">
         <Arguments>
            <Argument name="arg1" type="attribute" value="lastname"/>
            <Argument name="arg2" type="literal"   value=", "/>
            <Argument name="arg3" type="attribute" value="firstname"/>
         </Arguments>
         <Operations>
            <Operation type="read"/>
            <Operation type="search"/>
         </Operations>
      </Function>
   </Functions>
</Attribute>

Use Case: forgottenPasswordAnswers

Release 1.x Design: forgottenPasswordAnswers

<Attribute id="forgottenPasswordAnswers" access="private" multivalued="true">
   <Functions>
      <Function id="Modify" mode="toService" classname="org.openptk.provision.definition.functions.ModifyAttributes">
         <Operations>
            <Operation type="read"/>
         </Operations>
         <Arguments>
            <Argument name="include" type="literal" value="forgottenPasswordData"/>
         </Arguments>
      </Function>
      <Function id="ForgottenPwd" mode="toFramework" classname="org.openptk.provision.definition.functions.ForgottenPassword">
         <Arguments>
            <Argument name="source"         type="literal" value="forgottenPasswordData"/>
            <Argument name="type"           type="literal" value="answers"/>
            <Argument name="innerdelimiter" type="literal" value="|"/>
            <Argument name="outerdelimiter" type="literal" value="^"/>
         </Arguments>
         <Operations>
            <Operation type="read"/>
         </Operations>
      </Function>
   </Functions>
</Attribute>

Scenario A: forgottenPasswordAnswers

For the READ Operation a Function needs to run for both toService and toFramework:

  • toService Function
    1. Generate the new "data" Attribute and add it to the Request
    2. Remove the original (this) Attribute from the Request
  • toFramework Function
    1. Generate the new "answers" Attribute and add it to the Response
    2. Remove the "data" Attribute from the Response
Operation
(toService)
Input has
Attribute
Attribute
has Value
Run
Function
Behavior
READ +
+ include / remove Attributes
UPDATE + + + create the value(s)
  +   x error, must have value(s)
Operation
(toFramework)
Result has
Attribute
Attribute
has Value
Run
Function
Behavior
READ     + create value (see note 1)

Notes:

  1. If the dependent Attribute (forgottenPasswordData) is NOT part of the Input/Request, the System will automatically "include" it in the Request before it is sent to the Service and then "remove" it before the Response is sent to the User
<Attribute id="forgottenPasswordAnswers" access="private" multivalued="true">
   <Functions>
      <Function id="Modify" classname="org.openptk.provision.definition.functions.ModifyAttributes">
         <Arguments>
            <Argument name="include" type="literal" value="forgottenPasswordData"/>
         </Arguments>
         <Operations>
            <Operation type="read"/>
         </Operations>
      </Function>
      <Function id="ForgottenPwd" classname="org.openptk.provision.definition.functions.ForgottenPassword">
         <Arguments>
            <Argument name="source"         type="literal" value="forgottenPasswordData"/>
            <Argument name="type"           type="literal" value="answers"/>
            <Argument name="innerdelimiter" type="literal" value="|"/>
            <Argument name="outerdelimiter" type="literal" value="^"/>
         </Arguments>
         <Operations>
            <Operation type="read"/>
         </Operations>
      </Function>
   </Functions>
</Attribute>