Class: TaskJuggler::Query
Overview
A query can be used to retrieve any property attribute after the scheduling run has been completed. It is possible to make a Query before the scheduling run has been completed, but it only produces good results for static attributes. And for such queries, the PropertyTreeNode.get and [] functions are a lot more efficient.
When constructing a Query, a set of variables need to be set that is sufficient enough to identify a unique attribute. Some attribute are computed dynamically and further variables such as a start and end time will be incorporated into the result computation.
The result is returned as String (Query#result), in numerical form (Query#numericalResult) if available as number, and as an entity that can be used for sorting (Query#sortableResult). To get the result, Query#process needs to be called. In case an error occured, Query#ok is set to false and Query#errorMessage contains an error message.
Constant Summary collapse
- @@ps =
%w( project propertyType propertyId property scopePropertyType scopePropertyId scopeProperty attributeId scenario scenarioIdx loadUnit numberFormat currencyFormat timeFormat listItem listType hideJournalEntry journalMode journalAttributes sortJournalEntries costAccount revenueAccount selfContained )
Instance Attribute Summary collapse
-
#end ⇒ Object
Returns the value of attribute end.
-
#endIdx ⇒ Object
Returns the value of attribute endIdx.
-
#errorMessage ⇒ Object
Returns the value of attribute errorMessage.
-
#numerical ⇒ Object
writeonly
Sets the attribute numerical.
-
#ok ⇒ Object
Returns the value of attribute ok.
-
#rti ⇒ Object
writeonly
Sets the attribute rti.
-
#sortable ⇒ Object
writeonly
Sets the attribute sortable.
-
#start ⇒ Object
Returns the value of attribute start.
-
#startIdx ⇒ Object
Returns the value of attribute startIdx.
-
#string ⇒ Object
writeonly
Sets the attribute string.
Instance Method Summary collapse
-
#assignList(listItems) ⇒ Object
Converts the String items in listItems into a RichTextIntermediate objects and assigns it as result of the query.
-
#initialize(parameters = { }) ⇒ Query
constructor
Create a new Query object.
-
#process ⇒ Object
This method tries to resolve the query and return a result.
-
#result ⇒ Object
Return the result in the orginal form.
-
#scaleDuration(value) ⇒ Object
Convert a duration to the format specified by @loadUnit.
-
#scaleLoad(value) ⇒ Object
Convert a load or effort value to the format specified by @loadUnit.
-
#setCustomData(name, data) ⇒ Object
Set a custom data entry.
-
#to_num ⇒ Object
Return the result of the Query as Integer or Float.
-
#to_rti ⇒ Object
Return the result as RichTextIntermediate object.
-
#to_s ⇒ Object
Return the result of the Query as String.
-
#to_sort ⇒ Object
Return the result in the best suited type and format for sorting.
Constructor Details
#initialize(parameters = { }) ⇒ Query
Create a new Query object. The parameters need to be sufficent to uniquely identify an attribute.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/taskjuggler/Query.rb', line 53 def initialize(parameters = { }) @selfContained = false @@ps.each do |p| instance_variable_set('@' + p, parameters[p] ? parameters[p] : nil) end # instance_variable_set does not call writer functions. So we need to # handle @start, @end, @startIdx and @endIdx separately. %w( end endIdx start startIdx ).each do |p| send(p + '=', parameters[p]) if parameters[p] end # The custom data hash can be filled with results to be returned for # special attributes that are not directly property attributes or # computed attributes. @customData = {} reset end |
Instance Attribute Details
#end ⇒ Object
Returns the value of attribute end.
48 49 50 |
# File 'lib/taskjuggler/Query.rb', line 48 def end @end end |
#endIdx ⇒ Object
Returns the value of attribute endIdx.
48 49 50 |
# File 'lib/taskjuggler/Query.rb', line 48 def endIdx @endIdx end |
#errorMessage ⇒ Object
Returns the value of attribute errorMessage.
47 48 49 |
# File 'lib/taskjuggler/Query.rb', line 47 def errorMessage @errorMessage end |
#numerical=(value) ⇒ Object (writeonly)
Sets the attribute numerical
49 50 51 |
# File 'lib/taskjuggler/Query.rb', line 49 def numerical=(value) @numerical = value end |
#ok ⇒ Object
Returns the value of attribute ok.
47 48 49 |
# File 'lib/taskjuggler/Query.rb', line 47 def ok @ok end |
#rti=(value) ⇒ Object (writeonly)
Sets the attribute rti
49 50 51 |
# File 'lib/taskjuggler/Query.rb', line 49 def rti=(value) @rti = value end |
#sortable=(value) ⇒ Object (writeonly)
Sets the attribute sortable
49 50 51 |
# File 'lib/taskjuggler/Query.rb', line 49 def sortable=(value) @sortable = value end |
#start ⇒ Object
Returns the value of attribute start.
48 49 50 |
# File 'lib/taskjuggler/Query.rb', line 48 def start @start end |
#startIdx ⇒ Object
Returns the value of attribute startIdx.
48 49 50 |
# File 'lib/taskjuggler/Query.rb', line 48 def startIdx @startIdx end |
#string=(value) ⇒ Object (writeonly)
Sets the attribute string
49 50 51 |
# File 'lib/taskjuggler/Query.rb', line 49 def string=(value) @string = value end |
Instance Method Details
#assignList(listItems) ⇒ Object
Converts the String items in listItems into a RichTextIntermediate objects and assigns it as result of the query.
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/taskjuggler/Query.rb', line 220 def assignList(listItems) list = +'' listItems.each do |item| case @listType when nil, :comma list += ', ' unless list.empty? list += item when :bullets list += "* #{item}\n" when :numbered list += "# #{item}\n" end end @sortable = @string = list rText = RichText.new(list) @rti = rText.generateIntermediateFormat end |
#process ⇒ Object
This method tries to resolve the query and return a result. In case it finds an attribute that matches the query, it returns true; false otherwise. The actual result data is stored in the Query object. It can then be retrieved by the caller with the methods to_s(), to_num(), to_sort() and result().
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'lib/taskjuggler/Query.rb', line 123 def process reset begin # Resolve property reference from property ID. if @propertyId && (@property.nil? || @propertyId[0] == '!') @property = resolvePropertyId(@propertyType, @propertyId) unless @property @errorMessage = "Unknown property '#{@propertyId}' queried" return @ok = false end end unless @property # No property was provided. We are looking for a project attribute. supportedAttrs = %w( copyright currency end journal name now projectid start version ) unless supportedAttrs.include?(@attributeId) @errorMessage = "Unsupported project attribute '#{@attributeId}'" return @ok = false end if @project.respond_to?(attributeId) @project.send(attributeId, self) else attr = @project[@attributeId] end if attr.is_a?(TjTime) @sortable = @numerical = attr @string = attr.to_s(@timeFormat) else @sortable = @string = attr end return @ok = true end # Same for the scope property. if !@scopeProperty.nil? && !@scopePropertyId.nil? @scopeProperty = resolvePropertyId(@scopePropertyType, @scopePropertyId) unless @scopeProperty @errorMessage = "Unknown scope property #{@scopePropertyId} queried" return @ok = false end end # Make sure the have a reference to the project. @project = @property.project unless @project if @scenario && !@scenarioIdx @scenarioIdx = @project.scenarioIdx(@scenario) unless @scenarioIdx raise "Query cannot resolve scenario '#{@scenario}'" end end queryMethodName = 'query_' + @attributeId # First we check for non-scenario-specific query functions. if (data = @customData[@attributeId]) @sortable = data[:sortable] @numerical = data[:numerical] @string = data[:string] @rti = data[:rti] elsif @property.respond_to?(queryMethodName) @property.send(queryMethodName, self) elsif @scenarioIdx && @property.data && @property.data[@scenarioIdx].respond_to?(queryMethodName) # Then we check for scenario-specific ones via the @data member. @property.send(queryMethodName, @scenarioIdx, self) else # The result is a BaseAttribute begin # The user may also provide a scenario index for # non-scenario-specific values. We need to check if the attribute # is really scenario specific or not because # PropertyTreeNode::getAttribute can only handle an index for # scenario-specific attributs. aType = @property.attributeDefinition(@attributeId) raise ArgumentError unless aType scIdx = aType.scenarioSpecific ? @scenarioIdx : nil @attr = @property.getAttribute(@attributeId, scIdx) if @attr.nil? && @attr.is_a?(DateAttribute) @errorMessage = "Attribute '#{@attributeId}' of property " + "'#{@property.fullId}' has undefined value." return @ok = false end rescue ArgumentError @errorMessage = "Unknown attribute '#{@attributeId}' queried" return @ok = false end end rescue TjException @errorMessage = $!. return @ok = false end @ok = true end |
#result ⇒ Object
Return the result in the orginal form. It may be nil.
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/taskjuggler/Query.rb', line 263 def result if @attr if @attr.value && @attr.is_a?(ReferenceAttribute) @attr.value[0] else @attr.value end elsif @numerical @numerical elsif @rti @rti else @string end end |
#scaleDuration(value) ⇒ Object
Convert a duration to the format specified by @loadUnit. value is the duration effort in days. The return value is the converted value with optional unit as a String.
282 283 284 285 |
# File 'lib/taskjuggler/Query.rb', line 282 def scaleDuration(value) scaleValue(value, [ 24 * 60, 24, 1, 1.0 / 7, 1.0 / 30.42, 1.0 / 91.25, 1.0 / 365 ]) end |
#scaleLoad(value) ⇒ Object
Convert a load or effort value to the format specified by @loadUnit. work is the effort in man days. The return value is the converted value with optional unit as a String.
290 291 292 293 294 295 296 297 298 |
# File 'lib/taskjuggler/Query.rb', line 290 def scaleLoad(value) scaleValue(value, [ @project.dailyWorkingHours * 60, @project.dailyWorkingHours, 1.0, 1.0 / @project.weeklyWorkingDays, 1.0 / @project.monthlyWorkingDays, 1.0 / (@project.yearlyWorkingDays / 4), 1.0 / @project.yearlyWorkingDays ]) end |
#setCustomData(name, data) ⇒ Object
Set a custom data entry. name is the name of the pseudo attribute. data must be a Hash that contains the value for :numberical, :string, :sortable or :rti results.
114 115 116 |
# File 'lib/taskjuggler/Query.rb', line 114 def setCustomData(name, data) @customData[name] = data end |
#to_num ⇒ Object
Return the result of the Query as Integer or Float. The result may be nil.
245 246 247 |
# File 'lib/taskjuggler/Query.rb', line 245 def to_num @attr ? @attr.to_num : @numerical end |
#to_rti ⇒ Object
Return the result as RichTextIntermediate object. The result may be nil.
256 257 258 259 260 |
# File 'lib/taskjuggler/Query.rb', line 256 def to_rti return @attr.value if @attr.is_a?(RichTextAttribute) @attr ? @attr.to_rti(self) : @rti end |
#to_s ⇒ Object
Return the result of the Query as String. The result may be nil.
239 240 241 |
# File 'lib/taskjuggler/Query.rb', line 239 def to_s @attr ? @attr.to_s(self) : (@rti ? @rti.to_s : (@string || '')) end |
#to_sort ⇒ Object
Return the result in the best suited type and format for sorting. The result may be nil.
251 252 253 |
# File 'lib/taskjuggler/Query.rb', line 251 def to_sort @attr ? @attr.to_sort : @sortable end |