├── .gitignore
├── BestPracticeAuditSuggestionsAndToDoList.md
├── BestPracticeAuditTests.md
├── README.md
├── Transformers
├── BestPractice-BreakpointAnalysis.fmx
├── BestPractice-NoFeaturesTester.fmx
├── BestPractice-PerformanceAnalysis.fmx
├── BestPractice-ReaderAnalysis.fmx
├── BestPractice-ReportCollation.fmx
├── BestPractice-ReportHeader.fmx
├── BestPractice-ReportSummary.fmx
├── BestPractice-StyleAnalysis.fmx
├── BestPractice-TransformerAnalysis.fmx
├── BestPractice-WorkspaceAnalysis.fmx
└── BestPractice_WriterAnalysis.fmx
└── Workspaces
├── BestPracticeIncomingEmailTest.fmw
├── BestPracticeReportGenerator2017.fmw
├── BestPracticeReportGenerator2017ForServer.fmw
└── BestPracticeReportGenerator2017_bothDesktopAndServer.fmw
/.gitignore:
--------------------------------------------------------------------------------
1 | # Keep thumbnail files out of repository
2 | *.log
3 | *.recover
4 | *_log.ffs
--------------------------------------------------------------------------------
/BestPracticeAuditSuggestionsAndToDoList.md:
--------------------------------------------------------------------------------
1 | # Best Practice Audit #
2 |
3 | Suggestions and reports still to do.
4 |
5 | ## Server Implementation ##
6 |
7 | - Try to create a single workspace that will work on both server and desktop
8 | - ie something with tests that directs data different ways depending on the platform
9 | - Maybe a master workspace that calls either ReportDesktop.fmw or ReportServer.fmw????
10 | - Make a webhook(?) for GitHub to trigger upload of updated transformers to Server
11 |
12 |
13 | ## Report Structure ##
14 |
15 | Ways to improve the layout and structure of the HTML report
16 |
17 | - Improve the style of the HTML
18 | - The report is fairly basic. I'm sure we can do better.
19 | - The report header datetimes are affected by a bug in the formatting of dates. PR#77159 is fixed in 2017.1 - so when we switch to 2017.1 it will be good
20 | - However... in 2017.1 we should add a DateFormatter to give dates a more readable style
21 | - Check whether 'Custom HTML' can now replace some aspects of the 2016.1 implementation
22 | - eg there are StringReplacers in ReportCollation.fmx that might be avoided if ReportGenerators can be improved
23 | - Include a list of links to the subsections either before or immediately after the header to facilitate navigation
24 | - This needs a way to set an ID in a header. Either custom HTML or FME update (Filed PR#77044)
25 |
26 |
27 | ## Report 1: HEADER ##
28 |
29 | Suggestions and updates for the report header
30 |
31 | - Implement other updates from lost contribution on KnowledgeCentre Q+A
32 | - [DONE - Sigbjørn - Norkart]- File properties, (size, creation date, edit date, last run date): Sigbjørn: Can still be downloaded from https://knowledge.safe.com/storage/attachments/5971-bestpracticereportgenerator-norkart-sigbj%C3%B8rn.zip
33 | - [Mark I] - Made a few updates to use Sigbjorn's style, but using the new FileProperties feature type
34 | - Maybe add tests for documentation? Color-coding of bookmarks? (Some notes while watching Martin Koch at FMEUC)
35 |
36 | ## Report 2: WORKSPACE ##
37 |
38 | Suggestions and updates for the Workspace report
39 |
40 | - Check for a workspace devoid of content (ie no readers, no writers, no transformers): ERROR
41 | - Check how long it takes to open the project/file size - or some other metric to indicate that the project is too large
42 | - File size is often representative of large schemas and doesn't always mean overcomplicated
43 | - Add a section that checks for startup and shutdown scripts.
44 | - Check for embedded database connections as a security issue - readers, writers, transformers
45 | - Currently we can't tell in the FMW reader what is a db connection and which is embedded
46 |
47 |
48 | ## Report 3: STYLE ##
49 |
50 | Suggestions and updates for the Style report
51 |
52 | - If we knew the position of objects we might identify crossing connections (unlikely, but hey)
53 |
54 | ## Report 4: BREAKPOINTS ##
55 |
56 | Suggestions and updates for the Breakpoints report
57 |
58 | - Make this a general CONNECTIONS report
59 | - Test for disabled connections
60 |
61 | ## Report 5: READERS ##
62 |
63 | Suggestions and updates for the Readers report
64 |
65 | - Test for all Reader FT's connected to same transformer - where a merge filter could be used
66 | - Again, with connection info in 2017 this might be possible
67 | - Information or warning where it would be possible to implement a where clause on a reader
68 | - For instance an empty where clause followed by a Tester after a reader
69 | - Test connections to databases and file locations using the information in the workspace
70 |
71 | ## Report 6: WRITERS ##
72 |
73 | Suggestions and updates for the Writers report
74 |
75 | - Give a warning if Writers/Writer FTs are not connected
76 | - 2017 introduced connection info, so this might now be possible
77 | - Test for all Writer FT's connected to same filter transformer - where a fanout could be used
78 | - Again, with connection info in 2017 this might be possible
79 | - Test connections to databases and file locations using the information in the workspace
80 |
81 | ## Report 7: Transformers ##
82 |
83 | Suggestions and updates for the Transformers report
84 |
85 | - List the most-used transformer category
86 | - This would need a lookup table from transformer<->category, since category is not returned by the FMW reader
87 | - Where parameters are set to an attribute value, warn to include error checking to ensure the attribute exists
88 | - Currently we can't tell if a parameter is set to an attribute value (or whether it is a fixed string)
89 | - Check the possibility of losing features / lack of error trapping.
90 | - For instance if there exists a Tester with a connection only to the Passed port
91 | - Basically any filter transformer with an unconnected output port (connect to Null writer/Logger instead?)
92 | - Check groupings (ie common sections of transformers) eg to say "this should be a custom transformer"
93 | - Test if transformer names have been changed (if not, could not be best practice?)
94 | - Or check where there is a long series of _1, _2, _3, _4, etc on transformer names
95 | - Ping URLs used in a HTTPCaller to see if they respond
96 |
97 |
98 | ## Report 8: PERFORMANCE ##
99 |
100 | Suggestions and updates for the Performance report
101 |
102 | - Transformers with Group By and Parallell Processing as attributes: List everyone and red/green based on Parallell is active or not
103 | - Featuremergers: List everyone and red/green based on if they have Suppliers first or not
104 | - List all writers and directions that they write in - and let the user know that the first writer should have the largest dataset etc.
105 | - List all readers and directions that they read in - and let the user know this
106 | - Check which logging options are enabled (DEBUG etc should be turned off on production)
107 |
108 | ## Report SUMMARY ##
109 |
110 | Suggestions and updates for the report summary
111 |
112 | - Report the number of tests carried out
113 | - Maybe add published parameters for the user to select which tests to carry out
114 | - Report the number of tests, number of passes, number of Warnings, number of fails, number of N/A (eg no readers).
115 | - Create a quality report
116 | - Maybe score the workspace as (objects/((errors*2)+(warnings)))?
117 | - Maybe if any errors exist, the workspace fails (should not be put into production)
118 | - If WARNs only then it can be put into production, but not without first confirming these warnings are not a problem.
119 | - If PASSes only then it can be put into production. Well done.
120 | - Report the time taken to process the workspace
121 | - Report the number of readers, writers, transformers
122 |
123 |
124 | ## New Reports or Projects ##
125 |
126 | Analyze folder of workspaces (assess relationship between workspaces - which are parent, child, etc) (Some notes while watching Martin Koch at FMEUC)
127 |
128 | ### Customization ###
129 |
130 | Maybe we can allow the end user to choose which tests to carry out, rather than doing them all?
131 |
132 | ### Screenshot ###
133 |
134 | Can we somehow open a workspace and screenshot it? That way we could add screenshots to the report
135 |
136 | ### Log File Analysis ###
137 |
138 | Analyze a log file to look for best practice issues.
139 |
140 | - Look for time discrepancies
141 | - Look for low memory or disk space
142 | - Look for temp folder on same drive as operating system
143 | - Look for warnings and errors
144 |
145 | ### Template Analysis ###
146 |
147 | The ability to submit a template, have it run, and analyze the log file (maybe use as a benchmark??)
148 |
--------------------------------------------------------------------------------
/BestPracticeAuditTests.md:
--------------------------------------------------------------------------------
1 | # Best Practice Reports #
2 |
3 | ## Report 1: HEADER ##
4 |
5 | **Header 1: Title**
6 |
7 | **Header 2: General Information**
8 |
9 | - Logs: Report name, Report datetime, Workspace name, File size, Creation datetime, Modified datetime, Last Run datetime
10 | - Warnings about the limit of this procedure.
11 | - Note current build number.
12 |
13 | ---
14 |
15 | ## Report 2: WORKSPACE ##
16 |
17 | **Workspace 1: Workspace Version**
18 |
19 | - Test which version of FME the last edits were made in compared to the current FME version.
20 | - If last edits are an older version, WARN about testing before deploying on the current version.
21 | - If last edits are a newer version, FAIL. Give an ERROR about using a beta build to construct a workspace.
22 | - If last edits are the same version, PASS.
23 |
24 | **Workspace 2: Workspace Properties**
25 |
26 | - Test for name and category being set.
27 | - If one or the other are not set, WARN about this being bad for Best Practice.
28 | - If both are set, PASS.
29 |
30 | ---
31 |
32 | ## Report 3: STYLE ##
33 |
34 | **Style 1: Bookmarks**
35 |
36 | - Test for no bookmarks.
37 | - If there are no bookmarks, FAIL. Give an ERROR about this being bad for Best Practice.
38 | - Calculate the number of transformers per bookmark.
39 | - If there are too few bookmarks (>10 transformers per bookmark), WARN as being bad for Best Practice
40 | - If there are too many bookmarks (<5 transformers per bookmark), WARN as being bad for Best Practice
41 | - If there are an appropriate number of bookmarks, PASS.
42 |
43 | **Style 2: Annotations**
44 |
45 | - Test for no annotations.
46 | - If there are no annotations, FAIL. Give an ERROR about this being bad for Best Practice.
47 | - Calculate the number of transformers per annotation.
48 | - If there are too few annotations (>5 transformers per annotation), WARN as being bad for Best Practice
49 | - If there are too many annotations (<3 transformers per annotation), WARN as being bad for Best Practice
50 | - If there are an appropriate number of annotations, PASS.
51 |
52 | ---
53 |
54 | ## Report 4: BREAKPOINTS ##
55 |
56 | **Breakpoints 1: Breakpoints**
57 |
58 | - Check for breakpoints.
59 | - If there are enabled breakpoints, FAIL. Give an ERROR about putting a workspace into production with these.
60 | - If there are disabled breakpoints, WARN about putting a workspace into production with these.
61 | - If there are no breakpoints, PASS.
62 |
63 | ---
64 |
65 | ## Report 5: READERS ##
66 |
67 | **Readers 0: Zero Readers**
68 |
69 | - Check for no Readers at all.
70 | - If there are no readers, bypass other tests. Give a generic No Readers message.
71 |
72 | **Readers 1: Build Number**
73 |
74 | - Check each reader's "Generate Build" number against the current FME version.
75 | - If the Generate Build was an older version, WARN suggesting upgrade before deploying on the current version.
76 | - If there are no older versions, PASS.
77 |
78 | **Readers 2a: Disabled Readers**
79 |
80 | - Check for disabled readers.
81 | - If there are disabled readers, WARN that these are not useful when putting a workspace into production.
82 | - If there are no disabled readers, PASS.
83 |
84 | **Readers 2b: Disabled Feature Types**
85 |
86 | - Check for disabled feature types.
87 | - If there are disabled feature types, WARN that these are not useful when putting a workspace into production.
88 | - If there are no disabled feature types, PASS.
89 |
90 | **Readers 3: Dangling Readers**
91 |
92 | - Check for dangling readers (those without a feature type).
93 | - If there are dangling readers, FAIL. Give an ERROR that these are positively bad when putting a workspace into production.
94 | - If there are no dangling readers, PASS.
95 |
96 | **Readers 4: Excess Feature Types**
97 |
98 | - Check for a reader with >10 feature types.
99 | - If there are readers with >10 feature types, WARN that this indicates the possible need for a merge filter.
100 | - If there are no readers with >10 feature types, PASS.
101 |
102 | **Readers 5: Published Parameters**
103 |
104 | - Check for basic reader parameters still published.
105 | - If there are basic reader parameters still published, WARN that these might not be required.
106 | - If there are no basic reader parameters still published, PASS.
107 |
108 | **Readers 6: Unconnected Feature Types**
109 |
110 | - Check for reader feature types whose name is not a match in the connections list
111 | - If there are feature types without a match, WARN that these could affect performance and should be removed
112 | - If there are no unconnected feature types, PASS.
113 |
114 | ---
115 |
116 | ## Report 6: WRITERS ##
117 |
118 | **Writers 0: Zero Writers**
119 |
120 | - Check for no Writers at all.
121 | - If there are no writers, bypass other tests. Give a generic No Writers message.
122 |
123 | **Writers 1: Build Number**
124 |
125 | - Check each writer's "Generate Build" number against the current FME version.
126 | - If the Generate Build was an older version, WARN suggesting upgrade before deploying on the current version.
127 | - If there are no older versions, PASS.
128 |
129 | **Writers 2a: Disabled Writers**
130 |
131 | - Check for disabled writers.
132 | - If there are disabled writers, WARN that these are not useful when putting a workspace into production.
133 | - If there are no disabled writers, PASS.
134 |
135 | **Writers 2b: Disabled Feature Types**
136 |
137 | - Check for disabled feature types.
138 | - If there are disabled feature types, WARN that these are not useful when putting a workspace into production.
139 | - If there are no disabled feature types, PASS.
140 |
141 | **Writers 3: Dangling Writers**
142 |
143 | - Check for dangling writer (those without a feature type).
144 | - If there are dangling writers, WARN that these are not useful when putting a workspace into production.
145 | - If there are no dangling writers, PASS.
146 |
147 | **Writers 4: Invalid Feature Type Names**
148 |
149 | - Check for writer feature type names with possibly invalid characters
150 | - If there are characters outside of A-Z,a-z,0-9, WARN that these may be invalid (though FME should handle anyway).
151 | - If there are no characters outside of A-Z,a-z,0-9, PASS.
152 |
153 | **Writers 5: Mixed Case Attr Names**
154 |
155 | - Check Writer Attr Names for instances of mixed-case names (eg some UPPER, some lower, some MixedCase)
156 | - If there are mixed-case names, WARN that this is not good practice.
157 | - If there are no mixed-case names, PASS.
158 |
159 | **Writers 6: Coordinate Systems**
160 |
161 | - Check for a writer setting a coordinate system.
162 | - Check for a reader setting a coordinate system.
163 | - Check for a CoordinateSystemSetter transformer.
164 | - If a writer sets a coordinate system, and no reader sets it, and there is no CoordinateSystemSetter, WARN that FME needs to know what to reproject from
165 | - If there are no writers with coordinate systems, or there are but a reader/transformer sets it, PASS.
166 |
167 | **Writers 7: Published Parameters**
168 |
169 | - Check for basic writer parameters still published.
170 | - If there are basic writer parameters still published, WARN that these might not be required.
171 | - If there are no basic writer parameters still published, PASS.
172 |
173 | ---
174 |
175 | ## Report 7: Transformers ##
176 |
177 | **Transformers 1: Transformer Histogram**
178 |
179 | - List the most-used transformers
180 |
181 | **Transformers 2: Percentage Check**
182 |
183 | - Check percentage of overall count
184 | - Check if there are 6 or more transformers (else the test is not worth doing)
185 | - If there are >5 transformers and >=25% are all the same type, WARN that this might not be a good scenario
186 |
187 | **Transformers 3: Transformer Version**
188 |
189 | - Check whether an update is required.
190 | - If a transformer is not the latest version, WARN
191 |
192 | **Transformers 4: Inspectors and Loggers**
193 |
194 | - Check for Inspector transformers
195 | - Enabled Inspectors = ERROR (note how bad this is for Server)
196 | - Disabled Inspectors = WARN
197 | - Check for Logger transformers
198 | - Enabled Loggers = ERROR (note how bad this is for Server)
199 | - Disabled Loggers = WARNING
200 |
201 | **Transformers 5: FMEFunctionCaller**
202 |
203 | - Check for FMEFunctionCaller transformers
204 | - If one exists, it indicates low-level badness. WARN (but a very strong one)
205 |
206 | **Transformers 6: Similar Parameters**
207 |
208 | - Check for transformer parameters that are the same value
209 | - Suggest these might be better as a user parameter (possibly private) or Custom Transformer: WARN
210 |
211 | ---
212 |
213 | ## Report 8: PERFORMANCE ##
214 |
215 | **Performance 0: Zero Transformers**
216 |
217 | - Check for no transformers at all.
218 | - If there are no transformers, bypass other transformer-related tests. Give a generic No Transformers message.
219 |
220 | **Performance 1: Parallel Processing**
221 |
222 | - Check parallel processing parameters for use of Aggressive or Extreme.
223 | - If there are cases of Aggressive or Extreme, WARN that this may not guarantee good performance.
224 | - If there are no cases of Aggressive or Extreme, PASS.
225 |
226 | **Performance 2: Parallel Processing 2**
227 |
228 | - Check for multiple uses of Parallel Processing.
229 | - If there are multiple uses, WARN that this may spawn too many processes.
230 | - If there are not multiple uses, PASS.
231 |
232 | **Performance 3: Performance Parameters**
233 |
234 | - Check for use of transformers with parameters for performance improvements (eg Clippers first)
235 | - Tests for Clipper/Displacer/FeatureMerger/NeighborFinder/PointOnAreaOverlayer/SpatialFilter
236 | - If such transformers exist, but don't use that parameter, WARN that this may impact performance.
237 | - If such transformers exist, and use that parameter, PASS.
238 |
239 | ---
240 |
241 | ## Report 9999: SUMMARY ##
242 |
243 | **Summary 1**
244 |
245 | - List the number of Errors
246 |
247 | **Summary 2**
248 |
249 | - List the number of Warnings
250 |
251 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BestPractice
2 | A Best Practices analysis tool for FME Workspaces. Related post on FME Knowledge center can be found here: https://knowledge.safe.com/questions/37858/fme-best-practice-validation-project-you-can-help.html
3 |
4 | This project includes workspaces and custom transformers that carry out best practice tests. There are (currently) two workspaces in the project. One of them is for use on FME Server, particularly with notifications. The other is for use on FME Desktop.
5 |
6 | **Version:** Will work on FME(R) 2017.0.0.0 (20170228 - Build 17259) or newer
7 |
8 | ## Installing the Project (Desktop) ##
9 | The easiest way to install this project is to download/fork it onto a local machine and in FME Workbench use Tools > FME Options > Default Paths, add the download folder as a Shared FME Folder.
10 |
11 | Because the download folder includes subfolders for Workspaces and Transformers, FME Workbench will automatically locate and install this functionality on startup.
12 |
13 | ## Using the Project (Desktop) ##
14 | On FME Desktop open and run the main workspace, pointing its published parameters to the workspace you wish to analyze.
15 |
16 | A HTML report will be generated and written to the desired location, reporting on the Best Practices used in developing that workspace.
17 |
18 | ## Installing the Project (Server) ##
19 | This method is to install the project for use with the email notification services.
20 |
21 | - Copy the transformers to Resources\Engine\Transformers on FME Server. You can use either a file browser or the FME Server web interface.
22 | - Create two notification topics; one for incoming notifications and one for outgoing
23 | - Create a notification publication of type email that is tied to the incoming notification topic
24 | - Create a notification subscription of type email that is tied to the outgoing notification topic
25 | - Publish the workspace to FME Server
26 | - Register the workspace against the notification service
27 | - Under the notification service parameters:
28 | - Set the workspace to subscribe to the incoming notification topic
29 | - Set the Source TextFile reader to receive the incoming topic message
30 | - Set the workspace to post (on success) to the outgoing notification topic
31 | - Set the Destination TextFile writer to post data to the outgoing topic message
32 |
33 | ## Using the Project (Server) ##
34 | Send an email to the incoming email publication. The workspace should be added as an attachment. The topic will be triggered and run the assessment workspace. The workspace will create the output report and send it by email back to the From email address.
35 |
36 | The name of the report will be taken from the email subject line.
37 |
38 | The report and a copy of the workspace will be copied to the folder Resources\Data\BestPractice
39 |
40 |
41 | ## Contribute
42 | Please do contribute and help improve this project if you wish.
43 |
44 | The ToDo list markdown document in this repository includes a list of suggested updates you might wish to try.
45 |
46 | **TODO:** *Tutorial on how to submit your suggested updates.*
47 |
48 | Some rules and suggestions for contributions:
49 |
50 | - Only use this version of FME to edit the files: 2017.0.0.0 (20170228 - Build 17259)
51 | - Before doing any work, make sure you have the latest versions of the files (in case someone else has made changes too)
52 | - All the tests fall inside custom transformers, that way the same transformers can be used for both desktop and server workspaces
53 | - Because the custom transformers are used by both desktop and server, use only functionality that is compatible with both platforms
54 | - for example, avoid using paths and/or assuming this will be on a Windows platform
55 | - If there are changes that are platform specific then make them to the **workspace** not to the **transformers**
56 | - If you update one workspace, please update the other too
57 | - for example if you add a new input port to a custom transformer, you should update that transformer in both the desktop and server workspaces
58 | - hopefully we can someday merge the two to create a single, unified workspace
59 |
--------------------------------------------------------------------------------
/Transformers/BestPractice-BreakpointAnalysis.fmx:
--------------------------------------------------------------------------------
1 | #!
2 | #!
https:docs.safe.com fme html FME_Desktop_Documentation FME_Workbench Workbench feature_inspection_about.htm Feature Inspection a h3 }}HEADER{{TEXT;@EvaluateExpression(FDIV,STRING_ENCODED,Breakpoint Count: Value NumBreakpoints ,$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_HTMLReportGenerator_2);HEADER;H4;ALIGNMENT;LEFT;COLOR;0 0 0}}LIST{{ATTR;HTMLBkptError;STYLE;NONE;COLOR;125 0 0;BADGE;}}LIST{{ATTR;HTMLBkptWarning;STYLE;NONE;COLOR;200 125 0;BADGE;}}HEADER{{TEXT; strong Recommendations: strong You may wish to remove these breakpoint s . Breakpoints should be used solely for debugging and removed before putting a workspace into production.;HEADER;NO;ALIGNMENT;LEFT;COLOR;0 0 0" fme_html5_group_by "" fme_html5_xformer_name "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_HTMLReportGenerator_2" 832 | 833 | 834 | FACTORY_DEF * PythonFactory FACTORY_NAME $(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_HTMLReportGenerator_2 INPUT FEATURE_TYPE $(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_HTMLReportGenerator_2_PROCESSED PYTHON_NAMESPACE FMEOBJECTS SYMBOL_NAME reportgenerator.html5assembler.HTML5Assembler OUTPUT PYOUTPUT FEATURE_TYPE "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_HTMLReportGenerator_2_OUTPUT" 835 | 836 | 837 | 838 | 839 | # ------------------------------------------------------------------------- 840 | 841 | 842 | FACTORY_DEF * AttrSetFactory FACTORY_NAME $(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_AttributeManager_4 INPUT FEATURE_TYPE "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_BestPractice-NoFeaturesTester_NoInput" MULTI_FEATURE_MODE NO NULL_ATTR_MODE NO_OP ATTRSET_CREATE_DIRECTIVES _PROPAGATE_MISSING_FDIV ACTION_COLUMN 3 DEF_VAL_COLUMN 2 ATTR_ACTION "" "BreakPointText" " strong PASS: strong You have no breakpoints in your workspace" "SET_TO" OUTPUT OUTPUT FEATURE_TYPE "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_AttributeManager_4_OUTPUT" 843 | 844 | # ------------------------------------------------------------------------- 845 | 846 | FACTORY_DEF * TeeFactory INPUT FEATURE_TYPE "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_AttributeManager_4_OUTPUT" OUTPUT FEATURE_TYPE $(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_HTMLReportGenerator_PROCESSED fme_html5_title "" fme_html5_config "HEADER{{TEXT;Feature Inspection Analysis;HEADER;H3;ALIGNMENT;LEFT;COLOR;0 0 0}}HTML{{HTML; h3 a href= https:docs.safe.com fme html FME_Desktop_Documentation FME_Workbench Workbench feature_inspection_about.htm Feature Inspection a h3 }}HEADER{{TEXT;Breakpoint Count: 0;HEADER;H4;ALIGNMENT;LEFT;COLOR;0 0 0}}LIST{{ATTR;BreakPointText;STYLE;NONE;COLOR;0 125 0;BADGE;" fme_html5_group_by "" fme_html5_xformer_name "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_HTMLReportGenerator" 847 | 848 | 849 | FACTORY_DEF * PythonFactory FACTORY_NAME $(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_HTMLReportGenerator INPUT FEATURE_TYPE $(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_HTMLReportGenerator_PROCESSED PYTHON_NAMESPACE FMEOBJECTS SYMBOL_NAME reportgenerator.html5assembler.HTML5Assembler OUTPUT PYOUTPUT FEATURE_TYPE "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_HTMLReportGenerator_OUTPUT" 850 | 851 | 852 | 853 | 854 | # ------------------------------------------------------------------------- 855 | 856 | 857 | FACTORY_DEF * AttrSetFactory FACTORY_NAME $(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_AttributeManager INPUT FEATURE_TYPE "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_HTMLReportGenerator_OUTPUT" INPUT FEATURE_TYPE "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_HTMLReportGenerator_2_OUTPUT" MULTI_FEATURE_MODE NO NULL_ATTR_MODE NO_OP ATTRSET_CREATE_DIRECTIVES _PROPAGATE_MISSING_FDIV ACTION_COLUMN 3 DEF_VAL_COLUMN 2 ATTR_ACTION "" "ReportOrder" "4" "SET_TO" OUTPUT OUTPUT FEATURE_TYPE "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_AttributeManager_OUTPUT" 858 | 859 | FACTORY_DEF * TeeFactory FACTORY_NAME "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_Output:Summary1492628397 Output Collector" INPUT FEATURE_TYPE "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_Junction_9_Output" OUTPUT FEATURE_TYPE "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_Output:Summary" 860 | FACTORY_DEF * TeeFactory FACTORY_NAME "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_Output:Report1492628397 Output Collector" INPUT FEATURE_TYPE "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_AttributeManager_OUTPUT" OUTPUT FEATURE_TYPE "$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME)_Output:Report" 861 | INCLUDE [puts {MACRO WB_CURRENT_CONTEXT $(WB_OLD_CONTEXT_$(BestPractice-BreakpointAnalysis_WORKSPACE_NAME))}] 862 | -------------------------------------------------------------------------------- /Transformers/BestPractice-NoFeaturesTester.fmx: -------------------------------------------------------------------------------- 1 | #! 2 | #! This transformer is a copy of the NoFeaturesTester specifically for the Best Practices Analysis project. 5 | # 391 | #! START_HEADER 392 | #! END_HEADER 393 | 394 | LOG_TIMINGS YES 395 | LOG_FILTER_MASK -1 396 | DEFAULT_MACRO WB_CURRENT_CONTEXT 397 | DEFAULT_MACRO BestPractice-NoFeaturesTester_WORKSPACE_NAME "" 398 | INCLUDE [puts {MACRO WB_OLD_CONTEXT_$(BestPractice-NoFeaturesTester_WORKSPACE_NAME) $(WB_CURRENT_CONTEXT)}; puts {MACRO WB_CURRENT_CONTEXT $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)}] 399 | FACTORY_DEF * TeeFactory FACTORY_NAME "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Input1491251795 Input Splitter" INPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Input" OUTPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Input_0_X7/VGfyvaBc=" OUTPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Input_1_KG5E4Al4jII=" 400 | # ------------------------------------------------------------------------- 401 | 402 | Tcl2 proc $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CoordSysRemover {} { global FME_CoordSys; set FME_CoordSys {}; } 403 | MACRO $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_XML NOT_ACTIVATED 404 | MACRO $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CLASSIC NOT_ACTIVATED 405 | MACRO $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_2D3D 2D_GEOMETRY 406 | MACRO $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_COORDSIt checks whether there are any input features. If not, then a single feature is ouput via the NOINPUT port. If INPUT features exist, then they are output via the INPUT output port.
6 | #Other transformers often generate features that signify an error condition. This transformer can be used to check for those features and if those features exists, then a separate action can be triggered.
7 | #Example
8 | #This may be useful to test if any data emerges from a reader, when the 'Ignore Failed Readers' advanced parameter is set to yes.
9 | # TRANSFORMER_END 10 | #! SHOW_ANNOTATIONS="true" 11 | #! USAGE="<p>Input Ports Input Features to be checked for existence</p> <p>Output Ports NoInput If no Input features exist, a single featue is returned via the NoInput port</p> <p>Output Any feature that entered the Input port is returned via the Output port</p>" 12 | #! FME_DOCUMENT_GUID="b6681f62-cb89-11e5-8a24-a45e60ee7e79" 13 | #! MARKDOWN_USAGE="Input Ports Input Features to be checked for existence Output Ports NoInput If no Input features exist, a single featue is returned via the NoInput port Output Any feature that entered the Input port is returned via the Output port " 14 | #! DOC_TOP_LEFT="-150 -600" 15 | #! BLOCKED_LOOPING="No" 16 | #! DOC_EXTENTS="3000 600" 17 | #! FME_PROCESS_GROUPS_ORDERED="No" 18 | #! ATTR_TYPE_ENCODING="SDF" 19 | #! LAST_SAVE_DATE="2017-04-03T15:36:35" 20 | #! EXPLICIT_BOOKMARK_ORDER="false" 21 | #! WARN_INVALID_XFORM_PARAM="Yes" 22 | #! FME_SERVER_SERVICES="" 23 | #! ZOOM_SCALE="100" 24 | #! WORKSPACE_VERSION="1" 25 | #! PASSWORD="" 26 | #! PYTHON_COMPATIBILITY="27" 27 | #! FMX_ATTRIBUTE_PROPOGATION_MODE="AUTO" 28 | #! FMX_INSERT_MODE="Linked by Default" 29 | #! HISTORY="2012-02-10,Aaron<space>Koning,Created,2016-02-04,Gerhard<space>Fischl,Compatibility<space>Update<space>for<space>FME<space>2016,2017-04-03,iMark,Exported<space>for<space>use<space>in<space>Best<space>Practices<space>Analysis" 30 | #! FME_PROCESS_COUNT="NO_PARALLELISM" 31 | #! FME_BUILD_NUM="17259" 32 | #! USE_MARKDOWN="YES" 33 | #! MAX_LOOP_ITERATIONS="" 34 | #! ITERATION_COUNT_ATTR="" 35 | #! FME_PROCESS_GROUP_BY="" 36 | #! CATEGORY="BestPractices" 37 | #! FME_DOCUMENT_PRIORGUID="d05c5f40-cb85-11e5-8a24-a45e60ee7e79,3ef3b7b8-cb87-11e5-8a24-a45e60ee7e79,9989f71e-cb87-11e5-8a24-a45e60ee7e79,6bf468c4-cb88-11e5-8a24-a45e60ee7e79" 38 | #! XFORM_DEPRECATED="No" 39 | #! MARKDOWN_DESCRIPTION="This transformer is a copy of the NoFeaturesTester specifically for the Best Practices Analysis project. It checks whether there are any input features. If not, then a single feature is ouput via the NOINPUT port. If INPUT features exist, then they are output via the INPUT output port. Other transformers often generate features that signify an error condition. This transformer can be used to check for those features and if those features exists, then a separate action can be triggered. Example This may be useful to test if any data emerges from a reader, when the 'Ignore Failed Readers' advanced parameter is set to yes. " 40 | #! DESCRIPTION="<p>This transformer is a copy of the NoFeaturesTester specifically for the Best Practices Analysis project.</p> <p>It checks whether there are any input features. If not, then a single feature is ouput via the NOINPUT port. If INPUT features exist, then they are output via the INPUT output port.</p> <p>Other transformers often generate features that signify an error condition. This transformer can be used to check for those features and if those features exists, then a separate action can be triggered.</p> <p>Example </p> <p>This may be useful to test if any data emerges from a reader, when the 'Ignore Failed Readers' advanced parameter is set to yes.</p>" 41 | #! TITLE="BestPractice-NoFeaturesTester" 42 | #! LAST_SAVE_BUILD="FME(R) 2017.0.0.0 (20170228 - Build 17259 - WIN32)" 43 | #! SHOW_INFO_NODES="true" 44 | #! FME_LINKED_TRANSFORMER_VERSION="1" 45 | #! VIEW_POSITION="-187.502 62.5006" 46 | #! > 47 | #!48 | #! 49 | #!50 | #! 51 | #!52 | #! 53 | #!54 | #! 55 | #!56 | #! 57 | #!58 | #! 59 | #!60 | #! 121 | #!75 | #! 90 | #! 105 | #! 120 | #! 122 | #! 123 | #!124 | #! 125 | #!126 | #! 270 | #!137 | #! 151 | #!138 | #! 139 | #! 140 | #! 141 | #! 142 | #! 143 | #! 144 | #! 145 | #! 146 | #! 147 | #! 148 | #! 149 | #! 150 | #! 162 | #! 177 | #!163 | #! 164 | #! 165 | #! 166 | #! 167 | #! 168 | #! 169 | #! 170 | #! 171 | #! 172 | #! 173 | #! 174 | #! 175 | #! 176 | #! 188 | #! 200 | #!189 | #! 190 | #! 191 | #! 192 | #! 193 | #! 194 | #! 195 | #! 196 | #! 197 | #! 198 | #! 199 | #! 211 | #! 224 | #!212 | #! 213 | #! 214 | #! 215 | #! 216 | #! 217 | #! 218 | #! 219 | #! 220 | #! 221 | #! 222 | #! 223 | #! 235 | #! 269 | #!236 | #! 237 | #! 238 | #! 239 | #! 240 | #! 241 | #! 242 | #! 243 | #! 244 | #! 245 | #! 246 | #! 247 | #! 248 | #! 249 | #! 250 | #! 251 | #! 252 | #! 253 | #! 254 | #! 255 | #! 256 | #! 257 | #! 258 | #! 259 | #! 260 | #! 261 | #! 262 | #! 263 | #! 264 | #! 265 | #! 266 | #! 267 | #! 268 | #! 271 | #! 303 | #!281 | #! 282 | #!291 | #! 292 | #!301 | #! 302 | #!304 | #! 382 | #!315 | #! 326 | #! 337 | #! 348 | #! 359 | #! 370 | #! 381 | #! 383 | #! 384 | #!385 | #! 386 | #!387 | #! 388 | #!389 | #! 390 | #!407 | INCLUDE [ if { {Geometry Object} == {Geometry Object} } { puts {MACRO $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_XML *} } ] 408 | INCLUDE [ if { {Geometry Object} == {2D Coordinate List} } { puts {MACRO $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_2D3D 2D_GEOMETRY}; puts {MACRO $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CLASSIC *} } ] 409 | INCLUDE [ if { {Geometry Object} == {3D Coordinate List} } { puts {MACRO $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_2D3D 3D_GEOMETRY}; puts {MACRO $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CLASSIC *} } ] 410 | INCLUDE [ if { {Geometry Object} == {2D Min/Max Box} } { set comment { We need to turn the COORDS which are minX minY maxX maxY into a full polygon list of coordinates }; set splitCoords [split [string trim { }]]; if { [llength $splitCoords] > 4} { set trimmedCoords {}; foreach item $splitCoords { if { $item != {} } {lappend trimmedCoords $item} }; set splitCoords $trimmedCoords; }; if { [llength $splitCoords] != 4 } { error {$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator: Coordinate list is expected to be a space delimited list of four numbers as 'minx miny maxx maxy' - ` ' is invalid}; }; set minX [lindex $splitCoords 0]; set minY [lindex $splitCoords 1]; set maxX [lindex $splitCoords 2]; set maxY [lindex $splitCoords 3]; puts "MACRO $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_COORDS $minX $minY $minX $maxY $maxX $maxY $maxX $minY $minX $minY"; puts {MACRO $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_2D3D 2D_GEOMETRY}; puts {MACRO $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CLASSIC *} } ] 411 | FACTORY_DEF $($(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_XML) CreationFactory FACTORY_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_XML_Creator CREATE_AT_END no OUTPUT FEATURE_TYPE _____CREATED______ @Geometry(FROM_ENCODED_STRING, ?xml version= 1.0encoding= US_ASCIIstandalone= no? geometry dimension= 2null geometry ) 412 | FACTORY_DEF $($(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CLASSIC) CreationFactory FACTORY_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CLASSIC_Creator $($(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_2D3D) $($(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_COORDS) CREATE_AT_END no OUTPUT FEATURE_TYPE _____CREATED______ 413 | FACTORY_DEF * TeeFactory FACTORY_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_Cloner INPUT FEATURE_TYPE _____CREATED______ NUMBER_OF_COPIES 1 COPY_NUMBER_ATTRIBUTE "no_features" OUTPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CREATED" @Tcl2($(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CoordSysRemover) @CoordSys() fme_feature_type $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator 414 | 415 | FACTORY_DEF * BranchingFactory FACTORY_NAME "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CREATED Brancher -1 14" INPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CREATED" TARGET_FACTORY "$(WB_CURRENT_CONTEXT)_CREATOR_BRANCH_TARGET" OUTPUT PASSED FEATURE_TYPE * @RemoveAttributes("$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CREATED Brancher -1 14".BranchingFactory.Count) 416 | # ------------------------------------------------------------------------- 417 | FACTORY_DEF * TeeFactory FACTORY_NAME "$(WB_CURRENT_CONTEXT)_CREATOR_BRANCH_TARGET" INPUT FEATURE_TYPE * OUTPUT FEATURE_TYPE * 418 | # ------------------------------------------------------------------------- 419 | 420 | INCLUDE [ puts "MACRO REAL_RATE [expr 1 * -1 ]" ] 421 | FACTORY_DEF * SamplingFactory FACTORY_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Sampler SAMPLE_RATE $(REAL_RATE) SAMPLE_ORDER ORIGINAL INPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Input_1_KG5E4Al4jII=" OUTPUT SAMPLED FEATURE_TYPE ___SAMPLED___ 422 | # This TeeFactory is needed because Sampler will still output features if it has no OUTPUT clauses specified. 423 | # This way we behave nicely even if there are no output connections on the transformer. See PR#28886. 424 | 425 | FACTORY_DEF * TeeFactory FACTORY_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Sampler_Sampled INPUT FEATURE_TYPE ___SAMPLED___ OUTPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Sampler_SAMPLED" 426 | 427 | 428 | # ------------------------------------------------------------------------- 429 | 430 | DEFAULT_MACRO __$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator_0ced5274_ecd9_472e_9306_888c15b4e2e50_GROUP_BY 431 | 432 | DYNAMIC_FUNCTION_CONFIGURATION Python FMEOBJECTS 433 | DYNAMIC_FUNCTION_CONFIGURATION Python import StatisticsCalculator 434 | DYNAMIC_FUNCTION_CONFIGURATION Python "StatisticsCalculator.connectTransformer( '$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator',{ 'GROUP_BY_MACRO':'__$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator_0ced5274_ecd9_472e_9306_888c15b4e2e50_GROUP_BY', 'STATS_ATTRS':'no_features', 'COUNT_ATTR':'NFT_count', 'COMPUTE_HISTOGRAM':'NO', 'HISTO_ATTR':' ', 'PREPEND_ATTR_NAME':'No', 'encoded_result_attrs':True, None:None})" 435 | FACTORY_DEF * TeeFactory FACTORY_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator_InputProcessor INPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Creator_CREATED" INPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Sampler_SAMPLED" OUTPUT FEATURE_TYPE __ORIGINAL__ @Python(StatisticsCalculator.recordFeature,$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator) 436 | FACTORY_DEF * TeeFactory FACTORY_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator_UnneededInputNuker INPUT FEATURE_TYPE __ORIGINAL__ 437 | FACTORY_DEF * SortFactory FACTORY_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator_CompleteOutputter INPUT FEATURE_TYPE __UNUSED_INPUT_TO_GUARANTEE_FACTORY_DOESNT_CONSUME_EVERYTHING__ 438 | FACTORY_DEF * CreationFactory FACTORY_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator_SummaryCreator CREATE_AT_END NUMBER_TO_CREATE 1 OUTPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator_SUMMARY" 439 | FACTORY_DEF * ElementFactory FACTORY_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator_SummaryExploder LIST_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator_stats{} MODE LEAN_AND_MEAN CLONE_GEOMETRY no INPUT FEATURE_TYPE __UNUSED_INPUT_TO_GUARANTEE_FACTORY_DOESNT_CONSUME_EVERYTHING__ INPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator_SUMMARY" @Python(StatisticsCalculator.summarizeStatistics,$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator,__SINGLE_GUY__) OUTPUT ELEMENT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator_SUMMARY" 440 | 441 | # ------------------------------------------------------------------------- 442 | 443 | FACTORY_DEF * TestFactory FACTORY_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Tester_2 INPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_StatisticsCalculator_SUMMARY" TEST @EvaluateExpression(FDIV,STRING_ENCODED, Value NFT_count ,$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Tester_2) = 1 ENCODED BOOLEAN_OPERATOR OR OUTPUT PASSED FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Tester_2_PASSED" 444 | # ------------------------------------------------------------------------- 445 | 446 | FACTORY_DEF * AttrSetFactory FACTORY_NAME $(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_AttributeCreator INPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Tester_2_PASSED" MULTI_FEATURE_MODE NO NULL_ATTR_MODE NO_OP ATTRSET_CREATE_DIRECTIVES _PROPAGATE_MISSING_FDIV ATTR_ACTION "" "no_features" "SET_TO" "true" OUTPUT OUTPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_AttributeCreator_OUTPUT" 447 | 448 | 449 | FACTORY_DEF * TeeFactory FACTORY_NAME "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_NoInput1491251795 Output Collector" INPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_AttributeCreator_OUTPUT" OUTPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_NoInput" @RemoveAttributes(no_features,NFT_count) 450 | FACTORY_DEF * TeeFactory FACTORY_NAME "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Output1491251795 Output Collector" INPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Input_0_X7/VGfyvaBc=" OUTPUT FEATURE_TYPE "$(BestPractice-NoFeaturesTester_WORKSPACE_NAME)_Output" 451 | INCLUDE [puts {MACRO WB_CURRENT_CONTEXT $(WB_OLD_CONTEXT_$(BestPractice-NoFeaturesTester_WORKSPACE_NAME))}] 452 | -------------------------------------------------------------------------------- /Transformers/BestPractice-ReportCollation.fmx: -------------------------------------------------------------------------------- 1 | #! 2 | #! This transformer takes Best Practice reports that have been summarized and creates a final HTML report from them. 5 | # 6 | # TRANSFORMER_END 7 | #! FME_DOCUMENT_PRIORGUID="770b1e20-fff3-4e52-bf4c-195d83788e28,81010d15-5caf-419f-8752-9e7ff5b79a86" 8 | #! LAST_SAVE_BUILD="FME(R) 2017.0.0.0 (20170228 - Build 17259 - WIN32)" 9 | #! ITERATION_COUNT_ATTR="" 10 | #! MAX_LOOP_ITERATIONS="" 11 | #! FME_SERVER_SERVICES="" 12 | #! BLOCKED_LOOPING="No" 13 | #! SHOW_ANNOTATIONS="true" 14 | #! DESCRIPTION="<p>This transformer takes Best Practice reports that have been summarized and creates a final HTML report from them.</p> " 15 | #! WORKSPACE_VERSION="1" 16 | #! FMX_INSERT_MODE="Linked by Default" 17 | #! EXPLICIT_BOOKMARK_ORDER="false" 18 | #! SHOW_INFO_NODES="true" 19 | #! FME_LINKED_TRANSFORMER_VERSION="1" 20 | #! PYTHON_COMPATIBILITY="27" 21 | #! MARKDOWN_USAGE="" 22 | #! PASSWORD="" 23 | #! FME_BUILD_NUM="17259" 24 | #! LAST_SAVE_DATE="2017-04-04T16:38:21" 25 | #! FME_PROCESS_COUNT="NO_PARALLELISM" 26 | #! CATEGORY="BestPractices" 27 | #! VIEW_POSITION="-1950.02 900.009" 28 | #! FME_DOCUMENT_GUID="5fc6dc8d-d93a-4503-8172-5efb4347d4b0" 29 | #! ZOOM_SCALE="100" 30 | #! ATTR_TYPE_ENCODING="SDF" 31 | #! DOC_TOP_LEFT="-872.399 -496.88" 32 | #! USAGE="" 33 | #! FME_PROCESS_GROUP_BY="" 34 | #! HISTORY="3rd<space>April<space>2017,iMark," 35 | #! FME_PROCESS_GROUPS_ORDERED="No" 36 | #! MARKDOWN_DESCRIPTION="This transformer takes Best Practice reports that have been summarized and creates a final HTML report from them." 37 | #! DOC_EXTENTS="2822.41 1243.76" 38 | #! FMX_ATTRIBUTE_PROPOGATION_MODE="AUTO" 39 | #! WARN_INVALID_XFORM_PARAM="Yes" 40 | #! XFORM_DEPRECATED="No" 41 | #! TITLE="BestPractice-ReportCollation" 42 | #! USE_MARKDOWN="YES" 43 | #! > 44 | #! 445 | DEFAULT_MACRO $(BestPractice-ReportCollation_WORKSPACE_NAME)_HTML_CONTENT45 | #! 46 | #!47 | #! 48 | #!49 | #! 50 | #!51 | #! 52 | #!53 | #! 54 | #!55 | #! 66 | #!60 | #! 65 | #! 67 | #! 128 | #!82 | #! 97 | #! 112 | #! 127 | #! 129 | #! 130 | #!131 | #! 143 | #!142 | #! 144 | #! 321 | #!155 | #! 164 | #!156 | #! 157 | #! 158 | #! 159 | #! 160 | #! 161 | #! 162 | #! 163 | #! 175 | #! 190 | #!176 | #! 177 | #! 178 | #! 179 | #! 180 | #! 181 | #! 182 | #! 183 | #! 184 | #! 185 | #! 186 | #! 187 | #! 188 | #! 189 | #! 201 | #! 216 | #!202 | #! 203 | #! 204 | #! 205 | #! 206 | #! 207 | #! 208 | #! 209 | #! 210 | #! 211 | #! 212 | #! 213 | #! 214 | #! 215 | #! 227 | #! 242 | #!228 | #! 229 | #! 230 | #! 231 | #! 232 | #! 233 | #! 234 | #! 235 | #! 236 | #! 237 | #! 238 | #! 239 | #! 240 | #! 241 | #! 253 | #! 268 | #!254 | #! 255 | #! 256 | #! 257 | #! 258 | #! 259 | #! 260 | #! 261 | #! 262 | #! 263 | #! 264 | #! 265 | #! 266 | #! 267 | #! 279 | #! 294 | #!280 | #! 281 | #! 282 | #! 283 | #! 284 | #! 285 | #! 286 | #! 287 | #! 288 | #! 289 | #! 290 | #! 291 | #! 292 | #! 293 | #! 305 | #! 320 | #!306 | #! 307 | #! 308 | #! 309 | #! 310 | #! 311 | #! 312 | #! 313 | #! 314 | #! 315 | #! 316 | #! 317 | #! 318 | #! 319 | #! 322 | #! 346 | #!331 | #! 332 | #!342 | #! 345 | #!343 | #! 344 | #! 347 | #! 436 | #!358 | #! 369 | #! 380 | #! 391 | #! 402 | #! 413 | #! 424 | #! 435 | #! 437 | #! 438 | #!439 | #! 440 | #!441 | #! 442 | #!443 | #! 444 | #!Value html_content 446 | DEFAULT_MACRO $(BestPractice-ReportCollation_WORKSPACE_NAME)_REPORTORDER Value ReportOrder 447 | #! START_HEADER 448 | #! END_HEADER 449 | 450 | LOG_TIMINGS YES 451 | LOG_FILTER_MASK -1 452 | DEFAULT_MACRO WB_CURRENT_CONTEXT 453 | DEFAULT_MACRO BestPractice-ReportCollation_WORKSPACE_NAME "" 454 | INCLUDE [puts {MACRO WB_OLD_CONTEXT_$(BestPractice-ReportCollation_WORKSPACE_NAME) $(WB_CURRENT_CONTEXT)}; puts {MACRO WB_CURRENT_CONTEXT $(BestPractice-ReportCollation_WORKSPACE_NAME)}] 455 | FACTORY_DEF * TeeFactory FACTORY_NAME "$(BestPractice-ReportCollation_WORKSPACE_NAME)_Input:Report1491341901 Input Splitter" INPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_Input:Report" OUTPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_Input:Report" "@EvaluateExpression(ATTR_CREATE_EXPR_PROPAGATE_MISSING_FDIV,html_content,$($(BestPractice-ReportCollation_WORKSPACE_NAME)_HTML_CONTENT),ReportOrder,$($(BestPractice-ReportCollation_WORKSPACE_NAME)_REPORTORDER), FEATURE_TYPE)" 456 | # ------------------------------------------------------------------------- 457 | 458 | FACTORY_DEF * SortFactory FACTORY_NAME $(BestPractice-ReportCollation_WORKSPACE_NAME)_Sorter INPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_Input:Report" SORT_BY ReportOrder NUMERIC ASCENDING OUTPUT SORTED FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_Sorter_SORTED" 459 | 460 | # ------------------------------------------------------------------------- 461 | 462 | MACRO casemac 463 | INCLUDE [ if { {NO} == {NO} } { puts {MACRO casemac -nocase}} ] 464 | Tcl2 proc $(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_99bd30e5_0412_454c_9a1e_923a9d4bbfff9_replacer { findText replaceText invalidValue} { set attrs [split \"html_content\" {,}]; set findValue [FME_DecodeText $findText]; set replaceValue [FME_DecodeText $replaceText]; foreach attr $attrs { set attrVal [FME_GetAttribute $attr]; set noMatch true; if {{NO} == {YES}} { set newAttrVal [FME_ReplaceRegex $(casemac) $findValue $attrVal $replaceValue]; } else { set newAttrVal [string map $(casemac) [list $findValue $replaceValue] $attrVal]; }; if { $newAttrVal ne $attrVal } { set noMatch false; FME_SetAttribute $attr $newAttrVal; }; if {$noMatch} { if { $invalidValue == {FME_NULL_VALUE} } { FME_SetAttributeNull $attr; } elseif { $invalidValue != {_FME_NO_OP_} } { FME_SetAttribute $attr [FME_DecodeText $invalidValue]; }; }; }; } 465 | FACTORY_DEF * TeeFactory FACTORY_NAME $(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer INPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_Sorter_SORTED" OUTPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_OUTPUT" @Tcl2("$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_99bd30e5_0412_454c_9a1e_923a9d4bbfff9_replacer { lt strong gt } { strong } {_FME_NO_OP_}") 466 | 467 | # ------------------------------------------------------------------------- 468 | 469 | MACRO casemac 470 | INCLUDE [ if { {NO} == {NO} } { puts {MACRO casemac -nocase}} ] 471 | Tcl2 proc $(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_2_af753dde_1bf2_4388_abd6_a3cfd566efe99_replacer { findText replaceText invalidValue} { set attrs [split \"html_content\" {,}]; set findValue [FME_DecodeText $findText]; set replaceValue [FME_DecodeText $replaceText]; foreach attr $attrs { set attrVal [FME_GetAttribute $attr]; set noMatch true; if {{NO} == {YES}} { set newAttrVal [FME_ReplaceRegex $(casemac) $findValue $attrVal $replaceValue]; } else { set newAttrVal [string map $(casemac) [list $findValue $replaceValue] $attrVal]; }; if { $newAttrVal ne $attrVal } { set noMatch false; FME_SetAttribute $attr $newAttrVal; }; if {$noMatch} { if { $invalidValue == {FME_NULL_VALUE} } { FME_SetAttributeNull $attr; } elseif { $invalidValue != {_FME_NO_OP_} } { FME_SetAttribute $attr [FME_DecodeText $invalidValue]; }; }; }; } 472 | FACTORY_DEF * TeeFactory FACTORY_NAME $(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_2 INPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_OUTPUT" OUTPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_2_OUTPUT" @Tcl2("$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_2_af753dde_1bf2_4388_abd6_a3cfd566efe99_replacer { lt strong gt } { strong } {_FME_NO_OP_}") 473 | 474 | # ------------------------------------------------------------------------- 475 | 476 | MACRO casemac 477 | INCLUDE [ if { {NO} == {NO} } { puts {MACRO casemac -nocase}} ] 478 | Tcl2 proc $(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_3_ce906ab0_f188_4878_937b_56e24cd17db09_replacer { findText replaceText invalidValue} { set attrs [split \"html_content\" {,}]; set findValue [FME_DecodeText $findText]; set replaceValue [FME_DecodeText $replaceText]; foreach attr $attrs { set attrVal [FME_GetAttribute $attr]; set noMatch true; if {{NO} == {YES}} { set newAttrVal [FME_ReplaceRegex $(casemac) $findValue $attrVal $replaceValue]; } else { set newAttrVal [string map $(casemac) [list $findValue $replaceValue] $attrVal]; }; if { $newAttrVal ne $attrVal } { set noMatch false; FME_SetAttribute $attr $newAttrVal; }; if {$noMatch} { if { $invalidValue == {FME_NULL_VALUE} } { FME_SetAttributeNull $attr; } elseif { $invalidValue != {_FME_NO_OP_} } { FME_SetAttribute $attr [FME_DecodeText $invalidValue]; }; }; }; } 479 | FACTORY_DEF * TeeFactory FACTORY_NAME $(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_3 INPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_2_OUTPUT" OUTPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_3_OUTPUT" @Tcl2("$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_3_ce906ab0_f188_4878_937b_56e24cd17db09_replacer { lt br gt } { br } {_FME_NO_OP_}") 480 | 481 | # ------------------------------------------------------------------------- 482 | 483 | MACRO casemac 484 | INCLUDE [ if { {NO} == {NO} } { puts {MACRO casemac -nocase}} ] 485 | Tcl2 proc $(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_4_154b1673_502e_419e_be27_308681b425ed9_replacer { findText replaceText invalidValue} { set attrs [split \"html_content\" {,}]; set findValue [FME_DecodeText $findText]; set replaceValue [FME_DecodeText $replaceText]; foreach attr $attrs { set attrVal [FME_GetAttribute $attr]; set noMatch true; if {{NO} == {YES}} { set newAttrVal [FME_ReplaceRegex $(casemac) $findValue $attrVal $replaceValue]; } else { set newAttrVal [string map $(casemac) [list $findValue $replaceValue] $attrVal]; }; if { $newAttrVal ne $attrVal } { set noMatch false; FME_SetAttribute $attr $newAttrVal; }; if {$noMatch} { if { $invalidValue == {FME_NULL_VALUE} } { FME_SetAttributeNull $attr; } elseif { $invalidValue != {_FME_NO_OP_} } { FME_SetAttribute $attr [FME_DecodeText $invalidValue]; }; }; }; } 486 | FACTORY_DEF * TeeFactory FACTORY_NAME $(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_4 INPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_3_OUTPUT" OUTPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_4_OUTPUT" @Tcl2("$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_4_154b1673_502e_419e_be27_308681b425ed9_replacer { lt i gt } { i } {_FME_NO_OP_}") 487 | 488 | # ------------------------------------------------------------------------- 489 | 490 | MACRO casemac 491 | INCLUDE [ if { {NO} == {NO} } { puts {MACRO casemac -nocase}} ] 492 | Tcl2 proc $(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_5_5e1205a9_3d97_4526_8153_b992bcb34acc9_replacer { findText replaceText invalidValue} { set attrs [split \"html_content\" {,}]; set findValue [FME_DecodeText $findText]; set replaceValue [FME_DecodeText $replaceText]; foreach attr $attrs { set attrVal [FME_GetAttribute $attr]; set noMatch true; if {{NO} == {YES}} { set newAttrVal [FME_ReplaceRegex $(casemac) $findValue $attrVal $replaceValue]; } else { set newAttrVal [string map $(casemac) [list $findValue $replaceValue] $attrVal]; }; if { $newAttrVal ne $attrVal } { set noMatch false; FME_SetAttribute $attr $newAttrVal; }; if {$noMatch} { if { $invalidValue == {FME_NULL_VALUE} } { FME_SetAttributeNull $attr; } elseif { $invalidValue != {_FME_NO_OP_} } { FME_SetAttribute $attr [FME_DecodeText $invalidValue]; }; }; }; } 493 | FACTORY_DEF * TeeFactory FACTORY_NAME $(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_5 INPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_4_OUTPUT" OUTPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_5_OUTPUT" @Tcl2("$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_5_5e1205a9_3d97_4526_8153_b992bcb34acc9_replacer { lt i gt } { i } {_FME_NO_OP_}") 494 | 495 | # ------------------------------------------------------------------------- 496 | 497 | FACTORY_DEF * TeeFactory INPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_StringReplacer_5_OUTPUT" OUTPUT FEATURE_TYPE $(BestPractice-ReportCollation_WORKSPACE_NAME)_HTMLLayouter_PROCESSED fme_html5_layout "VERTICAL" fme_html5_column " " fme_html5_row " " fme_html5_title "" fme_html5_div_style "VERTICAL" 498 | 499 | 500 | FACTORY_DEF * PythonFactory FACTORY_NAME $(BestPractice-ReportCollation_WORKSPACE_NAME)_HTMLLayouter INPUT FEATURE_TYPE $(BestPractice-ReportCollation_WORKSPACE_NAME)_HTMLLayouter_PROCESSED PYTHON_NAMESPACE FMEOBJECTS SYMBOL_NAME reportgenerator.html5layouter.HTML5Layouter OUTPUT PYOUTPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_HTMLLayouter_OUTPUT" 501 | 502 | FACTORY_DEF * TeeFactory FACTORY_NAME "$(BestPractice-ReportCollation_WORKSPACE_NAME)_Output1491341901 Output Collector" INPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_HTMLLayouter_OUTPUT" OUTPUT FEATURE_TYPE "$(BestPractice-ReportCollation_WORKSPACE_NAME)_Output" 503 | INCLUDE [puts {MACRO WB_CURRENT_CONTEXT $(WB_OLD_CONTEXT_$(BestPractice-ReportCollation_WORKSPACE_NAME))}] 504 | -------------------------------------------------------------------------------- /Transformers/BestPractice-ReportHeader.fmx: -------------------------------------------------------------------------------- 1 | #! 2 | #! This transformer creates a Best Practice report that acts as the report header. 5 | # 6 | # TRANSFORMER_END 7 | #! TITLE="BestPractice-ReportHeader" 8 | #! FME_PROCESS_GROUP_BY="" 9 | #! FME_DOCUMENT_PRIORGUID="0276fa73-5fa2-4c85-9899-f6fd16b9a1cf" 10 | #! VIEW_POSITION="-1656.27 156.252" 11 | #! FME_SERVER_SERVICES="" 12 | #! CATEGORY="BestPractices" 13 | #! ATTR_TYPE_ENCODING="SDF" 14 | #! USAGE="" 15 | #! EXPLICIT_BOOKMARK_ORDER="false" 16 | #! FME_BUILD_NUM="17259" 17 | #! WARN_INVALID_XFORM_PARAM="Yes" 18 | #! SHOW_INFO_NODES="true" 19 | #! SHOW_ANNOTATIONS="true" 20 | #! MARKDOWN_DESCRIPTION="This transformer creates a Best Practice report that acts as the report header." 21 | #! DOC_EXTENTS="3400.4 1041.44" 22 | #! MARKDOWN_USAGE="" 23 | #! PYTHON_COMPATIBILITY="27" 24 | #! FMX_ATTRIBUTE_PROPOGATION_MODE="AUTO" 25 | #! WORKSPACE_VERSION="1" 26 | #! HISTORY="19.april<space>2017,Sigbj<u00f8>rn<space>Herstad<space>-<space>Norkart,Added<space>file<space>information,3rd<space>April<space>2017,iMark," 27 | #! BLOCKED_LOOPING="No" 28 | #! FME_DOCUMENT_GUID="88d76233-fc09-49c0-a7f0-fcc685e6e7d2" 29 | #! ITERATION_COUNT_ATTR="" 30 | #! ZOOM_SCALE="100" 31 | #! USE_MARKDOWN="YES" 32 | #! LAST_SAVE_BUILD="FME(R) 2017.0.0.0 (20170228 - Build 17259 - WIN32)" 33 | #! DOC_TOP_LEFT="-1378.14 -963.315" 34 | #! MAX_LOOP_ITERATIONS="" 35 | #! FME_PROCESS_COUNT="NO_PARALLELISM" 36 | #! DESCRIPTION="<p>This transformer creates a Best Practice report that acts as the report header.</p> " 37 | #! XFORM_DEPRECATED="No" 38 | #! FME_PROCESS_GROUPS_ORDERED="No" 39 | #! LAST_SAVE_DATE="2017-04-20T11:26:42" 40 | #! PASSWORD="" 41 | #! FMX_INSERT_MODE="Linked by Default" 42 | #! FME_LINKED_TRANSFORMER_VERSION="2" 43 | #! > 44 | #!