#### libremiliacr
#### Copyright(C) 2020-2024 Remilia Scarlet <remilia@posteo.jp>
####
#### This program is free software: you can redistribute it and/or modify
#### it under the terms of the GNU General Public License as published
#### the Free Software Foundation, either version 3 of the License, or
#### (at your option) any later version.
####
#### This program is distributed in the hope that it will be useful,
#### but WITHOUT ANY WARRANTY; without even the implied warranty of
#### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
#### GNU General Public License for more details.
####
#### You should have received a copy of the GNU General Public License
#### along with this program.If not, see<http:####www.gnu.org/licenses/.>
require "./resolver"
module RemiLib::Config
# The `ResolverSet` allows a collection of `Resolver` instances to be used in
# a prioritized way.
class ResolverSet
@resolvers : Array(Resolver)
# Creates a new `ResolverSet` instance.
def initialize(*res : Resolver)
@resolvers = res.to_a
end
# Returns the `Resolver` at the given index.
def [](idx : Int)
@resolvers[idx]
end
# Appends a `Resolver` to the end of this set.
def <<(res : Resolver)
@resolvers << res
end
# Inserts the given `Resolver` at the given index.
def insert(idx : Int, res : Resolver)
@resolvers.insert(idx, res)
end
# Deletes the given `Resolver` from the given index.
def delete_at(idx : Int)
@resolvers.delete_at(idx)
end
# If the given `Resolver` exists in this set, it is removed from this set
# and returned. Otherwise, this returns `nil`.
def delete(res : Resolver) : Resolver?
@resolvers.delete(res)
end
# Loops over all of the `Resolver` instances in this set, yielding each one
# sequentially.
def each(&)
@resolvers.each do |res|
yield res
end
end
# Associates a data file named `filename` with a symbolic name for every one
# of the associated `Resolver` instances. The symbolic name must be unique
# for every `Resolver`.
def defineDataFile(symname : Symbol, filename : String|Path)
@resolvers.each &.defineDataFile(symname, filename)
end
# Associates a data file named `filename` with a symbolic name for every one
# of the associated `Resolver` instances.
#
# If the symbol is not unique to any of the `Resolver`s in this set, then
# the old path is forgotten for that `Resolver` and the symbol becomes
# associated with the new path.
def defineDataFile!(symname : Symbol, filename : String|Path)
@resolvers.each &.defineDataFile!(symname, filename)
end
protected def getDataFilePath(symname : Symbol) : Path?
@resolvers.find do |res|
if res.dataFiles.has_key?(symname)
return res.getDataFilePath(symname)
end
end
nil
end
# Given a symbolic name for a data file, this looks at each `Resolver` in
# the order it appears in this set. The first `Resolver` that knows about
# the data file will return the `Path` associated with it.
#
# If the symbol is not registered with any `Resolver`s in this set, then
# this raises an `UnknownDataFileError`.
def dataFile(symname : Symbol) : Path
getDataFilePath(symname) ||
raise UnknownDataFileError.new("Data file is not registered in any Resolvers: #{symname}")
end
# Given a symbolic name for a data file, this looks at each `Resolver` in
# the order it appears in this set. The first `Resolver` that knows about
# the data file will return the `Path` associated with it.
#
# If the symbol is not registered with any `Resolver`s in this set, then
# this returns `nil`.
def dataFile?(symname : Symbol) : Path?
getDataFilePath(symname)
end
# Given a symbolic name for a data file, this looks at each `Resolver` in
# the order it appears in the set. The first `Resolver` that knows about
# the data file will then open a new `File` stream and yield it. If the
# symbol is not registered with any `Resolver`, then this raises an
# `UnknownDataFileError`.
def dataFile(symname : Symbol, &) : Nil
File.open(datafile(symname)) do |file|
yield file
end
end
# Given a symbolic name for a data file, this looks at each `Resolver` in
# the order it appears in the set. The first `Resolver` that knows about
# the data file will then open a new `File` stream and yield it, then return
# `true`. If the symbol is not registered with any `Resolver`, then this
# returns `false`.
def dataFile?(symname : Symbol, &) : Bool
if filename = dataFile?(symname)
File.open(filename) do |file|
yield file
end
true
else
false
end
end
end
end
|