Class Index [+]

Quicksearch

TaskJuggler::TjpExportRE

This specialization of ReportBase implements an export of the project data in the TJP syntax format.

Public Class Methods

new(report) click to toggle source

Create a new object and set some default values.

    # File lib/taskjuggler/reports/TjpExportRE.rb, line 23
23:     def initialize(report)
24:       super(report)
25: 
26:       @supportedTaskAttrs = %( booking complete depends flags maxend
27:                                 maxstart minend minstart note priority
28:                                 projectid responsible )
29:       @supportedResourceAttrs = %( flags vacation workinghours )
30:     end

Public Instance Methods

generateIntermediateFormat() click to toggle source
    # File lib/taskjuggler/reports/TjpExportRE.rb, line 32
32:     def generateIntermediateFormat
33:       super
34:     end
to_tjp() click to toggle source

Return the project data in TJP syntax format.

    # File lib/taskjuggler/reports/TjpExportRE.rb, line 37
37:     def to_tjp
38:       # Prepare the resource list.
39:       @resourceList = PropertyList.new(@project.resources)
40:       @resourceList.setSorting(a('sortResources'))
41:       @resourceList = filterResourceList(@resourceList, nil, a('hideResource'),
42:                                          a('rollupResource'), a('openNodes'))
43:       @resourceList.sort!
44: 
45:       # Prepare the task list.
46:       @taskList = PropertyList.new(@project.tasks)
47:       @taskList.setSorting(a('sortTasks'))
48:       @taskList = filterTaskList(@taskList, nil, a('hideTask'), a('rollupTask'),
49:                                  a('openNodes'))
50:       @taskList.sort!
51: 
52:       getBookings
53: 
54:       @file = ''
55: 
56:       generateProjectProperty if a('definitions').include?('project')
57: 
58:       generateFlagDeclaration if a('definitions').include?('flags')
59:       generateProjectIDs if a('definitions').include?('projectids')
60:       generateResourceList if a('definitions').include?('resources')
61:       generateTaskList if a('definitions').include?('tasks')
62: 
63:       generateTaskAttributes unless a('taskAttributes').empty?
64:       generateResourceAttributes unless a('resourceAttributes').empty?
65: 
66:       @file
67:     end

Private Instance Methods

generateAttribute(property, attrId, indent, scenarioIdx = nil) click to toggle source
     # File lib/taskjuggler/reports/TjpExportRE.rb, line 343
343:     def generateAttribute(property, attrId, indent, scenarioIdx = nil)
344:       val = scenarioIdx ? property[attrId, scenarioIdx] : property.get(attrId)
345:       return if val.nil? || (val.is_a?(Array) && val.empty?) ||
346:                 (scenarioIdx && inheritable?(property, attrId, scenarioIdx))
347: 
348:       generateAttributeText(property.getAttribute(attrId, scenarioIdx).to_tjp,
349:                             indent, scenarioIdx)
350:     end
generateAttributeText(text, indent, scenarioIdx = nil) click to toggle source
     # File lib/taskjuggler/reports/TjpExportRE.rb, line 352
352:     def generateAttributeText(text, indent, scenarioIdx = nil)
353:       @file << ' ' * indent
354:       tag = ''
355:       if !scenarioIdx.nil? && scenarioIdx != 0
356:         tag = "#{@project.scenario(scenarioIdx).id}:"
357:         @file << tag
358:       end
359:       @file << "#{indentBlock(text, indent + tag.length + 2)}\n"
360:     end
generateBooking(task, indent, scenarioIdx) click to toggle source
     # File lib/taskjuggler/reports/TjpExportRE.rb, line 390
390:     def generateBooking(task, indent, scenarioIdx)
391:       return unless @bookings[scenarioIdx].include?(task)
392: 
393:       # Convert Hash into an [ Resource, Booking ] Array sorted by Resource
394:       # ID. This guarantees a reproducible order.
395:       resourceBookings = @bookings[scenarioIdx][task].sort do |a, b|
396:         a[0].fullId <=> b[0].fullId
397:       end
398: 
399:       resourceBookings.each do |resourceId, booking|
400:         generateAttributeText('booking ' + booking.to_tjp, indent, scenarioIdx)
401:       end
402:     end
generateCustomAttributeDeclarations(tag, propertySet, attributes) click to toggle source
     # File lib/taskjuggler/reports/TjpExportRE.rb, line 96
 96:     def generateCustomAttributeDeclarations(tag, propertySet, attributes)
 97:       # First we search the attribute definitions for any user defined
 98:       # attributes and count them.
 99:       customAttributes = 0
