Parent

Class Index [+]

Quicksearch

TaskJuggler::PropertyList

The PropertyList is a utility class that can be used to hold a list of properties. It’s derived from an Array, so it can hold the properties in a well defined order. The order can be determined by an arbitrary number of sorting levels. A sorting level specifies an attribute who’s value should be used for sorting, a scenario index if necessary and the sorting direction (up/down). All nodes in the PropertyList must belong to the same PropertySet.

Attributes

query[W]
propertySet[R]
query[R]
sortingLevels[R]
sortingCriteria[R]
sortingUp[R]
scenarioIdx[R]

Public Class Methods

new(arg, copyItems = true) click to toggle source

A PropertyList is always bound to a certain PropertySet. All properties in the list must be of that set.

    # File lib/PropertyList.rb, line 30
30:     def initialize(arg, copyItems = true)
31:       @items = copyItems ? arg.to_ary : []
32:       if arg.is_a?(PropertySet)
33:         # Create a PropertyList from the given PropertySet.
34:         @propertySet = arg
35:         # To keep the list sorted, we may have to access Property attributes.
36:         # Pre-scheduling, we can only use static attributes. Post-scheduling,
37:         # we can include dynamic attributes as well. This query template will
38:         # be used to query attributes when it has been set. Otherwise the list
39:         # can only be sorted by static attributes.
40:         @query = nil
41:         resetSorting
42:         addSortingCriteria('seqno', true, 1)
43:         sort!
44:       else
45:         # Create a PropertyList from a given other PropertyList.
46:         @propertySet = arg.propertySet
47:         @query = arg.query ? arg.query.dup : nil
48:         @sortingLevels = arg.sortingLevels
49:         @sortingCriteria = arg.sortingCriteria.dup
50:         @sortingUp = arg.sortingUp.dup
51:         @scenarioIdx = arg.scenarioIdx.dup
52:       end
53:     end

Public Instance Methods

addSortingCriteria(criteria, up, scIdx) click to toggle source

Append a new sorting level to the existing levels.

     # File lib/PropertyList.rb, line 98
 98:     def addSortingCriteria(criteria, up, scIdx)
 99:       unless @propertySet.knownAttribute?(criteria) ||
100:              @propertySet.hasQuery?(criteria, scIdx)
101:         raise TjException.new, "Unknown attribute #{criteria} used for " +
102:                                'sorting criterium'
103:       end
104:       if scIdx == 1
105:         if @propertySet.scenarioSpecific?(criteria)
106:           raise TjException.new, "Attribute #{criteria} is scenario specific." +
107:                 "You must specify a scenario id."
108:         end
109:       else
110:         if @propertySet.project.scenario(scIdx).nil?
111:           raise TjException.new, "Unknown scenario index #{scIdx} used."
112:         end
113:         if !@propertySet.scenarioSpecific?(criteria)
114:           raise TjException.new, "Attribute #{criteria} is not scenario " +
115:                                  "specific"
116:         end
117:       end
118:       @sortingCriteria.push(criteria)
119:       @sortingUp.push(up)
120:       @scenarioIdx.push(scIdx)
121:       @sortingLevels += 1
122:     end
append(list) click to toggle source

Append another Array of PropertyTreeNodes or a PropertyList to this. The list will be sorted again.

    # File lib/PropertyList.rb, line 84
84:     def append(list)
85:       if $DEBUG
86:         list.each do |node|
87:           unless node.propertySet == @propertySet
88:             raise "Fatal Error: All nodes must belong to the same PropertySet."
89:           end
90:         end
91:       end
92: 
93:       @items.concat(list)
94:       sort!
95:     end
index() click to toggle source

This function sets the index attribute of all the properties in the list. The index starts with 0 and increases for each property.

     # File lib/PropertyList.rb, line 173
173:     def index
174:       i = 0
175:       @items.each do |p|
176:         p.set('index', i += 1)
177:       end
178:     end
itemIndex(item) click to toggle source

Return the Array index of item or nil.

     # File lib/PropertyList.rb, line 167
167:     def itemIndex(item)
168:       @items.index(item)
169:     end
method_missing(func, *args, &block) click to toggle source

This class should be a derived class of Array. But since it re-defines sort!() and still needs to call Array::sort!() I took a different route. All missing methods will be propagated to the @items Array.

    # File lib/PropertyList.rb, line 58
58:     def method_missing(func, *args, &block)
59:       @items.method(func).call(*args, &block)
60:     end
resetSorting() click to toggle source

Clear all sorting levels.

    # File lib/PropertyList.rb, line 75
