Skip to content
Newer
Older
100755 568 lines (510 sloc) 23 KB
b210049 @fufler first commit
authored
1 #!/bin/env python2
2 # Copyright (C) 2011 Alex Ermakov
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
71d3c50 @fufler * Indentation changed to tabs
authored
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
b210049 @fufler first commit
authored
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
71d3c50 @fufler * Indentation changed to tabs
authored
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
b210049 @fufler first commit
authored
16
17 # import section
18 import argparse
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
19 import copy
b210049 @fufler first commit
authored
20 import os
71d3c50 @fufler * Indentation changed to tabs
authored
21 import sys
b210049 @fufler first commit
authored
22 import re
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
23 import libxml2
b210049 @fufler first commit
authored
24
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
25 # exception classes
26 class ValidationException(Exception):
27 '''Super class for validation exceptions.'''
28 pass
b210049 @fufler first commit
authored
29
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
30 class InvalidSchemaException(ValidationException):
31 '''Exception to raise when schema is invalid.'''
32 pass
71d3c50 @fufler * Indentation changed to tabs
authored
33
34
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
35 class InvalidProcDefException(ValidationException):
36 '''Exception to raise when process definition is invalid.'''
37 pass
71d3c50 @fufler * Indentation changed to tabs
authored
38
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
39 class InvalidTaskModelException(ValidationException):
40 '''Exception to raise when task model is invalid.'''
41 pass
42
43 # config generator class
44 class ConfigGenerator:
45 '''ConfigGenerator class. Generates skeleton of Alfresco configuration files'''
46
47 def noErr(self, ctx, str):
48 '''Dummy function to suppress error messages.'''
49 pass
50
51 def __init__(self, xmlFile, addComments = False):
52 '''Class constructor. Collects some information needed for config generation, loads XML.
53
54 Keyword arguments:
55 addComments -- add comments to result XML (default False)
56 xmlFile -- file that contains XML to parse
57
58 '''
59 # get path to script
60 self.scriptPath = os.path.dirname(sys.argv[0])
61 # default options
62 self.addComments = addComments
63 self.xmlFile = xmlFile
64 # suppress all error messages from libxml2
65 libxml2.registerErrorHandler(self.noErr, None)
66 # load xml
67 self.xml = libxml2.readFile(xmlFile, None, 0)
68
69 def removeBlankNodes(self, node):
70 '''Removes all blank nodes from result xml'''
71
72 # iterate through node children and remove blank nodes
73 item = node.children
74 while item:
75 if item.isBlankNode():
76 # remove node
77 t = item.next
78 item.unlinkNode()
79 # get next node
80 item = t
81 else:
82 # call recursively
83 self.removeBlankNodes(item)
84 # get next node
85 item = item.next
86
87
88 def validateProcessDefinition(self):
89 '''Validates process definition and return default namespace on success.'''
90 # try to validate XML as jpdl-3.1
91 ns = 'urn:jbpm.org:jpdl-3.1'
92 try:
93 # load 3.1 schema
94 schema_parser_ctx = libxml2.schemaNewParserCtxt(os.path.join(self.scriptPath, 'schemas', 'jpdl-3.1.xsd'))
95 schema = schema_parser_ctx.schemaParse()
96 valid_schema = schema.schemaNewValidCtxt()
97 except libxml2.libxmlError, e:
98 raise InvalidSchemaException('jpdl-3.1 schema is invalid')
99 # validate
100 if self.xml.schemaValidateDoc(valid_schema):
101 # it's not jpdl-3.1, try to validate as jpdl-3.2
102 ns = 'urn:jbpm.org:jpdl-3.2'
103 try:
104 # load 3.2 schema
105 schema_parser_ctx = libxml2.schemaNewParserCtxt(os.path.join(self.scriptPath, 'schemas', 'jpdl-3.2.xsd'))
106 schema = schema_parser_ctx.schemaParse()
107 valid_schema = schema.schemaNewValidCtxt()
108 except libxml2.libxmlError, e:
109 raise InvalidSchemaException('jpdl-3.2 schema is invalid')
110 # validate
111 if self.xml.schemaValidateDoc(valid_schema):
112 # throw exception, because document is not valid
113 raise InvalidProcDefException('This is not valid jpdl-3.1 or jpdl-3.2 XML.');
114
115 # return default namespace
116 return ns
117
118 def validateTaskModel(self):
119 '''Validates task model XML and returns default namespace on success'''
120 try:
121 # load schema
122 schema_parser_ctx = libxml2.schemaNewParserCtxt(os.path.join(self.scriptPath, 'schemas', 'modelSchema.xsd'))
123 schema = schema_parser_ctx.schemaParse()
124 valid_schema = schema.schemaNewValidCtxt()
125 except libxml2.libxmlError, e:
126 raise InvalidSchemaException('Task model schema is invalid')
127
e418e4a @fufler * fixed task model validation
authored
128 # validate
129 if self.xml.schemaValidateDoc(valid_schema):
130 # throw exception, because document is not valid
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
131 raise InvalidTaskModelException('Task model XML is invalid.')
132
133 return 'http://www.alfresco.org/model/dictionary/1.0'
134
135
136 def addSwimlanes(self):
137 '''Parses process definition and adds swimlane tags to the top of it.'''
138
139 # set result type
140 self.xmlResult = True
141 # validate process definition XML
142 ns = self.validateProcessDefinition()
143 # clone xml
144 self.result = copy.copy(self.xml)
145 # get new xpath context
146 ctx = self.result.xpathNewContext()
147 # register default namespace
148 ctx.xpathRegisterNs('dd', ns)
149
150 # populate swimlane list
151 swimlanes = [x.prop('swimlane') for x in ctx.xpathEval('/dd:process-definition/dd:task-node/dd:task[@swimlane != \'\']')]
152 # iterate through swimlane list and generate nodes
153 for swimlane in swimlanes:
154 # create new node
155 swimlaneNode = self.result.newDocNode(None, 'swimlane', None)
156 swimlaneNode.setProp('name', swimlane)
157 # create assignment if swimlane != initiator
158 if swimlane != 'initiator':
159 # set assignment
160 assignmentNode = self.result.newDocNode(None, 'assignment', None)
161 assignmentNode.setProp('class', 'org.alfresco.repo.workflow.jbpm.AlfrescoAssignment')
162 swimlaneNode.addChild(assignmentNode)
163 # set actor
164 assignmentNode.addChild(self.result.newDocNode(None, 'actor', '#{'+swimlane+'}'))
165 # add comment if needed
166 if self.addComments:
167 self.result.getRootElement().addChild(self.result.newDocComment("'"+swimlane+"' swimlane"))
168 # add swimlane to tree
169 self.result.getRootElement().addChild(swimlaneNode)
170
171 def generateTaskModel(self, addMetaData = False, addMandatoryAspects = False, addItemActions = False, addAspectDef = False):
172 '''Parses process definition and generates task model for it.
173
174 Keyword arguments:
175 addMetadata -- add metadata to result XML (default False)
176 addMandatoryAspects -- add <mandatory-aspects> tag to each type item (default False)
177 addItemActions -- add overrides section for bpm:packageItemActionGroup property to each type item (default False)
178 addAspectDef -- add custom aspect definition section to the end of task model XML (default False)
179
180 '''
181
182 # set result type
183 self.xmlResult = True
184 # validate process definition XML
185 ns = self.validateProcessDefinition()
186 # get new xpath context
187 ctx = self.xml.xpathNewContext()
188 # register default namespace
189 ctx.xpathRegisterNs('dd', ns)
190 # create model skeleton
191 modelTemplate = '''<?xml version='1.0'?><model xmlns='http://www.alfresco.org/model/dictionary/1.0'></model>'''
192 importTemplate = '''<imports><import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d" /><import uri="http://www.alfresco.org/model/bpm/1.0" prefix="bpm" /></imports>'''
193 customAspectTemplate = '''<aspects><aspect name='ns:customAspect'><title>Custom aspect sample</title><properties><property name='ns:customProperty'><type>d:string</type><mandatory>false</mandatory><multiple>false</multiple></property></properties></aspect></aspects>'''
194 overridesTemplate = '''<overrides><property name='bpm:packageItemActionGroup'><default>edit_package_item_actions</default></property></overrides>'''
195
196 self.result = libxml2.parseMemory(modelTemplate, len(modelTemplate))
197 root = self.result.getRootElement()
198 # add metadata
199 if self.addComments:
200 root.addChild(self.result.newDocComment('Model metadata'))
201 root.addChild(self.result.newDocNode(None, 'description', 'Task model for '+self.xmlFile))
202 root.addChild(self.result.newDocNode(None, 'author', os.getenv('USER')))
203 root.addChild(self.result.newDocNode(None, 'version', '1.0'))
204 # add import section
205 if self.addComments:
206 root.addChild(self.result.newDocComment('Import necessary namespaces'))
207 root.addChild(libxml2.parseMemory(importTemplate, len(importTemplate)).getRootElement())
208 # populate task list
209 tasks = ctx.xpathEval('/dd:process-definition/dd:*/dd:task')
210 # iterate through all task and build task model and collect namespaces
211 namespaces = set()
212 parentNode = {'start-state': 'bpm:startTask', 'task-node': 'bpm:workflowTask'}
213 typesNode = self.result.newDocNode(None, 'types', None)
214 ns = ''
215 for task in tasks:
216 taskName = task.prop('name')
217 # extract namespace
218 gr = re.search('^(.+):(.*)$', taskName)
219 if gr:
220 ns = gr.group(1)
221 else:
222 ns = ''
223 namespaces.add(ns)
224 # add new type element
225 typeNode = self.result.newDocNode(None, 'type', None)
226 typeNode.setProp('name', taskName)
227 # add parent node
228 typeNode.addChild(self.result.newDocNode(None, 'parent', parentNode[task.parent.name]))
229 # add overrides section
230 if addItemActions:
231 if self.addComments:
232 typeNode.addChild(self.result.newDocComment('overrides default properties values'))
233 typeNode.addChild(libxml2.parseMemory(overridesTemplate, len(overridesTemplate)).getRootElement())
234 # add mandatory aspects
235 if addMandatoryAspects:
236 aspectsNode = self.result.newDocNode(None, 'mandatory-aspects', None)
237 # add bpm:assignee for start task
238 if task.parent.name == 'start-state':
239 aspectsNode.addChild(self.result.newDocNode(None, 'aspect', 'bpm:assignee'))
240 # add custom aspect
241 aspectsNode.addChild(self.result.newDocNode(None, 'aspect', ns+':customAspect'))
242 # add aspects to tree
243 if self.addComments:
244 typeNode.addChild(self.result.newDocComment('Task mandatory aspects'))
245 typeNode.addChild(aspectsNode)
71d3c50 @fufler * Indentation changed to tabs
authored
246
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
247 # add node to tree
248 if self.addComments:
249 typesNode.addChild(self.result.newDocComment('Type for '+taskName+' task'))
250 typesNode.addChild(typeNode)
251
252 # add found namespaces to task model
253 namespacesNode = self.result.newDocNode(None, 'namespaces', None)
254 for ns in namespaces:
255 # create new node
256 namespaceNode = self.result.newDocNode(None, 'namespace', None)
257 namespaceNode.setProp('prefix', ns)
258 namespaceNode.setProp('uri', 'https://github.com/fufler/aconfgen/prefix/'+ns)
259 # add node to tree
260 namespacesNode.addChild(namespaceNode)
261
262 # add namespaces and types node to tree
263 if self.addComments:
264 root.addChild(self.result.newDocComment('List of found namespaces in process definition'))
265 root.addChild(namespacesNode)
266 if self.addComments:
267 root.addChild(self.result.newDocComment('List of types'))
268 root.addChild(typesNode)
269 # add custom aspect definition
270 if addAspectDef:
271 if self.addComments:
272 root.addChild(self.result.newDocComment('Custom aspect definition sample'))
273 # replace ns: with last found namespace (we expect exact one)
274 customAspectTemplate = customAspectTemplate.replace('ns:', ns+':')
275 root.addChild(libxml2.parseMemory(customAspectTemplate, len(customAspectTemplate)).getRootElement())
276 # set models name using last found namespace
277 self.result.getRootElement().setProp('name', ns+':samplemodel')
278
279
280
281 def generateWorkflowUIConfig(self, processName, addLabelId = False, addSets = False):
282 '''Generates skeleton of share-custom-config.xml for workflow UI rendering.
283
284 Keyword arguments:
285 processName -- process name to use in generated config (default '')
286 addLabelId -- insert label-id attribute into each filed tag (default False)
287 addSets -- add sets definitions to each form (default False)
288
289 '''
290
291 # set result type
292 self.xmlResult = True
293 # validate xml
294 ns = self.validateTaskModel()
295 # get new xpath context
296 ctx = self.xml.xpathNewContext()
297 # register default namespace
298 ctx.xpathRegisterNs('dd', ns)
299 # build config for workflow UI rendering
300 # create new document and root node
301 self.result = libxml2.newDoc('1.0')
302 root = self.result.newDocNode(None, 'alfresco-config', None)
303 self.result.setRootElement(root)
304 # populate task type list
305 types = ctx.xpathEval('/dd:model/dd:types/dd:type')
306 # iterate throught all types and build config
307 for typeNode in types:
308 ctx.setContextNode(typeNode)
309 # create config node
310 configNode = self.result.newDocNode(None, 'config', None)
311 # if this is startTask then we should use another condition
312 if 'bpm:startTask' in [x.content for x in ctx.xpathEval('dd:parent')]:
313 configNode.setProp('evalutor', 'string-compare')
314 configNode.setProp('condition', 'jbpm$'+processName)
315 else:
316 configNode.setProp('evalutor', 'task-type')
317 configNode.setProp('condition', typeNode.prop('name'))
318 if self.addComments:
319 root.addChild(self.result.newDocComment('Form config for '+typeNode.prop('name')+' rendering'))
320 root.addChild(configNode)
321 # create forms and form nodes
322 formsNode = self.result.newDocNode(None, 'forms', None)
323 formNode = self.result.newDocNode(None, 'form', None)
324 configNode.addChild(formsNode)
325 formsNode.addChild(formNode)
326 # create field-visibility and appearance nodes
327 fieldVisNode = self.result.newDocNode(None, 'field-visibility', None)
328 if self.addComments:
329 formNode.addChild(self.result.newDocComment('List of fields to render'))
330 formNode.addChild(fieldVisNode)
331 appearanceNode = self.result.newDocNode(None, 'appearance', None)
332 if self.addComments:
333 formNode.addChild(self.result.newDocComment('Fields appearance configuration'))
334 formNode.addChild(appearanceNode)
335 # add sets definitions
336 if self.addComments:
337 fieldVisNode.addChild(self.result.newDocComment('Controls sets'))
338 if addSets:
339 if self.addComments:
340 appearanceNode.addChild(self.result.newDocComment('Sets definition'))
341 # top set
342 setNode = self.result.newDocNode(None, 'set', None)
343 setNode.setProp('id', 'info')
344 setNode.setProp('appearance', '')
345 if addLabelId:
346 setNode.setProp('label-id', 'workflow.set.task.info')
347 appearanceNode.addChild(setNode)
348 # other set
349 setNode = self.result.newDocNode(None, 'set', None)
350 setNode.setProp('id', 'other')
351 setNode.setProp('appearance', 'title')
352 if addLabelId:
353 setNode.setProp('label-id', 'workflow.set.other')
354 appearanceNode.addChild(setNode)
355 # items set
356 setNode = self.result.newDocNode(None, 'set', None)
357 setNode.setProp('id', 'items')
358 setNode.setProp('appearance', 'title')
359 if addLabelId:
360 setNode.setProp('label-id', 'workflow.set.items')
361 appearanceNode.addChild(setNode)
362 # response set
363 if 'bpm:startTask' not in [x.content for x in ctx.xpathEval('dd:parent')]:
364 setNode = self.result.newDocNode(None, 'set', None)
365 setNode.setProp('id', 'response')
366 setNode.setProp('appearance', 'title')
367 if addLabelId:
368 setNode.setProp('label-id', 'workflow.set.response')
369 appearanceNode.addChild(setNode)
370
371 # populate all aspects for type
372 aspects = [x.content for x in ctx.xpathEval('dd:mandatory-aspects/dd:aspect')]
373 # for each aspect try to find its definition to extract all properties and associations
374 if self.addComments:
375 appearanceNode.addChild(self.result.newDocComment('Fields'))
376 for aspect in aspects:
377 aspectDefNode = ctx.xpathEval('/dd:model/dd:aspects/dd:aspect[@name=\''+aspect+'\']')
378 # if list is not empty then choose first element (because we expect at most one aspect definition)
379 if len(aspectDefNode):
380 aspectDefNode = aspectDefNode[0]
381 # find all properties and associations
382 ctx.setContextNode(aspectDefNode)
383 fields = [x.prop('name') for x in ctx.xpathEval('dd:properties/dd:property') + ctx.xpathEval('dd:associations/dd:association')]
384 # add them to tree
385 for field in fields:
386 # create show and field nodes
387 showNode = self.result.newDocNode(None, 'show', None)
388 showNode.setProp('id', field)
389 fieldVisNode.addChild(showNode)
390 fieldNode = self.result.newDocNode(None, 'field', None)
391 fieldNode.setProp('id', field)
392 if addLabelId:
393 fieldNode.setProp('label-id', 'label.'+field.replace(':','_'))
394 if addSets:
395 fieldNode.setProp('set', 'other')
396 appearanceNode.addChild(fieldNode)
397 else:
398 # aspect definition not found, add field with the same name as aspect
399 # create show and field nodes
400 showNode = self.result.newDocNode(None, 'show', None)
401 showNode.setProp('id', aspect)
402 fieldVisNode.addChild(showNode)
403 fieldNode = self.result.newDocNode(None, 'field', None)
404 fieldNode.setProp('id', aspect)
405 if addLabelId:
406 fieldNode.setProp('label-id', 'label.'+aspect.replace(':','_'))
407 if addSets:
408 fieldNode.setProp('set', 'other')
409 appearanceNode.addChild(fieldNode)
410 # add items field
411 showNode = self.result.newDocNode(None, 'show', None)
412 showNode.setProp('id', 'packageItems')
413 fieldVisNode.addChild(showNode)
414 fieldNode = self.result.newDocNode(None, 'field', None)
415 fieldNode.setProp('id', 'packageItems')
416 if addSets:
417 fieldNode.setProp('set', 'items')
418 appearanceNode.addChild(fieldNode)
419 # add transitions field
420 ctx.setContextNode(typeNode)
421 if 'bpm:startTask' not in [x.content for x in ctx.xpathEval('dd:parent')]:
422 showNode = self.result.newDocNode(None, 'show', None)
423 showNode.setProp('id', 'transitions')
424 fieldVisNode.addChild(showNode)
425 fieldNode = self.result.newDocNode(None, 'field', None)
426 fieldNode.setProp('id', 'transitions')
427 if addSets:
428 fieldNode.setProp('set', 'response')
429 appearanceNode.addChild(fieldNode)
430 else:
431 # create form for workflow details rendering
432 configNode = configNode.copyNodeList()
433 # replace condition
434 configNode.setProp('evalutor', 'task-type')
435 configNode.setProp('condition', typeNode.prop('name'))
436 if self.addComments:
437 root.addChild(self.result.newDocComment('Form config to display workflow info'))
438 # remove info set
439 if addSets:
440 resctx = self.result.xpathNewContext()
441 resctx.setContextNode(configNode)
442 resctx.xpathEval('forms/form/appearance/set[@id=\'info\']')[0].unlinkNode()
443 # add to tree
444 root.addChild(configNode)
445
446 def generateWorkflowBundle(self):
447 '''Generates workflow internationalization bundle'''
448
449 # set result type
450 self.xmlResult = False
451
452 def generateWorkflowBundle(self):
453 '''Generates workflow internationalization bundle (tasks and transitions)'''
454
455 # set result type
456 self.xmlResult = False
457 # validate process definition XML
458 ns = self.validateProcessDefinition()
459 # get new xpath context
460 ctx = self.xml.xpathNewContext()
461 # register default namespace
462 ctx.xpathRegisterNs('dd', ns)
463 # get process name
464 procName = self.xml.getRootElement().prop('name').replace(':', '_')
465 # add process string
466 tmp = [procName+'.workflow']
467 # get tasks with non-empty name replacing : by _ and add them to temporary list
468 tmp.extend([procName+'.task.'+x.prop('name').replace(':', '_') for x in ctx.xpathEval('/dd:process-definition/dd:task-node/dd:task[@name!=\'\']')])
469 # get all transitions and add them to temporary list
470 tmp.extend([procName+'.node.'+x.parent.prop('name')+'.transition.'+x.prop('name') for x in ctx.xpathEval('/dd:process-definition/dd:task-node[@name!=\'\']/dd:transition[@name!=\'\']')])
471 # create result list
472 self.result = []
473 for x in tmp:
474 self.result.extend([x+'.title=', x+'.description='])
475
476
477 def generateShareBundle(self):
478 '''Generates share internationalization bundle for found label-id attributes'''
479 # set result type
480 self.xmlResult = False
481 # get new xpath context
482 ctx = self.xml.xpathNewContext()
483 self.result = [x.prop('label-id')+'=' for x in ctx.xpathEval('/alfresco-config/config/forms/form/appearance/field[@label-id!=\'\']')]
484
485 def printListResult(self):
486 '''Prints result list'''
487
488 for x in self.result:
489 print(x)
490
491 # run script
492 if __name__ == '__main__':
493 # parse command line arguments
494
495 # create argument parser
496 parser = argparse.ArgumentParser(description='Generates skeleton of some Alfresco configuration files using process definition XML, task model, share custom config.')
497
498 # add file argument
499 parser.add_argument('file', metavar='XML', help='XML file, containing process definition in jPDL/workflow model/share config (use \'-\' to read from stdin)')
500
501 # add group of arguments for specifying action to perform
502 actionArgs = parser.add_mutually_exclusive_group( required=True)
503 actionArgs.add_argument('-s', '--swimlanes', action='store_true', help='generate swimlane tags for process definition')
504 actionArgs.add_argument('-m', '--model', action='store_true', help='generate skeleton of workflow model XML')
505 actionArgs.add_argument('-w', '--workflow-ui', action='store_true', help='generate skeleton of share-config-custom.xml for workflow UI rendering')
506 actionArgs.add_argument('-W', '--workflow-i18n', action='store_true', help='generate workflow internationalization bundle')
507 actionArgs.add_argument('-e', '--share-i18n', action='store_true', help='generate share internationalization bundle')
508
509 # add arguments related to model generation
510 modelArgs = parser.add_argument_group('Model generation options')
511 modelArgs.add_argument('-M', '--mandatory-aspects', action='store_true', help='add mandatory-aspects section to each workflow model type')
512 modelArgs.add_argument('-d', '--metadata', action='store_true', help='add metadata to model')
513 modelArgs.add_argument('-i', '--item-actions', action='store_true', help='add item-actions section to each workflow model type')
514 modelArgs.add_argument('-a', '--aspect', action='store_true', help='add dummy aspect definition section')
515
516 # add arguments related to share config generation
517 workflowUIArgs = parser.add_argument_group('Workflow UI config generation options')
09bac56 @fufler * errors in help string fixed
authored
518 workflowUIArgs.add_argument('-n', '--process-name', default='', action='store', help='workflow process name to be used in generated config (adds $jbpm prefix automatically)')
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
519 workflowUIArgs.add_argument('-l', '--label-id', action='store_true', help='insert label-id attribute into each field tag')
09bac56 @fufler * errors in help string fixed
authored
520 workflowUIArgs.add_argument('-S', '--sets', action='store_true', help='add sets definitions and set correspoding field attribute')
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
521
522 # add arguments related to XML output
523 outputArgs = parser.add_argument_group('Output arguments')
524 outputArgs.add_argument('-f', '--format', action='store_true', help='format output with blanks (works only if -r specified)')
09bac56 @fufler * errors in help string fixed
authored
525 outputArgs.add_argument('-c', '--comments', action='store_true', help='add comments to resulting XML')
526 outputArgs.add_argument('-r', '--remove-blanks', action='store_true', help='remove all blank nodes from resulting XML')
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
527
528 # parse arguments
529 args = parser.parse_args()
530
531 # create ConfigGenerator
71d3c50 @fufler * Indentation changed to tabs
authored
532 try:
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
533 confgen = ConfigGenerator(args.file, args.comments)
534 except libxml2.libxmlError, e:
535 print('Cannot parse XML. Terminating.')
536 sys.exit(1);
71d3c50 @fufler * Indentation changed to tabs
authored
537
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
538 try:
539 if args.swimlanes:
540 # add swimlane tags
541 confgen.addSwimlanes()
542 elif args.model:
543 # generate task model
544 confgen.generateTaskModel(args.metadata, args.mandatory_aspects, args.item_actions, args.aspect)
545 elif args.workflow_ui:
546 # generate workflow UI config
547 confgen.generateWorkflowUIConfig(args.process_name, args.label_id, args.sets)
548 elif args.workflow_i18n:
549 # generate workflow internationalization bundle
550 confgen.generateWorkflowBundle()
551 elif args.share_i18n:
552 # generate share internationalization bundle
553 confgen.generateShareBundle()
554 except ValidationException, e:
555 print('XML validation failed: '+e.message)
71d3c50 @fufler * Indentation changed to tabs
authored
556 sys.exit(1)
557
bfabd37 @fufler * aconfgen.oy rewritten from scratch using libxml2 for xml parsing
authored
558 # do diffrent stuff depending on result type
559 if confgen.xmlResult:
560 # remove blank nodes
561 if args.remove_blanks:
562 confgen.removeBlankNodes(confgen.result)
563 # output XML
564 confgen.result.saveFormatFileEnc('-', 'utf-8', args.format)
565 else:
566 # print strings
567 confgen.printListResult()
Something went wrong with that request. Please try again.