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

s_mach.datadiff.impl.SeqDataDiffImpl.scala Maven / Gradle / Ivy

/*
                    ,i::,
               :;;;;;;;
              ;:,,::;.
            1ft1;::;1tL
              t1;::;1,
               :;::;               _____       __  ___              __
          fCLff ;:: tfLLC         / ___/      /  |/  /____ _ _____ / /_
         CLft11 :,, i1tffLi       \__ \ ____ / /|_/ // __ `// ___// __ \
         1t1i   .;;   .1tf       ___/ //___// /  / // /_/ // /__ / / / /
       CLt1i    :,:    .1tfL.   /____/     /_/  /_/ \__,_/ \___//_/ /_/
       Lft1,:;:       , 1tfL:
       ;it1i ,,,:::;;;::1tti      s_mach.datadiff
         .t1i .,::;;; ;1tt        Copyright (c) 2014 S-Mach, Inc.
         Lft11ii;::;ii1tfL:       Author: [email protected]
          .L1 1tt1ttt,,Li
            ...1LLLL...
*/
package s_mach.datadiff.impl

import scala.language.higherKinds
import scala.collection.generic.CanBuildFrom
import scala.collection.JavaConverters._
import difflib.{ DiffUtils, Chunk => JChunk, Delta => JDelta, InsertDelta, ChangeDelta, DeleteDelta }
import s_mach.datadiff._

class SeqDataDiffImpl[A,M[AA] <: Seq[AA]](implicit
  cbf:CanBuildFrom[Nothing, A, M[A]]
) extends DataDiff[M[A],SeqPatch[A]] {
  import SeqPatch._
  
  val noChange = SeqPatch.noChange

  def jchunkToChunk(jchunk: JChunk[A]) : Chunk[A] = {
    Chunk(jchunk.getPosition, jchunk.getLines.asScala.toVector)
  }

  def jdeltaToDelta(jdelta: JDelta[A]) : Delta[A] = {
    val original = jchunkToChunk(jdelta.getOriginal)
    val revised = jchunkToChunk(jdelta.getRevised)
    jdelta match {
      case i:InsertDelta[A] => Delta(Insert, original, revised)
      case c:ChangeDelta[A] => Delta(Change, original, revised)
      case d:DeleteDelta[A] => Delta(Delete, original, revised)
    }
  }

  def chunkToJChunk(chunk: Chunk[A]) : JChunk[A] = new JChunk[A](chunk.position, chunk.lines.asJava)

  def deltaToJDelta(delta: Delta[A]) : JDelta[A] = {
    val original = chunkToJChunk(delta.original)
    val revised = chunkToJChunk(delta.revised)
    delta._type match {
      case Insert => new InsertDelta[A](original, revised)
      case Change => new ChangeDelta[A](original, revised)
      case Delete => new DeleteDelta[A](original, revised)
    }
  }
  
  override def calcDiff(oldValue: M[A], newValue: M[A]): Patch = {
    val jPatch = DiffUtils.diff(oldValue.asJava, newValue.asJava)
    if(jPatch.getDeltas.isEmpty) {
      noChange
    } else {
      SeqPatch(jPatch.getDeltas.asScala.iterator.map(jdeltaToDelta).toVector)
    }
  }

  override def applyPatch(value: M[A], patch: Patch): M[A] = {
    if(patch != noChange) {
      val builder = cbf()
      val jPatch = new difflib.Patch[A]
      patch.zomDelta.foreach(delta => jPatch.addDelta(deltaToJDelta(delta)))
      jPatch.applyTo(value.asJava).iterator.asScala.foreach(builder.+=)
      builder.result()
    } else {
      value
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy