diff --git a/src/main/scala/eu/neverblink/jelly/cli/App.scala b/src/main/scala/eu/neverblink/jelly/cli/App.scala index 7a19fd3..9b869f6 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/App.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/App.scala @@ -21,4 +21,5 @@ object App extends CommandsEntryPoint: override def commands: Seq[Command[?]] = Seq( Version, RdfFromJelly, + RdfToJelly, ) diff --git a/src/main/scala/eu/neverblink/jelly/cli/JellyCommand.scala b/src/main/scala/eu/neverblink/jelly/cli/JellyCommand.scala index d62f021..2714d0f 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/JellyCommand.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/JellyCommand.scala @@ -1,8 +1,9 @@ package eu.neverblink.jelly.cli import caseapp.* +import eu.neverblink.jelly.cli.util.IoUtil -import java.io.{ByteArrayOutputStream, OutputStream, PrintStream} +import java.io.* import scala.compiletime.uninitialized case class JellyOptions( @@ -18,6 +19,8 @@ abstract class JellyCommand[T <: HasJellyOptions: {Parser, Help}] extends Comman private var isDebug = false final protected[cli] var out = System.out final protected[cli] var err = System.err + final protected[cli] var in = System.in + private var osOut: ByteArrayOutputStream = uninitialized private var osErr: ByteArrayOutputStream = uninitialized @@ -25,14 +28,16 @@ abstract class JellyCommand[T <: HasJellyOptions: {Parser, Help}] extends Comman * @param test * true to enable, false to disable */ - def testMode(test: Boolean): Unit = + private def testMode(test: Boolean): Unit = this.isTest = test if test then + in = ByteArrayInputStream(Array()) osOut = ByteArrayOutputStream() out = PrintStream(osOut) osErr = ByteArrayOutputStream() err = PrintStream(osErr) else + in = System.in out = System.out err = System.err @@ -76,31 +81,77 @@ abstract class JellyCommand[T <: HasJellyOptions: {Parser, Help}] extends Comman osOut.reset() osErr.reset() App.main(args.toArray) - (osOut.toString, osErr.toString) + (osOut.toString("UTF-8"), osErr.toString("UTF-8")) + + private def validateTestMode(): Unit = + if !isTest then throw new IllegalStateException("Not in test mode") + + final def getOutString: String = + validateTestMode() + out.flush() + val s = osOut.toString + osOut.reset() + s + + final def getOutBytes: Array[Byte] = + validateTestMode() + out.flush() + val b = osOut.toByteArray + osOut.reset() + b - final def getOutContent: String = - if isTest then - out.flush() - val s = osOut.toString - osOut.reset() - s - else throw new IllegalStateException("Not in test mode") + private final def getStdIn: InputStream = + if isTest then in + else System.in + + final def setStdIn(data: ByteArrayInputStream): Unit = + validateTestMode() + in.reset() + in = data final def getOutStream: OutputStream = if isTest then osOut else System.out - protected def getStdOut: OutputStream = + private def getStdOut: OutputStream = if isTest then osOut else System.out - final def getErrContent: String = - if isTest then - err.flush() - val s = osErr.toString - osErr.reset() - s - else throw new IllegalStateException("Not in test mode") + final def getErrString: String = + validateTestMode() + err.flush() + val s = osErr.toString + osErr.reset() + s + + final def getErrBytes: Array[Byte] = + validateTestMode() + err.flush() + val b = osErr.toByteArray + osErr.reset() + b + + /** This method matches the CLI input and output options to the correct file or standard + * input/output + * @param inputOption + * @param outputOption + * @return + */ + final def getIoStreamsFromOptions( + inputOption: Option[String], + outputOption: Option[String], + ): (InputStream, OutputStream) = + val inputStream = inputOption match { + case Some(fileName: String) => + IoUtil.inputStream(fileName) + case _ => getStdIn + } + val outputStream = outputOption match { + case Some(fileName: String) => + IoUtil.outputStream(fileName) + case None => getStdOut + } + (inputStream, outputStream) @throws[ExitException] final override def exit(code: Int): Nothing = diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJelly.scala b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJelly.scala index 68d6bc5..550e2ee 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJelly.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJelly.scala @@ -3,7 +3,6 @@ import caseapp.* import com.google.protobuf.InvalidProtocolBufferException import eu.neverblink.jelly.cli.* import eu.neverblink.jelly.cli.command.rdf.RdfFormatOption.* -import eu.neverblink.jelly.cli.util.IoUtil import eu.ostrzyciel.jelly.convert.jena.riot.JellyLanguage import eu.ostrzyciel.jelly.core.proto.v1.RdfStreamFrame import eu.ostrzyciel.jelly.core.{IoUtils, RdfProtoDeserializationError} @@ -13,10 +12,7 @@ import org.apache.jena.riot.{RDFLanguages, RDFParser, RiotException} import java.io.{InputStream, OutputStream} object RdfFromJellyPrint extends RdfCommandPrintUtil: - // We exclude JellyBinary because translating JellyBinary to JellyBinary makes no sense - override val validFormats: List[RdfFormatOption] = - RdfFormatOption.values.filterNot(_ == JellyBinary).toList - + override val validFormats: List[RdfFormatOption] = List(JellyText, NQuads) override val defaultFormat: RdfFormatOption = NQuads case class RdfFromJellyOptions( @@ -38,16 +34,8 @@ object RdfFromJelly extends JellyCommand[RdfFromJellyOptions]: ) override def doRun(options: RdfFromJellyOptions, remainingArgs: RemainingArgs): Unit = - val inputStream = remainingArgs.remaining.headOption match { - case Some(fileName: String) => - IoUtil.inputStream(fileName) - case _ => System.in - } - val outputStream = options.outputFile match { - case Some(fileName: String) => - IoUtil.outputStream(fileName) - case None => getStdOut - } + val (inputStream, outputStream) = + this.getIoStreamsFromOptions(remainingArgs.remaining.headOption, options.outputFile) doConversion(inputStream, outputStream, options.outputFormat) /** This method takes care of proper error handling and matches the desired output format to the @@ -58,8 +46,8 @@ object RdfFromJelly extends JellyCommand[RdfFromJellyOptions]: * @param outputStream * OutputStream * @throws JellyDeserializationError - * @throws ParsingError - * @throws InvalidFormatSpecified + * @throws JenaRiotException + * @throws InvalidJellyFile */ private def doConversion( inputStream: InputStream, diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfToJelly.scala b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfToJelly.scala new file mode 100644 index 0000000..ceb397e --- /dev/null +++ b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfToJelly.scala @@ -0,0 +1,85 @@ +package eu.neverblink.jelly.cli.command.rdf +import caseapp.* +import com.google.protobuf.InvalidProtocolBufferException +import eu.neverblink.jelly.cli.* +import eu.neverblink.jelly.cli.command.rdf.RdfFormatOption.* +import eu.ostrzyciel.jelly.convert.jena.riot.JellyLanguage +import eu.ostrzyciel.jelly.core.RdfProtoSerializationError +import org.apache.jena.riot.system.StreamRDFWriter +import org.apache.jena.riot.{RDFLanguages, RDFParser, RiotException} + +import java.io.{InputStream, OutputStream} + +object RdfToJellyPrint extends RdfCommandPrintUtil: + override val validFormats: List[RdfFormatOption] = List(NQuads) + override val defaultFormat: RdfFormatOption = NQuads + +case class RdfToJellyOptions( + @Recurse + common: JellyOptions = JellyOptions(), + @ExtraName("to") outputFile: Option[String] = None, + @ValueDescription("Input format.") + @HelpMessage( + RdfToJellyPrint.helpMsg, + ) + @ExtraName("in-format") inputFormat: Option[String] = None, +) extends HasJellyOptions + +object RdfToJelly extends JellyCommand[RdfToJellyOptions]: + override def group = "rdf" + + override def names: List[List[String]] = List( + List("rdf", "to-jelly"), + ) + + override def doRun(options: RdfToJellyOptions, remainingArgs: RemainingArgs): Unit = + val (inputStream, outputStream) = + getIoStreamsFromOptions(remainingArgs.remaining.headOption, options.outputFile) + doConversion(inputStream, outputStream, options.inputFormat) + + /** This method takes care of proper error handling and matches the desired output format to the + * correct conversion + * + * @param inputStream + * InputStream + * @param outputStream + * OutputStream + * @throws JellySerializationError + * @throws JenaRiotException + * @throws InvalidJellyFile + */ + private def doConversion( + inputStream: InputStream, + outputStream: OutputStream, + format: Option[String], + ): Unit = + try { + format match { + case Some(f: String) => + RdfFormatOption.find(f) match + case Some(NQuads) => nQuadToJelly(inputStream, outputStream) + case _ => + throw InvalidFormatSpecified( + f, + RdfToJellyPrint.validFormatsString, + ) // if anything else, it's an invalid option + case None => + nQuadToJelly(inputStream, outputStream) // default option if no parameter supplied + } + } catch + case e: RdfProtoSerializationError => + throw JellySerializationError(e.getMessage) + case e: RiotException => + throw JenaRiotException(e) + case e: InvalidProtocolBufferException => + throw InvalidJellyFile(e) + + /** This method reads the NQuad file, rewrites it to Jelly and writes it to some output stream + * @param inputStream + * InputStream + * @param outputStream + * OutputStream + */ + private def nQuadToJelly(inputStream: InputStream, outputStream: OutputStream): Unit = + val jellyWriter = StreamRDFWriter.getWriterStream(outputStream, JellyLanguage.JELLY) + RDFParser.source(inputStream).lang(RDFLanguages.NQUADS).parse(jellyWriter) diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/RdfFromJellySpec.scala b/src/test/scala/eu/neverblink/jelly/cli/command/RdfFromJellySpec.scala index 0fdbe2b..762ca2c 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/RdfFromJellySpec.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/RdfFromJellySpec.scala @@ -16,11 +16,13 @@ import scala.util.Using class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: + protected val dHelper: DataGenHelper = DataGenHelper("testRdfFromJelly") + "rdf from-jelly command" should { "handle conversion of Jelly to NTriples" when { "a file to output stream" in { - val jellyFile = DataGenHelper.generateJellyFile(3) - val nQuadString = DataGenHelper.generateNQuadString(3) + val jellyFile = dHelper.generateJellyFile(3) + val nQuadString = dHelper.generateNQuadString(3) val (out, err) = RdfFromJelly.runTestCommand(List("rdf", "from-jelly", jellyFile)) val sortedOut = out.split("\n").map(_.trim).sorted @@ -29,8 +31,9 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: } "input stream to output stream" in { - DataGenHelper.generateJellyInputStream(3) - val nQuadString = DataGenHelper.generateNQuadString(3) + val input = dHelper.generateJellyInputStream(3) + RdfFromJelly.setStdIn(input) + val nQuadString = dHelper.generateNQuadString(3) val (out, err) = RdfFromJelly.runTestCommand( List("rdf", "from-jelly", "--out-format", RdfFormatOption.NQuads.cliOptions.head), ) @@ -39,9 +42,9 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: sortedOut should contain theSameElementsAs sortedQuads } "a file to file" in { - val jellyFile = DataGenHelper.generateJellyFile(3) - val nQuadString = DataGenHelper.generateNQuadString(3) - val outputFile = DataGenHelper.generateOutputFile(RDFLanguages.NQUADS) + val jellyFile = dHelper.generateJellyFile(3) + val nQuadString = dHelper.generateNQuadString(3) + val outputFile = dHelper.generateFile(RDFLanguages.NQUADS) val (out, err) = RdfFromJelly.runTestCommand( List("rdf", "from-jelly", jellyFile, "--to", outputFile), @@ -54,9 +57,10 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: out.length should be(0) } "an input stream to file" in { - DataGenHelper.generateJellyInputStream(3) - val outputFile = DataGenHelper.generateOutputFile(RDFLanguages.NQUADS) - val nQuadString = DataGenHelper.generateNQuadString(3) + val input = dHelper.generateJellyInputStream(3) + RdfFromJelly.setStdIn(input) + val outputFile = dHelper.generateFile(RDFLanguages.NQUADS) + val nQuadString = dHelper.generateNQuadString(3) val (out, err) = RdfFromJelly.runTestCommand(List("rdf", "from-jelly", "--to", outputFile)) val sortedOut = Using.resource(Source.fromFile(outputFile)) { content => @@ -69,7 +73,7 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: } "handle conversion of Jelly binary to text" when { "a file to output stream" in { - val jellyFile = DataGenHelper.generateJellyFile(3) + val jellyFile = dHelper.generateJellyFile(3) val (out, err) = RdfFromJelly.runTestCommand( List( @@ -107,11 +111,11 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: RdfFromJelly.runTestCommand(List("rdf", "from-jelly", nonExist)) } val msg = InputFileNotFound(nonExist).getMessage - RdfFromJelly.getErrContent should include(msg) + RdfFromJelly.getErrString should include(msg) exception.code should be(1) } "input file is not accessible" in { - val jellyFile = DataGenHelper.generateJellyFile(3) + val jellyFile = dHelper.generateJellyFile(3) val permissions = PosixFilePermissions.fromString("---------") Files.setPosixFilePermissions( Paths.get(jellyFile), @@ -123,14 +127,14 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: RdfFromJelly.runTestCommand(List("rdf", "from-jelly", jellyFile)) } val msg = InputFileInaccessible(jellyFile).getMessage - RdfFromJelly.getErrContent should include(msg) + RdfFromJelly.getErrString should include(msg) exception.code should be(1) } "output file cannot be created" in { - val jellyFile = DataGenHelper.generateJellyFile(3) - val unreachableDir = DataGenHelper.makeTestDir() + val jellyFile = dHelper.generateJellyFile(3) + val unreachableDir = dHelper.makeTestDir() Paths.get(unreachableDir).toFile.setWritable(false) - val quadFile = DataGenHelper.generateOutputFile() + val quadFile = dHelper.generateFile() val exception = intercept[ExitException] { @@ -139,12 +143,13 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: ) } val msg = OutputFileCannotBeCreated(quadFile).getMessage - RdfFromJelly.getErrContent should include(msg) + Paths.get(unreachableDir).toFile.setWritable(true) + RdfFromJelly.getErrString should include(msg) exception.code should be(1) } - "parsing error occurs" in { - val jellyFile = DataGenHelper.generateJellyFile(3) - val quadFile = DataGenHelper.generateOutputFile() + "deserializing error occurs" in { + val jellyFile = dHelper.generateJellyFile(3) + val quadFile = dHelper.generateFile() RdfFromJelly.runTestCommand( List("rdf", "from-jelly", jellyFile, "--to", quadFile), ) @@ -155,14 +160,14 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: ) } val msg = InvalidJellyFile(new InvalidProtocolBufferException("")).getMessage - val errContent = RdfFromJelly.getErrContent + val errContent = RdfFromJelly.getErrString errContent should include(msg) errContent should include("Run with --debug to see the complete stack trace.") exception.code should be(1) } "parsing error occurs with debug set" in { - val jellyFile = DataGenHelper.generateJellyFile(3) - val quadFile = DataGenHelper.generateOutputFile() + val jellyFile = dHelper.generateJellyFile(3) + val quadFile = dHelper.generateFile() RdfFromJelly.runTestCommand( List("rdf", "from-jelly", jellyFile, "--to", quadFile), ) @@ -173,14 +178,14 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: ) } val msg = InvalidJellyFile(new InvalidProtocolBufferException("")).getMessage - val errContent = RdfFromJelly.getErrContent + val errContent = RdfFromJelly.getErrString errContent should include(msg) errContent should include("eu.neverblink.jelly.cli.InvalidJellyFile") exception.code should be(1) } "invalid output format supplied" in { - val jellyFile = DataGenHelper.generateJellyFile(3) - val quadFile = DataGenHelper.generateOutputFile() + val jellyFile = dHelper.generateJellyFile(3) + val quadFile = dHelper.generateFile() val exception = intercept[ExitException] { RdfFromJelly.runTestCommand( @@ -188,7 +193,7 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: ) } val msg = InvalidFormatSpecified("invalid", RdfFromJellyPrint.validFormatsString) - RdfFromJelly.getErrContent should include(msg.getMessage) + RdfFromJelly.getErrString should include(msg.getMessage) exception.code should be(1) } } diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/RdfToJellySpec.scala b/src/test/scala/eu/neverblink/jelly/cli/command/RdfToJellySpec.scala new file mode 100644 index 0000000..99a224c --- /dev/null +++ b/src/test/scala/eu/neverblink/jelly/cli/command/RdfToJellySpec.scala @@ -0,0 +1,87 @@ +package eu.neverblink.jelly.cli.command + +import eu.neverblink.jelly.cli.{ExitException, InvalidFormatSpecified} +import eu.neverblink.jelly.cli.command.helpers.{CleanUpAfterTest, DataGenHelper} +import eu.neverblink.jelly.cli.command.rdf.{RdfFormatOption, RdfToJelly, RdfToJellyPrint} +import eu.ostrzyciel.jelly.convert.jena.riot.JellyLanguage +import org.apache.jena.rdf.model.{Model, ModelFactory} +import org.scalatest.matchers.should.Matchers +import org.scalatest.wordspec.AnyWordSpec +import org.apache.jena.riot.RDFParser + +import java.io.{ByteArrayInputStream, FileInputStream, InputStream} +import scala.util.Using + +class RdfToJellySpec extends AnyWordSpec with Matchers with CleanUpAfterTest: + + protected val dHelper: DataGenHelper = DataGenHelper("testRdfToJelly") + + def translateJellyBack(inputStream: InputStream): Model = + Using(inputStream) { content => + val newModel = ModelFactory.createDefaultModel() + RDFParser.source(content).lang(JellyLanguage.JELLY).parse(newModel) + newModel + } match { + case scala.util.Success(value) => value + case scala.util.Failure(exception) => throw exception + } + + "rdf to-jelly command" should { + "handle conversion of NTriples to Jelly" when { + "a file to output stream" in { + val nQuadFile = dHelper.generateNQuadFile(3) + val tripleModel = dHelper.generateTripleModel(3) + val (out, err) = + RdfToJelly.runTestCommand(List("rdf", "to-jelly", nQuadFile)) + val newIn = new ByteArrayInputStream(RdfToJelly.getOutBytes) + val content = translateJellyBack(newIn) + content.containsAll(tripleModel.listStatements()) + } + + "a file to file" in { + val nQuadFile = dHelper.generateNQuadFile(3) + val newFile = dHelper.generateFile(JellyLanguage.JELLY) + val tripleModel = dHelper.generateTripleModel(3) + val (out, err) = + RdfToJelly.runTestCommand(List("rdf", "to-jelly", nQuadFile, "--to", newFile)) + val content = translateJellyBack(new FileInputStream(newFile)) + content.containsAll(tripleModel.listStatements()) + } + + "input stream to output stream" in { + val testNumber = 10 + val input = dHelper.generateNQuadInputStream(testNumber) + RdfToJelly.setStdIn(input) + val tripleModel = dHelper.generateTripleModel(testNumber) + val (out, err) = RdfToJelly.runTestCommand( + List("rdf", "to-jelly", "--in-format", RdfFormatOption.NQuads.cliOptions.head), + ) + val newIn = new ByteArrayInputStream(RdfToJelly.getOutBytes) + val content = translateJellyBack(newIn) + content.containsAll(tripleModel.listStatements()) + } + + "an input stream to file" in { + val testNumber = 23 + val input = dHelper.generateNQuadInputStream(testNumber) + RdfToJelly.setStdIn(input) + val newFile = dHelper.generateFile(JellyLanguage.JELLY) + val tripleModel = dHelper.generateTripleModel(testNumber) + val (out, err) = RdfToJelly.runTestCommand(List("rdf", "to-jelly", "--to", newFile)) + val content = translateJellyBack(new FileInputStream(newFile)) + content.containsAll(tripleModel.listStatements()) + } + } + "throw proper exception" when { + "invalid format is specified" in { + val jellyFile = dHelper.generateNQuadFile(3) + val exception = + intercept[ExitException] { + RdfToJelly.runTestCommand(List("rdf", "to-jelly", jellyFile, "--in-format", "invalid")) + } + val msg = InvalidFormatSpecified("invalid", RdfToJellyPrint.validFormatsString) + RdfToJelly.getErrString should include(msg.getMessage) + exception.code should be(1) + } + } + } diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/CleanUpAfterTest.scala b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/CleanUpAfterTest.scala index 4d73c62..a328ead 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/CleanUpAfterTest.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/CleanUpAfterTest.scala @@ -1,12 +1,14 @@ package eu.neverblink.jelly.cli.command.helpers -import org.scalatest.BeforeAndAfterEach +import org.scalatest.{BeforeAndAfterEach, BeforeAndAfterAll} import org.scalatest.wordspec.AnyWordSpec -trait CleanUpAfterTest extends BeforeAndAfterEach { +trait CleanUpAfterTest extends BeforeAndAfterEach, BeforeAndAfterAll { this: AnyWordSpec => - override def afterEach(): Unit = { - DataGenHelper.cleanUpFiles() - DataGenHelper.resetInputStream() + + protected val dHelper: DataGenHelper + + override def afterAll(): Unit = { + dHelper.cleanUpFiles() } } diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/DataGenHelper.scala b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/DataGenHelper.scala index 2d8436d..f6f7436 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/DataGenHelper.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/DataGenHelper.scala @@ -2,7 +2,7 @@ package eu.neverblink.jelly.cli.command.helpers import eu.ostrzyciel.jelly.convert.jena.riot.JellyLanguage import org.apache.jena.rdf.model.{Model, ModelFactory, ResourceFactory} -import org.apache.jena.riot.{RDFDataMgr, RDFLanguages, Lang} +import org.apache.jena.riot.{Lang, RDFDataMgr, RDFLanguages} import java.io.{ByteArrayInputStream, ByteArrayOutputStream, FileOutputStream} import java.nio.file.{Files, Paths} @@ -11,11 +11,8 @@ import scala.util.Using /** This class will be used to generate test data */ -object DataGenHelper: - private val testDir = "test" - private val testFile = "testInput.jelly" - private val inputStream = System.in - protected val outputFiles = ListBuffer[String]() +class DataGenHelper(testDir: String = "test"): + private val outputFiles: ListBuffer[String] = ListBuffer[String]() /** This method generates a triple model with nTriples * @param nTriples @@ -40,29 +37,55 @@ object DataGenHelper: /** This method generates a Jelly file with nTriples * @param nTriples * number of triples to generate - * @param fileName - * name of the file to generate * @return * String */ def generateJellyFile(nTriples: Int): String = val model = generateTripleModel(nTriples) + val newFile = generateFile(JellyLanguage.JELLY) // TODO: Add configurable generation for different variants of Jelly (small strict etc) - Using.resource(FileOutputStream(testFile)) { file => + Using.resource(FileOutputStream(newFile)) { file => RDFDataMgr.write(file, model, JellyLanguage.JELLY) } - testFile + newFile + + /** This method generates a Jelly byte array + * + * @param nTriples + * number of triples to generate + * @return + * String + */ + def generateJellyBytes(nTriples: Int): Array[Byte] = + val model = generateTripleModel(nTriples) + val outputStream = new ByteArrayOutputStream() + RDFDataMgr.write(outputStream, model, JellyLanguage.JELLY) + outputStream.toByteArray + + /** This method generates a NQuad file with nTriples + * @param nTriples + * number of triples to generate + * @return + * String + */ + def generateNQuadFile(nTriples: Int): String = + val model = generateTripleModel(nTriples) + val newFile = generateFile(RDFLanguages.NQUADS) + Using.resource(FileOutputStream(newFile)) { file => + RDFDataMgr.write(file, model, RDFLanguages.NQUADS) + } + newFile /** This method generates a Jelly byte input stream with nTriples * @param nTriples * number of triples to generate */ - def generateJellyInputStream(nTriples: Int): Unit = + def generateJellyInputStream(nTriples: Int): ByteArrayInputStream = val model = generateTripleModel(nTriples) val outputStream = new ByteArrayOutputStream() RDFDataMgr.write(outputStream, model, JellyLanguage.JELLY) val jellyStream = new ByteArrayInputStream(outputStream.toByteArray) - System.setIn(jellyStream) + jellyStream /** This method generates a NQuad string with nTriples * @param nTriples @@ -76,15 +99,29 @@ object DataGenHelper: RDFDataMgr.write(outputStream, model, RDFLanguages.NQUADS) outputStream.toString + /** This method generates an NQuad input stream with nTriples + * + * @param nTriples + * number of triples to generate + * @return + * String + */ + def generateNQuadInputStream(nTriples: Int): ByteArrayInputStream = + val model = generateTripleModel(nTriples) + val outputStream = new ByteArrayOutputStream() + RDFDataMgr.write(outputStream, model, RDFLanguages.NQUADS) + val nQuadStream = new ByteArrayInputStream(outputStream.toByteArray) + nQuadStream + /** Make test dir */ def makeTestDir(): String = Files.createDirectories(Paths.get(testDir)) testDir - /** Generates and then cleans the file for test purposes + /** Generates the file for test purposes */ - def generateOutputFile(format: Lang = RDFLanguages.NQUADS): String = + def generateFile(format: Lang = RDFLanguages.NQUADS): String = if !Files.exists(Paths.get(testDir)) then makeTestDir() val extension = format.getFileExtensions.get(0) val fileName = s"${testDir}/testOutput${outputFiles.size}.${extension}" @@ -92,9 +129,5 @@ object DataGenHelper: fileName def cleanUpFiles(): Unit = - Files.deleteIfExists(Paths.get(testFile)) for file <- outputFiles do Files.deleteIfExists(Paths.get(file)) Files.deleteIfExists(Paths.get(testDir)) - - def resetInputStream(): Unit = - System.setIn(inputStream)