Class: TaskJuggler::PropertySet

Inherits:
Object
  • Object
show all
Defined in:
lib/taskjuggler/PropertySet.rb

Overview

A PropertySet is a collection of properties of the same kind. Properties can be Task, Resources, Scenario, Shift or Accounts objects. All properties of the same kind belong to the same PropertySet. A property may only belong to one PropertySet in the Project. The PropertySet holds the definitions for the attributes. All Properties of the set will have a set of these attributes.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project, flatNamespace) ⇒ PropertySet

Returns a new instance of PropertySet.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/taskjuggler/PropertySet.rb', line 29

def initialize(project, flatNamespace)
  if $DEBUG && project.nil?
    raise "project parameter may not be NIL"
  end
  # Indicates whether the namespace of this PropertySet is flat or not. In a
  # flat namespace all property IDs must be unique. Otherwise only the IDs
  # within a group of siblings must be unique. The full ID of the Property
  # is then composed of the siblings ID prefixed by the parent ID. ID fields
  # are separated by dots.
  @flatNamespace = flatNamespace
  # The main Project data structure reference.
  @project = project
  # A list of all PropertyTreeNodes in this set.
  @properties = Array.new
  # A hash of all PropertyTreeNodes in this set, hashed by their ID. This is
  # the same data as in @properties, but hashed by ID for faster access.
  @propertyMap = Hash.new

  # This is the blueprint for PropertyTreeNode attribute sets. Whever a new
  # PropertTreeNode is created, an attribute is created for each definition
  # in this list.
  @attributeDefinitions = Hash.new
  [
    [ 'id',   'ID',       StringAttribute, false,  false,  false,  '' ],
    [ 'name', 'Name',     StringAttribute, false,  false,  false,  '' ],
    [ 'seqno', 'Seq. No', IntegerAttribute, false,  false,  false,  0 ]
  ].each { |a| addAttributeType(AttributeDefinition.new(*a)) }
end

Instance Attribute Details

#attributeDefinitionsObject (readonly)

Returns the value of attribute attributeDefinitions.



27
28
29
# File 'lib/taskjuggler/PropertySet.rb', line 27

def attributeDefinitions
  @attributeDefinitions
end

#flatNamespaceObject (readonly)

Returns the value of attribute flatNamespace.



27
28
29
# File 'lib/taskjuggler/PropertySet.rb', line 27

def flatNamespace
  @flatNamespace
end

#projectObject (readonly)

Returns the value of attribute project.



27
28
29
# File 'lib/taskjuggler/PropertySet.rb', line 27

def project
  @project
end

Instance Method Details

#[](id) ⇒ Object

Return the PropertyTreeNode object with ID id from the set or nil if not present.



230
231
232
# File 'lib/taskjuggler/PropertySet.rb', line 230

def [](id)
  @propertyMap[id]
end

#addAttributeType(attributeType) ⇒ Object

Use the function to declare the various attributes that properties of this PropertySet can have. The attributes must be declared before the first property is added to the set.



61
62
63
64
65
66
67
68
# File 'lib/taskjuggler/PropertySet.rb', line 61

def addAttributeType(attributeType)
  if !@properties.empty?
    raise "Fatal Error: Attribute types must be defined before " +
          "properties are added."
  end

  @attributeDefinitions[attributeType.id] = attributeType
end

#addProperty(property) ⇒ Object

Add the new PropertyTreeNode object property to the set. The set is indexed by ID. In case an object with the same ID already exists in the set it will be overwritten.

Whenever the set has been extended, the ‘bsi’ and ‘tree’ attributes of the properties are no longer up-to-date. You must call index() before using these attributes.



182
183
184
185
186
187
# File 'lib/taskjuggler/PropertySet.rb', line 182

def addProperty(property)
  # The PropertyTreeNode objects are indexed by ID or hierachical ID
  # depending on the name space setting of this set.
  @propertyMap[property.id] = property
  @properties << property
end

#attributeName(attrId) ⇒ Object

Returns the name (human readable description) of the attribute with the Id specified by attrId.



155
156
157
158
159
160
161
162
163
# File 'lib/taskjuggler/PropertySet.rb', line 155