100:       propertySet.eachAttributeDefinition do |ad|
101:         customAttributes += 1 if ad.userDefined
102:       end
103:       # Return if there are no user defined attributes.
104:       return if customAttributes == 0
105: 
106:       # Generate definitions for each user defined attribute that is in the
107:       # taskAttributes list.
108:       @file << '  extend ' + tag + "{\n"
109:         propertySet.eachAttributeDefinition do |ad|
110:           next unless ad.userDefined && attributes.include?(ad.id)
111: 
112:           @file << "    #{ad.objClass.tjpId} #{ad.id} " +
113:                    "#{quotedString(ad.name)}\n"
114:         end
115:       @file << "  }\n"
116:     end
generateFlagDeclaration() click to toggle source
     # File lib/taskjuggler/reports/TjpExportRE.rb, line 118
118:     def generateFlagDeclaration
119:       flags = []
120: 
121:       properties = @resourceList + @taskList
122: 
123:       properties.each do |property|
124:         a('scenarios').each do |scenarioIdx|
125:           property['flags', scenarioIdx].each do |flag|
126:             flags << flag unless flags.include?(flag)
127:           end
128:         end
129:       end
130:       flags.sort
131:       unless flags.empty?
132:         @file << "flags #{flags.join(', ')}\n\n"
133:       end
134:     end
generateProjectIDs() click to toggle source
     # File lib/taskjuggler/reports/TjpExportRE.rb, line 136
136:     def generateProjectIDs
137:       # Compile a list of all projectIDs from the tasks in the taskList.
138:       projectIDs = []
139:       a('scenarios').each do |scenarioIdx|
140:         @taskList.each do |task|
141:           pid = task['projectid', scenarioIdx]
142:           projectIDs << pid unless pid.nil? || projectIDs.include?(pid)
143:         end
144:       end
145: 
146:       @file << "projectids #{projectIDs.join(', ')}\n\n" unless projectIDs.empty?
147:     end
generateProjectProperty() click to toggle source
    # File lib/taskjuggler/reports/TjpExportRE.rb, line 71
71:     def generateProjectProperty
72:       @file << "project #{@project['projectid']} \"#{@project['name']}\" " +
73:                "\"#{@project['version']}\" #{@project['start']} - " +
74:                "#{@project['end']} {\n"
75:       generateAttributeText("timezone \"#{@project['timezone']}\"", 2)
76:       generateCustomAttributeDeclarations('resource', @project.resources,
77:                                           a('resourceAttributes'))
78:       generateCustomAttributeDeclarations('task', @project.tasks,
79:                                           a('taskAttributes'))
80:       generateScenarioDefinition(@project.scenario(0), 2)
81:       @file << "}\n\n"
82:     end
generateResource(resource, indent) click to toggle source
     # File lib/taskjuggler/reports/TjpExportRE.rb, line 160
160:     def generateResource(resource, indent)
161:       Log.activity if resource.sequenceNo % 100 == 0
162: 
163:       @file << ' ' * indent + "resource #{resource.id} " +
164:                "#{quotedString(resource.name)}"
165:       @file << ' {' unless resource.children.empty?
166:       @file << "\n"
167: 
168:       # Call this function recursively for all children that are included in the
169:       # resource list as well.
170:       resource.children.each do |subresource|
171:         if @resourceList.include?(subresource)
172:           generateResource(subresource, indent + 2)
173:         end
174:       end
175: 
176:       @file << ' ' * indent + "}\n" unless resource.children.empty?
177:     end
generateResourceAttributes() click to toggle source

Generate a list of resource supplement statements that include the rest of the attributes.

     # File lib/taskjuggler/reports/TjpExportRE.rb, line 274
274:     def generateResourceAttributes
275:       @resourceList.each do |resource|
276:         Log.activity if resource.sequenceNo % 100 == 0
277: 
278:         @file << "supplement resource #{resource.fullId} {\n"
279:         @project.resources.eachAttributeDefinition do |attrDef|
280:           id = attrDef.id
281:           next if (!@supportedResourceAttrs.include?(id) &&
282:                    !attrDef.userDefined) ||
283:                   !a('resourceAttributes').include?(id)
284: 
285:           if attrDef.scenarioSpecific
286:             a('scenarios').each do |scenarioIdx|
287:               next if inheritable?(resource, id, scenarioIdx)
288:               generateAttribute(resource, id, 2, scenarioIdx)
289:             end
290:           else
291:             generateAttribute(resource, id, 2)
292:           end
293:         end
294: 
295:         @file << "}\n"
296:       end
297:     end
generateResourceList() click to toggle source
     # File lib/taskjuggler/reports/TjpExportRE.rb, line 149
