M2SFP 1.8 - View Loaders
Table of Contents
This is a working document and is subject to change.
Comments regarding this M2SFP are welcome. Please leave your comments by using the form at the bottom of this entry.
This M2SFP feature has been filed under ticket #175.
Overview
One of the Mach-II XML configuration file sections that can become rather unruly is the <page-views> section. A smart developer will use some sort of convention when structuring views and page-view names. However, this becomes rather tedious over time as the size of the application grows because you have to manually add each <page-view> in XML. It can be prone to error because it's an to forget to add a new <page-view>. View loaders are a CFC that would allow a developers to load views based on convention such as using an ANT-style path matching pattern.
Using the pattern view loader, each directory and file name would be translated into a page-view name using a configurable delimiter. For example if a view with the path of /aboutUs/index.cfm was found, it would be translated into a page-view name of aboutUs.index. The translation starts with directories and the file name that start after the ANT-style pattern end. Therefore, a deeply nested directory may require a prefix.
The addition of view loaders would allow developers to auto-register page-views by convention thus reducing a normally tedious task of registering views. Also, developers could define multiple view-loaders in the page-views section or create their own loader by extending a particular Mach-II CFC.
Configuration Syntax
As always with new features to Mach-II, bundled view loaders will use "smart" defaults with the option to use explicit configuration for custom situations. The Mach-II 1.8 release will ship with one view loader bundled that matches views by a ANT-style wildcard pattern matching like algorithm.
Smart Defaults Syntax
<page-views>
<!-- This would load all views with the pattern of "/views/**/*.cfm"
which is the most basic and common pattern -->
<view-loader type="MachII.framework.viewLoaders.PatternViewLoader" />
<!-- Normal static page-view nodes are allowed -->
<page-view name="someView" page="/views/someView.cfm"/>
</page-views>
Customized Configuration Syntax
<page-views>
<view-loader type="MachII.framework.viewLoaders.PatternViewLoader">
<parameters>
<!-- An ANT-style patterns using wildcards to find views to load -->
<parameter name="pattern" value="/views/**/*.cfm" />
<!-- A string to prefix the <page-view> name with (matches only
starts after first pattern character is detected).
Optional, showing default value if attribute is omitted -->
<parameter name="prefix" value="" />
<!-- Character to use when building the <page-view> names.
Optional, showing default value if attribute is omitted -->
<parameter name="nameDelimiter" value="." />
<!-- A list or array of ANT-style patterns or static paths to
exclude from the pattern search routine.
Optional, takes a list or an array -->
<parameter name="exclude" value="/views/includes/**,/views/otherDir/**" />
- or -
<parameter name="exclude">
<array>
<element value="/views/includes/**"/>
<element value="/views/otherDir/**"/>
</array>
</parameter>
<!-- Boolean indicator to throw an exception if no matches are found
Optional, takes a boolean and defaults to "true" -->
<parameter name="throwIfNoMatches" value="true"/>
</parameters>
</view-loader>
<!-- Normal static page-view nodes are allowed or additional view-loaders -->
<page-view name="someView" page="/views/someView.cfm"/>
</page-views>
Definition Parameter Key Details
| Attribute | Required | Datatype | Default | Description |
| pattern | recommended | string | /views/**/*.cfm | An ANT-style patterns using wildcards to find views to load. |
| prefix | optional | string | [zero length string] | A string to prefix the <page-view> name with (matches only starts after first pattern character is detected). |
| nameDelimiter | optional | string | . [period] | Character to use when building the <page-view> names. Example: . = aboutUs.people.peterFarrell, _ = aboutUs_people_peterFarrell, - = aboutUs-people-peterFarrell |
| exclude | optional | list (comma delimited) or array | [zero length string] | A list or array of ANT-style patterns or static paths to exclude from the pattern search routine. |
| throwIfNoMatches | optional | boolean | true | Throws an exception if no matches are found. Used to help debugging otherwise a page-view not found exception is usually generated which does not necessary point to the a problem with the view loader. |
Using Patterns
| Wilcard | Description |
| * | Matches zero or more characters. |
| ? | Matches exactly one character. |
| ** | Matches zero or more directories. |
Example Patterns
| Pattern / Prefix / Name Delimiter | Pattern Resullts |
| /views/products/**/*.cfm products . | Matches (corresponding <page-view> name): /views/products/index.cfm = products.index /views/products/SE10/index.cfm = products.SE10.index /views/products/SE10/details.cfm = products.SE10.details /views/products/ST80/index.cfm = products.SE80.index /views/products/ST80/details.cfm = products.SE80.details Does Not Match: /views/index.cfm /views/aboutUs/index.cfm /views/aboutUs/managementTeam.cfm |
| /views/**/*.cfm [no prefix] . | Matches (corresponding <page-view> name): /views/index.cfm = index /views/aboutUs/index.cfm = aboutUs.index /views/aboutUs/managementTeam.cfm = aboutUs.managmentTeam /views/products/index.cfm = products.index /views/products/SE10/index.cfm = products.SE10.index /views/products/SE10/details.cfm = products.SE10.details /views/products/ST80/index.cfm = products.SE80.index /views/products/ST80/details.cfm = products.SE80.details Does Not Match: /views/index.htm /views/readme.txt |
| /views/index??.cfm homePages _ | Matches (corresponding <page-view> name): /views/index01.cfm = homePages_index01 /views/index02.cfm = homePages_index02 /views/indexAA.cfm = homePages_indexAA Does Not Match: /views/index01.htm /views/index1.cfm /views/indexA.cfm /views/indexOther.cfm /views/anotherDir/index01.cfm (Remember that ? matches a single character, so the above example matches only files that start with "index", followed by two wildcard characters and then ".cfm".) |
Additional Implementation Information
- View loaders are configured and run in the order they are defined in the XML.
- Static <page-view> cannot be overrided by views registered by a view loader.
- The PatternViewLoader generates <page-view> names starting with directories and file name starting with the path that starts after the pattern. Use the prefix attribute to prepend a string in front of the generated page view name.
Common Errors
- An error like No matches found for pattern '/views/customPattern/**/*.cfm' in module '' can occur when you include an exclude patterns that are the same or similar to the search pattern. Be sure that your exclude patterns do not duplicate your search pattern. Common debugging technique includes commenting out your exclude patterns and slowing adding them in to find the problematic exclude pattern.
Feel free to add comments regarding this M2SFP:
Comment by Sami Hoda on Wed Nov 19 14:37:50 2008
Definitely something much needed and helpful!
Comment by anonymous on Sat 02 May 2009 11:42:00 AM UTC
Perhaps someone make an example for this one?
" The translation starts with directories and the file name that start after the ANT-style pattern end. Therefore, a deeply nested directory may require a prefix. "
If I am getting this correctly, the prefix will make it possible to get prefixfoo.viewnameX from this.is.a.deeply.nested.viewnameX?
Comment by peterfarrell on Sun 03 May 2009 05:31:50 AM UTC
Yes, that is correct. If your pattern is /this/is/a/deeply/nested/**/*.cfm and you had a prefix of prefixfoo then you would get prefixfoo.nameOfViewHere. The dot path starts at the first pattern character, so everything before the double asterisk is left off the dot path that is generated for the view page name.