def attributeName(attrId)
  # Some attributes are hardwired into the properties. These need to be
  # treated separately.
  if @attributeDefinitions.include?(attrId)
    return @attributeDefinitions[attrId].name
  end

  nil
end

#attributeType(attrId) ⇒ Object

Return the type of the attribute with the Id specified by attrId.



166
167
168
169
170
171
172
173
# File 'lib/taskjuggler/PropertySet.rb', line 166

def attributeType(attrId)
  # Hardwired attributes need special treatment.
  if @attributeDefinitions.has_key?(attrId)
    @attributeDefinitions[attrId].objClass
  else
    nil
  end
end

#clearPropertiesObject

Call this function to delete all registered properties.



223
224
225
226
# File 'lib/taskjuggler/PropertySet.rb', line 223

def clearProperties
  @properties.clear
  @propertyMap.clear
end

#defaultValue(attrId) ⇒ Object

Return the default value of the attribute.



147
148
149
150
151
# File 'lib/taskjuggler/PropertySet.rb', line 147

def defaultValue(attrId)
  return nil if @attributeDefinitions[attrId].nil?

  @attributeDefinitions[attrId].default
end

#eachObject

Iterator over all PropertyTreeNode objects in this set.



299
300
301
302
303
# File 'lib/taskjuggler/PropertySet.rb', line 299

def each
  @properties.each do |value|
    yield(value)
  end
end

#eachAttributeDefinitionObject

Iterate over all attribute definitions.



71
72
73
74
75
# File 'lib/taskjuggler/PropertySet.rb', line 71

def eachAttributeDefinition
  @attributeDefinitions.sort.each do |key, value|
    yield(value)
  end
end

#empty?Boolean

Return true if the set is empty.

Returns:

  • (Boolean)


284
285
286
# File 'lib/taskjuggler/PropertySet.rb', line 284

def empty?
  @properties.empty?
end

#hasQuery?(attrId, scenarioIdx = nil) ⇒ Boolean

Check whether the PropertyTreeNode has a calculated attribute with the ID attrId. For scenarioSpecific attributes scenarioIdx needs to be provided.

Returns:

  • (Boolean)


85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/taskjuggler/PropertySet.rb', line 85

def hasQuery?(attrId, scenarioIdx = nil)
  return false if @properties.empty?

  property = @properties.first
  methodName = 'query_' + attrId
  # First we check for non-scenario-specific query functions.
  if property.respond_to?(methodName)
    return true
  elsif scenarioIdx
    # Then we check for scenario-specific ones via the @data member.
    return property.data[scenarioIdx].respond_to?(methodName)
  end
  false
end

#indexObject

Update the breakdown structure indicies (bsi). This method needs to be called whenever the set has been modified.



236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/taskjuggler/PropertySet.rb', line 236

def index
  each do |p|
    bsIdcs = p.getBSIndicies
    bsi = ""
    first = true
    bsIdcs.each do |idx|
      if first
        first = false
      else
        bsi += '.'
      end
      bsi += idx.to_s
    end
    p.force('bsi', bsi)
  end
end

#inheritedFromParent?(attrId) ⇒ Boolean

Return whether the attribute with attrId is inherited from parent.

Returns:

  • (Boolean)


128
129
130
131
132
133
# File 'lib/taskjuggler/PropertySet.rb', line 128

def inheritedFromParent?(attrId)
  # All hardwired attributes are not inherited.
  return false if @attributeDefinitions[attrId].nil?

  @attributeDefinitions[attrId].inheritedFromParent
end

#inheritedFromProject?(attrId) ⇒ Boolean

Return whether the attribute with attrId is inherited from the global scope.

Returns:

  • (Boolean)


120
121
122
123
124
125
# File 'lib/taskjuggler/PropertySet.rb', line 120

def inheritedFromProject?(attrId)
  # All hardwired attributes are not inherited.
  return false if @attributeDefinitions[attrId].nil?

  @attributeDefinitions[attrId].inheritedFromProject
end

#itemsObject Also known as: length

Return the number of PropertyTreeNode objects in this set.



276
277
278
# File 'lib/taskjuggler/PropertySet.rb', line 276

