blob: 02756b86c64aa11cf4281874e61cd6fc2f6b45be [file] [log] [blame]
/* Copyright (c) 2012-2015 Tresys Technology, LLC. All rights reserved.
*
* Developed by: Tresys Technology, LLC
* http://www.tresys.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal with
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimers.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimers in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the names of Tresys Technology, nor the names of its contributors
* may be used to endorse or promote products derived from this Software
* without specific prior written permission.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
* SOFTWARE.
*/
package edu.illinois.ncsa.daffodil.schema
/**
* Diffable is a facility for comparing objects for equality, and providing valuable diagnostic capability
* when they are different by capturing why they are different.
*
* The theme here is "Design for Test" - unit tests in particular need to compare rich data structures.
* Equality will tell you if the test passes or not, but be very little help in isolating why the structures
* are not equal. Diff fixes this by saving the point at which the structures are different, and returning that
* as the diagnostic of why they aren't equal.
*
* At a small cost in performance, it is better to implement diff than equals. Equals is realized in terms of diff
* for classes that mix in trait Diffable.
*
* If a class does NOT have a diff method, and does not inherit one from a parent class, then it is compared via
* equals to compute differences.
*/
//trait Diffable {
//
// def diff(o:Any) : Similarity
//
// /**
// * We define equals in terms of diff so that we don't have to maintain two very analogous pieces of code.
// */
// override def equals(o:Any) : Boolean = {
// o match {
// case x:Diffable => {
// val diff = Diffable.diff(this, x)
// diff == Same
// }
// case _ => false
// }
// }
//}
//
//object Diffable {
// def diffLists(a: List[Diffable], xa: List[Diffable]): Similarity = {
// var subDiff: Similarity = Same
// if (a.length != xa.length) return DifferentLength(a, xa)
// (a, xa).zipped map { (a: Diffable, xa: Diffable) =>
// subDiff = a.diff(xa)
// if (subDiff != Same) return subDiff
// }
// subDiff
// }
//
// def diff(a :Any, b:Any) : Similarity = {
// a match {
// case a1 : Diffable => a1.diff(b)
// case _ => b match {
// case b1 : Diffable => b1.diff(a)
// case _ => {
// if (a == b) Same // degenerates to equality checking. Danger! equality can be defined in terms of diff! It *should* be ok....
// else Different(a, b)
// }
// }
// }
// }
//}
//
//sealed abstract class Similarity
//case object Same extends Similarity
//case object Different {
// def apply(a : Any, b : Any) : Difference = {
// System.err.println("can we stop here?")
// new Difference(a, b, null, null)
// }
//
// val r = new scala.util.Random // try using random numbers to defeat any constant folding
//
// @volatile var dummy : Int = 0
//
// def breakpoint(arg : Int) : Int = {
// sideEffect(arg)
// return dummy // a line for a breakpoint
// }
//
// def sideEffect(arg : Int) {
// if (arg == 0) return
// dummy = arg - 1
// sideEffect(dummy) // maybe true recursion (not tail recursion) will defeat it.
// // Scala not letting me breakpoint in these constructors. Wierd.
// // Try to force it to give me someplace for a breakpoint.
// System.err.println("breakpoint " + dummy)
// }
//}
//
//class Difference(a : Any, b : Any, location : String, objectWithin : Any,
// dummy : Int // the purpose of this arg is that this 5 arg constructor is quasi-private. You are supposed to use the
// // case object as a factory. But we want a "real constructor" that we can put a breakpoint into.
// // TBD is there a better idiom for all this?
// ) extends Similarity {
//
// val _dummy = dummy
//
// /**
// * constructor is here just to allow us to call the breakpoint routine allowing us to debug when
// * differences are detected.
// */
// def this(a : Any, b : Any, location : String, objectWithin : Any) =
// this(a, b, location, objectWithin, Different.breakpoint(Different.r.nextInt(2)))
//
// override def toString : String = {
// val aStr = if (a == null) "null" else a.toString()
// val bStr = if (b == null) "null" else b.toString()
// "Difference(" + aStr + ", " + bStr + ")"
// }
//}
//case class DifferentLength(a : Any, b : Any) extends Similarity
//case object DifferentType extends Similarity