class CalendariumRomanum::Sanctorale

One of the two main {Calendar} components. Contains celebrations with fixed date, mostly feasts of saints.

Basically a mapping {AbstractDate} => Array<{Celebration}> additionally enforcing some constraints:

Attributes

days[R]
metadata[RW]

Sanctorale metadata.

Data files may contain YAML front matter. If provided, it's loaded by {SanctoraleLoader} and stored in this property. All data files bundled in the gem (see {Data}) have YAML front matter which is a Hash with a few standardized keys. While YAML also supports top-level content of other types, sanctorale data authors should stick to the convention of using Hash as the top-level data structure of their front matters.

@return [Hash, nil] @since 0.7.0

solemnities[R]

Content subset - only {Celebration}s in the rank(s) of solemnity.

@return [Hash<AbstractDate=>Celebration>]

symbols[R]

Public Class Methods

new() click to toggle source
# File lib/calendarium-romanum/sanctorale.rb, line 18
def initialize
  @days = {}
  @solemnities = {}
  @symbols = Set.new
  @metadata = nil
end

Public Instance Methods

==(b) click to toggle source

@return [Boolean] @since 0.6.0

# File lib/calendarium-romanum/sanctorale.rb, line 227
def ==(b)
  self.class == b.class &&
    days == b.days
end
[](date) click to toggle source

Retrieves {Celebration}s for the given date

@param date [AbstractDate, Date] @return [Array<Celebration>] (may be empty) @since 0.6.0

# File lib/calendarium-romanum/sanctorale.rb, line 166
def [](date)
  adate = date.is_a?(AbstractDate) ? date : AbstractDate.from_date(date)
  @days[adate] || []
end
add(month, day, celebration) click to toggle source

Adds a new {Celebration}

@param month [Integer] @param day [Integer] @param celebration [Celebration] @return [void] @raise [ArgumentError]

when performing the operation would break the object's invariant
# File lib/calendarium-romanum/sanctorale.rb, line 68
def add(month, day, celebration)
  date = AbstractDate.new(month, day)

  unless @days[date].nil? || @days[date].empty?
    present = @days[date][0]
    if present.rank != Ranks::MEMORIAL_OPTIONAL
      raise ArgumentError.new("On #{date} there is already a #{present.rank}. No more celebrations can be added.")
    elsif celebration.rank != Ranks::MEMORIAL_OPTIONAL
      raise ArgumentError.new("Celebration of rank #{celebration.rank} cannot be grouped, but there is already another celebration on #{date}")
    end
  end

  unless celebration.symbol.nil?
    if @symbols.include? celebration.symbol
      raise ArgumentError.new("Attempted to add Celebration with duplicate symbol #{celebration.symbol.inspect}")
    end

    @symbols << celebration.symbol
  end

  unless @days.has_key? date
    @days[date] = []
  end

  if celebration.solemnity?
    @solemnities[date] = celebration
  end

  @days[date] << celebration
end
by_symbol(symbol) click to toggle source

If the instance contains a {Celebration} identified by the specified symbol, returns it's date and the {Celebration} itself, nil otherwise.

@param symbol [Symbol] @return [Array<AbstractDate, Celebration>, nil] @since 0.9.0

# File lib/calendarium-romanum/sanctorale.rb, line 247
def by_symbol(symbol)
  return nil unless provides_celebration? symbol

  @days.each_pair do |date, celebrations|
    found = celebrations.find {|c| c.symbol == symbol }
    return [date, found] if found
  end

  # reaching this point would mean that contents of @symbols and @days are not consistent
  raise 'this point should never be reached'
end
each_day() { |date, celebrations| ... } click to toggle source

Enumerates dates for which any {Celebration}s are available

@yield [AbstractDate, Array<Celebration>] the array is never empty @return [void, Enumerator] if called without a block, returns Enumerator

# File lib/calendarium-romanum/sanctorale.rb, line 195
def each_day
  return to_enum(__method__) unless block_given?

  @days.each_pair do |date, celebrations|
    yield date, celebrations
  end
end
empty?() click to toggle source

It is empty if it doesn't contain any {Celebration}

@return [Boolean]

# File lib/calendarium-romanum/sanctorale.rb, line 213
def empty?
  @days.empty?
end
freeze() click to toggle source

Freezes the instance