149:     def generateResourceList
150:       # The resource definitions are generated recursively. So we only need to
151:       # start it for the top-level resources.
152:       @resourceList.each do |resource|
153:         if resource.parent.nil?
154:           generateResource(resource, 0)
155:         end
156:       end
157:       @file << "\n"
158:     end
generateScenarioDefinition(scenario, indent) click to toggle source
    # File lib/taskjuggler/reports/TjpExportRE.rb, line 84
84:     def generateScenarioDefinition(scenario, indent)
85:       @file << "#{' ' * indent}scenario #{scenario.id} " +
86:                "#{quotedString(scenario.name)} {\n"
87:       scenario.children.each do |sc|
88:         generateScenarioDefinition(sc, indent + 2)
89:       end
90:       @file << "#{' ' * (indent + 2)}active " +
91:                "#{scenario.get('active') ? 'yes' : 'no'}\n"
92:       @file << "#{' ' * indent}}\n"
93:     end
generateTask(task, indent) click to toggle source

Generate a task definition. It only contains a very small set of attributes that have to be passed on the the nested tasks at creation time. All other attributes are declared in subsequent supplement statements.

     # File lib/taskjuggler/reports/TjpExportRE.rb, line 193
193:     def generateTask(task, indent)
194:       Log.activity if task.sequenceNo % 100 == 0
195: 
196:       @file << ' ' * indent + "task #{task.id} " +
197:                "#{quotedString(task.name)} {\n"
198: 
199:       if a('taskAttributes').include?('depends')
200:         a('scenarios').each do |scenarioIdx|
201:           generateTaskDependency(scenarioIdx, task, 'depends', indent + 2)
202:           generateTaskDependency(scenarioIdx, task, 'precedes', indent + 2)
203:         end
204:       end
205: 
206:       # Call this function recursively for all children that are included in the
207:       # task list as well.
208:       task.children.each do |subtask|
209:         if @taskList.include?(subtask)
210:           generateTask(subtask, indent + 2)
211:         end
212:       end
213: 
214:       # Determine whether this task has subtasks that are included in the
215:       # report or whether this is a leaf task for the report.
216:       isLeafTask = true
217:       task.children.each do |subtask|
218:         if @taskList.include?(subtask)
219:           isLeafTask = false
220:           break
221:         end
222:       end
223: 
224:       # For leaf tasks we put some attributes right here.
225:       if isLeafTask
226:         a('scenarios').each do |scenarioIdx|
227:           generateAttribute(task, 'start', indent + 2, scenarioIdx)
228:           if task['milestone', scenarioIdx]
229:             if task['scheduled', scenarioIdx]
230:               generateAttributeText('milestone', indent + 2, scenarioIdx)
231:             end
232:           else
233:             generateAttribute(task, 'end', indent + 2, scenarioIdx)
234:             generateAttributeText('scheduling ' +
235:                                   (task['forward', scenarioIdx] ?
236:                                    'asap' : 'alap'),
237:                                   indent + 2, scenarioIdx)
238:           end
239:           if task['scheduled', scenarioIdx] &&
240:              !inheritable?(task, 'scheduled', scenarioIdx)
241:             generateAttributeText('scheduled', indent + 2, scenarioIdx)
242:           end
243:         end
244:       end
245: 
246:       @file << ' ' * indent + "}\n"
247:     end
generateTaskAttributes() click to toggle source

Generate a list of task supplement statements that include the rest of the attributes.

     # File lib/taskjuggler/reports/TjpExportRE.rb, line 301
301:     def generateTaskAttributes
302:       @taskList.each do |task|
303:         Log.activity if task.sequenceNo % 100 == 0
304: 
305:         @file << "supplement task #{task.fullId} {\n"
306:         # Declare adopted tasks.
307:         adoptees = ""
308:         task.adoptees.each do |adoptee|
309:           next unless @taskList.include?(adoptee)
310: 
311:           adoptees += ', ' unless adoptees.empty?
312:           adoptees += adoptee.fullId
313:         end
314:         generateAttributeText("adopt #{adoptees}", 2) unless adoptees.empty?
315: 
316:         @project.tasks.eachAttributeDefinition do |attrDef|
317:           id = attrDef.id
318: 
319:           next if (!@supportedTaskAttrs.include?(id) && !attrDef.userDefined) ||
320:                   !a('taskAttributes').include?(id)
321: 
322:           if attrDef.scenarioSpecific
323:             a('scenarios').each do |scenarioIdx|
324:               # Some attributes need special treatment.
325:               case id
326:               when 'depends'
327:                 next     # already taken care of
328:               when 'booking'
329:                 generateBooking(task, 2, scenarioIdx)
330:               else
331:                 generateAttribute(task, id, 2, scenarioIdx)
332:               end
333:             end
334:           else
335:             generateAttribute(task, id, 2)
336:           end
337:         end
338: 
339:         @file << "}\n"
340:       end
341:     end
generateTaskDependency(scenarioIdx, task, tag, indent) click to toggle source

