class TaskJuggler::LogicalFunction

The LogicalFunction is a specialization of the LogicalOperation. It models a function call in a LogicalExpression.

Attributes

arguments[RW]
name[RW]

Public Class Methods

new(opnd) click to toggle source

Create a new LogicalFunction. opnd is the name of the function.

# File lib/taskjuggler/LogicalFunction.rb, line 44
def initialize(opnd)
  if opnd[-1] == ?_
    # Function names with a trailing _ are like their counterparts without
    # the _. But during evaluation the property and the scope properties
    # will be switched.
    @name = opnd[0..-2]
    @invertProperties = true
  else
    @name = opnd
    @invertProperties = false
  end
  @arguments = []
end

Public Instance Methods

eval(expr) click to toggle source

Evaluate the function by calling it with the arguments.

# File lib/taskjuggler/LogicalFunction.rb, line 76
def eval(expr)
  # Call the function and return the result.
  send(name, expr, @arguments)
end
setArgumentsAndCheck(args) click to toggle source

Register the arguments of the function and check if the name is a known function and the number of arguments match this function. If not, return an [ id, message ] error. Otherwise nil.

# File lib/taskjuggler/LogicalFunction.rb, line 61
def setArgumentsAndCheck(args)
  unless @@functions.include?(@name)
    return [ 'unknown_function',
             "Unknown function #{@name} used in logical expression." ]
  end
  if @@functions[@name] != args.length
    return [ 'wrong_no_func_arguments',
             "Wrong number of arguments for function #{@name}. Got " +
             "#{args.length} instead of #{@@functions[@name]}." ]
  end
  @arguments = args
  nil
end
to_s() click to toggle source

Return a textual expression of the function call.

# File lib/taskjuggler/LogicalFunction.rb, line 82
def to_s
  "#{@name}(#{@arguments.join(', ')})"
end

Private Instance Methods

