Upload
coral-lyons
View
214
Download
0
Tags:
Embed Size (px)
Citation preview
FF 11: Hooks
A presentation by Robin Upton (2009-05-09)Latest version at www.altruists.org/ff11
Attribution – NonCommercial - ShareAlikewww.altruists.org
V1.0.1
http://www.altruists.org/ff11
Recommended Pre-requisite: FF10: Access Control
What is a Hook?
This presentation describes Hooks, which are XSLT-based transforms designed for extensibility and the semantic web.
Hooks have XML definitions such as the below:
Hooks are implemented by a set of handlers:
This defines the global handle used to refer to this hook:
Handlers link a namespace to a stylesheet.
<handler namespace="*" src="core/hooks/activate.xslt"/>
<handler namespace="http://friend2friend.net/" src="core/hooks/activate.xslt"/>
<hook rdf:about="http://friend2friend.net/hooks/activate">
</hook>
Hook declarations need a ‘wildcard’ handler, with namespace= “*”.
Processing Hooks
Like services, hooks are explicitly requested by URI:
<hookreq function=”some-uri”>
The first step is to retrieve the compiled list of all handlers for this hook.
Unlike services, they must contain XML elements.
<demo:example> ... </demo:example>
<demo:etc>... some XML ...</demo:etc>
<data xmlns=””/>
<xxx:data/>
<xyz:haddock/>
</hookreq>
Choosing A Handler
The child nodes of the hook request are processed by namespace.
<hookreq function=”some-uri”>
<demo:example> ... </demo:example>
<demo:etc>... some XML ...</demo:etc>
<data xmlns=””/>
<xxx:data/>
<xyz:haddock/>
</hookreq>
All handlers apply only to data of one particular namespace...
except for the wildcard handler, which catches all unspecified namespaces.
<handler namespace=””
...>
<handler namespace=”*”
...>
<handler namespace= ”..demo..”
...>
Applying Handlers
Handlers are just XSL Templates, applied to the data item they matched:
<hookreq function=”some-uri”>
<demo:example/>
<demo:etc/>
<data xmlns=””/>
<xxx:data/>
<xyz:haddock/>
</hookreq>
<handler namespace="demo"/>
<handler namespace =""/>
Handler templates
<handler namespace ="*"/>
Theoutputof the
separateXSL
transformsis
serialised.
hookreq
output
F2F clients apply this hook to the semantic (XML) data...
http://friend2friend.net/hooks/render
XML items that users may see should define a handler for this hook.For example, <f2f:fatal-error>:
http://www.altruists.org/ff12
semantic(XML)
display(XHTML)
hooks/render
to produce the display data for showing users.
rdf:about=
<?xml version="1.0"?><f2f:fatal-error xmlns:f2f="http://friend2friend.net/" xmlns="http://friend2friend.net/"><f2f:libxml-info><f2f:libxml level="error" message="Element '{http://friend2friend.net/}servicereq': This element is not expected. Expected is ( {http://friend2friend.net/}then )." code="1871" line="2" column="0"/></f2f:libxml-info><f2f:soft-exception code="5702" crunchid="3" file="/home/home/robin/f2f/hardcode/php/softnode.php" line="392" level="fatal-error" message="Failed input schema validation!" node="/f2f/lib" thread="3" system="default"> <f2f:servicereq function="http://friend2friend.net/modules/lib/if" did="1" id="2"><f2f:test>0</f2f:test><f2f:servicereq xmlns="http://friend2friend.net/" function="*" f2f:escaped="*"> <f2f:then>We're from the government. We're here to help you.</f2f:then><f2f:else>Nope!</f2f:else></f2f:servicereq></f2f:servicereq><f2f:trace><f2f:call function="http://friend2friend.net/modules/lib/if" thread="1" node="/f2f/lib" crunchid="2" uid="1"><f2f:input><f2f:servicereq xmlns:f2f="http://friend2friend.net/" function="http://friend2friend.net/modules/lib/if" id="1"><f2f:test>0</f2f:test><f2f:then>We're from the government. We're here to help you.</f2f:then><f2f:else>Nope!</f2f:else></f2f:servicereq></f2f:input><f2f:output><f2f:servicereq xmlns:f2f="http://friend2friend.net/" function="http://friend2friend.net/modules/lib/if" did="1"><f2f:test>0</f2f:test> <f2f:servicereq xmlns="http://friend2friend.net/" function="*" f2f:escaped="*"><f2f:then>We're from the government. We're here to help you.</f2f:then><f2f:else>Nope!</f2f:else></f2f:servicereq></f2f:servicereq></f2f:output></f2f:call><f2f:call function="http://friend2friend.net/modules/lib/if" thread="1" node="/f2f/lib" crunchid="2" uid="1"><f2f:input> <f2f:servicereq xmlns:f2f="http://friend2friend.net/" function="http://friend2friend.net/modules/lib/if" id="1"><f2f:test>0</f2f:test><f2f:then>We're from the government. We're here to help you.</f2f:then><f2f:else>Nope!</f2f:else></f2f:servicereq></f2f:input><f2f:output><f2f:servicereq xmlns:f2f="http://friend2friend.net/" function="http://friend2friend.net/modules/lib/if" did="1"><f2f:test>0</f2f:test><f2f:servicereq xmlns="http://friend2friend.net/" function="*" f2f:escaped="*"><f2f:then>We're from the government. We're here to help you.</f2f:then><f2f:else>Nope!</f2f:else></f2f:servicereq></f2f:servicereq></f2f:output></f2f:call></f2f:trace></f2f:soft-exception><f2f:hard-exception code="0" file="/home/home/robin/f2f/hardcode/php/mylog.php" line="255" level="fatal-error" message="Failed input schema validation! "><f2f:trace><call file="/home/home/robin/f2f/hardcode/php/softnode.php" line="376" function="crunchThreadDoCustom" class="softnode" type="->"><args><item class="thread"><f2f:thread xmlns:f2f="http://friend2friend.net/" modified="1" uid="1" status="1" refdepth="4" srautonumber="1" filter-position="exec" filter-step="0" filter-direction="down" id="3"><f2f:data><f2f:servicereq function="http://friend2friend.net/modules/lib/if" did="1" id="2"><f2f:test>0</f2f:test><f2f:servicereq xmlns="http://friend2friend.net/" function="*" f2f:escaped="*"><f2f:then>We're from the government. We're here to help you.</f2f:then><f2f:else>Nope!</f2f:else></f2f:servicereq></f2f:servicereq></f2f:data></f2f:thread></item><item class="string">3</item><item class="DOMElement"><f2f:servicereq xmlns:f2f="http://friend2friend.net/" function="http://friend2friend.net/modules/lib/if" did="1" id="2"><f2f:test>0</f2f:test><f2f:servicereq xmlns="http://friend2friend.net/" function="*" f2f:escaped="*"><f2f:then>We're from the government. We're here to help you.</f2f:then><f2f:else>Nope!</f2f:else></f2f:servicereq></f2f:servicereq></item><item class="array"><item class="string" name="rdf:about">http://friend2friend.net/modules/lib/if</item><item class="string" name="src">/home/home/robin/f2f/modules/lib/if.xslt</item><item class="string" name="version">1.0</item><item class="string" name="midput">*</item><item class="string" name="output">*</item><item class="string" name="id">80</item><item class="string" name="input">/home/home/robin/f2f/modules/lib/compiled/if.input.xsd</item><item class="string" name="visibility">protected</item><item class="string" name="node">/f2f/lib</item></item></args></call><call file="/home/home/robin/f2f/hardcode/php/softnode.php" line="430" function="crunchThreadDo" class="softnode" type="->"><args><item class="thread"><f2f:thread xmlns:f2f="http://friend2friend.net/" modified="1" uid="1" status="1" refdepth="4" srautonumber="1" filter-position="exec" filter-step="0" filter-direction="down" id="3"><f2f:data><f2f:servicereq function="http://friend2friend.net/modules/lib/if" did="1" id="2"><f2f:test>0</f2f:test><f2f:servicereq xmlns="http://friend2friend.net/" function="*" f2f:escaped="*"><f2f:then>We're from the government. We're here to help you.</f2f:then><f2f:else>Nope!</f2f:else></f2f:servicereq></f2f:servicereq></f2f:data></f2f:thread></item><item class="string">1</item><item class="DOMElement"><f2f:servicereq xmlns:f2f="http://friend2friend.net/" function="http://friend2friend.net/modules/lib/if" did="1" id="2"><f2f:test>0</f2f:test><f2f:servicereq xmlns="http://friend2friend.net/" function="*" f2f:escaped="*"><f2f:then>We're from the government. We're here to help you.</f2f:then><f2f:else>Nope!</f2f:else></f2f:servicereq></f2f:servicereq></item><item class="array"><item class="string" name="rdf:about">http://friend2friend.net/modules/lib/if</item><item class="string" name="src">/home/home/robin/f2f/modules/lib/if.xslt</item><item class="string" name="version">1.0</item><item class="string" name="midput">*</item><item class="string" name="output">*</item><item class="string" name="id">80</item><item class="string" name="input">/home/home/robin/f2f/modules/lib/compiled/if.input.xsd</item><item class="string" name="visibility">protected</item><item class="string" name="node">/f2f/lib</item></item></args></call><call file="/home/home/robin/f2f/hardcode/php/softnode.php" line="537" function="crunchThreadFilter" class="softnode" type="->"><args><item class="thread"><f2f:thread xmlns:f2f="http://friend2friend.net/" id="1" uid="1" refdepth="3" modified="1" status="1" srautonumber="2"><f2f:parent thread="5" sreq="1" node="/f2f"/><f2f:data><f2f:servicereq function="http://friend2friend.net/modules/lib/if" did="1" id="2"><f2f:test>0</f2f:test><f2f:servicereq xmlns="http://friend2friend.net/" function="*" f2f:escaped="*"><f2f:then>We're from the government. We're here to help you.</f2f:then><f2f:else>Nope!</f2f:else></f2f:servicereq></f2f:servicereq></f2f:data> </f2f:thread></item><item class="DOMElement"><f2f:servicereq xmlns:f2f="http://friend2friend.net/" function="http://friend2friend.net/modules/lib/if" did="1" id="2"><f2f:test>0</f2f:test><f2f:servicereq xmlns="http://friend2friend.net/" function="*" f2f:escaped="*"><f2f:then>We're from the government. We're here to help you.</f2f:then><f2f:else>Nope!</f2f:else></f2f:servicereq></f2f:servicereq></item><item class="array"><item class="string" name="rdf:about">http://friend2friend.net/modules/lib/if</item> <item class="string" name="src">/home/home/robin/f2f/modules/lib/if.xslt</item><item class="string" name="version">1.0</item><item class="string" name="midput">*</item><item class="string" name="output">*</item><item class="string" name="id">80</item><item class="string" name="input">/home/home/robin/f2f/modules/lib/compiled/if.input.xsd</item><item class="string" name="visibility">protected</item><item class="string" name="node">/f2f/lib</item></item></args></call><call file="/home/home/robin/f2f/hardcode/php/softnode.php" line="213" function="crunchThreadStart" class="softnode" type="->"><args><item class="thread"><f2f:thread xmlns:f2f="http://friend2friend.net/" id="1" uid="1" refdepth="3" modified="1" status="1" srautonumber="2"><f2f:parent thread="5" sreq="1" node="/f2f"/><f2f:data><f2f:servicereq function="http://friend2friend.net/modules/lib/if" did="1" id="2"><f2f:test>0</f2f:test><f2f:servicereq xmlns="http://friend2friend.net/" function="*" f2f:escaped="*"><f2f:then>We're from the government. We're here to help you.</f2f:then><f2f:else>Nope!</f2f:else></f2f:servicereq></f2f:servicereq></f2f:data></f2f:thread></item></args></call><call file="/home/home/robin/f2f/hardcode/php/softsystem.php" line="612" function="crunch" class="softnode" type="->"><args/></call><call file="/home/home/robin/f2f/hardcode/php/debug.php" line="90" function="crunch" class="softsystem" type="->"><args><item class="string">60</item></args></call></f2f:trace></f2f:hard-exception></f2f:fatal-error>
http://friend2friend.net/hooks/render transforms a mass of XML...
...into a more easily understood graphical representation.
The icon module makes an <icon:icon> for any XML.A hook was the best vehicle for this because it...
Icon Module Example
Moreover it couldn’t be programmed as a service, because it...
...applies to XML from many different modules.
...is a data transform.
...should apply to data as yet unknown.(i.e. actions & images for yet to be created XML)
<icon:icon> has a simple structure:
http://friend2friend.net/modules/icon/hooks/make
Conveniently, the F2F core system defines hooks that match the above meanings, so icon/hooks/make can build on them.
<icon><caption> Icon name </caption><image> Image URI </image><payload>
... XML describing what to do ...</payload>
</icon>
rdf:about=
<xsl:template match=”*”/>
<xsl:copy-of select=”.”/>
<xsl:copy-of select=”.”/>
<xsl:copy-of select=”.”/>
</xsl:template>
Nesting Hooks
<icon:icon><icon:caption>
<f2f:hookreq function=”http://friend2friend.net/hooks/name”>
</f2f:hookreq></icon:caption><icon:image>
<f2f:hookreq function=”http://friend2friend.net/hooks/imageURI”>
</f2f:hookreq></icon:image><icon:payload>
<f2f:hookreq function=”http://friend2friend.net/hooks/activate”>
</f2f:hookreq></icon:payload>
</icon:icon>
This template is applied to the contents of the <hookreq> below...
desktop
<f2f:folder location=“/desktop”>
<f2f:folder location=“/desktop”>
<f2f:folder location=“/desktop”>
This creates 3 more hook requests which are processed...The wildcard handler script to make icons is as follows:
→
http://friend2friend.net/images/folder</icon:image>
<f2f:servicereq f2f:escaped=”!” function=”http://f2f.name/explorer”><f2f:location>/desktop</f2f:location>
</f2f:servicereq></icon:payload>
<f2f:hookreq function=“http://friend2friend.net/modules/icon/hooks/get”><f2f:folder location=“/desktop”>
</f2f:hookreq>
desktop</icon:caption>
Processing is complete:
Summary
Modules may both define their own hooks and contribute handlers to existing hooks.
Recommended Follow-up: FF12: Clients
http://www.altruists.org/ff12
A hook is a globally referencable data transform.
Data is handled by different XSL Transforms,
according to namespace.
rdf:about= "http://friend2friend.net/hooks/activate"
<hand
ler
namesp
ace=".
.
src=”.
..”/><ha
name
src=
<h
namsrc