75:     def resetSorting
76:       @sortingLevels = 0
77:       @sortingCriteria = []
78:       @sortingUp = []
79:       @scenarioIdx = []
80:     end
setSorting(modes) click to toggle source

Set all sorting levels as Array of triplets.

    # File lib/PropertyList.rb, line 67
67:     def setSorting(modes)
68:       resetSorting
69:       modes.each do |mode|
70:         addSortingCriteria(*mode)
71:       end
72:     end
sort!() click to toggle source

Sort the properties according to the currently defined sorting criteria.

     # File lib/PropertyList.rb, line 132
132:     def sort!
133:       if treeMode?
134:         # Tree sorting is somewhat complex. It will be based on the 'tree'
135:         # attribute of the PropertyTreeNodes but we have to update them first
136:         # based on the other sorting criteria.
137: 
138:         # Remove the tree sorting mode first.
139:         sc = @sortingCriteria.delete_at(0)
140:         su = @sortingUp.delete_at(0)
141:         si = @scenarioIdx.delete_at(0)
142:         @sortingLevels -= 1
143: 
144:         # Sort the list based on the rest of the modes.
145:         sortInternal
146:         # The update the 'index' attributes of the PropertyTreeNodes.
147:         index
148:         # An then the 'tree' attributes.
149:         indexTree
150: 
151:         # Restore the 'tree' sorting mode again.
152:         @sortingCriteria.insert(0, sc)
153:         @sortingUp.insert(0, su)
154:         @scenarioIdx.insert(0, si)
155:         @sortingLevels += 1
156: 
157:         # Sort again, now based on the updated 'tree' attributes.
158:         sortInternal
159:       else
160:         sortInternal
161:       end
162:       # Update indexes.
163:       index
164:     end
to_ary() click to toggle source
    # File lib/PropertyList.rb, line 62
62:     def to_ary
63:       @items.dup
64:     end
treeMode?() click to toggle source

If the first sorting level is ‘tree’ the breakdown structure of the list is preserved. This is a somewhat special mode and this function returns true if the mode is set.

     # File lib/PropertyList.rb, line 127
127:     def treeMode?
128:       @sortingLevels > 0 && @sortingCriteria[0] == 'tree'
129:     end

Private Instance Methods

indexTree() click to toggle source

Update the ‘tree’ indicies that are needed for the ‘tree’ sorting mode.

     # File lib/PropertyList.rb, line 195
195:     def indexTree
196:       @items.each do |property|
197:         # The indicies are an Array if the 'index' attributes for this
198:         # property and all its parents.
199:         treeIdcs = property.getIndicies
200:         # Now convert them to a String.
201:         tree = ''
202:         treeIdcs.each do |idx|
203:           # Prefix the level index with zeros so that we always have a 6
204:           # digit long String. 6 digits should be large enough for all
205:           # real-world projects.
206:           tree += idx.to_s.rjust(6, '0')
207:         end
208:         property.set('tree', tree)
209:       end
210:     end
sortInternal() click to toggle source
     # File lib/PropertyList.rb, line 212
212:     def sortInternal
213:       @items.sort! do |a, b|
214:         res = 0
215:         @sortingLevels.times do |i|
216:           if @query
217:             # In case we have a Query reference, we get the two values with this
218:             # query.
219:             @query.scenarioIdx = @scenarioIdx[i] < 0 ? nil : @scenarioIdx[i]
220:             @query.attributeId = @sortingCriteria[i]
221: 
222:             @query.property = a
223:             @query.process
224:             aVal = @query.to_sort
225: 
226:             @query.property = b
227:             @query.process
228:             bVal = @query.to_sort
229:           else
230:             # In case we don't have a query, we use the static mechanism.
231:             # If the scenario index is negative we have a non-scenario-specific
232:             # attribute.
233:             if @scenarioIdx[i] < 0
234:               if @sortingCriteria[i] == 'id'
235:                 aVal = a.fullId
236:                 bVal = b.fullId
237:               else
238:                 aVal = a.get(@sortingCriteria[i])
239:                 bVal = b.get(@sortingCriteria[i])
240:               end
241:             else
242:               aVal = a[@sortingCriteria[i], @scenarioIdx[i]]
243:               bVal = b[@sortingCriteria[i], @scenarioIdx[i]]
244:             end
245:           end
246:           res = aVal <=> bVal
247:           # Invert the result if we have to sort in decreasing order.
248:           res = -res unless @sortingUp[i]
249:           # If the two elements are equal on this compare level we try the next
250:           # level.
251:           break if res != 0
252:         end
253:         res
254:       end
255:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.