Calls superclass method
# File lib/calendarium-romanum/sanctorale.rb, line 218
def freeze
  @days.freeze
  @days.values.each(&:freeze)
  @solemnities.freeze
  super
end
get(*args) click to toggle source

Retrieves {Celebration}s for the given date

@overload get(date)

@param date[AbstractDate, Date]

@overload get(month, day)

@param month [Integer]
@param day [Integer]

@return (see [])

# File lib/calendarium-romanum/sanctorale.rb, line 179
def get(*args)
  if args.size == 1 && args[0].is_a?(Date)
    month = args[0].month
    day = args[0].day
  else
    month, day = args
  end

  date = AbstractDate.new(month, day)
  self[date]
end
initialize_dup(other) click to toggle source

@api private

# File lib/calendarium-romanum/sanctorale.rb, line 32
def initialize_dup(other)
  @days = other.days.dup
  @solemnities = other.solemnities.dup
  @symbols = other.symbols.dup
  @metadata = Marshal.load Marshal.dump other.metadata # deep copy
end
merge(other) click to toggle source

Returns a new copy containing {Celebration}s from both self and other.

@param other [Sanctorale] @return [Sanctorale] @since 0.9.0

# File lib/calendarium-romanum/sanctorale.rb, line 157
def merge(other)
  dup.tap {|dupped| dupped.update other }
end
provides_celebration?(symbol) click to toggle source

Does this instance provide celebration identified by symbol symbol?

@param symbol [Symbol] @return [Boolean] @since 0.9.0

# File lib/calendarium-romanum/sanctorale.rb, line 237
def provides_celebration?(symbol)
  @symbols.include? symbol
end
replace(month, day, celebrations, symbol_uniqueness: true) click to toggle source

Replaces content of the given day by given {Celebration}s

@param month [Integer] @param day [Integer] @param celebrations [Array<Celebration>] @param symbol_uniqueness [true|false]

allows disabling symbol uniqueness check.
Internal feature, not intended for use by client code.

@return [void] @raise [ArgumentError]

when performing the operation would break the object's invariant
# File lib/calendarium-romanum/sanctorale.rb, line 110
def replace(month, day, celebrations, symbol_uniqueness: true)
  date = AbstractDate.new(month, day)

  symbols_without_day = @symbols
  unless @days[date].nil?
    old_symbols = @days[date].collect(&:symbol).compact
    symbols_without_day = @symbols - old_symbols
  end

  new_symbols = celebrations.collect(&:symbol).compact
  duplicate = symbols_without_day.intersection new_symbols
  if symbol_uniqueness && !duplicate.empty?
    raise ArgumentError.new("Attempted to add Celebrations with duplicate symbols #{duplicate.to_a.inspect}")
  end

  @symbols = symbols_without_day
  @symbols.merge new_symbols

  if celebrations.first.solemnity?
    @solemnities[date] = celebrations.first
  elsif @solemnities.has_key? date
    @solemnities.delete date
  end

  @days[date] = celebrations.dup
end
size() click to toggle source

Returns count of days with {Celebration}s filled

@return [Integer]

# File lib/calendarium-romanum/sanctorale.rb, line 206
def size
  @days.size
end
update(other) click to toggle source

Updates the receiver with {Celebration}s from another instance.

For each date contained in other the content of self is replaced by that of other.

@param other [Sanctorale] @return [void] @raise (see replace)

# File lib/calendarium-romanum/sanctorale.rb, line 145
def update(other)
  other.each_day do |date, celebrations|
    replace date.month, date.day, celebrations, symbol_uniqueness: false
  end
  rebuild_symbols
end

Protected Instance Methods

rebuild_symbols() click to toggle source

Builds the registry of celebration symbols anew, raises error if any duplicates are found.

# File lib/calendarium-romanum/sanctorale.rb, line 265
def rebuild_symbols
  @symbols = Set.new
  duplicates = []

  @days.each_pair do |date,celebrations|
    celebrations.each do |celebration|
      if @symbols.include?(celebration.symbol) &&
         !duplicates.include?(celebration.symbol) &&
         !celebration.symbol.nil?
        duplicates << celebration.symbol
      end

      @symbols << celebration.symbol
    end
  end

  unless duplicates.empty?
    raise ArgumentError.new("Duplicate celebration symbols: #{duplicates.inspect}")
  end
end