Skip to content

Latest commit

 

History

History
122 lines (96 loc) · 3.87 KB

README.asciidoc

File metadata and controls

122 lines (96 loc) · 3.87 KB

s_mach.datadiff: data difference engine

Build Status Test Coverage Codacy Badge Scaladocs: 2.11 2.12

s_mach.datadiff is an open-source data difference engine for Scala. Implementations of the DataDiff type-class are provided which can compute the difference between all data types, Option, Set, Seq, Map and all tuple types. A DataDiff implementation for any case class (or other type that has matching apply/unapply) can be generated at compile-time by the DataDiff.forProductType macro method. The difference between any two instances is stored as a patch type, which can be user-defined per type. Patches can be applied to instances of the original type to propagate computed changes. All provided DataDiff implementations are 100% strongly-typed and use absolutely no runtime reflection.

Include in SBT

  1. Add to build.sbt

    libraryDependencies += "net.s_mach" %% "datadiff" % "1.1.1"
    Note
    s_mach.datadiff is cross compiled for Scala 2.11/JDK6 and 2.12/JDK8

Versioning

s_mach.datadiff uses semantic versioning (http://semver.org/). s_mach.datadiff does not use the package private modifier. Instead, all code files outside of the s_mach.datadiff.impl package form the public interface and are governed by the rules of semantic versioning. Code files inside the s_mach.datadiff.impl package may be used by downstream applications and libraries. However, no guarantees are made as to the stability or interface of code in the s_mach.datadiff.impl package between versions.

Example

Welcome to Scala version 2.11.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_72).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :paste
// Entering paste mode (ctrl-D to finish)

import s_mach.datadiff._

case class Name(
  first: String,
  middle: Option[String],
  last: String
)

case class NamePatch(
  first: StringPatch,
  middle: OptionPatch[String, StringPatch],
  last: StringPatch
)

object Name {
  implicit val dataDiff_Name = DataDiff.forProductType[Name,NamePatch]
}

case class Person(
  name: Name,
  age: Int
)

case class PersonPatch(
  name: NamePatch,
  age: IntPatch
)

object Person {
  implicit val dataDiff_Person = DataDiff.forProductType[Person,PersonPatch]
}

val p1 = Person(Name("Gary",None,"Oldman"),56)
val p2 = Person(Name("Gary",Some("Freakn'"),"Oldman"),57)

// Exiting paste mode, now interpreting.

import s_mach.datadiff._
defined class Name
defined class NamePatch
defined object Name
defined class Person
defined class PersonPatch
defined object Person
p1: Person = Person(Name(Gary,None,Oldman),56)
p2: Person = Person(Name(Gary,Some(Freakn'),Oldman),57)

scala> val patch1 = p1 calcDiff p2
patch1: PersonPatch = PersonPatch(NamePatch(None,SetValue(Freakn'),None),1)

scala> patch1 == patchFor[Person].noChange
res0: Boolean = false

scala> val patch2 = p1 calcDiff p1
patch2: PersonPatch = PersonPatch(NamePatch(None,NoChange,None),0)

scala> patch2 == patchFor[Person].noChange
res1: Boolean = true

scala> val p3 = p1 applyPatch patch1
p3: Person = Person(Name(Gary,Some(Freakn'),Oldman),57)

scala> p3 == p2
res2: Boolean = true

scala> val p4 = p1 applyPatch patch2
p4: Person = Person(Name(Gary,None,Oldman),56)

scala> p4 == p1
res3: Boolean = true