Skip to content

Commit

Permalink
Allow writing to a Writer or OutputStream, to avoid constructing a hu…
Browse files Browse the repository at this point in the history
…ge string. Also drop support for Scala 2.12.
  • Loading branch information
balhoff committed Nov 19, 2024
1 parent 0c1b172 commit bdcd96d
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 192 deletions.
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ organization := "org.geneontology"

name := "owl-diff"

version := "1.2.2"
version := "1.3-SNAPSHOT"

publishMavenStyle := true

Expand All @@ -22,7 +22,7 @@ homepage := Some(url("https://github.com/balhoff/owl-diff"))

scalaVersion := "2.13.15"

crossScalaVersions := Seq("2.12.20", "2.13.15")
crossScalaVersions := Seq("2.13.15")

scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8")

Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/org/geneontology/owl/differ/Differ.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import org.semanticweb.owlapi.model._
import org.semanticweb.owlapi.model.parameters.Imports
import org.semanticweb.owlapi.util.AxiomSubjectProvider

import scala.collection.JavaConverters._
import scala.jdk.CollectionConverters._

object Differ {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,56 +1,85 @@
package org.geneontology.owl.differ.render

import org.apache.commons.io.output.ByteArrayOutputStream
import org.geneontology.owl.differ.Differ.BasicDiff
import org.geneontology.owl.differ.ShortFormFunctionalSyntaxObjectRenderer
import org.semanticweb.owlapi.model.{OWLImportsDeclaration, OWLObject}
import org.semanticweb.owlapi.util.ShortFormProvider

import java.io.{OutputStream, PrintWriter, Writer}
import java.nio.charset.StandardCharsets
import scala.util.Using

object BasicDiffRenderer {

def renderPlain(diff: BasicDiff): String = {
if (diff.isEmpty) "Ontologies are identical"
else {
val (left, right) = groups(diff)
val leftRendered = left.map(_.item.toString)
val rightRendered = right.map(_.item.toString)
if ((diff.left.id == diff.right.id) || (diff.left.id.isAnonymous && diff.right.id.isAnonymous)) format(leftRendered, rightRendered)
else format(leftRendered + diff.left.id.toString, rightRendered + diff.right.id.toString)
def renderPlainStream(diff: BasicDiff, stream: OutputStream): Unit =
Using.resource(new PrintWriter(stream)) { writer =>
renderPlainWriter(diff, writer)
}
}

def render(diff: BasicDiff, shortFormProvider: ShortFormProvider): String = {
if (diff.isEmpty) "Ontologies are identical"
else {
val renderer = new ShortFormFunctionalSyntaxObjectRenderer(shortFormProvider)
val (left, right) = groups(diff)
val leftRendered = left.map {
case OWLObjectItem(item) => renderer.render(item)
case OWLImportItem(item) => item.toString
def renderPlainWriter(diff: BasicDiff, givenWriter: Writer): Unit =
Using.resource(new PrintWriter(givenWriter)) { writer =>
if (diff.isEmpty) writer.println("Ontologies are identical")
else {
val (left, right) = groups(diff)
val leftRendered = left.map(_.item.toString)
val rightRendered = right.map(_.item.toString)
if ((diff.left.id == diff.right.id) || (diff.left.id.isAnonymous && diff.right.id.isAnonymous)) format(leftRendered, rightRendered, writer)
else format(leftRendered + diff.left.id.toString, rightRendered + diff.right.id.toString, writer)
}
val rightRendered = right.map {
case OWLObjectItem(item) => renderer.render(item)
case OWLImportItem(item) => item.toString
}

def renderPlain(diff: BasicDiff): String =
Using.resource(new ByteArrayOutputStream()) { stream =>
renderPlainStream(diff, stream)
stream.toString(StandardCharsets.UTF_8)
}

def renderStream(diff: BasicDiff, shortFormProvider: ShortFormProvider, stream: OutputStream): Unit =
Using.resource(new PrintWriter(stream)) { writer =>
renderWriter(diff, shortFormProvider, writer)
}

def renderWriter(diff: BasicDiff, shortFormProvider: ShortFormProvider, givenWriter: Writer): Unit =
Using.resource(new PrintWriter(givenWriter)) { writer =>
if (diff.isEmpty) writer.println("Ontologies are identical")
else {
val renderer = new ShortFormFunctionalSyntaxObjectRenderer(shortFormProvider)
val (left, right) = groups(diff)
val leftRendered = left.map {
case OWLObjectItem(item) => renderer.render(item)
case OWLImportItem(item) => item.toString
}
val rightRendered = right.map {
case OWLObjectItem(item) => renderer.render(item)
case OWLImportItem(item) => item.toString
}
if ((diff.left.id == diff.right.id) || (diff.left.id.isAnonymous && diff.right.id.isAnonymous)) format(leftRendered, rightRendered, writer)
else format(leftRendered + diff.left.id.toString, rightRendered + diff.right.id.toString, writer)
}
if ((diff.left.id == diff.right.id) || (diff.left.id.isAnonymous && diff.right.id.isAnonymous)) format(leftRendered, rightRendered)
else format(leftRendered + diff.left.id.toString, rightRendered + diff.right.id.toString)
}
}

def render(diff: BasicDiff, shortFormProvider: ShortFormProvider): String =
Using.resource(new ByteArrayOutputStream()) { stream =>
renderStream(diff, shortFormProvider, stream)
stream.toString(StandardCharsets.UTF_8)
}

private def groups(diff: BasicDiff): (Set[OWLItem[_]], Set[OWLItem[_]]) = {
val leftUnique: Set[OWLItem[_]] = diff.left.imports.map(OWLImportItem) ++ diff.left.annotations.map(OWLObjectItem) ++ diff.left.axioms.map(OWLObjectItem)
val rightUnique: Set[OWLItem[_]] = diff.right.imports.map(OWLImportItem) ++ diff.right.annotations.map(OWLObjectItem) ++ diff.right.axioms.map(OWLObjectItem)
(leftUnique, rightUnique)
}

private def format(removedLines: Set[String], addedLines: Set[String]): String = {
private def format(removedLines: Set[String], addedLines: Set[String], writer: PrintWriter): Unit = {
import org.geneontology.owl.differ.Util.replaceNewlines
val removedSorted = removedLines.map(replaceNewlines).map(ax => s"- $ax").toSeq.sorted.mkString("\n")
val addedSorted = addedLines.map(replaceNewlines).map(ax => s"+ $ax").toSeq.sorted.mkString("\n")
s"""${removedLines.size} axioms in left ontology but not in right ontology:
$removedSorted${if (removedSorted.nonEmpty) "\n" else ""}
${addedLines.size} axioms in right ontology but not in left ontology:
$addedSorted
"""
val removedSorted = removedLines.map(replaceNewlines).map(ax => s"- $ax").toSeq.sorted
val addedSorted = addedLines.map(replaceNewlines).map(ax => s"+ $ax").toSeq.sorted
writer.println(s"${removedLines.size} axioms in left ontology but not in right ontology:")
removedSorted.foreach(writer.println)
writer.println()
writer.println(s"${addedLines.size} axioms in right ontology but not in left ontology:")
addedSorted.foreach(writer.println)
}

private sealed trait OWLItem[T] {
Expand Down
Loading

0 comments on commit bdcd96d

Please sign in to comment.