hasalert(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 98
def hasalert(expr, args)
  property = properties(expr)[0]
  query = expr.query
  project = property.project
  !project['journal'].currentEntries(query.end, property,
                                     args[0], query.start,
                                     query.hideJournalEntry).empty?
end
isactive(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 107
def isactive(expr, args)
  property, scopeProperty = properties(expr)
  # The result can only be true when called for a Task property.
  return false unless property.is_a?(Task) ||
                      property.is_a?(Resource)
  project = property.project
  # 1st arg must be a scenario index.
  if (scenarioIdx = project.scenarioIdx(args[0])).nil?
    expr.error("Unknown scenario '#{args[0]}' used for function isactive()")
  end

  query = expr.query
  property.getAllocatedTime(scenarioIdx, query.startIdx, query.endIdx,
                            scopeProperty) > 0.0
end
ischildof(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 123
def ischildof(expr, args)
  # The the context property.
  property = properties(expr)[0]
  # Find the prospective parent ID in the current PropertySet.
  return false unless (parent = property.propertySet[args[0]])

  property.isChildOf?(parent)
end
isdependencyof(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 132
def isdependencyof(expr, args)
  property = properties(expr)[0]
  # The result can only be true when called for a Task property.
  return false unless property.is_a?(Task)
  project = property.project
  # 1st arg must be a task ID.
  return false if (task = project.task(args[0])).nil?
  # 2nd arg must be a scenario index.
  return false if (scenarioIdx = project.scenarioIdx(args[1])).nil?
  # 3rd arg must be an integer number.
  return false unless args[2].is_a?(Integer)

  property.isDependencyOf(scenarioIdx, task, args[2])
end
isdutyof(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 147
def isdutyof(expr, args)
  property = properties(expr)[0]
  # The result can only be true when called for a Task property.
  return false unless (task = property).is_a?(Task)
  project = task.project
  # 1st arg must be a resource ID.
  return false if (resource = project.resource(args[0])).nil?
  # 2nd arg must be a scenario index.
  return false if (scenarioIdx = project.scenarioIdx(args[1])).nil?

  task['assignedresources', scenarioIdx].include?(resource)
end
isfeatureof(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 160
def isfeatureof(expr, args)
  property = properties(expr)[0]
  # The result can only be true when called for a Task property.
  return false unless property.is_a?(Task)
  project = property.project
  # 1st arg must be a task ID.
  return false if (task = project.task(args[0])).nil?
  # 2nd arg must be a scenario index.
  return false if (scenarioIdx = project.scenarioIdx(args[1])).nil?

  property.isFeatureOf(scenarioIdx, task)
end
isleaf(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 173
def isleaf(expr, args)
  property = properties(expr)[0]
  return false unless property
  property.leaf?
end
ismilestone(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 179
def ismilestone(expr, args)
  property = properties(expr)[0]
  return false unless property
  # 1st arg must be a scenario index.
  return false if (scenarioIdx = property.project.scenarioIdx(args[0])).nil?

  property.is_a?(Task) && property['milestone', scenarioIdx]
end
isongoing(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 188
def isongoing(expr, args)
  property = properties(expr)[0]
  # The result can only be true when called for a Task property.
  return false unless (task = property).is_a?(Task)
  project = task.project
  # 1st arg must be a scenario index.
  if (scenarioIdx = project.scenarioIdx(args[0])).nil?
    expr.error("Unknown scenario '#{args[0]}' used for function " +
               "isongoing()")
  end

  query = expr.query
  iv1 = TimeInterval.new(query.start, query.end)
  tStart = task['start', scenarioIdx]
  tEnd = task['end', scenarioIdx]
  # This helps to show tasks with scheduling errors.
  return true unless tStart && tEnd
  iv2 = TimeInterval.new(tStart, tEnd)

  return iv1.overlaps?(iv2)
end
isresource(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 210
def isresource(expr, args)
  property = properties(expr)[0]
  return false unless property
  property.is_a?(Resource)
end
isresponsibilityof(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 216
def isresponsibilityof(expr, args)
  property = properties(expr)[0]
  # The result can only be true when called for a Task property.
  return false unless (task = property).is_a?(Task)
  project = task.project
  # 1st arg must be a resource ID.
  return false if (resource = project.resource(args[0])).nil?
  # 2nd arg must be a scenario index.
  return false if (scenarioIdx = project.scenarioIdx(args[1])).nil?

  task['responsible', scenarioIdx].include?(resource)
end
istask(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 229
def istask(expr, args)
  property = properties(expr)[0]
  return false unless property
  property.is_a?(Task)
end
isvalid(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 235
def isvalid(expr, args)
  property = properties(expr)[0]
  project = property.project
  attr = args[0]
  scenario, attr = args[0].split('.')
  if attr.nil?
    attr = scenario
    scenario = nil
  end
  expr.error("Argument must not be empty") unless attr
  if scenario && (scenarioIdx = project.scenarioIdx(scenario)).nil?
    expr.error("Unknown scenario '#{scenario}' used for function " +
               "isvalid()")
  end
  unless property.propertySet.knownAttribute?(attr)
    expr.error("Unknown attribute '#{attr}' used for function " +
               "isvalid()")
  end
  if scenario
    unless property.attributeDefinition(attr).scenarioSpecific
      expr.error("Attribute '#{attr}' of property '#{property.fullId}' " +
                 "is not scenario specific. Don't provide a scenario ID!")
    end
    !property[attr, scenarioIdx].nil?
  else
    if property.attributeDefinition(attr).scenarioSpecific
      expr.error("Attribute '#{attr}' of property '#{property.fullId}' " +
                 "is scenario specific. Please provide a scenario ID!")
    end
    !property.get(attr).nil?
  end
end
properties(expr) click to toggle source

Return the property and scope property as determined by the @invertProperties setting.

# File lib/taskjuggler/LogicalFunction.rb, line 90
def properties(expr)
  if @invertProperties
    return expr.query.scopeProperty, nil
  else
    return expr.query.property, expr.query.scopeProperty
  end
end
treelevel(expr, args) click to toggle source
# File lib/taskjuggler/LogicalFunction.rb, line 268
def treelevel(expr, args)
  property = properties(expr)[0]
  return 0 unless property
  property.level + 1
end