def items
  @properties.length
end

#knownAttribute?(attrId) ⇒ Boolean

Return true if there is an AttributeDefinition for attrId.

Returns:

  • (Boolean)


78
79
80
# File 'lib/taskjuggler/PropertySet.rb', line 78

def knownAttribute?(attrId)
  @attributeDefinitions.include?(attrId)
end

#levelSeqNo(property) ⇒ Object

Return the index of the top-level property in the set.



254
255
256
257
258
259
260
261
262
263
# File 'lib/taskjuggler/PropertySet.rb', line 254

def levelSeqNo(property)
  seqNo = 1
  @properties.each do |p|
    unless p.parent
      return seqNo if p == property
      seqNo += 1
    end
  end
  raise "Fatal Error: Unknow property #{property}"
end

#listAttribute?(attrId) ⇒ Boolean

Returns:

  • (Boolean)


142
143
144
# File 'lib/taskjuggler/PropertySet.rb', line 142

def listAttribute?(attrId)
  (ad = @attributeDefinitions[attrId]) && ad.objClass.isList?
end

#maxDepthObject

Return the maximum used number of breakdown levels. A flat list has a maxDepth of 1. A list with one sub level has a maxDepth of 2 and so on.



267
268
269
270
271
272
273
# File 'lib/taskjuggler/PropertySet.rb', line 267

def maxDepth
  md = 0
  each do |p|
    md = p.level if p.level > md
  end
  md + 1
end

#removeProperty(prop) ⇒ Object

Remove the PropertyTreeNode (and all its children) object from the set. prop can either be a property ID or a reference to the PropertyTreeNode.

TODO: This function does not take care of references to this PTN!



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/taskjuggler/PropertySet.rb', line 193

def removeProperty(prop)
  if prop.is_a?(String)
    property = @propertyMap[prop]
  else
    property = prop
  end

  # Iterate over all properties and eliminate references to this the
  # PropertyTreeNode to be removed.
  @properties.each do |p|
    p.removeReferences(p)
  end

  # Recursively remove all sub-nodes. The children list is modified during
  # the call, so we can't use an iterator here.
  until property.children.empty? do
    removeProperty(property.children.first)
  end

  @properties.delete(property)
  @propertyMap.delete(property.fullId)

  # Remove this node from the child list of the parent node.
  property.parent.children.delete(property) if property.parent


  property
end

#scenarioSpecific?(attrId) ⇒ Boolean

Return whether the attribute with attrId is scenario specific or not.

Returns:

  • (Boolean)


101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/taskjuggler/PropertySet.rb', line 101

def scenarioSpecific?(attrId)
  if @attributeDefinitions[attrId]
    # Check the 'scenarioSpecific' flag of the attribute definition.
    @attributeDefinitions[attrId].scenarioSpecific
  elsif (property = @properties.first) &&
        property && property.data &&
        property.data[0].respond_to?("query_#{attrId}")
    # We've found a query_ function for the attrId that is scenario
    # specific.
    true
  else
    # All hardwired, non-existing and non-scenario-specific query_
    # candidates.
    false
  end
end

#to_aryObject

Return the set of PropertyTreeNode objects as flat Array.



306
307
308
# File 'lib/taskjuggler/PropertySet.rb', line 306

def to_ary
  @properties.dup
end

#to_sObject



310
311
312
# File 'lib/taskjuggler/PropertySet.rb', line 310

def to_s
  PropertyList.new(self).to_s
end

#topLevelItemsObject

Return the number of top-level PropertyTreeNode objects. Top-Level items are no children.



290
291
292
293
294
295
296
# File 'lib/taskjuggler/PropertySet.rb', line 290

def topLevelItems
  items = 0
  @properties.each do |p|
    items += 1 unless p.parent
  end
  items
end

#userDefined?(attrId) ⇒ Boolean

Return whether or not the attribute was user defined.

Returns:

  • (Boolean)


136
137
138
139
140
# File 'lib/taskjuggler/PropertySet.rb', line 136

def userDefined?(attrId)
  return false if @attributeDefinitions[attrId].nil?

  @attributeDefinitions[attrId].userDefined
end