Rendering Pipeline

When a message containing complex structured objects is received the Symphony UI will need to make routing decisions about which APP, if any, should be presented the object to render.

Rather than expecting the message originator to mark the complex object with enough meta-data to allow every user to distribute messages in whatever way they may choose, one or more enrichment Apps may be configured by the receiver to add necessary meta data to perform the desired routing.

At UI start time all installed Apps will register their interest in and capability to, enrich and / or render complex entities. For each entity type they register they will provide the latest version of that type which they understand. They are required to be capable of handling that and all prior defined versions of the given entity type. When a message containing a complex entity is received the system will establish the list of candidate Apps which could process the entity. The version number of the received entity is formed of a major/minor version number and since changes in minor version are specified to be backwards compatible any app which has registered a major version number greater than or equal to the major version of the received entity will be considered eligible to process it.

User Preferences

Preferences regarding which App should be selected in the event that more than one is eligible to render an entity or the order in which enrichment Apps should be called if there are multiple eligible enrichers, can be specified by the end user or by the pod administrator. A global default order will be asserted where necessary to ensure consistent and repeatable behavior. The user's own preferences take precedence over the pod defined defaults which take precedence over any Symphony defined global defaults.

Preferences can be specified in two ways, firstly the user or the pod administrator can drag and drop the installed Apps in the App Store View in order to place them in a desired order. Apps nearer the top of this list will be selected in preference to Apps nearer the bottom of the list.

Secondly the user or pod administrator can define expressions to select specific Apps for particular received entities based on the values of attributes defined in the received entity. This is intended to be an 80/20 solution in that we envisage that in 80% of cases the desired result should be achievable simply by dragging and dropping Apps into the desired order, and only in the 20% of cases with the most complex requirements would it be necessary to write election expressions.

For example the following Entity could be received:

<entity type="org.symphonyoss.fin.price" version="0.1"/>
    <entity type="org.symphonyoss.fin.security" version="0.1"/>
        <attribute name="id" type="org.symphonyoss.fin.security.id.isin" priority=0 value="US0378331005"/>
        <presentationML>Apple</presentationML>
    </entity>
    <entity type="org.symphonyoss.fin.venue" version="0.1"/>
        <attribute name="id" type="org.symphonyoss.fin.venue.id.mic" priority=0 value="45"/>
        <presentationML>The New York Stock Exchange (NYSE)</presentationML>
    </entity>
    <entity type="org.symphonyoss.time.moment" version="0.1"/>
        <attribute name="at" type="org.symphonyoss.time.millis" value=1463758200000/>
        <presentationML>Friday, May 20, 2016 3:30:00 PM UTC</presentationML>
    </entity>
    <presentationML>Apple common stock on NYSE at 2016-05-20 15:30 Z $95.27</presentationML>
</entity>

The expressions to select enriching Apps might look like this:

if (org.symphonyoss.fin.venue/org.symphonyoss.fin.venue.id.mic == "45")
	enrich "App1", "App2"
else if (type == "org.symphonyoss.fin.price")
	enrich "App1"
else
	enrich "App3"


This means that entities which contain a venue with the mic code 45 will be enriched by App1 followed by App2, other price objects will be enriched only by App1 and all other entities will be enriched by App3.

After enrichment by the two Apps the entity has been expanded to:


<entity type="org.symphonyoss.fin.price" version="0.1"/>
    <entity type="org.symphonyoss.fin.security" version="0.1"/>
        <attribute name="id" type="org.symphonyoss.fin.security.id.isin" priority=0 value="US0378331005"/>
    	<attribute name="id" type="org.symphonyoss.fin.security.id.cusip" enrichment="1" value="037833100"/>
    	<attribute name="id" type="org.symphonyoss.fin.security.id.openfigi" enrichment="2" value="BBG000B9XRY4"/>
		<attribute type="org.symphonyoss.type.country"  enrichment="1" value="US"/>
		<attribute type="com.example.fin.tier" enrichment="2" value="BlueChip"/>
		<attribute type="com.example.fin.sector" enrichment="2" value="Tech"/>
		<presentationML>Apple</presentationML>
        <presentationML enrichment="1">Apple common stock</presentationML>
		<presentationML enrichment="2"><b>Apple</b> common stock, traded on NYSE</presentationML>
    </entity>
    <entity type="org.symphonyoss.fin.venue" version="0.1"/>
        <attribute name="id" type="org.symphonyoss.fin.venue.id.mic" priority=0 value="45"/>
        <presentationML>The New York Stock Exchange (NYSE)</presentationML>
    </entity>
    <entity type="org.symphonyoss.time.moment" version="0.1"/>
        <attribute name="at" type="org.symphonyoss.time.millis" value=1463758200000/>
        <presentationML>Friday, May 20, 2016 3:30:00 PM UTC</presentationML>
    </entity>
    <presentationML>Apple common stock on NYSE at 2016-05-20 15:30 Z $95.27</presentationML>
</entity>


The expressions to select rendering Apps might look like this:

if (type == "org.symphonyoss.fin.price" && (org.symphonyoss.type.country == "US" || com.example.fin.sector == "Tech"))
	render "App1"
else if (type == "org.symphonyoss.fin.price")
	render "App1"
else
	render "App3"


This syntax allows expressions to be evaluated based upon the value of attributes as follows (in BNF):

expression 	= name "==" value				; exact match to a quoted string
			/ name "!=" value				; not exact match
			/ name "~=" regex				; regex match, specifics of regex syntax TBD
			/ name ">" number				; numerical greater than, false if the value of name is not a number, value need not be quoted
			/ name ">=" number				; numerical greater than or equal, false if the value of name is not a number, value need not be quoted
			/ name "<" number				; numerical less than, false if the value of name is not a number, value need not be quoted
			/ name "<=" number				; numerical less than or equal, false if the value of name is not a number, value need not be quoted
			/ "(" expression ")"			; for precedence 
			/ expression "&&" expression	; logical AND
			/ expression "||" expression	; logical OR
 
applist		= appname
			/ applist "," appname
 
statement 	= "render" appname
			/ "enrich" applist
			/ "if" "(" expression ")" statement [ "else" statement ]

Final Rendering Stage

Once the routing is complete the object will be forwarded to an app to be rendered. The rendering app will be expected to be capable of providing

  1. A compact, in-line representation of the entity in PresentationML
  2. A fixed size hover card representation in HTML5
  3. An expanded representation to be rendered in line in HTML5

The default representation when a message is first displayed will be either the compact or expanded view depending on configuration preferences set at the pod level and by the user. As with everything else in this document, the user remains in ultimate control.


Need help? Email help@finos.org we'll get back to you.

Content on this page is licensed under the CC BY 4.0 license.
Code on this page is licensed under the Apache 2.0 license.