diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 60f2008..c65f77d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,6 +15,11 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: '23.x' + registry-url: https://registry.npmjs.org/ - name: Set up JDK uses: actions/setup-java@v4 with: @@ -33,3 +38,15 @@ jobs: if: startsWith(github.ref, 'refs/tags/') env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Generate SBOM with cdxgen + run: | + npm install -g @cyclonedx/cdxgen + cdxgen -t sbt -o bom.json . -p --no-recurse + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Create Release + if: startsWith(github.ref, 'refs/tags/') + uses: softprops/action-gh-release@v2 + with: + files: | + bom.json diff --git a/build.sbt b/build.sbt index ba0b980..1fdfbed 100644 --- a/build.sbt +++ b/build.sbt @@ -1,7 +1,7 @@ name := "overflowdb2" ThisBuild / organization := "io.appthreat" -ThisBuild / version := "1.0.0" -ThisBuild / scalaVersion := "3.3.1" +ThisBuild / version := "1.0.1" +ThisBuild / scalaVersion := "3.5.2" publish / skip := true lazy val core = project.in(file("core")) @@ -12,7 +12,7 @@ lazy val coreTests = project.in(file("core-tests")).dependsOn(formats, testdomai lazy val traversalTests = project.in(file("traversal-tests")).dependsOn(formats) ThisBuild / libraryDependencies ++= Seq( - "org.scalatest" %% "scalatest" % "3.2.17" % Test + "org.scalatest" %% "scalatest" % "3.2.19" % Test ) ThisBuild / scalacOptions ++= Seq( diff --git a/core/build.sbt b/core/build.sbt index aecf9e7..8d0957c 100644 --- a/core/build.sbt +++ b/core/build.sbt @@ -2,7 +2,7 @@ name := "odb2-core" libraryDependencies ++= Seq( "net.sf.trove4j" % "core" % "3.1.0", - "org.msgpack" % "msgpack-core" % "0.9.1", + "org.msgpack" % "msgpack-core" % "0.9.8", "com.h2database" % "h2-mvstore" % "1.4.200" ) githubOwner := "appthreat" diff --git a/formats/build.sbt b/formats/build.sbt index fae2fed..2da4227 100644 --- a/formats/build.sbt +++ b/formats/build.sbt @@ -1,8 +1,8 @@ name := "odb2-formats" libraryDependencies ++= Seq( - "com.github.tototoshi" %% "scala-csv" % "1.3.10", - "org.scala-lang.modules" %% "scala-xml" % "2.2.0", + "com.github.tototoshi" %% "scala-csv" % "2.0.0", + "org.scala-lang.modules" %% "scala-xml" % "2.3.0", "com.github.pathikrit" %% "better-files" % "3.9.2" % Test, "com.github.scopt" %% "scopt" % "4.1.0", "io.spray" %% "spray-json" % "1.3.6" diff --git a/formats/src/main/scala/overflowdb/formats/ExporterMain.scala b/formats/src/main/scala/overflowdb/formats/ExporterMain.scala index fc4bfc9..481a677 100644 --- a/formats/src/main/scala/overflowdb/formats/ExporterMain.scala +++ b/formats/src/main/scala/overflowdb/formats/ExporterMain.scala @@ -20,8 +20,8 @@ import scala.util.Using object ExporterMain: def apply( - nodeFactories: Seq[NodeFactory[_]], - edgeFactories: Seq[EdgeFactory[_]] + nodeFactories: Seq[NodeFactory[?]], + edgeFactories: Seq[EdgeFactory[?]] ): Array[String] => Unit = args => OParser .parse(parser, args, Config(Paths.get("/dev/null"), null, Paths.get("/dev/null"))) diff --git a/formats/src/main/scala/overflowdb/formats/ImporterMain.scala b/formats/src/main/scala/overflowdb/formats/ImporterMain.scala index b6c8a81..fc25811 100644 --- a/formats/src/main/scala/overflowdb/formats/ImporterMain.scala +++ b/formats/src/main/scala/overflowdb/formats/ImporterMain.scala @@ -18,8 +18,8 @@ import scala.util.Using object ImporterMain extends App: def apply( - nodeFactories: Seq[NodeFactory[_]], - edgeFactories: Seq[EdgeFactory[_]], + nodeFactories: Seq[NodeFactory[?]], + edgeFactories: Seq[EdgeFactory[?]], convertPropertyForPersistence: Any => Any = identity ): Array[String] => Unit = args => OParser diff --git a/formats/src/main/scala/overflowdb/formats/graphson/GraphSONProtocol.scala b/formats/src/main/scala/overflowdb/formats/graphson/GraphSONProtocol.scala index 429ad41..61fa0e2 100644 --- a/formats/src/main/scala/overflowdb/formats/graphson/GraphSONProtocol.scala +++ b/formats/src/main/scala/overflowdb/formats/graphson/GraphSONProtocol.scala @@ -40,7 +40,7 @@ object GraphSONProtocol extends DefaultJsonProtocol: ) case x => serializationError(s"unsupported propertyValue: $x") - def read(value: JsValue): PropertyValue with Product = + def read(value: JsValue): PropertyValue & Product = value match case JsString(v) => return StringValue(v) case JsBoolean(v) => return BooleanValue(v) @@ -50,7 +50,7 @@ object GraphSONProtocol extends DefaultJsonProtocol: case x: Seq[?] => readNonList(x) case null => deserializationError("PropertyValue expected") - def readNonList(value: Seq[?]): PropertyValue with Product = value match + def readNonList(value: Seq[?]): PropertyValue & Product = value match case Seq(JsNumber(v), JsString(typ)) => if typ.equals(Type.Long.typ) then LongValue(v.toLongExact) else if typ.equals(Type.Int.typ) then IntValue(v.toIntExact) @@ -64,7 +64,7 @@ object GraphSONProtocol extends DefaultJsonProtocol: implicit object LongValueFormat extends RootJsonFormat[LongValue]: def write(c: LongValue): JsValue = PropertyValueJsonFormat.write(c) - def read(value: JsValue): LongValue with Product = + def read(value: JsValue): LongValue & Product = value.asJsObject.getFields("@value", "@type") match case Seq(JsNumber(v), JsString(typ)) if typ.equals(Type.Long.typ) => LongValue(v.toLongExact) diff --git a/formats/src/main/scala/overflowdb/formats/graphson/package.scala b/formats/src/main/scala/overflowdb/formats/graphson/package.scala index ac6a9ac..5f16838 100644 --- a/formats/src/main/scala/overflowdb/formats/graphson/package.scala +++ b/formats/src/main/scala/overflowdb/formats/graphson/package.scala @@ -43,7 +43,7 @@ package object graphson: Type.Double else if clazz.isAssignableFrom(classOf[String]) then Type.String - else if clazz.isAssignableFrom(classOf[List[_]]) then + else if clazz.isAssignableFrom(classOf[List[?]]) then Type.List else throw new AssertionError( diff --git a/formats/src/main/scala/overflowdb/formats/neo4jcsv/ColumnDefinitions.scala b/formats/src/main/scala/overflowdb/formats/neo4jcsv/ColumnDefinitions.scala index a8b1273..12cb001 100644 --- a/formats/src/main/scala/overflowdb/formats/neo4jcsv/ColumnDefinitions.scala +++ b/formats/src/main/scala/overflowdb/formats/neo4jcsv/ColumnDefinitions.scala @@ -139,13 +139,13 @@ class ColumnDefinitions(propertyNames: Iterable[String]): value match case _: Iterable[?] => - deriveNeo4jTypeForArray(_.asInstanceOf[Iterable[_]]) + deriveNeo4jTypeForArray(_.asInstanceOf[Iterable[?]]) case _: IterableOnce[?] => - deriveNeo4jTypeForArray(_.asInstanceOf[IterableOnce[_]].iterator.toSeq) + deriveNeo4jTypeForArray(_.asInstanceOf[IterableOnce[?]].iterator.toSeq) case _: java.lang.Iterable[?] => - deriveNeo4jTypeForArray(_.asInstanceOf[java.lang.Iterable[_]].asScala) + deriveNeo4jTypeForArray(_.asInstanceOf[java.lang.Iterable[?]].asScala) case _: Array[?] => - deriveNeo4jTypeForArray(x => ArraySeq.unsafeWrapArray(x.asInstanceOf[Array[_]])) + deriveNeo4jTypeForArray(x => ArraySeq.unsafeWrapArray(x.asInstanceOf[Array[?]])) case scalarValue => ScalarColumnDef(deriveNeo4jTypeForScalarValue(scalarValue.getClass)) end deriveNeo4jType diff --git a/formats/src/main/scala/overflowdb/formats/package.scala b/formats/src/main/scala/overflowdb/formats/package.scala index 07b7b26..d8a6a7b 100644 --- a/formats/src/main/scala/overflowdb/formats/package.scala +++ b/formats/src/main/scala/overflowdb/formats/package.scala @@ -21,10 +21,10 @@ package object formats: */ def isList(clazz: Class[?]): Boolean = clazz.isArray || - classOf[java.lang.Iterable[_]].isAssignableFrom(clazz) || - classOf[IterableOnce[_]].isAssignableFrom(clazz) + classOf[java.lang.Iterable[?]].isAssignableFrom(clazz) || + classOf[IterableOnce[?]].isAssignableFrom(clazz) - val iterableForList: PartialFunction[Any, Iterable[_]] = { + val iterableForList: PartialFunction[Any, Iterable[?]] = { case it: Iterable[?] => it case it: IterableOnce[?] => it.iterator.toSeq case it: java.lang.Iterable[?] => it.asScala diff --git a/project/build.properties b/project/build.properties index abbbce5..db1723b 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.8 +sbt.version=1.10.5 diff --git a/traversal-tests/src/test/scala/overflowdb/algorithm/LowestCommonAncestorsTests.scala b/traversal-tests/src/test/scala/overflowdb/algorithm/LowestCommonAncestorsTests.scala index 0917924..1d736b6 100644 --- a/traversal-tests/src/test/scala/overflowdb/algorithm/LowestCommonAncestorsTests.scala +++ b/traversal-tests/src/test/scala/overflowdb/algorithm/LowestCommonAncestorsTests.scala @@ -44,27 +44,27 @@ class LowestCommonAncestorsTests extends AnyWordSpec { "empty set" in { val relevantNodes = Set.empty[Node] - LowestCommonAncestors(relevantNodes)(_.parents) shouldBe Set.empty + LowestCommonAncestors(relevantNodes)(using _.parents) shouldBe Set.empty } "one node" in { val relevantNodes = Set(D) - LowestCommonAncestors(relevantNodes)(_.parents) shouldBe relevantNodes + LowestCommonAncestors(relevantNodes)(using _.parents) shouldBe relevantNodes } "node E and H" in { val relevantNodes = Set(E, H) - LowestCommonAncestors(relevantNodes)(_.parents) shouldBe Set(B, C) + LowestCommonAncestors(relevantNodes)(using _.parents) shouldBe Set(B, C) } "node B,E,H" in { val relevantNodes = Set(B, E, H) - LowestCommonAncestors(relevantNodes)(_.parents) shouldBe Set(A) + LowestCommonAncestors(relevantNodes)(using _.parents) shouldBe Set(A) } "node A,B,E,H" in { val relevantNodes = Set(A, B, E, H) - LowestCommonAncestors(relevantNodes)(_.parents) shouldBe Set.empty + LowestCommonAncestors(relevantNodes)(using _.parents) shouldBe Set.empty } "cyclic dependencies" in { diff --git a/traversal-tests/src/test/scala/overflowdb/traversal/PathTraversalTests.scala b/traversal-tests/src/test/scala/overflowdb/traversal/PathTraversalTests.scala index 995cd42..4e6fe52 100644 --- a/traversal-tests/src/test/scala/overflowdb/traversal/PathTraversalTests.scala +++ b/traversal-tests/src/test/scala/overflowdb/traversal/PathTraversalTests.scala @@ -76,7 +76,7 @@ class PathTraversalTests extends AnyWordSpec with ExampleGraphSetup { verifyResults(center.start.enablePathTracking.both.both.dedup.path.toSetMutable) verifyResults(center.start.enablePathTracking.both.both.dedupBy(_.hashCode).path.toSetMutable) - def verifyResults(paths: collection.Set[Vector[_]]) = { + def verifyResults(paths: collection.Set[Vector[?]]) = { paths should contain(Vector(center, l1, l2)) paths should contain(Vector(center, r1, r2)) // paths.should(contain(oneOf(Seq(center, l1, center), Seq(center, r1, center)))) diff --git a/traversal-tests/src/test/scala/overflowdb/traversal/RepeatTraversalTests.scala b/traversal-tests/src/test/scala/overflowdb/traversal/RepeatTraversalTests.scala index a2904a7..180c836 100644 --- a/traversal-tests/src/test/scala/overflowdb/traversal/RepeatTraversalTests.scala +++ b/traversal-tests/src/test/scala/overflowdb/traversal/RepeatTraversalTests.scala @@ -298,7 +298,7 @@ class RepeatTraversalTests extends AnyWordSpec with ExampleGraphSetup { "traverses all nodes to outer limits exactly once, emitting and returning nothing, by default" in { val traversedNodes = mutable.ListBuffer.empty[Any] - def test(traverse: => Iterable[_]) = { + def test(traverse: => Iterable[?]) = { traversedNodes.clear() val results = traverse traversedNodes.size shouldBe 9 diff --git a/traversal/src/main/scala/overflowdb/SyntacticSugar.scala b/traversal/src/main/scala/overflowdb/SyntacticSugar.scala index 814d442..6a9120e 100644 --- a/traversal/src/main/scala/overflowdb/SyntacticSugar.scala +++ b/traversal/src/main/scala/overflowdb/SyntacticSugar.scala @@ -25,7 +25,7 @@ class GraphSugar(val graph: Graph) extends AnyVal: def `+`(label: String, id: Long, properties: Property[?]*): Node = graph.addNode(id, label, keyValuesAsSeq(properties)*) - private def keyValuesAsSeq(properties: Seq[Property[_]]): Seq[?] = + private def keyValuesAsSeq(properties: Seq[Property[?]]): Seq[?] = val builder = Seq.newBuilder[Any] builder.sizeHint(properties.size * 2) properties.foreach { kv => @@ -42,7 +42,7 @@ class NodeSugar(val node: Node) extends AnyVal: def ---(label: String, properties: Property[?]*): SemiEdge = new SemiEdge(node, label, properties) -private[overflowdb] class SemiEdge(outNode: Node, label: String, properties: Seq[Property[_]]): +private[overflowdb] class SemiEdge(outNode: Node, label: String, properties: Seq[Property[?]]): def -->(inNode: Node): Edge = val keyValues = new Array[Any](properties.size * 2) var i: Int = 0 diff --git a/traversal/src/main/scala/overflowdb/traversal/PathAwareTraversal.scala b/traversal/src/main/scala/overflowdb/traversal/PathAwareTraversal.scala index 487cb43..9a83606 100644 --- a/traversal/src/main/scala/overflowdb/traversal/PathAwareTraversal.scala +++ b/traversal/src/main/scala/overflowdb/traversal/PathAwareTraversal.scala @@ -85,7 +85,7 @@ class PathAwareTraversal[A](val wrapped: Iterator[(A, Vector[Any])]) extends Ite .getOrElse(Iterator.empty) }) - private[traversal] def _sideEffect(f: A => _): PathAwareTraversal[A] = + private[traversal] def _sideEffect(f: A => ?): PathAwareTraversal[A] = new PathAwareTraversal(wrapped.map { case (a, p) => f(a); (a, p) }) diff --git a/traversal/src/main/scala/overflowdb/traversal/RepeatBehaviour.scala b/traversal/src/main/scala/overflowdb/traversal/RepeatBehaviour.scala index 3113836..df92211 100644 --- a/traversal/src/main/scala/overflowdb/traversal/RepeatBehaviour.scala +++ b/traversal/src/main/scala/overflowdb/traversal/RepeatBehaviour.scala @@ -4,8 +4,8 @@ import RepeatBehaviour.* trait RepeatBehaviour[A]: val searchAlgorithm: SearchAlgorithm.Value - val untilCondition: Option[A => Iterator[_]] - val whileCondition: Option[A => Iterator[_]] + val untilCondition: Option[A => Iterator[?]] + val whileCondition: Option[A => Iterator[?]] val maxDepth: Option[Int] val dedupEnabled: Boolean @@ -36,12 +36,12 @@ object RepeatBehaviour: def noop[A](builder: RepeatBehaviour.Builder[A]): Builder[A] = builder class Builder[A]: - private[this] var _shouldEmit: (A, Int) => Boolean = (_, _) => false - private[this] var _untilCondition: Option[Traversal[A] => Traversal[_]] = None - private[this] var _whileCondition: Option[Traversal[A] => Traversal[_]] = None - private[this] var _maxDepth: Option[Int] = None - private[this] var _dedupEnabled: Boolean = false - private[this] var _searchAlgorithm: SearchAlgorithm.Value = SearchAlgorithm.DepthFirst + private var _shouldEmit: (A, Int) => Boolean = (_, _) => false + private var _untilCondition: Option[Traversal[A] => Traversal[?]] = None + private var _whileCondition: Option[Traversal[A] => Traversal[?]] = None + private var _maxDepth: Option[Int] = None + private var _dedupEnabled: Boolean = false + private var _searchAlgorithm: SearchAlgorithm.Value = SearchAlgorithm.DepthFirst /** configure search algorithm to go "breadth first", rather than the default "depth first" */ diff --git a/traversal/src/main/scala/overflowdb/traversal/Traversal.scala b/traversal/src/main/scala/overflowdb/traversal/Traversal.scala index 50b7cc1..6f7e9f5 100644 --- a/traversal/src/main/scala/overflowdb/traversal/Traversal.scala +++ b/traversal/src/main/scala/overflowdb/traversal/Traversal.scala @@ -154,7 +154,7 @@ class TraversalLogicExt[A](val iterator: Iterator[A]) extends AnyVal: /** perform side effect without changing the contents of the traversal */ @Doc(info = "perform side effect without changing the contents of the traversal") - def sideEffect(fun: A => _): Traversal[A] = + def sideEffect(fun: A => ?): Traversal[A] = iterator match case pathAwareTraversal: PathAwareTraversal[A] => pathAwareTraversal._sideEffect(fun) case _ => @@ -320,7 +320,7 @@ class TraversalTrackingExt[A](val iterator: Iterator[A]) extends AnyVal: pathAwareTraversal.wrapped.map { _._1 } case _ => iterator - def isPathTracking: Boolean = iterator.isInstanceOf[PathAwareTraversal[_]] + def isPathTracking: Boolean = iterator.isInstanceOf[PathAwareTraversal[?]] /** retrieve entire path that has been traversed thus far prerequisite: enablePathTracking has * been called previously @@ -394,7 +394,7 @@ class TraversalRepeatExt[A](val trav: Iterator[A]) extends AnyVal: repeatTraversal: Traversal[A] => Traversal[B] )(implicit behaviourBuilder: RepeatBehaviour.Builder[B] => RepeatBehaviour.Builder[B] = - RepeatBehaviour.noop[B] _ + RepeatBehaviour.noop[B] ): Traversal[B] = val behaviour = behaviourBuilder(new RepeatBehaviour.Builder[B]).build val _repeatTraversal = diff --git a/traversal/src/main/scala/overflowdb/traversal/help/TraversalHelp.scala b/traversal/src/main/scala/overflowdb/traversal/help/TraversalHelp.scala index 1a5416d..ecee70d 100644 --- a/traversal/src/main/scala/overflowdb/traversal/help/TraversalHelp.scala +++ b/traversal/src/main/scala/overflowdb/traversal/help/TraversalHelp.scala @@ -27,10 +27,10 @@ class TraversalHelp(searchPackages: DocSearchPackages): def forElementSpecificSteps(elementClass: Class[?], verbose: Boolean): String = val isNode = classOf[NodeDb].isAssignableFrom(elementClass) - val isNodeRef = classOf[NodeRef[_]].isAssignableFrom(elementClass) + val isNodeRef = classOf[NodeRef[?]].isAssignableFrom(elementClass) val stepDocs = - def parentTraitsRecursively(clazz: Class[?]): List[Class[_]] = + def parentTraitsRecursively(clazz: Class[?]): List[Class[?]] = val parents = clazz.getInterfaces.to(List) parents ++ parents.flatMap(parentTraitsRecursively) @@ -79,7 +79,7 @@ class TraversalHelp(searchPackages: DocSearchPackages): * to then extract the \@Doc annotations for all steps, and group them by the elementType (e.g. * node.Method). */ - lazy val stepDocsByElementType: Map[Class[_], List[StepDoc]] = { + lazy val stepDocsByElementType: Map[Class[?], List[StepDoc]] = { for packageName <- packageNamesToSearch traversal <- findClassesAnnotatedWith(packageName, classOf[help.Traversal]) @@ -91,18 +91,18 @@ class TraversalHelp(searchPackages: DocSearchPackages): private def findClassesAnnotatedWith[Annotation <: JAnnotation]( packageName: String, annotationClass: Class[Annotation] - ): Iterator[Class[_]] = + ): Iterator[Class[?]] = new Reflections(packageName).getTypesAnnotatedWith(annotationClass).asScala.iterator lazy val genericStepDocs: Iterable[StepDoc] = - findStepDocs(classOf[traversal.TraversalSugarExt[_]]) ++ findStepDocs( - classOf[traversal.TraversalFilterExt[_]] - ) ++ findStepDocs(classOf[traversal.TraversalLogicExt[_]]) ++ findStepDocs( - classOf[traversal.TraversalTrackingExt[_]] - ) ++ findStepDocs(classOf[traversal.TraversalRepeatExt[_]]) + findStepDocs(classOf[traversal.TraversalSugarExt[?]]) ++ findStepDocs( + classOf[traversal.TraversalFilterExt[?]] + ) ++ findStepDocs(classOf[traversal.TraversalLogicExt[?]]) ++ findStepDocs( + classOf[traversal.TraversalTrackingExt[?]] + ) ++ findStepDocs(classOf[traversal.TraversalRepeatExt[?]]) lazy val genericNodeStepDocs: Iterable[StepDoc] = - findStepDocs(classOf[NodeTraversal[_]]) ++ findStepDocs(classOf[ElementTraversal[_]]) + findStepDocs(classOf[NodeTraversal[?]]) ++ findStepDocs(classOf[ElementTraversal[?]]) protected def findStepDocs(traversal: Class[?]): Iterable[StepDoc] = DocFinder