All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sageserpent.kineticmerge.core.Sources.scala Maven / Gradle / Ivy

package com.sageserpent.kineticmerge.core

// TODO: is `Sources` the right name? Should it be `Side` or `SourcesFromSide` etc?
/** Represents a collection of sources broken down by paths into files - so a
  * working directory tree, or a Git commit, or possibly even some completely
  * unrelated files sparsely scattered around several unrelated directory trees.
  * To facilitate testing, the notion of the [[PathType]] is left generic - so
  * while it could be a [[String]] or [[java.nio.file.Path]], it could also be a
  * simple [[Int]] that labels a [[File]].
  *
  * @note
  *   Methods on a [[Sources]] instance should only be passed a [[Section]]
  *   created by the same [[Sources]] instance, it's up to the client to be
  *   consistent.
  */
trait Sources[Path, Element]:
  val filesByPath: Map[Path, File[Element]] = filesByPathUtilising(
    Set.empty
  )

  def paths: Set[Path]

  /** Yield an isolated section covering part of the file at {@code path} as
    * demarcated by {@code startOffset} and {@code size} .
    * @note
    *   The file referred to by {@code path} is implied; there is no actual
    *   [[File]] object associated with the section by default.
    * @note
    *   Sections are associated with the [[Sources]] instance that yielded them;
    *   mixing up sections belonging to another [[Sources]] instance is not
    *   supported, unless both [[Sources]] instances are deemed equivalent.
    */
  def section(path: Path)(startOffset: Int, size: Int): Section[Element]

  /** @return
    *   The [[Path]] that implies the file that {@code section} refers to.
    */
  def pathFor(section: Section[Element]): Path

  /** Yield a breakdown of [[File]] instances arranged by [[Path]], such that
    * each of the {@code mandatorySections} is present in a [[File]] instance.
    *
    * This adds additional sections to fill in gaps between the ones given in
    * {@code mandatorySections} ; where a path has no associated section from
    * {@code mandatorySections} , it will be given a [[File]] instance with one
    * section covering the entire file content.
    *
    * @note
    *   {@code mandatorySections} may be an empty set - this then yields an
    *   initial coarse breakdown into files of one section each.
    * @note
    *   {@code candidateGapChunksByPath} is used when filling gaps - if a gap on
    *   a path has a candidate chunk as a subsequence, the gap will be split up
    *   so that the chunk forms its own section. Only one candidate chunk is
    *   used for a gap fill (if any).
    */
  def filesByPathUtilising(
      mandatorySections: Set[Section[Element]],
      candidateGapChunksByPath: Map[Path, Set[IndexedSeq[Element]]] = Map.empty
  ): Map[Path, File[Element]]
end Sources




© 2015 - 2025 Weber Informatics LLC | Privacy Policy