Generate ‘depends’ or ‘precedes’ attributes for a task.

     # File lib/taskjuggler/reports/TjpExportRE.rb, line 250
250:     def generateTaskDependency(scenarioIdx, task, tag, indent)
251:       return unless a('taskAttributes').include?('depends')
252: 
253:       taskDeps = task[tag, scenarioIdx]
254:       unless taskDeps.empty?
255:         str = "#{tag} "
256:         first = true
257:         taskDeps.each do |dep|
258:           next if inheritable?(task, tag, scenarioIdx, dep) ||
259:                   (task.parent && task.parent[tag, scenarioIdx].include?(dep))
260: 
261:           if first
262:             first = false
263:           else
264:             str << ', '
265:           end
266:           str << dep.task.fullId
267:         end
268:         generateAttributeText(str, indent, scenarioIdx) unless first
269:       end
270:     end
generateTaskList() click to toggle source
     # File lib/taskjuggler/reports/TjpExportRE.rb, line 179
179:     def generateTaskList
180:       # The task definitions are generated recursively. So we only need to start
181:       # it for the top-level tasks.
182:       @taskList.each do |task|
183:         if task.parent.nil?
184:           generateTask(task, 0)
185:         end
186:       end
187:     end
getBookings() click to toggle source

Get the booking data for all resources that should be included in the report.

     # File lib/taskjuggler/reports/TjpExportRE.rb, line 364
364:     def getBookings
365:       @bookings = {}
366:       if a('taskAttributes').include?('booking')
367:         a('scenarios').each do |scenarioIdx|
368:           @bookings[scenarioIdx] = {}
369:           @resourceList.each do |resource|
370:             # Get the bookings for this resource hashed by task.
371:             bookings = resource.getBookings(scenarioIdx,
372:                                             Interval.new(a('start'), a('end')))
373:             next if bookings.nil?
374: 
375:             # Now convert/add them to a tripple-stage hash by scenarioIdx, task
376:             # and then resource.
377:             bookings.each do |task, booking|
378:               next unless @taskList.include?(task)
379: 
380:               if !@bookings[scenarioIdx].include?(task)
381:                 @bookings[scenarioIdx][task] = {}
382:               end
383:               @bookings[scenarioIdx][task][resource] = booking
384:             end
385:           end
386:         end
387:       end
388:     end
indentBlock(text, indent) click to toggle source

This utility function is used to indent multi-line attributes. All attributes should be filtered through this function. Attributes that contain line breaks will be indented properly. In addition to the indentation specified by indent all but the first line will be indented after the first word of the first line. The text may not end with a line break.

     # File lib/taskjuggler/reports/TjpExportRE.rb, line 410
410:     def indentBlock(text, indent)
411:       out = ''
412:       firstSpace = 0
413:       text.length.times do |i|
414:         if firstSpace == 0 && text[i] == \ \# There must be a space after ?
415:           firstSpace = i
416:         end
417:         out << text[i]
418:         if text[i] == \n\
419:           out += ' ' * (indent + firstSpace - 1)
420:         end
421:       end
422:       out
423:     end
inheritable?(property, attrId, scenarioIdx, listItem = nil) click to toggle source

Return true if the attribute value for attrId can be inherited from the parent scenario.

     # File lib/taskjuggler/reports/TjpExportRE.rb, line 436
436:     def inheritable?(property, attrId, scenarioIdx, listItem = nil)
437:       parentScenario = @project.scenario(scenarioIdx).parent
438:       return false unless parentScenario
439: 
440:       parentScenarioIdx = @project.scenarioIdx(parentScenario)
441:       parentAttr = property[attrId, parentScenarioIdx]
442:       if parentAttr.is_a?(Array) && listItem
443:         return parentAttr.include?(listItem)
444:       else
445:         return property[attrId, scenarioIdx] == parentAttr
446:       end
447:     end
quotedString(str) click to toggle source
     # File lib/taskjuggler/reports/TjpExportRE.rb, line 425
425:     def quotedString(str)
426:       if str[1] == \n\
427:         "-8<-\n#{str}\n->8-"
428:       else
429:         escaped = str.gsub("\"", '\"')
430:         "\"#{escaped}\""
431:       end
432:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.