taskjuggler 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +280 -0
- data/README +31 -0
- data/Rakefile +20 -0
- data/benchmarks/UTF-8-Strings.rb +58 -0
- data/benchmarks/allocate.tjp +30 -0
- data/benchmarks/booking.tjp +62 -0
- data/benchmarks/depends.tjp +112 -0
- data/benchmarks/htmltaskreport.tjp +45 -0
- data/benchmarks/runbench.rb +24 -0
- data/bin/tj3 +3 -0
- data/bin/tj3man +3 -0
- data/doc/classes/AppConfig.html +808 -0
- data/doc/classes/Arguments.html +226 -0
- data/doc/classes/String.html +395 -0
- data/doc/classes/TaskJuggler.html +1358 -0
- data/doc/classes/TaskJuggler/Account.html +257 -0
- data/doc/classes/TaskJuggler/AccountScenario.html +218 -0
- data/doc/classes/TaskJuggler/Allocation.html +419 -0
- data/doc/classes/TaskJuggler/AllocationAttribute.html +291 -0
- data/doc/classes/TaskJuggler/AttributeBase.html +608 -0
- data/doc/classes/TaskJuggler/AttributeDefinition.html +259 -0
- data/doc/classes/TaskJuggler/Booking.html +307 -0
- data/doc/classes/TaskJuggler/BookingListAttribute.html +263 -0
- data/doc/classes/TaskJuggler/BooleanAttribute.html +261 -0
- data/doc/classes/TaskJuggler/CSVFile.html +325 -0
- data/doc/classes/TaskJuggler/Charge.html +279 -0
- data/doc/classes/TaskJuggler/ChargeListAttribute.html +229 -0
- data/doc/classes/TaskJuggler/ChargeSet.html +440 -0
- data/doc/classes/TaskJuggler/ChargeSetListAttribute.html +276 -0
- data/doc/classes/TaskJuggler/ColumnTable.html +260 -0
- data/doc/classes/TaskJuggler/DateAttribute.html +194 -0
- data/doc/classes/TaskJuggler/DependencyListAttribute.html +267 -0
- data/doc/classes/TaskJuggler/DurationAttribute.html +229 -0
- data/doc/classes/TaskJuggler/FixnumAttribute.html +194 -0
- data/doc/classes/TaskJuggler/FlagListAttribute.html +263 -0
- data/doc/classes/TaskJuggler/FloatAttribute.html +229 -0
- data/doc/classes/TaskJuggler/GanttChart.html +667 -0
- data/doc/classes/TaskJuggler/GanttContainer.html +441 -0
- data/doc/classes/TaskJuggler/GanttHeader.html +280 -0
- data/doc/classes/TaskJuggler/GanttHeaderScaleItem.html +245 -0
- data/doc/classes/TaskJuggler/GanttLine.html +398 -0
- data/doc/classes/TaskJuggler/GanttLoadStack.html +327 -0
- data/doc/classes/TaskJuggler/GanttMilestone.html +415 -0
- data/doc/classes/TaskJuggler/GanttRouter.html +425 -0
- data/doc/classes/TaskJuggler/GanttTaskBar.html +429 -0
- data/doc/classes/TaskJuggler/HTMLDocument.html +240 -0
- data/doc/classes/TaskJuggler/HTMLGraphics.html +231 -0
- data/doc/classes/TaskJuggler/Interval.html +552 -0
- data/doc/classes/TaskJuggler/IntervalListAttribute.html +267 -0
- data/doc/classes/TaskJuggler/KeywordDocumentation.html +796 -0
- data/doc/classes/TaskJuggler/Limits.html +416 -0
- data/doc/classes/TaskJuggler/Limits/Limit.html +381 -0
- data/doc/classes/TaskJuggler/LimitsAttribute.html +261 -0
- data/doc/classes/TaskJuggler/Log.html +613 -0
- data/doc/classes/TaskJuggler/LogicalAttribute.html +226 -0
- data/doc/classes/TaskJuggler/LogicalExpression.html +251 -0
- data/doc/classes/TaskJuggler/LogicalFlag.html +229 -0
- data/doc/classes/TaskJuggler/LogicalFunction.html +324 -0
- data/doc/classes/TaskJuggler/LogicalOperation.html +299 -0
- data/doc/classes/TaskJuggler/Macro.html +194 -0
- data/doc/classes/TaskJuggler/MacroParser.html +360 -0
- data/doc/classes/TaskJuggler/MacroTable.html +366 -0
- data/doc/classes/TaskJuggler/Message.html +281 -0
- data/doc/classes/TaskJuggler/MessageHandler.html +215 -0
- data/doc/classes/TaskJuggler/Project.html +1606 -0
- data/doc/classes/TaskJuggler/ProjectFileParser.html +412 -0
- data/doc/classes/TaskJuggler/PropertyList.html +597 -0
- data/doc/classes/TaskJuggler/PropertySet.html +1200 -0
- data/doc/classes/TaskJuggler/PropertyTreeNode.html +1449 -0
- data/doc/classes/TaskJuggler/Query.html +600 -0
- data/doc/classes/TaskJuggler/RealFormat.html +252 -0
- data/doc/classes/TaskJuggler/ReferenceAttribute.html +194 -0
- data/doc/classes/TaskJuggler/Report.html +528 -0
- data/doc/classes/TaskJuggler/ReportElement.html +1070 -0
- data/doc/classes/TaskJuggler/ReportTable.html +497 -0
- data/doc/classes/TaskJuggler/ReportTableCell.html +518 -0
- data/doc/classes/TaskJuggler/ReportTableColumn.html +364 -0
- data/doc/classes/TaskJuggler/ReportTableElement.html +644 -0
- data/doc/classes/TaskJuggler/ReportTableLegend.html +343 -0
- data/doc/classes/TaskJuggler/ReportTableLine.html +431 -0
- data/doc/classes/TaskJuggler/Resource.html +211 -0
- data/doc/classes/TaskJuggler/ResourceListAttribute.html +267 -0
- data/doc/classes/TaskJuggler/ResourceListRE.html +249 -0
- data/doc/classes/TaskJuggler/ResourceScenario.html +1137 -0
- data/doc/classes/TaskJuggler/RichText.html +537 -0
- data/doc/classes/TaskJuggler/RichTextAttribute.html +229 -0
- data/doc/classes/TaskJuggler/RichTextDocument.html +418 -0
- data/doc/classes/TaskJuggler/RichTextElement.html +829 -0
- data/doc/classes/TaskJuggler/RichTextException.html +212 -0
- data/doc/classes/TaskJuggler/RichTextParser.html +317 -0
- data/doc/classes/TaskJuggler/RichTextProtocolExample.html +303 -0
- data/doc/classes/TaskJuggler/RichTextProtocolHandler.html +194 -0
- data/doc/classes/TaskJuggler/RichTextScanner.html +561 -0
- data/doc/classes/TaskJuggler/RichTextSnip.html +364 -0
- data/doc/classes/TaskJuggler/RichTextSyntaxRules.html +883 -0
- data/doc/classes/TaskJuggler/Scenario.html +163 -0
- data/doc/classes/TaskJuggler/ScenarioData.html +354 -0
- data/doc/classes/TaskJuggler/Scoreboard.html +638 -0
- data/doc/classes/TaskJuggler/Shift.html +255 -0
- data/doc/classes/TaskJuggler/ShiftAssignment.html +488 -0
- data/doc/classes/TaskJuggler/ShiftAssignments.html +715 -0
- data/doc/classes/TaskJuggler/ShiftAssignmentsAttribute.html +261 -0
- data/doc/classes/TaskJuggler/ShiftScenario.html +282 -0
- data/doc/classes/TaskJuggler/SourceFileInfo.html +247 -0
- data/doc/classes/TaskJuggler/StringAttribute.html +229 -0
- data/doc/classes/TaskJuggler/SymbolAttribute.html +194 -0
- data/doc/classes/TaskJuggler/SyntaxReference.html +516 -0
- data/doc/classes/TaskJuggler/TOCEntry.html +242 -0
- data/doc/classes/TaskJuggler/TableColumnDefinition.html +273 -0
- data/doc/classes/TaskJuggler/TableOfContents.html +256 -0
- data/doc/classes/TaskJuggler/Task.html +203 -0
- data/doc/classes/TaskJuggler/TaskDependency.html +251 -0
- data/doc/classes/TaskJuggler/TaskListAttribute.html +267 -0
- data/doc/classes/TaskJuggler/TaskListRE.html +250 -0
- data/doc/classes/TaskJuggler/TaskScenario.html +2206 -0
- data/doc/classes/TaskJuggler/TextParser.html +670 -0
- data/doc/classes/TaskJuggler/TextParser/Pattern.html +923 -0
- data/doc/classes/TaskJuggler/TextParser/Rule.html +779 -0
- data/doc/classes/TaskJuggler/TextParser/StackElement.html +267 -0
- data/doc/classes/TaskJuggler/TextParser/TextParserResultArray.html +212 -0
- data/doc/classes/TaskJuggler/TextParser/TokenDoc.html +221 -0
- data/doc/classes/TaskJuggler/TextScanner.html +708 -0
- data/doc/classes/TaskJuggler/TextScanner/BufferStreamHandle.html +355 -0
- data/doc/classes/TaskJuggler/TextScanner/FileStreamHandle.html +341 -0
- data/doc/classes/TaskJuggler/TextScanner/StreamHandle.html +260 -0
- data/doc/classes/TaskJuggler/TjException.html +185 -0
- data/doc/classes/TaskJuggler/TjTime.html +1845 -0
- data/doc/classes/TaskJuggler/TjpExample.html +310 -0
- data/doc/classes/TaskJuggler/TjpExportRE.html +329 -0
- data/doc/classes/TaskJuggler/TjpSyntaxRules.html +8928 -0
- data/doc/classes/TaskJuggler/UserManual.html +606 -0
- data/doc/classes/TaskJuggler/WorkingHours.html +582 -0
- data/doc/classes/TaskJuggler/WorkingHoursAttribute.html +284 -0
- data/doc/classes/TaskJuggler/XMLBlob.html +207 -0
- data/doc/classes/TaskJuggler/XMLComment.html +206 -0
- data/doc/classes/TaskJuggler/XMLDocument.html +293 -0
- data/doc/classes/TaskJuggler/XMLElement.html +341 -0
- data/doc/classes/TaskJuggler/XMLNamedText.html +174 -0
- data/doc/classes/TaskJuggler/XMLText.html +221 -0
- data/doc/files/COPYING.html +448 -0
- data/doc/files/README.html +134 -0
- data/doc/files/lib/AccountScenario_rb.html +116 -0
- data/doc/files/lib/Account_rb.html +118 -0
- data/doc/files/lib/Allocation_rb.html +118 -0
- data/doc/files/lib/AppConfig_rb.html +116 -0
- data/doc/files/lib/AttributeBase_rb.html +106 -0
- data/doc/files/lib/AttributeDefinition_rb.html +106 -0
- data/doc/files/lib/Attributes_rb.html +130 -0
- data/doc/files/lib/Booking_rb.html +106 -0
- data/doc/files/lib/ChargeSet_rb.html +116 -0
- data/doc/files/lib/Charge_rb.html +116 -0
- data/doc/files/lib/HTMLDocument_rb.html +116 -0
- data/doc/files/lib/Interval_rb.html +116 -0
- data/doc/files/lib/KeywordDocumentation_rb.html +122 -0
- data/doc/files/lib/Limits_rb.html +116 -0
- data/doc/files/lib/Log_rb.html +116 -0
- data/doc/files/lib/LogicalExpression_rb.html +122 -0
- data/doc/files/lib/LogicalFlag_rb.html +116 -0
- data/doc/files/lib/LogicalFunction_rb.html +116 -0
- data/doc/files/lib/LogicalOperation_rb.html +116 -0
- data/doc/files/lib/MacroParser_rb.html +118 -0
- data/doc/files/lib/MacroTable_rb.html +122 -0
- data/doc/files/lib/MessageHandler_rb.html +106 -0
- data/doc/files/lib/Message_rb.html +116 -0
- data/doc/files/lib/ProjectFileParser_rb.html +122 -0
- data/doc/files/lib/Project_rb.html +148 -0
- data/doc/files/lib/PropertyList_rb.html +106 -0
- data/doc/files/lib/PropertySet_rb.html +118 -0
- data/doc/files/lib/PropertyTreeNode_rb.html +106 -0
- data/doc/files/lib/Query_rb.html +116 -0
- data/doc/files/lib/RealFormat_rb.html +106 -0
- data/doc/files/lib/ResourceScenario_rb.html +116 -0
- data/doc/files/lib/Resource_rb.html +118 -0
- data/doc/files/lib/RichTextDocument_rb.html +120 -0
- data/doc/files/lib/RichTextElement_rb.html +120 -0
- data/doc/files/lib/RichTextParser_rb.html +120 -0
- data/doc/files/lib/RichTextProtocolExample_rb.html +120 -0
- data/doc/files/lib/RichTextProtocolHandler_rb.html +106 -0
- data/doc/files/lib/RichTextScanner_rb.html +116 -0
- data/doc/files/lib/RichTextSnip_rb.html +118 -0
- data/doc/files/lib/RichTextSyntaxRules_rb.html +106 -0
- data/doc/files/lib/RichText_rb.html +118 -0
- data/doc/files/lib/ScenarioData_rb.html +118 -0
- data/doc/files/lib/Scenario_rb.html +116 -0
- data/doc/files/lib/Scoreboard_rb.html +106 -0
- data/doc/files/lib/ShiftAssignments_rb.html +116 -0
- data/doc/files/lib/ShiftScenario_rb.html +116 -0
- data/doc/files/lib/Shift_rb.html +118 -0
- data/doc/files/lib/SourceFileInfo_rb.html +106 -0
- data/doc/files/lib/SyntaxReference_rb.html +122 -0
- data/doc/files/lib/TOCEntry_rb.html +118 -0
- data/doc/files/lib/TableColumnDefinition_rb.html +106 -0
- data/doc/files/lib/TableOfContents_rb.html +118 -0
- data/doc/files/lib/TaskDependency_rb.html +106 -0
- data/doc/files/lib/TaskJuggler_rb.html +120 -0
- data/doc/files/lib/TaskScenario_rb.html +116 -0
- data/doc/files/lib/Task_rb.html +118 -0
- data/doc/files/lib/TextParser/Pattern_rb.html +116 -0
- data/doc/files/lib/TextParser/Rule_rb.html +106 -0
- data/doc/files/lib/TextParser/StackElement_rb.html +106 -0
- data/doc/files/lib/TextParser/TokenDoc_rb.html +106 -0
- data/doc/files/lib/TextParser_rb.html +124 -0
- data/doc/files/lib/TextScanner_rb.html +128 -0
- data/doc/files/lib/Tj3Config_rb.html +118 -0
- data/doc/files/lib/TjException_rb.html +106 -0
- data/doc/files/lib/TjTime_rb.html +118 -0
- data/doc/files/lib/TjpExample_rb.html +116 -0
- data/doc/files/lib/TjpSyntaxRules_rb.html +106 -0
- data/doc/files/lib/UTF8String_rb.html +132 -0
- data/doc/files/lib/UserManual_rb.html +124 -0
- data/doc/files/lib/WorkingHours_rb.html +116 -0
- data/doc/files/lib/XMLDocument_rb.html +116 -0
- data/doc/files/lib/XMLElement_rb.html +116 -0
- data/doc/files/lib/reports/CSVFile_rb.html +116 -0
- data/doc/files/lib/reports/ColumnTable_rb.html +116 -0
- data/doc/files/lib/reports/GanttChart_rb.html +122 -0
- data/doc/files/lib/reports/GanttContainer_rb.html +116 -0
- data/doc/files/lib/reports/GanttHeaderScaleItem_rb.html +106 -0
- data/doc/files/lib/reports/GanttHeader_rb.html +116 -0
- data/doc/files/lib/reports/GanttLine_rb.html +126 -0
- data/doc/files/lib/reports/GanttLoadStack_rb.html +116 -0
- data/doc/files/lib/reports/GanttMilestone_rb.html +116 -0
- data/doc/files/lib/reports/GanttRouter_rb.html +106 -0
- data/doc/files/lib/reports/GanttTaskBar_rb.html +116 -0
- data/doc/files/lib/reports/HTMLGraphics_rb.html +106 -0
- data/doc/files/lib/reports/ReportElement_rb.html +118 -0
- data/doc/files/lib/reports/ReportTableCell_rb.html +106 -0
- data/doc/files/lib/reports/ReportTableColumn_rb.html +106 -0
- data/doc/files/lib/reports/ReportTableElement_rb.html +122 -0
- data/doc/files/lib/reports/ReportTableLegend_rb.html +106 -0
- data/doc/files/lib/reports/ReportTableLine_rb.html +116 -0
- data/doc/files/lib/reports/ReportTable_rb.html +118 -0
- data/doc/files/lib/reports/Report_rb.html +126 -0
- data/doc/files/lib/reports/ResourceListRE_rb.html +122 -0
- data/doc/files/lib/reports/TaskListRE_rb.html +122 -0
- data/doc/files/lib/reports/TjpExportRE_rb.html +116 -0
- data/doc/files/lib/taskjuggler3_rb.html +276 -0
- data/doc/files/lib/tj3man_rb.html +189 -0
- data/doc/fr_class_index.html +285 -0
- data/doc/fr_file_index.html +223 -0
- data/doc/fr_method_index.html +1953 -0
- data/doc/index.html +21 -0
- data/doc/rdoc-style.css +299 -0
- data/examples/tutorial.tjp +361 -0
- data/gem_spec.rb +30 -0
- data/lib/Account.rb +50 -0
- data/lib/AccountScenario.rb +39 -0
- data/lib/Allocation.rb +102 -0
- data/lib/AppConfig.rb +134 -0
- data/lib/AttributeBase.rb +131 -0
- data/lib/AttributeDefinition.rb +47 -0
- data/lib/Attributes.rb +478 -0
- data/lib/BatchProcessor.rb +209 -0
- data/lib/Booking.rb +59 -0
- data/lib/Charge.rb +71 -0
- data/lib/ChargeSet.rb +126 -0
- data/lib/HTMLDocument.rb +59 -0
- data/lib/Interval.rb +127 -0
- data/lib/KeywordDocumentation.rb +560 -0
- data/lib/Limits.rb +219 -0
- data/lib/Log.rb +160 -0
- data/lib/LogicalExpression.rb +71 -0
- data/lib/LogicalFlag.rb +34 -0
- data/lib/LogicalFunction.rb +102 -0
- data/lib/LogicalOperation.rb +118 -0
- data/lib/MacroParser.rb +77 -0
- data/lib/MacroTable.rb +84 -0
- data/lib/Message.rb +56 -0
- data/lib/MessageHandler.rb +34 -0
- data/lib/Project.rb +662 -0
- data/lib/ProjectFileParser.rb +333 -0
- data/lib/PropertyList.rb +181 -0
- data/lib/PropertySet.rb +304 -0
- data/lib/PropertyTreeNode.rb +461 -0
- data/lib/Query.rb +227 -0
- data/lib/RealFormat.rb +73 -0
- data/lib/Resource.rb +42 -0
- data/lib/ResourceScenario.rb +511 -0
- data/lib/RichText.rb +147 -0
- data/lib/RichTextDocument.rb +139 -0
- data/lib/RichTextElement.rb +391 -0
- data/lib/RichTextParser.rb +66 -0
- data/lib/RichTextProtocolExample.rb +65 -0
- data/lib/RichTextProtocolHandler.rb +35 -0
- data/lib/RichTextScanner.rb +390 -0
- data/lib/RichTextSnip.rb +104 -0
- data/lib/RichTextSyntaxRules.rb +265 -0
- data/lib/Scenario.rb +27 -0
- data/lib/ScenarioData.rb +65 -0
- data/lib/Scoreboard.rb +141 -0
- data/lib/Shift.rb +48 -0
- data/lib/ShiftAssignments.rb +291 -0
- data/lib/ShiftScenario.rb +46 -0
- data/lib/SourceFileInfo.rb +37 -0
- data/lib/SyntaxReference.rb +284 -0
- data/lib/TOCEntry.rb +76 -0
- data/lib/TableColumnDefinition.rb +54 -0
- data/lib/TableOfContents.rb +46 -0
- data/lib/Task.rb +37 -0
- data/lib/TaskDependency.rb +39 -0
- data/lib/TaskJuggler.rb +84 -0
- data/lib/TaskScenario.rb +1622 -0
- data/lib/TextParser.rb +416 -0
- data/lib/TextParser/Pattern.rb +263 -0
- data/lib/TextParser/Rule.rb +171 -0
- data/lib/TextParser/StackElement.rb +45 -0
- data/lib/TextParser/TokenDoc.rb +38 -0
- data/lib/TextScanner.rb +682 -0
- data/lib/Tj3Config.rb +27 -0
- data/lib/TjException.rb +27 -0
- data/lib/TjTime.rb +395 -0
- data/lib/TjpExample.rb +119 -0
- data/lib/TjpSyntaxRules.rb +4022 -0
- data/lib/UTF8String.rb +100 -0
- data/lib/UserManual.rb +282 -0
- data/lib/WorkingHours.rb +323 -0
- data/lib/XMLDocument.rb +54 -0
- data/lib/XMLElement.rb +175 -0
- data/lib/reports/CSVFile.rb +146 -0
- data/lib/reports/ColumnTable.rb +66 -0
- data/lib/reports/GanttChart.rb +308 -0
- data/lib/reports/GanttContainer.rb +107 -0
- data/lib/reports/GanttHeader.rb +141 -0
- data/lib/reports/GanttHeaderScaleItem.rb +42 -0
- data/lib/reports/GanttLine.rb +329 -0
- data/lib/reports/GanttLoadStack.rb +113 -0
- data/lib/reports/GanttMilestone.rb +80 -0
- data/lib/reports/GanttRouter.rb +375 -0
- data/lib/reports/GanttTaskBar.rb +95 -0
- data/lib/reports/HTMLGraphics.rb +65 -0
- data/lib/reports/Report.rb +344 -0
- data/lib/reports/ReportElement.rb +427 -0
- data/lib/reports/ReportTable.rb +144 -0
- data/lib/reports/ReportTableCell.rb +142 -0
- data/lib/reports/ReportTableColumn.rb +82 -0
- data/lib/reports/ReportTableElement.rb +852 -0
- data/lib/reports/ReportTableLegend.rb +167 -0
- data/lib/reports/ReportTableLine.rb +87 -0
- data/lib/reports/ResourceListRE.rb +72 -0
- data/lib/reports/TaskListRE.rb +73 -0
- data/lib/reports/TjpExportRE.rb +394 -0
- data/lib/taskjuggler3.rb +106 -0
- data/lib/tj3man.rb +88 -0
- data/manual/Day_To_Day_Juggling +168 -0
- data/manual/Getting_Started +61 -0
- data/manual/How_To_Contribute +185 -0
- data/manual/Installation +68 -0
- data/manual/Intro +102 -0
- data/manual/Reporting_Bugs +26 -0
- data/manual/Rich_Text_Attributes +90 -0
- data/manual/TaskJuggler_2x_Migration +40 -0
- data/manual/Tutorial +579 -0
- data/manual/fdl +450 -0
- data/prj_cfg.rb +43 -0
- data/setup.rb +1585 -0
- data/tasks/csts.rake +72 -0
- data/tasks/gem.rake +14 -0
- data/tasks/manual.rake +10 -0
- data/tasks/missing.rake +21 -0
- data/tasks/rcov.rake +14 -0
- data/tasks/rdoc.rake +17 -0
- data/tasks/rexml_fix.rb +16 -0
- data/tasks/rexml_fix_19.rb +49 -0
- data/tasks/show.rake +21 -0
- data/tasks/stats.rake +25 -0
- data/tasks/test.rake +11 -0
- data/test/MessageChecker.rb +53 -0
- data/test/TestSuite/CSV-Reports/celltext-Reference.csv +14 -0
- data/test/TestSuite/CSV-Reports/celltext.tjp +7 -0
- data/test/TestSuite/CSV-Reports/genrefs +6 -0
- data/test/TestSuite/CSV-Reports/project-1.tji +57 -0
- data/test/TestSuite/CSV-Reports/resourcereport-Reference.csv +4 -0
- data/test/TestSuite/CSV-Reports/resourcereport.tjp +10 -0
- data/test/TestSuite/CSV-Reports/resourcereport_with_tasks-Reference.csv +22 -0
- data/test/TestSuite/CSV-Reports/resourcereport_with_tasks.tjp +11 -0
- data/test/TestSuite/CSV-Reports/sortByTree-Reference.csv +14 -0
- data/test/TestSuite/CSV-Reports/sortByTree.tjp +8 -0
- data/test/TestSuite/CSV-Reports/sortBy_duration.down-Reference.csv +14 -0
- data/test/TestSuite/CSV-Reports/sortBy_duration.down.tjp +10 -0
- data/test/TestSuite/CSV-Reports/sortBy_effort.up-Reference.csv +14 -0
- data/test/TestSuite/CSV-Reports/sortBy_effort.up.tjp +10 -0
- data/test/TestSuite/CSV-Reports/sortBy_plan.start.down-Reference.csv +14 -0
- data/test/TestSuite/CSV-Reports/sortBy_plan.start.down.tjp +10 -0
- data/test/TestSuite/CSV-Reports/taskreport-Reference.csv +14 -0
- data/test/TestSuite/CSV-Reports/taskreport.tjp +10 -0
- data/test/TestSuite/CSV-Reports/taskreport_with_resources-Reference.csv +24 -0
- data/test/TestSuite/CSV-Reports/taskreport_with_resources.tjp +11 -0
- data/test/TestSuite/Scheduler/Correct/Allocate.tjp +86 -0
- data/test/TestSuite/Scheduler/Correct/AutomaticMilestones.tjp +63 -0
- data/test/TestSuite/Scheduler/Correct/Booking.tjp +161 -0
- data/test/TestSuite/Scheduler/Correct/Depends.tjp +50 -0
- data/test/TestSuite/Scheduler/Correct/Duration.tjp +34 -0
- data/test/TestSuite/Scheduler/Correct/InheritStartEnd.tjp +129 -0
- data/test/TestSuite/Scheduler/Correct/Limits.tjp +81 -0
- data/test/TestSuite/Scheduler/Correct/MultipleMandatories.tjp +43 -0
- data/test/TestSuite/Scheduler/Correct/Optimize-1.tjp +28 -0
- data/test/TestSuite/Scheduler/Correct/Optimize-2.tjp +33 -0
- data/test/TestSuite/Scheduler/Correct/Optimize-3.tjp +33 -0
- data/test/TestSuite/Scheduler/Correct/Optimize-4.tjp +34 -0
- data/test/TestSuite/Scheduler/Correct/Optimize-5.tjp +62 -0
- data/test/TestSuite/Scheduler/Correct/Precedes.tjp +50 -0
- data/test/TestSuite/Scheduler/Correct/Shift.tjp +102 -0
- data/test/TestSuite/Scheduler/Errors/account_no_leaf.tjp +13 -0
- data/test/TestSuite/Scheduler/Errors/booking_conflict.tjp +10 -0
- data/test/TestSuite/Scheduler/Errors/booking_no_duty.tjp +9 -0
- data/test/TestSuite/Scheduler/Errors/booking_on_vacation.tjp +9 -0
- data/test/TestSuite/Scheduler/Errors/container_booking.tjp +14 -0
- data/test/TestSuite/Scheduler/Errors/container_duration.tjp +11 -0
- data/test/TestSuite/Scheduler/Errors/effort_no_allocations.tjp +7 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_1.tjp +19 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_10.tjp +36 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_11.tjp +27 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_12.tjp +20 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_13.tjp +27 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_14.tjp +26 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_2.tjp +24 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_3.tjp +18 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_4.tjp +36 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_5.tjp +37 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_6.tjp +35 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_7.tjp +46 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_8.tjp +51 -0
- data/test/TestSuite/Scheduler/Errors/loop_detected_9.tjp +20 -0
- data/test/TestSuite/Scheduler/Errors/maxend.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/maxstart.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/milestone_booking.tjp +10 -0
- data/test/TestSuite/Scheduler/Errors/milestone_duration.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/milestone_start_end.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/minend.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/minstart.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/multiple_durations.tjp +11 -0
- data/test/TestSuite/Scheduler/Errors/no_tasks.tjp +6 -0
- data/test/TestSuite/Scheduler/Errors/not_scheduled.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/task_depend_child.tjp +10 -0
- data/test/TestSuite/Scheduler/Errors/task_depend_multi.tjp +13 -0
- data/test/TestSuite/Scheduler/Errors/task_depend_parent.tjp +11 -0
- data/test/TestSuite/Scheduler/Errors/task_depend_self.tjp +10 -0
- data/test/TestSuite/Scheduler/Errors/task_depend_unknown.tjp +10 -0
- data/test/TestSuite/Scheduler/Errors/task_overspecified_1.tjp +9 -0
- data/test/TestSuite/Scheduler/Errors/task_overspecified_2.tjp +14 -0
- data/test/TestSuite/Scheduler/Errors/task_overspecified_3.tjp +14 -0
- data/test/TestSuite/Scheduler/Errors/task_underspecified_1.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/task_underspecified_2.tjp +8 -0
- data/test/TestSuite/Scheduler/Errors/task_underspecified_3.tjp +9 -0
- data/test/TestSuite/Syntax/Correct/Account.tjp +53 -0
- data/test/TestSuite/Syntax/Correct/Allocate-1.tjp +24 -0
- data/test/TestSuite/Syntax/Correct/Alternative.tjp +13 -0
- data/test/TestSuite/Syntax/Correct/AutoMacros.tjp +14 -0
- data/test/TestSuite/Syntax/Correct/Booking.tjp +26 -0
- data/test/TestSuite/Syntax/Correct/Caption.tjp +33 -0
- data/test/TestSuite/Syntax/Correct/Celltext.tjp +28 -0
- data/test/TestSuite/Syntax/Correct/Comments.tjp +29 -0
- data/test/TestSuite/Syntax/Correct/Complete.tjp +16 -0
- data/test/TestSuite/Syntax/Correct/CompletedWork.tji +20 -0
- data/test/TestSuite/Syntax/Correct/CriticalPath.tjp +31 -0
- data/test/TestSuite/Syntax/Correct/Currencyformat.tjp +12 -0
- data/test/TestSuite/Syntax/Correct/CustomAttributes.tjp +14 -0
- data/test/TestSuite/Syntax/Correct/Depends1.tjp +22 -0
- data/test/TestSuite/Syntax/Correct/Durations.tjp +29 -0
- data/test/TestSuite/Syntax/Correct/Efficiency.tjp +19 -0
- data/test/TestSuite/Syntax/Correct/Export.tjp +40 -0
- data/test/TestSuite/Syntax/Correct/Flags.tjp +32 -0
- data/test/TestSuite/Syntax/Correct/Freeze.tjp +28 -0
- data/test/TestSuite/Syntax/Correct/Gap.tjp +15 -0
- data/test/TestSuite/Syntax/Correct/HtmlTaskReport.tjp +33 -0
- data/test/TestSuite/Syntax/Correct/Limits-1.tjp +71 -0
- data/test/TestSuite/Syntax/Correct/LoadUnits.tjp +31 -0
- data/test/TestSuite/Syntax/Correct/Macro-1.tjp +19 -0
- data/test/TestSuite/Syntax/Correct/Mandatory.tjp +17 -0
- data/test/TestSuite/Syntax/Correct/Milestone.tjp +12 -0
- data/test/TestSuite/Syntax/Correct/MinMax.tjp +17 -0
- data/test/TestSuite/Syntax/Correct/Numberformat.tjp +12 -0
- data/test/TestSuite/Syntax/Correct/Period.tjp +16 -0
- data/test/TestSuite/Syntax/Correct/Persistent.tjp +11 -0
- data/test/TestSuite/Syntax/Correct/Precedes1.tjp +17 -0
- data/test/TestSuite/Syntax/Correct/Priority.tjp +30 -0
- data/test/TestSuite/Syntax/Correct/Project.tjp +21 -0
- data/test/TestSuite/Syntax/Correct/ProjectIDs.tjp +23 -0
- data/test/TestSuite/Syntax/Correct/RawHTML.tjp +29 -0
- data/test/TestSuite/Syntax/Correct/Reports.tjp +54 -0
- data/test/TestSuite/Syntax/Correct/Resource.tjp +20 -0
- data/test/TestSuite/Syntax/Correct/Responsible.tjp +16 -0
- data/test/TestSuite/Syntax/Correct/Scenario.tjp +15 -0
- data/test/TestSuite/Syntax/Correct/Scheduling.tjp +26 -0
- data/test/TestSuite/Syntax/Correct/Select.tjp +27 -0
- data/test/TestSuite/Syntax/Correct/Shift.tjp +55 -0
- data/test/TestSuite/Syntax/Correct/Simple.tjp +25 -0
- data/test/TestSuite/Syntax/Correct/String.tjp +12 -0
- data/test/TestSuite/Syntax/Correct/Supplement.tjp +24 -0
- data/test/TestSuite/Syntax/Correct/TaskRoot.tjp +34 -0
- data/test/TestSuite/Syntax/Correct/TimeFrame.tjp +19 -0
- data/test/TestSuite/Syntax/Correct/Timezone.tjp +8 -0
- data/test/TestSuite/Syntax/Correct/Vacation.tjp +33 -0
- data/test/TestSuite/Syntax/Correct/csvtest +16 -0
- data/test/TestSuite/Syntax/Correct/manual2example.rb +24 -0
- data/test/TestSuite/Syntax/Correct/tutorial.tjp +485 -0
- data/test/TestSuite/Syntax/Errors/bad_include.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/booking_group.tjp +14 -0
- data/test/TestSuite/Syntax/Errors/booking_milestone.tjp +13 -0
- data/test/TestSuite/Syntax/Errors/booking_no_leaf.tjp +13 -0
- data/test/TestSuite/Syntax/Errors/chargeset.tjp +14 -0
- data/test/TestSuite/Syntax/Errors/chargeset_master.tjp +15 -0
- data/test/TestSuite/Syntax/Errors/container_attribute.tjp +13 -0
- data/test/TestSuite/Syntax/Errors/cost_acct_no_top.tjp +24 -0
- data/test/TestSuite/Syntax/Errors/cost_rev_same.tjp +24 -0
- data/test/TestSuite/Syntax/Errors/date_in_range.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/effort_zero.tjp +8 -0
- data/test/TestSuite/Syntax/Errors/empty.tjp +1 -0
- data/test/TestSuite/Syntax/Errors/export_bad_extn.tjp +9 -0
- data/test/TestSuite/Syntax/Errors/extend_id_cap.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/interval_end_in_range.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/interval_start_in_range.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/leaf_resource_id_expected.tjp +12 -0
- data/test/TestSuite/Syntax/Errors/misaligned_date.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/no_csv_suffix.tjp +10 -0
- data/test/TestSuite/Syntax/Errors/no_html_suffix.tjp +10 -0
- data/test/TestSuite/Syntax/Errors/operand_attribute.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/operand_unkn_flag.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/operand_unkn_scen.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/overtime_range.tjp +13 -0
- data/test/TestSuite/Syntax/Errors/purge_no_list.tjp +8 -0
- data/test/TestSuite/Syntax/Errors/purge_unknown_id.tjp +8 -0
- data/test/TestSuite/Syntax/Errors/report_end.tjp +10 -0
- data/test/TestSuite/Syntax/Errors/report_redifinition.tjp +10 -0
- data/test/TestSuite/Syntax/Errors/report_start.tjp +10 -0
- data/test/TestSuite/Syntax/Errors/resource_exists.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/resource_id_expected.tjp +8 -0
- data/test/TestSuite/Syntax/Errors/rev_acct_no_top.tjp +24 -0
- data/test/TestSuite/Syntax/Errors/scenario_exists.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/shift_assignment_overlap.tjp +15 -0
- data/test/TestSuite/Syntax/Errors/shift_exists.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/shift_id_expected.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/sloppy_range.tjp +13 -0
- data/test/TestSuite/Syntax/Errors/sort_direction.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/sort_unknown_scen.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/sorting_crit_exptd1.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/sorting_crit_exptd2.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/sorting_wbs.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/start_before_end1.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/start_before_end2.tjp +6 -0
- data/test/TestSuite/Syntax/Errors/task_complete.tjp +8 -0
- data/test/TestSuite/Syntax/Errors/task_exists.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/task_priority.tjp +8 -0
- data/test/TestSuite/Syntax/Errors/task_without_chargeset.tjp +9 -0
- data/test/TestSuite/Syntax/Errors/time_interval.tjp +12 -0
- data/test/TestSuite/Syntax/Errors/too_many_bangs.tjp +10 -0
- data/test/TestSuite/Syntax/Errors/undecl_flag.tjp +6 -0
- data/test/TestSuite/Syntax/Errors/unknown_projectid.tjp +7 -0
- data/test/TestSuite/Syntax/Errors/unknown_scenario_id.tjp +6 -0
- data/test/TestSuite/Syntax/Errors/unknown_scenario_idx.tjp +11 -0
- data/test/TestSuite/Syntax/Errors/unknown_task.tjp +10 -0
- data/test/all.rb +31 -0
- data/test/test_BatchProcessor.rb +54 -0
- data/test/test_CSV-Reports.rb +101 -0
- data/test/test_Limits.rb +104 -0
- data/test/test_LogicalExpression.rb +110 -0
- data/test/test_MacroTable.rb +51 -0
- data/test/test_Project.rb +57 -0
- data/test/test_PropertySet.rb +71 -0
- data/test/test_Query.rb +83 -0
- data/test/test_RealFormat.rb +83 -0
- data/test/test_RichText.rb +869 -0
- data/test/test_Scheduler.rb +42 -0
- data/test/test_ShiftAssignments.rb +77 -0
- data/test/test_Syntax.rb +41 -0
- data/test/test_TextScanner.rb +95 -0
- data/test/test_TjTime.rb +114 -0
- data/test/test_TjpExample.rb +169 -0
- data/test/test_UTF8String.rb +84 -0
- data/test/test_WorkingHours.rb +56 -0
- metadata +649 -0
data/lib/PropertySet.rb
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#!/usr/bin/env ruby -w
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
#
|
|
4
|
+
# = PropertySet.rb -- The TaskJuggler III Project Management Software
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2006, 2007, 2008, 2009 by Chris Schlaeger <cs@kde.org>
|
|
7
|
+
#
|
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
|
10
|
+
# published by the Free Software Foundation.
|
|
11
|
+
#
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
require 'AttributeDefinition'
|
|
15
|
+
require 'PropertyTreeNode'
|
|
16
|
+
|
|
17
|
+
class TaskJuggler
|
|
18
|
+
|
|
19
|
+
# A PropertySet is a collection of properties of the same kind. Properties can
|
|
20
|
+
# be Task, Resources, Scenario, Shift or Accounts objects. All properties of
|
|
21
|
+
# the same kind belong to the same PropertySet. A property may only belong to
|
|
22
|
+
# one PropertySet in the Project. The PropertySet holds the definitions for
|
|
23
|
+
# the attributes. All Properties of the set will have a set of these
|
|
24
|
+
# attributes.
|
|
25
|
+
class PropertySet
|
|
26
|
+
|
|
27
|
+
attr_reader :project, :flatNamespace, :attributeDefinitions
|
|
28
|
+
|
|
29
|
+
def initialize(project, flatNamespace)
|
|
30
|
+
if $DEBUG && project.nil?
|
|
31
|
+
raise "project parameter may not be NIL"
|
|
32
|
+
end
|
|
33
|
+
# Indicates whether the namespace of this PropertySet is flat or not. In a
|
|
34
|
+
# flat namespace all property IDs must be unique. Otherwise only the IDs
|
|
35
|
+
# within a group of siblings must be unique. The full ID of the Property
|
|
36
|
+
# is then composed of the siblings ID prefixed by the parent ID. ID fields
|
|
37
|
+
# are separated by dots.
|
|
38
|
+
@flatNamespace = flatNamespace
|
|
39
|
+
# The main Project data structure reference.
|
|
40
|
+
@project = project
|
|
41
|
+
# This is the blueprint for PropertyTreeNode attribute sets. Whever a new
|
|
42
|
+
# PropertTreeNode is created, an attribute is created for each definition
|
|
43
|
+
# in this list.
|
|
44
|
+
@attributeDefinitions = Hash.new
|
|
45
|
+
# A list of all PropertyTreeNodes in this set.
|
|
46
|
+
@properties = Array.new
|
|
47
|
+
# A hash of all PropertyTreeNodes in this set, hashed by their ID. This is
|
|
48
|
+
# the same data as in @properties, but hashed by ID for faster access.
|
|
49
|
+
@propertyMap = Hash.new
|
|
50
|
+
|
|
51
|
+
# IDs and names of the built-in attributes. TODO: Check performance impact
|
|
52
|
+
# when making them normal attributes.
|
|
53
|
+
@@fixedAttributeNames = {
|
|
54
|
+
'id' => 'ID',
|
|
55
|
+
'name' => 'Name',
|
|
56
|
+
'seqno' => 'Seq. No.'
|
|
57
|
+
}
|
|
58
|
+
# And their types.
|
|
59
|
+
@@fixedAttributesTypes = {
|
|
60
|
+
'id' => :String,
|
|
61
|
+
'name' => :String,
|
|
62
|
+
'seqno' => :Fixnum
|
|
63
|
+
}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Inherit all attributes of each property from the parent scenario.
|
|
67
|
+
def inheritAttributesFromScenario
|
|
68
|
+
@properties.each { |p| p.inheritAttributesFromScenario }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Use the function to declare the various attributes that properties of this
|
|
72
|
+
# PropertySet can have. The attributes must be declared before the first
|
|
73
|
+
# property is added to the set.
|
|
74
|
+
def addAttributeType(attributeType)
|
|
75
|
+
if !@properties.empty?
|
|
76
|
+
raise "Fatal Error: Attribute types must be defined before " +
|
|
77
|
+
"properties are added."
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
@attributeDefinitions[attributeType.id] = attributeType
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Iterate over all attribute definitions.
|
|
84
|
+
def eachAttributeDefinition
|
|
85
|
+
@attributeDefinitions.each do |key, value|
|
|
86
|
+
yield(value)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Return true if there is an AttributeDefinition for _attrId_.
|
|
91
|
+
def knownAttribute?(attrId)
|
|
92
|
+
@@fixedAttributeNames.include?(attrId) ||
|
|
93
|
+
@attributeDefinitions.include?(attrId)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Return whether the attribute with _attrId_ is scenario specific or not.
|
|
97
|
+
def scenarioSpecific?(attrId)
|
|
98
|
+
# All hardwired attributes are not scenario specific.
|
|
99
|
+
return false if @attributeDefinitions[attrId].nil?
|
|
100
|
+
|
|
101
|
+
@attributeDefinitions[attrId].scenarioSpecific
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Return whether the attribute with _attrId_ is scenario specific or not.
|
|
105
|
+
def inheritable?(attrId)
|
|
106
|
+
# All hardwired attributes are not inheritable.
|
|
107
|
+
return false if @attributeDefinitions[attrId].nil?
|
|
108
|
+
|
|
109
|
+
@attributeDefinitions[attrId].inheritable
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Return whether or not the attribute was user defined.
|
|
113
|
+
def userDefined?(attrId)
|
|
114
|
+
return false if @attributeDefinitions[attrId].nil?
|
|
115
|
+
|
|
116
|
+
@attributeDefinitions[attrId].userDefined
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Return the default value of the attribute.
|
|
120
|
+
def defaultValue(attrId)
|
|
121
|
+
return nil if @attributeDefinitions[attrId].nil?
|
|
122
|
+
|
|
123
|
+
@attributeDefinitions[attrId].default
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Returns the name (human readable description) of the attribute with the
|
|
127
|
+
# Id specified by _attrId_.
|
|
128
|
+
def attributeName(attrId)
|
|
129
|
+
# Some attributes are hardwired into the properties. These need to be
|
|
130
|
+
# treated separately.
|
|
131
|
+
if @@fixedAttributeNames[attrId].nil?
|
|
132
|
+
if @attributeDefinitions.include?(attrId)
|
|
133
|
+
return @attributeDefinitions[attrId].name
|
|
134
|
+
end
|
|
135
|
+
else
|
|
136
|
+
return @@fixedAttributeNames[attrId]
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
nil
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Return the type of the attribute with the Id specified by _attrId_.
|
|
143
|
+
def attributeType(attrId)
|
|
144
|
+
# Hardwired attributes need special treatment.
|
|
145
|
+
if @@fixedAttributesTypes[attrId].nil?
|
|
146
|
+
if @attributeDefinitions.has_key?(attrId)
|
|
147
|
+
@attributeDefinitions[attrId].objClass
|
|
148
|
+
else
|
|
149
|
+
nil
|
|
150
|
+
end
|
|
151
|
+
else
|
|
152
|
+
@@fixedAttributesTypes[attrId]
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Add the new PropertyTreeNode object _property_ to the set. The set is
|
|
157
|
+
# indexed by ID. In case an object with the same ID already exists in the
|
|
158
|
+
# set it will be overwritten.
|
|
159
|
+
#
|
|
160
|
+
# Whenever the set has been extended, the 'wbs' and 'tree' attributes of the
|
|
161
|
+
# properties are no longer up-to-date. You must call index() before using
|
|
162
|
+
# these attributes.
|
|
163
|
+
def addProperty(property)
|
|
164
|
+
# The PropertySet defines the set of attribute that each PropertyTreeNode
|
|
165
|
+
# in this set has. Create these attributes with their default values.
|
|
166
|
+
@attributeDefinitions.each do |id, attributeType|
|
|
167
|
+
property.declareAttribute(attributeType)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# The PropertyTreeNode objects are indexed by ID or hierachical ID
|
|
171
|
+
# depending on the name space setting of this set.
|
|
172
|
+
if @flatNamespace
|
|
173
|
+
@propertyMap[property.id] = property
|
|
174
|
+
else
|
|
175
|
+
@propertyMap[property.fullId] = property
|
|
176
|
+
end
|
|
177
|
+
@properties << property
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Remove the PropertyTreeNode (and all its children) object from the set.
|
|
181
|
+
# _prop_ can either be a property ID or a reference to the PropertyTreeNode.
|
|
182
|
+
#
|
|
183
|
+
# TODO: This function does not take care of references to this PTN!
|
|
184
|
+
def removeProperty(prop)
|
|
185
|
+
if prop.is_a?(String)
|
|
186
|
+
property = @propertyMap[prop]
|
|
187
|
+
else
|
|
188
|
+
property = prop
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Recursively remove all sub-nodes. The children list is modified during
|
|
192
|
+
# the call, so we can't use an iterator here.
|
|
193
|
+
until property.children.empty? do
|
|
194
|
+
removeProperty(property.children.first)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
@properties.delete(property)
|
|
198
|
+
@propertyMap.delete(property.fullId)
|
|
199
|
+
|
|
200
|
+
# Remove this node from the child list of the parent node.
|
|
201
|
+
property.parent.children.delete(property) if property.parent
|
|
202
|
+
|
|
203
|
+
property
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Call this function to delete all registered properties.
|
|
207
|
+
def clearProperties
|
|
208
|
+
@properties.clear
|
|
209
|
+
@propertyMap.clear
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Return the PropertyTreeNode object with ID _id_ from the set or nil if not
|
|
213
|
+
# present.
|
|
214
|
+
def [](id)
|
|
215
|
+
@propertyMap[id]
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Update the WBS and tree indicies. This method needs to be called whenever
|
|
219
|
+
# the set has been modified.
|
|
220
|
+
def index
|
|
221
|
+
each do |p|
|
|
222
|
+
wbsIdcs = p.getWBSIndicies
|
|
223
|
+
tree = ""
|
|
224
|
+
wbs = ""
|
|
225
|
+
first = true
|
|
226
|
+
wbsIdcs.each do |idx|
|
|
227
|
+
# Prefix the level index with zeros so that we always have a 5 digit
|
|
228
|
+
# long String. 5 digits should be large enough for all real-world
|
|
229
|
+
# projects.
|
|
230
|
+
tree += idx.to_s.rjust(5, '0')
|
|
231
|
+
if first
|
|
232
|
+
first = false
|
|
233
|
+
else
|
|
234
|
+
wbs += '.'
|
|
235
|
+
end
|
|
236
|
+
wbs += idx.to_s
|
|
237
|
+
end
|
|
238
|
+
p.set('wbs', wbs)
|
|
239
|
+
p.set('tree', tree)
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Return the index of the top-level _property_ in the set.
|
|
244
|
+
def levelSeqNo(property)
|
|
245
|
+
seqNo = 1
|
|
246
|
+
@properties.each do |p|
|
|
247
|
+
unless p.parent
|
|
248
|
+
return seqNo if p == property
|
|
249
|
+
seqNo += 1
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
raise "Fatal Error: Unknow property #{property}"
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# Return the maximum used number of breakdown levels. A flat list has a
|
|
256
|
+
# maxDepth of 1. A list with one sub level has a maxDepth of 2 and so on.
|
|
257
|
+
def maxDepth
|
|
258
|
+
md = 0
|
|
259
|
+
each do |p|
|
|
260
|
+
md = p.level if p.level > md
|
|
261
|
+
end
|
|
262
|
+
md + 1
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Return the number of PropertyTreeNode objects in this set.
|
|
266
|
+
def items
|
|
267
|
+
@properties.length
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Return true if the set is empty.
|
|
271
|
+
def empty?
|
|
272
|
+
@properties.empty?
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Return the number of top-level PropertyTreeNode objects. Top-Level items
|
|
276
|
+
# are no children.
|
|
277
|
+
def topLevelItems
|
|
278
|
+
items = 0
|
|
279
|
+
@properties.each do |p|
|
|
280
|
+
items += 1 unless p.parent
|
|
281
|
+
end
|
|
282
|
+
items
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# Iterator over all PropertyTreeNode objects in this set.
|
|
286
|
+
def each
|
|
287
|
+
@properties.each do |value|
|
|
288
|
+
yield(value)
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# Return the set of PropertyTreeNode objects as flat Array.
|
|
293
|
+
def to_ary
|
|
294
|
+
@properties
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def to_s
|
|
298
|
+
PropertyList.new(self).to_s
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
end
|
|
304
|
+
|
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
#!/usr/bin/env ruby -w
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
#
|
|
4
|
+
# = PropertyTreeNode.rb -- The TaskJuggler III Project Management Software
|
|
5
|
+
#
|
|
6
|
+
# Copyright (c) 2006, 2007, 2008, 2009 by Chris Schlaeger <cs@kde.org>
|
|
7
|
+
#
|
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
|
10
|
+
# published by the Free Software Foundation.
|
|
11
|
+
#
|
|
12
|
+
|
|
13
|
+
class TaskJuggler
|
|
14
|
+
|
|
15
|
+
# This class is the base object for all Project properties. A Project property
|
|
16
|
+
# is a e. g. a Task, a Resource or other objects. Such properties can be
|
|
17
|
+
# arranged in tree form by assigning child properties to an existing property.
|
|
18
|
+
# The parent object needs to exist at object creation time. The
|
|
19
|
+
# PropertyTreeNode class holds all data and methods that are common to the
|
|
20
|
+
# different types of properties. Each property can have a set of predifined
|
|
21
|
+
# attributes. The PropertySet class holds collections of the same
|
|
22
|
+
# PropertyTreeNode objects and the defined attributes.
|
|
23
|
+
# Each PropertySet has a predefined set of attributes, but the attribute set
|
|
24
|
+
# can be extended by the user. E.g. a task has the predefined attribute
|
|
25
|
+
# 'start' and 'end' date. The user can extend tasks with a user defined
|
|
26
|
+
# attribute like an URL that contains more details about the task.
|
|
27
|
+
class PropertyTreeNode
|
|
28
|
+
|
|
29
|
+
attr_reader :propertySet, :id, :name, :parent, :project, :sequenceNo,
|
|
30
|
+
:children
|
|
31
|
+
attr_accessor :sourceFileInfo
|
|
32
|
+
|
|
33
|
+
# Create a new PropertyTreeNode object. _propertySet_ is the PropertySet
|
|
34
|
+
# that this PropertyTreeNode object belongs to. The PropertySet determines
|
|
35
|
+
# the attributes that are common to all Nodes in the set. _id_ is a String
|
|
36
|
+
# that is unique in the namespace of the set. _name_ is a user readable,
|
|
37
|
+
# short description of the object. _parent_ is the PropertyTreeNode that
|
|
38
|
+
# sits above this node in the object hierachy. A root object has a _parent_
|
|
39
|
+
# of nil. For sets with hierachical name spaces, parent can be nil and
|
|
40
|
+
# specified by a hierachical _id_ (e. g. 'father.son').
|
|
41
|
+
def initialize(propertySet, id, name, parent)
|
|
42
|
+
@propertySet = propertySet
|
|
43
|
+
if !@propertySet.flatNamespace && id.include?('.')
|
|
44
|
+
parentId = id[0..(id.rindex('.') - 1)]
|
|
45
|
+
# Set parent to the parent property if it's still nil.
|
|
46
|
+
parent = @propertySet[parentId] unless parent
|
|
47
|
+
if $DEBUG
|
|
48
|
+
if !parent || !@propertySet[parent.fullId]
|
|
49
|
+
raise "Fatal Error: parent must be member of same property set"
|
|
50
|
+
end
|
|
51
|
+
if parentId != parent.fullId
|
|
52
|
+
raise "Fatal Error: parent (#{parent.fullId}) and parent ID " +
|
|
53
|
+
"(#{parentId}) don't match"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
@id = id[(id.rindex('.') + 1).. -1]
|
|
57
|
+
else
|
|
58
|
+
@id = id
|
|
59
|
+
end
|
|
60
|
+
@name = name
|
|
61
|
+
@project = propertySet.project
|
|
62
|
+
@level = -1
|
|
63
|
+
@sourceFileInfo = nil
|
|
64
|
+
|
|
65
|
+
@parent = parent
|
|
66
|
+
@sequenceNo = @propertySet.items + 1
|
|
67
|
+
@children = Array.new
|
|
68
|
+
# In case we have a parent object, we register this object as child of
|
|
69
|
+
# the parent.
|
|
70
|
+
if (@parent)
|
|
71
|
+
@parent.addChild(self)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
@attributes = Hash.new
|
|
75
|
+
@scenarioAttributes = Array.new(@project.scenarioCount)
|
|
76
|
+
@project.scenarioCount.times do |i|
|
|
77
|
+
@scenarioAttributes[i] = Hash.new
|
|
78
|
+
end
|
|
79
|
+
# Scenario specific data
|
|
80
|
+
@data = nil
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Return the index of the child _node_.
|
|
84
|
+
def levelSeqNo(node)
|
|
85
|
+
@children.index(node) + 1
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Inherit values for the attributes from the parent node or the Project.
|
|
89
|
+
def inheritAttributes
|
|
90
|
+
# These attributes are being inherited from the Project.
|
|
91
|
+
whitelist = %w( limits priority projectid rate vacation workinghours )
|
|
92
|
+
|
|
93
|
+
# Inherit non-scenario-specific values
|
|
94
|
+
@propertySet.eachAttributeDefinition do |attrDef|
|
|
95
|
+
next if attrDef.scenarioSpecific || !attrDef.inheritable
|
|
96
|
+
|
|
97
|
+
aId = attrDef.id
|
|
98
|
+
if parent
|
|
99
|
+
# Inherit values from parent property
|
|
100
|
+
if parent.provided(aId) || parent.inherited(aId)
|
|
101
|
+
@attributes[aId].inherit(parent.get(aId))
|
|
102
|
+
end
|
|
103
|
+
else
|
|
104
|
+
# Inherit selected values from project if top-level property
|
|
105
|
+
if whitelist.index(aId)
|
|
106
|
+
if @project[aId]
|
|
107
|
+
@attributes[aId].inherit(@project[aId])
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Inherit scenario-specific values
|
|
114
|
+
@propertySet.eachAttributeDefinition do |attrDef|
|
|
115
|
+
next if !attrDef.scenarioSpecific || !attrDef.inheritable
|
|
116
|
+
|
|
117
|
+
@project.scenarioCount.times do |scenarioIdx|
|
|
118
|
+
if parent
|
|
119
|
+
# Inherit scenario specific values from parent property
|
|
120
|
+
if parent.provided(attrDef.id, scenarioIdx) ||
|
|
121
|
+
parent.inherited(attrDef.id, scenarioIdx)
|
|
122
|
+
@scenarioAttributes[scenarioIdx][attrDef.id].inherit(
|
|
123
|
+
parent[attrDef.id, scenarioIdx])
|
|
124
|
+
end
|
|
125
|
+
else
|
|
126
|
+
# Inherit selected values from project if top-level property
|
|
127
|
+
if whitelist.index(attrDef.id)
|
|
128
|
+
if @project[attrDef.id] &&
|
|
129
|
+
@scenarioAttributes[scenarioIdx][attrDef.id]
|
|
130
|
+
@scenarioAttributes[scenarioIdx][attrDef.id].inherit(
|
|
131
|
+
@project[attrDef.id])
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Inherit attribute values from the parent scenario. This is only being done
|
|
140
|
+
# for attributes that don't have a user-specified value already.
|
|
141
|
+
def inheritAttributesFromScenario
|
|
142
|
+
# Inherit scenario-specific values
|
|
143
|
+
@propertySet.eachAttributeDefinition do |attrDef|
|
|
144
|
+
next unless attrDef.scenarioSpecific
|
|
145
|
+
|
|
146
|
+
# We know that parent scenarios precede their children in the list. So
|
|
147
|
+
# it's safe to iterate over the list instead of recursively descend
|
|
148
|
+
# the tree.
|
|
149
|
+
@project.scenarioCount.times do |scenarioIdx|
|
|
150
|
+
scenario = @project.scenario(scenarioIdx)
|
|
151
|
+
next if scenario.parent.nil?
|
|
152
|
+
parentScenarioIdx = scenario.parent.sequenceNo - 1
|
|
153
|
+
# We copy only provided or inherited values from parent scenario when
|
|
154
|
+
# we don't have a provided or inherited value in this scenario.
|
|
155
|
+
if (provided(attrDef.id, parentScenarioIdx) ||
|
|
156
|
+
inherited(attrDef.id, parentScenarioIdx)) &&
|
|
157
|
+
!(provided(attrDef.id, scenarioIdx) ||
|
|
158
|
+
inherited(attrDef.id, scenarioIdx))
|
|
159
|
+
@scenarioAttributes[scenarioIdx][attrDef.id].inherit(
|
|
160
|
+
@scenarioAttributes[parentScenarioIdx][attrDef.id].get)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Returns a list of this node and all transient sub nodes.
|
|
167
|
+
def all
|
|
168
|
+
res = [ self ]
|
|
169
|
+
@children.each do |c|
|
|
170
|
+
res = res.concat(c.all)
|
|
171
|
+
end
|
|
172
|
+
res
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Return a list of all leaf nodes of this node.
|
|
176
|
+
def allLeaves
|
|
177
|
+
if leaf?
|
|
178
|
+
res = [ self ]
|
|
179
|
+
else
|
|
180
|
+
res = []
|
|
181
|
+
@children.each do |c|
|
|
182
|
+
res += c.allLeaves
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
res
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Iterator over all non-scenario-specific attributes of this node.
|
|
189
|
+
def eachAttribute
|
|
190
|
+
@attributes.each do |attr|
|
|
191
|
+
yield attr
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Iterator over all scenario-specific attributes of this node.
|
|
196
|
+
def eachScenarioAttribute(scenario)
|
|
197
|
+
@scenarioAttributes[scenario].each_value do |attr|
|
|
198
|
+
yield attr
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Return the full id of this node. For PropertySet objects with a flat
|
|
203
|
+
# namespace, this is just the ID. Otherwise, the full ID is composed of all
|
|
204
|
+
# IDs from the root node to this node, separating the IDs by a dot.
|
|
205
|
+
def fullId
|
|
206
|
+
res = @id
|
|
207
|
+
unless @propertySet.flatNamespace
|
|
208
|
+
t = self
|
|
209
|
+
until (t = t.parent).nil?
|
|
210
|
+
res = t.id + "." + res
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
res
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Returns the level that this property is on. Top-level properties return
|
|
217
|
+
# 0, their children 1 and so on. This value is cached internally, so it does
|
|
218
|
+
# not have to be calculated each time the function is called.
|
|
219
|
+
def level
|
|
220
|
+
return @level if @level >= 0
|
|
221
|
+
|
|
222
|
+
t = self
|
|
223
|
+
@level = 0
|
|
224
|
+
until (t = t.parent).nil?
|
|
225
|
+
@level += 1
|
|
226
|
+
end
|
|
227
|
+
@level
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Return the hierarchical index of this node. In project management lingo
|
|
231
|
+
# this is called the Work Breakdown Structure (WBS). The result is an Array
|
|
232
|
+
# with an index for each level from the root to this node.
|
|
233
|
+
def getWBSIndicies
|
|
234
|
+
idcs = []
|
|
235
|
+
p = self
|
|
236
|
+
begin
|
|
237
|
+
parent = p.parent
|
|
238
|
+
idcs.insert(0, parent ? parent.levelSeqNo(p) :
|
|
239
|
+
@propertySet.levelSeqNo(p))
|
|
240
|
+
p = parent
|
|
241
|
+
end while p
|
|
242
|
+
idcs
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Add _child_ node as child to this node.
|
|
246
|
+
def addChild(child)
|
|
247
|
+
if $DEBUG && child.propertySet != @propertySet
|
|
248
|
+
raise "Child nodes must belong to the same property set as the parent"
|
|
249
|
+
end
|
|
250
|
+
@children.push(child)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Find out if this property is a direct or indirect child of _ancestor_.
|
|
254
|
+
def isChildOf?(ancestor)
|
|
255
|
+
parent = self
|
|
256
|
+
while parent = parent.parent
|
|
257
|
+
return true if (parent == ancestor)
|
|
258
|
+
end
|
|
259
|
+
false
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# Return true if the node is a leaf node (has no children).
|
|
263
|
+
def leaf?
|
|
264
|
+
@children.empty?
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# Return true if the node has children.
|
|
268
|
+
def container?
|
|
269
|
+
!@children.empty?
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Return the top-level node for this node.
|
|
273
|
+
def root
|
|
274
|
+
n = self
|
|
275
|
+
while n.parent
|
|
276
|
+
n = n.parent
|
|
277
|
+
end
|
|
278
|
+
n
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# Register a new attribute with the PropertyTreeNode and create the
|
|
282
|
+
# instances for each scenario.
|
|
283
|
+
def declareAttribute(attributeType)
|
|
284
|
+
if attributeType.scenarioSpecific
|
|
285
|
+
@project.scenarioCount.times do |i|
|
|
286
|
+
attribute = newAttribute(attributeType)
|
|
287
|
+
@scenarioAttributes[i][attribute.id] = attribute
|
|
288
|
+
end
|
|
289
|
+
else
|
|
290
|
+
attribute = newAttribute(attributeType)
|
|
291
|
+
@attributes[attribute.id] = attribute
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# Return the type of the attribute with ID _attributeId_.
|
|
296
|
+
def attributeDefinition(attributeId)
|
|
297
|
+
@propertySet.attributeDefinitions[attributeId]
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Return the value of the non-scenario-specific attribute with ID
|
|
301
|
+
# _attributeId_. In case the attribute does not exist, an exception is
|
|
302
|
+
# raised.
|
|
303
|
+
def get(attributeId)
|
|
304
|
+
case attributeId
|
|
305
|
+
when 'id'
|
|
306
|
+
@id
|
|
307
|
+
when 'name'
|
|
308
|
+
@name
|
|
309
|
+
when 'seqno'
|
|
310
|
+
@sequenceNo
|
|
311
|
+
else
|
|
312
|
+
unless @attributes.has_key?(attributeId)
|
|
313
|
+
raise TjException.new, "Unknown attribute #{attributeId}"
|
|
314
|
+
end
|
|
315
|
+
@attributes[attributeId].get
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Return the value of the attribute with ID _attributeId_. In case this is a
|
|
320
|
+
# scenario-specific attribute, the scenario index needs to be provided by
|
|
321
|
+
# _scenarioIdx_.
|
|
322
|
+
def getAttr(attributeId, scenarioIdx = nil)
|
|
323
|
+
if scenarioIdx.nil?
|
|
324
|
+
@attributes[attributeId]
|
|
325
|
+
else
|
|
326
|
+
@scenarioAttributes[scenarioIdx][attributeId]
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
# Set the non-scenario-specific attribute with ID _attributeId_ to _value_.
|
|
331
|
+
# In case the attribute does not exist, an exception is raised.
|
|
332
|
+
def set(attributeId, value)
|
|
333
|
+
unless @attributes.has_key?(attributeId)
|
|
334
|
+
raise TjException.new, "Unknown attribute #{attributeId}"
|
|
335
|
+
end
|
|
336
|
+
@attributes[attributeId].set(value)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
# Set the scenario specific attribute with ID _attributeId_ for the scenario
|
|
340
|
+
# with index _scenario_ to _value_. In case the attribute does not exist, an
|
|
341
|
+
# exception is raised.
|
|
342
|
+
def []=(attributeId, scenario, value)
|
|
343
|
+
if @scenarioAttributes[scenario].has_key?(attributeId)
|
|
344
|
+
@scenarioAttributes[scenario][attributeId].set(value)
|
|
345
|
+
elsif @attributes.has_key?(attributeId)
|
|
346
|
+
@attributes[attributeId].set(value)
|
|
347
|
+
else
|
|
348
|
+
raise TjException.new, "Unknown attribute #{attributeId}"
|
|
349
|
+
end
|
|
350
|
+
@scenarioAttributes[scenario][attributeId].set(value)
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
# Return the value of the attribute with ID _attributeId_. For
|
|
354
|
+
# scenario-specific attributes, _scenario_ must indicate the index of the
|
|
355
|
+
# Scenario.
|
|
356
|
+
def [](attributeId, scenario)
|
|
357
|
+
if @scenarioAttributes[scenario].has_key?(attributeId)
|
|
358
|
+
@scenarioAttributes[scenario][attributeId].get
|
|
359
|
+
else
|
|
360
|
+
get(attributeId);
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
# This function returns true if the PropertyTreeNode has a query function
|
|
365
|
+
# for the given ID _queryId_. In case a _scenarioIdx_ is specified, the
|
|
366
|
+
# query function must be scenario specific.
|
|
367
|
+
def hasQuery?(queryId, scenarioIdx = nil)
|
|
368
|
+
methodName = 'query_' + queryId
|
|
369
|
+
if scenarioIdx
|
|
370
|
+
@data[scenarioIdx].respond_to?(methodName)
|
|
371
|
+
else
|
|
372
|
+
respond_to?(methodName)
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
# Returns true if the value of the attribute _attributeId_ (in scenario
|
|
377
|
+
# _scenarioIdx_) has been provided by the user.
|
|
378
|
+
def provided(attributeId, scenarioIdx = nil)
|
|
379
|
+
if scenarioIdx
|
|
380
|
+
return false if @scenarioAttributes[scenarioIdx][attributeId].nil?
|
|
381
|
+
@scenarioAttributes[scenarioIdx][attributeId].provided
|
|
382
|
+
else
|
|
383
|
+
return false if @attributes[attributeId].nil?
|
|
384
|
+
@attributes[attributeId].provided
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# Returns true if the value of the attribute _attributeId_ (in scenario
|
|
389
|
+
# _scenarioIdx_) has been inherited from a parent node or scenario.
|
|
390
|
+
def inherited(attributeId, scenarioIdx = nil)
|
|
391
|
+
if scenarioIdx
|
|
392
|
+
return false if @scenarioAttributes[scenarioIdx][attributeId].nil?
|
|
393
|
+
@scenarioAttributes[scenarioIdx][attributeId].inherited
|
|
394
|
+
else
|
|
395
|
+
return false if @attributes[attributeId].nil?
|
|
396
|
+
@attributes[attributeId].inherited
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
# Dump the class data in human readable form. Used for debugging only.
|
|
401
|
+
def to_s # :nodoc:
|
|
402
|
+
res = "#{self.class} #{fullId} \"#{@name}\"\n" +
|
|
403
|
+
" Sequence No: #{@sequenceNo}\n"
|
|
404
|
+
|
|
405
|
+
res += " Parent: #{@parent.fullId}\n" if @parent
|
|
406
|
+
children = ""
|
|
407
|
+
@children.each do |c|
|
|
408
|
+
children += ', ' unless children.empty?
|
|
409
|
+
children += c.fullId
|
|
410
|
+
end
|
|
411
|
+
res += ' Children: ' + children + "\n" unless children.empty?
|
|
412
|
+
@attributes.sort.each do |key, attr|
|
|
413
|
+
if attr.get != @propertySet.defaultValue(key)
|
|
414
|
+
res += indent(" #{key}: ", attr.to_s)
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
unless @scenarioAttributes.empty?
|
|
418
|
+
project.scenarioCount.times do |sc|
|
|
419
|
+
headerShown = false
|
|
420
|
+
@scenarioAttributes[sc].sort.each do |key, attr|
|
|
421
|
+
if attr.get != @propertySet.defaultValue(key)
|
|
422
|
+
unless headerShown
|
|
423
|
+
res += " Scenario #{project.scenario(sc).get('id')} (#{sc})\n"
|
|
424
|
+
headerShown = true
|
|
425
|
+
end
|
|
426
|
+
res += indent(" #{key}: ", attr.to_s)
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
res += '-' * 75 + "\n"
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
# Many PropertyTreeNode functions are scenario specific. These functions are
|
|
435
|
+
# provided by the class *Scenario classes. In case we can't find a function
|
|
436
|
+
# called for the base class we try to find it in corresponding *Scenario
|
|
437
|
+
# class.
|
|
438
|
+
def method_missing(func, scenarioIdx, *args)
|
|
439
|
+
@data[scenarioIdx].method(func).call(*args)
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
private
|
|
443
|
+
|
|
444
|
+
def newAttribute(attributeType)
|
|
445
|
+
attribute = attributeType.objClass.new(self, attributeType)
|
|
446
|
+
# If the attribute requires a pointer to the project, we'll hand it over.
|
|
447
|
+
if !attribute.value.nil? && attribute.respond_to?('setProject')
|
|
448
|
+
attribute.setProject(@project)
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
attribute
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
def indent(tag, str)
|
|
455
|
+
tag + str.gsub(/\n/, "\n#{' ' * tag.length}") + "\n"
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
end
|
|
461
|
+
|