Domino Design Code Injection
In an earlier entry I discussed how to maintain custom system databases. It works well when you add design elements or change them wholesale. However it doesn't work very well when you tweak design elements. Something like: adding one action in a form or using a different subform for a specific task. Once an updated system template is available, you have to go back and recreate all your changes in your template.
This entry discusses how to automate these little fixes. There are a number of moving parts involved:
Some simple examples:
This LotusScript was converted to HTML using the ls2html routine,
provided by Julian Robichaux at nsftools.com.
Now we need a pice of code that can do the transformation of the DXL. Unfortunately the LotusScript XML Parser is lacking, so we use some Java code to perform this step. After creating the class (without parameters, for LS2J comfort, we need to set the DXL as Document and then call injectCode with 3 parameters: xPath expression, codeSnippet to insert (must be an XML fragment) and insertion type (before/after/replace). See Part 2 for the Java code.
This entry discusses how to automate these little fixes. There are a number of moving parts involved:
- Export the design element using DXL. (You might need to set NotesDXLExporter.RichTextOption = RICHTEXTOPTION_RAW to make sure the fidelity of forms is maintained)
- Locate the entry/replace point. The best mechanism for that is XPath
- Locate the new code. This could be as easy as provide a string with the XML Snippet to pointing to an existing design element elsewhere. (We would use XPath again)
- Perform the insertion/replacement. We will have the option: before/after/replace
- Write back your changes and test it
- Add an action to a form/view
- Add a subform to a form
- Replace a validation formula in a field
- Insert a script library and a custom class into a form
- Add a field at the top or bottom of a form (our favorite hidden fields $$Return anyone
Some simple examples:
- * selects ANY element.
- / selects the root element, basically before any tags in the XML
- /database/form/actionbar selects the actionbar elements in all forms in our XML
- /database/form[1]/actionbar selects the actionbar element in the first form in our XML
- /database/form[@name='Message']/actionbar selects the actionbar element in the form Message in our XML
- /database/form[@name='Message'] //field[@name='Subject'] /code[@event='defaultvalue'] /formula Select the default value formula for the field "Subject". Please note the double slashes in front of the field. They are intentional. One slash says: a child, two slashes says any decendant down the document. Also: no spaces before/after the slashes. They are here for readablitity only.
- //field[code/@event='inputvalidation'] Any field that has an input validation formula
Sub InjectCodeIntoForm (formName AsString, xPath AsString, codeSnippet AsString)'Errorhandling omitted for clarityDim s AsNewNotesSessionDim db AsNotesDatabaseDim f AsNotesFormDim out AsNotesStreamDim ex AsNotesDXLExporterDim importer AsNotesDXLImporterDim col AsNotesNoteCollection'The strings holding the DXLDim rawDXL AsStringDim resultDXL AsStringSet db = s .CurrentDatabase 'Create a Note collection and add the formSet col = db .CreateNoteCollection (False)Set f = db .GetForm (formName ) col .BuildCollection Call col .Add (f )'Create the exporter and run the stuff outSet ex = s .CreateDXLExporter Set out = s .CreateStream ex .RichTextOption = RICHTEXTOPTION_RAW 'This is to get rawitems for untranslatable stuff ex .ValidationStyle = VALIDATIONSTYLE_NONE 'To make sure we don't generate a schema referenceCall ex .setinput (col )Call ex .setOutput (out ) ex .process 'Reset the stream and manipulate the DXL out .Position = 0 rawDXL = out .ReadText resultDXL = injectCode (rawDXL , xPath , codeSnippet )'Write it back out .Truncate Call out .WriteText (resultDXL ) out .Position = 0 Set importer = s .CreateDXLImporter 'Having the right importer options is important importer .CompileLotusScript =True importer .ReplaceDBProperties =False importer .ReplicaRequiredForReplaceOrUpdate =True importer .ACLImportOption = DXLIMPORTOPTION_IGNORE importer .DesignImportOption = DXLIMPORTOPTION_REPLACE_ELSE_IGNORE 'We only want to update the current form importer .DocumentImportOption = DXLIMPORTOPTION_IGNORE 'This is for design only importer .ExitOnFirstFatalError =False'Standard import executionCall importer .setInput (out )Call importer .setOutput (db )OnErrorResumeNextCall importer .Import Msgbox importer .logEndSub
provided by Julian Robichaux at nsftools.com.
Posted by Stephan H Wissel on 21 March 2008 | Comments (2) | categories: Show-N-Tell Thursday