From 4af6f3b4c93b06c668602c9eaac6ccf4f1e06819 Mon Sep 17 00:00:00 2001 From: Mike Bryant Date: Fri, 6 Jun 2025 12:03:52 +0100 Subject: [PATCH 01/15] Add experimental additional source for data provided via stdin As per unix custom, using '-' as the source prompts the mapper to read the data from stdin. To illustrate one use for this I've also added a new method on the launcher `launchMappingFromJsonData` which runs the mapping on a provided JsonNode object. Behind the scenes this using the stdin input, which is a bit of a hack tbh. A practical use for this is pushing data into the mapper, rather than letting it fetch data from sources, which is something you might want to do in a streaming context. I'm not going to pretend this is the optimal implementation however! --- .../shexml/MappingLauncher.scala | 21 ++++- .../shexml/helper/SourceHelper.scala | 4 +- .../shexml/visitor/RDFGeneratorVisitor.scala | 11 ++- .../herminiogarcia/shexml/FilmsStdin.scala | 82 +++++++++++++++++++ 4 files changed, 110 insertions(+), 8 deletions(-) create mode 100644 src/test/scala/com/herminiogarcia/shexml/FilmsStdin.scala diff --git a/src/main/scala/com/herminiogarcia/shexml/MappingLauncher.scala b/src/main/scala/com/herminiogarcia/shexml/MappingLauncher.scala index 458e5d0..2e4b309 100644 --- a/src/main/scala/com/herminiogarcia/shexml/MappingLauncher.scala +++ b/src/main/scala/com/herminiogarcia/shexml/MappingLauncher.scala @@ -1,5 +1,6 @@ package com.herminiogarcia.shexml +import com.fasterxml.jackson.databind.{JsonNode, ObjectMapper} import com.herminiogarcia.shexml.antlr.{ShExMLLexer, ShExMLParser} import com.herminiogarcia.shexml.ast._ import com.herminiogarcia.shexml.helper.{OrphanBNodeRemover, SourceHelper} @@ -11,7 +12,7 @@ import org.apache.jena.query.{Dataset, DatasetFactory} import org.apache.jena.riot.{RDFDataMgr, RDFFormat, RDFLanguages} import com.typesafe.scalalogging.Logger -import java.io.ByteArrayOutputStream +import java.io.{ByteArrayInputStream, ByteArrayOutputStream} import scala.collection.mutable /** @@ -48,6 +49,24 @@ class MappingLauncher(val username: String = "", val password: String = "", driv generateResultingRDF(ast, varTable) } + def launchMappingFromJsonData(mappingCode: String, data: JsonNode): Dataset = { + logger.info(s"Launching mapping with data") + logger.debug(s"Mapping rules $mappingCode") + val lexer = createLexer(mappingCode) + val parser = createParser(lexer) + val ast = createAST(parser) + val varTable = createVarTable(ast) + try { + val bytes = new ObjectMapper().writeValueAsBytes(data) + logger.trace(s"Data: ${data.toString}") + val inputBytes = new ByteArrayInputStream(bytes) + System.setIn(inputBytes) + generateResultingRDF(ast, varTable) + } finally { + System.setIn(System.in) + } + } + def launchRMLTranslation(mappingCode: String, prettify: Boolean = false): String = { logger.info(s"Launching ShExML to RML translation with prettify option to $prettify") logger.debug(s"Mapping rules $mappingCode") diff --git a/src/main/scala/com/herminiogarcia/shexml/helper/SourceHelper.scala b/src/main/scala/com/herminiogarcia/shexml/helper/SourceHelper.scala index 7787dad..a5221d8 100644 --- a/src/main/scala/com/herminiogarcia/shexml/helper/SourceHelper.scala +++ b/src/main/scala/com/herminiogarcia/shexml/helper/SourceHelper.scala @@ -23,7 +23,9 @@ class SourceHelper { def getContentFromRelativePath(path: String): LoadedSource = searchFileResult(path) match { case Some(result) => result case None => - val file = scala.io.Source.fromFile(path, "UTF-8") + val file = if (path.equals("-")) + scala.io.Source.fromInputStream(System.in, "UTF-8") + else scala.io.Source.fromFile(path, "UTF-8") try { val content = LoadedSource(file.mkString, path) saveFileResult(path, content) diff --git a/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala b/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala index 1db8f03..df8a2fe 100644 --- a/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala +++ b/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala @@ -1,6 +1,5 @@ package com.herminiogarcia.shexml.visitor -import com.fasterxml.jackson.databind.{JsonNode, ObjectMapper} import com.github.tototoshi.csv.{CSVReader, DefaultCSVFormat} import com.herminiogarcia.shexml.ast.{AST, Action, ActionOrLiteral, AutoIncrement, CSVPerRow, DataTypeGeneration, DataTypeLiteral, Declaration, Exp, FieldQuery, FunctionCalling, Graph, IRI, IteratorQuery, JdbcURL, Join, JsonPath, LangTagGeneration, LangTagLiteral, LiteralObject, LiteralObjectValue, LiteralSubject, Matcher, Matchers, ObjectElement, Predicate, PredicateObject, Prefix, QueryClause, RDFAlt, RDFBag, RDFCollection, RDFList, RDFSeq, RelativePath, ShExML, Shape, ShapeLink, ShapeVar, Sparql, SparqlColumn, Sql, SqlColumn, StringOperation, Substitution, URL, Union, Var, VarResult, Variable, XmlPath} import com.herminiogarcia.shexml.helper.{FunctionHubExecuter, LoadedSource, SourceHelper} @@ -50,6 +49,10 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, protected val xmlDocumentCache = new XMLDocumentCache() protected val functionHubExecuterCache = new FunctionHubExecuterCache() protected val defaultModel = dataset.getDefaultModel + protected val jsonPathConfiguration = Configuration.defaultConfiguration() + .addOptions(com.jayway.jsonpath.Option.ALWAYS_RETURN_LIST) + .addOptions(com.jayway.jsonpath.Option.DEFAULT_PATH_LEAF_TO_NULL) + .addOptions(com.jayway.jsonpath.Option.SUPPRESS_EXCEPTIONS) private val xmlProcessor = new Processor(false) @@ -437,11 +440,7 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, logger.debug(s"Retrieving cached result for already parsed JSON file") jsonNode case None => - val configuration = Configuration.defaultConfiguration() - .addOptions(com.jayway.jsonpath.Option.ALWAYS_RETURN_LIST) - .addOptions(com.jayway.jsonpath.Option.DEFAULT_PATH_LEAF_TO_NULL) - .addOptions(com.jayway.jsonpath.Option.SUPPRESS_EXCEPTIONS) - val context = com.jayway.jsonpath.JsonPath.using(configuration).parse(file.fileContent) + val context = com.jayway.jsonpath.JsonPath.using(jsonPathConfiguration).parse(file.fileContent) jsonObjectMapperCache.save(file, context) context } diff --git a/src/test/scala/com/herminiogarcia/shexml/FilmsStdin.scala b/src/test/scala/com/herminiogarcia/shexml/FilmsStdin.scala new file mode 100644 index 0000000..6b72765 --- /dev/null +++ b/src/test/scala/com/herminiogarcia/shexml/FilmsStdin.scala @@ -0,0 +1,82 @@ +package com.herminiogarcia.shexml + +import com.fasterxml.jackson.databind.ObjectMapper +import org.apache.jena.datatypes.xsd.XSDDatatype +import org.scalactic.source.Position +import org.scalatest.{BeforeAndAfter, BeforeAndAfterEach} +import org.scalatest.funsuite.AnyFunSuite +import org.scalatest.matchers.must.Matchers + +import scala.io.Source + +class FilmsStdin extends AnyFunSuite with Matchers with RDFStatementCreator with BeforeAndAfter { + + override def after(fun: => Any)(implicit pos: Position): Unit = try System.setIn(System.in) finally super.after(fun) + + private val example = + """ + PREFIX : + |SOURCE films_xml_file <./src/test/resources/filmsAlt.xml> + |SOURCE films_json_file <-> + |ITERATOR film_xml { + | FIELD name + | FIELD year + | FIELD country + | FIELD directors + | FIELD comment + |} + |ITERATOR film_json { + | FIELD name <['name of the film']> + | FIELD year + | FIELD country + | FIELD directors + | FIELD comment + |} + |EXPRESSION films + | + |:Films :film1 { + | a :Film ; + | :name [films.name] ; + | :year [films.year] ; + | :country [films.country] ; + | :director [films.directors] ; + | :comment [films.comment] ; + |} + """.stripMargin + + private val prefix = "http://example.com/" + val data = Source.fromInputStream(getClass.getClassLoader.getResourceAsStream("filmsAlt.json")).mkString + val node = new ObjectMapper().readTree(data) + + private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) + private val output = mappingLauncher.launchMappingFromJsonData(example, node).getDefaultModel + + + test("Shape film1 contains all the data, literal action, enhancement-#97") { + assert(output.contains(createStatementWithLiteral(prefix, "film1", "name", "Dunkirk", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "film1", "year", "2017", XSDDatatype.XSDinteger))) + assert(output.contains(createStatementWithLiteral(prefix, "film1", "country", "USA", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "film1", "director", "Christopher Nolan", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "film1", "year", "2010", XSDDatatype.XSDinteger))) + assert(output.contains(createStatementWithLiteral(prefix, "film1", "country", "USA", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "film1", "director", "Christopher Nolan", XSDDatatype.XSDstring))) + } + + test("Allow spaces in the JSONPath expression, bug-#98") { + assert(output.contains(createStatementWithLiteral(prefix, "film1", "name", "Inception", XSDDatatype.XSDstring))) + } + + test("Escape quote marks inside strings, enhancement-#99") { + assert(output.contains(createStatementWithLiteral(prefix, "film1", "comment", "A \"different\" movie", XSDDatatype.XSDstring))) + } + + test("Avoid URL generation when string does not start by it, bug-#100") { + assert(output.contains(createStatementWithLiteral(prefix, "film1", "comment", "Very interesting movie, see more comments on: http://example.com/comments", XSDDatatype.XSDstring))) + } + + test("No additional triples are generated") { + val triplesCount = 9 + assert(output.size() == triplesCount) + } + +} From 6f8b870b64c592d773f7bcaee011f58159ee7ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Mon, 11 Aug 2025 15:47:54 +0200 Subject: [PATCH 02/15] Added first experimental option to parallelise the execution of the engine. Closes #223 --- .github/workflows/scala.yml | 8 +- build.sbt | 3 + .../ParallelExecutionConfigurator.scala | 35 +++ .../ParallelExecutionConfigurator.scala | 35 +++ .../ParallelExecutionConfigurator.scala | 35 +++ .../com/herminiogarcia/shexml/Main.scala | 23 +- .../shexml/MappingLauncher.scala | 41 ++-- .../shexml/visitor/QuerySearcher.scala | 3 +- .../shexml/visitor/RDFGeneratorVisitor.scala | 214 ++++++++++-------- .../shexml/visitor/RMLGeneratorVisitor.scala | 6 +- .../visitor/VarTableBuilderVisitor.scala | 2 +- ...ieldsOutsideIteratorsWithImportsTest.scala | 14 +- .../shexml/AutoIncrementOnFunctionTest.scala | 14 +- .../CommentIteratorExpressionTest.scala | 15 +- .../herminiogarcia/shexml/CommentTest.scala | 15 +- .../ConditionalGenerationPredicateTest.scala | 14 +- ...lGenerationPredicateTestHierarchical.scala | 14 +- ...nalGenerationSubjectTestHierarchical.scala | 14 +- .../shexml/ConditionalGenerationTest.scala | 14 +- .../shexml/DeepHierarchyJSONTest.scala | 15 +- ...NWithUnorderedFieldsAndIteratorsTest.scala | 15 +- .../shexml/DeepHierarchyXMLTest.scala | 15 +- .../shexml/ExternalAndBuiltinFunctions.scala | 14 +- .../shexml/ExternalFunctionsTest.scala | 14 +- .../ExternalFunctionsWithDashedVarsTest.scala | 14 +- .../com/herminiogarcia/shexml/FilmsAlt.scala | 14 +- .../shexml/FilmsExternalQueryMySQLTest.scala | 14 +- .../shexml/FilmsMySQLTest.scala | 15 +- .../shexml/FilmsPostgresTest.scala | 15 +- .../shexml/FilmsRelativePathTest.scala | 14 +- .../shexml/FilmsSparqlFileTest.scala | 14 +- .../shexml/FilmsSparqlTest.scala | 14 +- .../FilmsTestIteratorsWithMissingValues.scala | 14 +- .../shexml/FilmsWithNullsTest.scala | 15 +- ...ultipleElementIteratorExpressionTest.scala | 19 +- .../shexml/JsonAndXmlEventsMapping.scala | 15 +- ...ndXmlEventsMappingIteratorExpression.scala | 15 +- .../JsonAndXmlEventsMappingWithBNode.scala | 15 +- ...onAndXmlEventsMappingWithBlankPrefix.scala | 14 +- ...ingWithBlankPrefixIteratorExpression.scala | 14 +- ...AndXmlEventsMappingWithExternalQuery.scala | 15 +- .../JsonAndXmlEventsMappingWithJoin.scala | 14 +- ...ntsMappingWithJoinIteratorExpression.scala | 14 +- .../MatcherIteratorExpressionTest.scala | 15 +- .../herminiogarcia/shexml/MatcherTest.scala | 15 +- ...ultipleElementIteratorExpressionTest.scala | 14 +- ...sionWithAutoIncrementWithStringsTest.scala | 14 +- ...ntIteratorExpressionWithCSVAndDBTest.scala | 14 +- ...ElementIteratorExpressionWithCSVTest.scala | 14 +- .../shexml/MultipleElementTest.scala | 14 +- .../shexml/ParallelConfigFixtures.scala | 75 ++++++ .../shexml/ParallelConfigurations.scala | 44 ++++ .../shexml/PrecompilationTest.scala | 3 +- .../PrecompilationWithParserErrorTest.scala | 3 +- .../PushedValueWithMultipleEntities.scala | 15 +- ...oNestedIteratorWithoutFieldInBetween.scala | 14 +- .../collectionsandcontainers/RDFAltTest.scala | 18 +- .../collectionsandcontainers/RDFBagTest.scala | 18 +- .../RDFListTest.scala | 18 +- .../collectionsandcontainers/RDFSeqTest.scala | 18 +- .../datatype/DataTypeGenerationFullURI.scala | 17 +- .../DataTypeGenerationWithoutPrefix.scala | 17 +- ...eftWithReviewsBadConditionOnNameTest.scala | 17 +- ...sJoinLeftWithReviewsBadConditionTest.scala | 17 +- ...lmsJoinLeftWithReviewsJoinOnNameTest.scala | 17 +- .../joins/FilmsJoinLeftWithReviewsTest.scala | 17 +- ...ghtWithReviewsBadConditionOnNameTest.scala | 17 +- ...JoinRightWithReviewsBadConditionTest.scala | 17 +- ...msJoinRightWithReviewsJoinOnNameTest.scala | 17 +- .../joins/FilmsJoinRightWithReviewsTest.scala | 17 +- .../AccessFieldsOutsideIterators.scala | 17 +- ...DataTypeAndLangTagGenerationFromData.scala | 17 +- .../mappingChallenges/JoinChallenge.scala | 17 +- ...MultiValueReferencesHierarchicalFile.scala | 17 +- .../rml/CommentIteratorExpressionTest.scala | 19 +- .../shexml/rml/CommentTest.scala | 19 +- ...DataTypeAndLangTagGenerationFromData.scala | 19 +- .../shexml/rml/FilmWithActorsTest.scala | 19 +- .../rml/FilmsExternalQueryMySQLTest.scala | 18 +- .../shexml/rml/FilmsMySQLTest.scala | 19 +- .../shexml/rml/FilmsPostgresTest.scala | 19 +- ...ultipleElementIteratorExpressionTest.scala | 23 +- .../shexml/rml/JsonAndXmlEventsMapping.scala | 19 +- ...ndXmlEventsMappingIteratorExpression.scala | 19 +- .../JsonAndXmlEventsMappingWithBNode.scala | 19 +- ...onAndXmlEventsMappingWithBlankPrefix.scala | 18 +- ...ingWithBlankPrefixIteratorExpression.scala | 18 +- ...AndXmlEventsMappingWithExternalQuery.scala | 19 +- .../rml/JsonAndXmlEventsMappingWithJoin.scala | 19 +- ...ntsMappingWithJoinIteratorExpression.scala | 18 +- ...mentIteratorExpressionPrettifiedTest.scala | 18 +- ...ultipleElementIteratorExpressionTest.scala | 18 +- ...ElementIteratorExpressionWithCSVTest.scala | 18 +- .../shexml/rml/MultipleElementTest.scala | 18 +- .../CommentIteratorExpressionTest.scala | 19 +- .../shexml/rmlPrettyPrint/CommentTest.scala | 19 +- ...DataTypeAndLangTagGenerationFromData.scala | 19 +- .../rmlPrettyPrint/FilmWithActorsTest.scala | 19 +- .../FilmsExternalQueryMySQLTest.scala | 19 +- .../rmlPrettyPrint/FilmsMySQLTest.scala | 19 +- .../rmlPrettyPrint/FilmsPostgresTest.scala | 19 +- ...ultipleElementIteratorExpressionTest.scala | 23 +- .../JsonAndXmlEventsMapping.scala | 19 +- ...ndXmlEventsMappingIteratorExpression.scala | 19 +- .../JsonAndXmlEventsMappingWithBNode.scala | 19 +- ...onAndXmlEventsMappingWithBlankPrefix.scala | 19 +- ...ingWithBlankPrefixIteratorExpression.scala | 19 +- ...AndXmlEventsMappingWithExternalQuery.scala | 19 +- .../JsonAndXmlEventsMappingWithJoin.scala | 19 +- ...ntsMappingWithJoinIteratorExpression.scala | 19 +- ...mentIteratorExpressionPrettifiedTest.scala | 19 +- ...ultipleElementIteratorExpressionTest.scala | 19 +- ...ElementIteratorExpressionWithCSVTest.scala | 19 +- .../rmlPrettyPrint/MultipleElementTest.scala | 19 +- .../shexml/shacl/FilmsTest.scala | 8 +- .../shacl/FilmsTestWithBlankNodes.scala | 7 +- .../shacl/JsonAndXmlEventsMapping.scala | 8 +- ...ntIteratorExpressionWithCSVAndDBTest.scala | 8 +- .../shexml/shacl/SHACLValidation.scala | 5 +- ...lmsWithInferredShapeMapAndBNodesTest.scala | 6 +- .../shex/FilmsWithInferredShapeMapTest.scala | 6 +- .../shexml/shex/JsonAndXmlEventsMapping.scala | 5 +- ...sionWithCSVAndDBInferredShapeMapTest.scala | 6 +- ...ntIteratorExpressionWithCSVAndDBTest.scala | 5 +- .../shexml/shex/ShExValidation.scala | 5 +- 125 files changed, 1701 insertions(+), 562 deletions(-) create mode 100644 src/main/scala-2.12/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala create mode 100644 src/main/scala-2.13/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala create mode 100644 src/main/scala-3/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala create mode 100644 src/test/scala/com/herminiogarcia/shexml/ParallelConfigFixtures.scala create mode 100644 src/test/scala/com/herminiogarcia/shexml/ParallelConfigurations.scala diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml index 51ea0a7..f17e70c 100644 --- a/.github/workflows/scala.yml +++ b/.github/workflows/scala.yml @@ -12,10 +12,16 @@ jobs: - name: Set up JDK 8 uses: actions/setup-java@v4 with: - java-version: '8' + java-version: '17' distribution: 'adopt' - uses: sbt/setup-sbt@v1 - name: Build the docker compose stack run: docker compose up -d - name: Run tests run: sbt --mem 2048 "+ test" + - name: Run tests parallel all + run: sbt --mem 2048 "+ testOnly * -- -Dparallel=all" + - name: Run tests parallel shapes + run: sbt --mem 2048 "+ testOnly * -- -Dparallel=shapes" + - name: Run tests parallel queries + run: sbt --mem 2048 "+ testOnly * -- -Dparallel=queries" diff --git a/build.sbt b/build.sbt index c0b0a0a..31829d2 100644 --- a/build.sbt +++ b/build.sbt @@ -38,6 +38,9 @@ lazy val shexml = project CrossVersion.partialVersion(scalaVersion.value) match { case Some((3, _)) => "org.scala-lang" % "scala-compiler" % "2.13.9" case Some((2, n)) if n >= 12 => "org.scala-lang" % "scala-compiler" % scalaVersion.value + }) ++ (CrossVersion.partialVersion(scalaVersion.value) match { + case Some((m, n)) if m >= 3 || m >= 2 && n >= 13 => Seq("org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.4") + case _ => Nil }), assembly / assemblyMergeStrategy := { case PathList("META-INF", "services", xs @ _*) => MergeStrategy.concat diff --git a/src/main/scala-2.12/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala b/src/main/scala-2.12/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala new file mode 100644 index 0000000..189a03d --- /dev/null +++ b/src/main/scala-2.12/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala @@ -0,0 +1,35 @@ +package com.herminiogarcia.shexml.helper + +import scala.collection.parallel.{ForkJoinTaskSupport, ParSeq} +import scala.util.Try + +class ParallelExecutionConfigurator(val parallelisationAspectsOptions: Map[String, Boolean], val numberOfThreads: Option[Int]) { + + def asParallelCollection[T](aspect: String, collection: Seq[T]): Either[Seq[T], ParSeq[T]] = { + if(!parallelisationAspectsOptions.getOrElse(aspect, false)) Left(collection) + else numberOfThreads match { + case Some(number) => + collection.par + val parallelCollection = collection.par + parallelCollection.tasksupport = new ForkJoinTaskSupport(new java.util.concurrent.ForkJoinPool(number)) + Right(parallelCollection) + case None => Right(collection.par) + } + } +} + +object ParallelExecutionConfigurator { + + def apply(parallelAspects: String, numberOfThreads: String): ParallelExecutionConfigurator = { + val parallelAspectsOptions = + if(parallelAspects.toLowerCase == "queries") Map[String, Boolean]("queries" -> true) + else if(parallelAspects.toLowerCase == "shapes") Map[String, Boolean]("shapes" -> true) + else Map[String, Boolean]("shapes" -> true, "queries" -> true) + new ParallelExecutionConfigurator( + parallelAspectsOptions, + Try(numberOfThreads.toInt).filter(_ > 0).toOption + ) + } + + def empty = new ParallelExecutionConfigurator(Map(), None) +} \ No newline at end of file diff --git a/src/main/scala-2.13/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala b/src/main/scala-2.13/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala new file mode 100644 index 0000000..8184dde --- /dev/null +++ b/src/main/scala-2.13/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala @@ -0,0 +1,35 @@ +package com.herminiogarcia.shexml.helper + +import scala.collection.parallel.CollectionConverters._ +import scala.collection.parallel.{ForkJoinTaskSupport, ParSeq} + +class ParallelExecutionConfigurator(val parallelisationAspectsOptions: Map[String, Boolean], val numberOfThreads: Option[Int]) { + + def asParallelCollection[T](aspect: String, collection: Seq[T]): Either[Seq[T], ParSeq[T]] = { + if(!parallelisationAspectsOptions.getOrElse(aspect, false)) Left(collection) + else numberOfThreads match { + case Some(number) => + collection.par + val parallelCollection = collection.par + parallelCollection.tasksupport = new ForkJoinTaskSupport(new java.util.concurrent.ForkJoinPool(number)) + Right(parallelCollection) + case None => Right(collection.par) + } + } +} + +object ParallelExecutionConfigurator { + + def apply(parallelAspects: String, numberOfThreads: String): ParallelExecutionConfigurator = { + val parallelAspectsOptions = + if(parallelAspects.toLowerCase == "queries") Map[String, Boolean]("queries" -> true) + else if(parallelAspects.toLowerCase == "shapes") Map[String, Boolean]("shapes" -> true) + else Map[String, Boolean]("shapes" -> true, "queries" -> true) + new ParallelExecutionConfigurator( + parallelAspectsOptions, + numberOfThreads.toIntOption.filter(_ > 0) + ) + } + + def empty = new ParallelExecutionConfigurator(Map(), None) +} \ No newline at end of file diff --git a/src/main/scala-3/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala b/src/main/scala-3/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala new file mode 100644 index 0000000..8184dde --- /dev/null +++ b/src/main/scala-3/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala @@ -0,0 +1,35 @@ +package com.herminiogarcia.shexml.helper + +import scala.collection.parallel.CollectionConverters._ +import scala.collection.parallel.{ForkJoinTaskSupport, ParSeq} + +class ParallelExecutionConfigurator(val parallelisationAspectsOptions: Map[String, Boolean], val numberOfThreads: Option[Int]) { + + def asParallelCollection[T](aspect: String, collection: Seq[T]): Either[Seq[T], ParSeq[T]] = { + if(!parallelisationAspectsOptions.getOrElse(aspect, false)) Left(collection) + else numberOfThreads match { + case Some(number) => + collection.par + val parallelCollection = collection.par + parallelCollection.tasksupport = new ForkJoinTaskSupport(new java.util.concurrent.ForkJoinPool(number)) + Right(parallelCollection) + case None => Right(collection.par) + } + } +} + +object ParallelExecutionConfigurator { + + def apply(parallelAspects: String, numberOfThreads: String): ParallelExecutionConfigurator = { + val parallelAspectsOptions = + if(parallelAspects.toLowerCase == "queries") Map[String, Boolean]("queries" -> true) + else if(parallelAspects.toLowerCase == "shapes") Map[String, Boolean]("shapes" -> true) + else Map[String, Boolean]("shapes" -> true, "queries" -> true) + new ParallelExecutionConfigurator( + parallelAspectsOptions, + numberOfThreads.toIntOption.filter(_ > 0) + ) + } + + def empty = new ParallelExecutionConfigurator(Map(), None) +} \ No newline at end of file diff --git a/src/main/scala/com/herminiogarcia/shexml/Main.scala b/src/main/scala/com/herminiogarcia/shexml/Main.scala index fc93f73..2bf3710 100644 --- a/src/main/scala/com/herminiogarcia/shexml/Main.scala +++ b/src/main/scala/com/herminiogarcia/shexml/Main.scala @@ -1,6 +1,6 @@ package com.herminiogarcia.shexml -import com.herminiogarcia.shexml.helper.PicocliLeftAlignedLayout +import com.herminiogarcia.shexml.helper.{ParallelExecutionConfigurator, PicocliLeftAlignedLayout} import picocli.CommandLine import picocli.CommandLine.{ArgGroup, Command, Option} @@ -40,9 +40,19 @@ class Main extends Callable[Int] { override def call(): Int = { val fileHandler = scala.io.Source.fromFile(file) + val parallelExecutionConfiguration = + if(generalTransformationOptions.parallel) ParallelExecutionConfigurator(generalTransformationOptions.parallelAspects, generalTransformationOptions.numberOfThreads) + else ParallelExecutionConfigurator.empty try { val fileContent = fileHandler.mkString - val mappingLauncher = new MappingLauncher(generalTransformationOptions.username, generalTransformationOptions.password, generalTransformationOptions.drivers, transformationModifiers.inferenceDatatype, transformationModifiers.normaliseURIs) + val mappingLauncher = new MappingLauncher( + generalTransformationOptions.username, + generalTransformationOptions.password, + generalTransformationOptions.drivers, + transformationModifiers.inferenceDatatype, + transformationModifiers.normaliseURIs, + parallelExecutionConfiguration + ) val outputContent = if(otherTransformations.rmlOutput) { mappingLauncher.launchRMLTranslation(fileContent) } else if(otherTransformations.rmlPrettifyOutput) { @@ -116,4 +126,13 @@ class GeneralTransformationOptions { @Option(names = Array("-d", "--drivers"), description = Array("Add more JDBC database drivers in the form of %% and separating them with \";\". Example: jdbc:postgresql%%org.postgresql.Driver;jdbc:oracle%%oracle.jdbc.OracleDriver")) var drivers: String = "" + + @Option(names = Array("--parallel"), description = Array("EXPERIMENTAL: Enables the execution of the engine in concurrent mode")) + var parallel: Boolean = false + + @Option(names = Array("--parallelAspects"), description = Array("EXPERIMENTAL: Allows to select the aspects that will be parallelised. The possible options are: \"queries\", \"shapes\", or \"all\".")) + var parallelAspects: String = "all" + + @Option(names = Array("--nThreads"), description = Array("EXPERIMENTAL: The number of threads to use in the parallelisation. Default to the number of virtual threads of the processor.")) + var numberOfThreads: String = "" } diff --git a/src/main/scala/com/herminiogarcia/shexml/MappingLauncher.scala b/src/main/scala/com/herminiogarcia/shexml/MappingLauncher.scala index d451d9d..96a8e7c 100644 --- a/src/main/scala/com/herminiogarcia/shexml/MappingLauncher.scala +++ b/src/main/scala/com/herminiogarcia/shexml/MappingLauncher.scala @@ -2,7 +2,7 @@ package com.herminiogarcia.shexml import com.herminiogarcia.shexml.antlr.{ShExMLLexer, ShExMLParser} import com.herminiogarcia.shexml.ast._ -import com.herminiogarcia.shexml.helper.{OrphanBNodeRemover, SourceHelper} +import com.herminiogarcia.shexml.helper.{OrphanBNodeRemover, ParallelExecutionConfigurator, SourceHelper} import com.herminiogarcia.shexml.parser.ASTCreatorVisitor import com.herminiogarcia.shexml.shex._ import com.herminiogarcia.shexml.visitor.{PushedOrPoppedValueSearchVisitor, RDFGeneratorVisitor, RMLGeneratorVisitor, VarTableBuilderVisitor} @@ -11,7 +11,9 @@ import org.apache.jena.query.{Dataset, DatasetFactory} import org.apache.jena.riot.{RDFDataMgr, RDFFormat, RDFLanguages} import com.typesafe.scalalogging.Logger +import scala.collection.JavaConverters._ import java.io.ByteArrayOutputStream +import java.util.concurrent.ConcurrentLinkedQueue import scala.collection.mutable /** @@ -19,7 +21,8 @@ import scala.collection.mutable */ class MappingLauncher(val username: String = "", val password: String = "", drivers: String = "", val inferenceDatatype: Boolean = false, - val normaliseURIs: Boolean = false) { + val normaliseURIs: Boolean = false, + val parallelCollectionConfigurator: ParallelExecutionConfigurator = new ParallelExecutionConfigurator(Map(), None)) { private val logger = Logger[MappingLauncher] @@ -69,9 +72,9 @@ class MappingLauncher(val username: String = "", val password: String = "", driv val parser = createParser(lexer) val ast = createAST(parser) val varTable = createVarTable(ast) - val inferencesTable = mutable.ListBuffer.empty[ShExMLInferredCardinalitiesAndDatatypes] + val inferencesTable = new ConcurrentLinkedQueue[ShExMLInferredCardinalitiesAndDatatypes]() generateInferencesFromShExML(ast, varTable, inferencesTable) - val shex = new ShExGeneratorVisitor(inferencesTable.toList).doVisit(ast, null) + val shex = new ShExGeneratorVisitor(inferencesTable.asScala.toList).doVisit(ast, null) new ShExPrinter().print(shex) } @@ -93,10 +96,10 @@ class MappingLauncher(val username: String = "", val password: String = "", driv val parser = createParser(lexer) val ast = createAST(parser) val varTable = createVarTable(ast) - val inferencesTable = mutable.ListBuffer.empty[ShExMLInferredCardinalitiesAndDatatypes] + val inferencesTable = new ConcurrentLinkedQueue[ShExMLInferredCardinalitiesAndDatatypes]() generateInferencesFromShExML(ast, varTable, inferencesTable) logger.info(s"Executing ShEx extraction process as base for the SHACL conversion") - val shex = new ShExGeneratorVisitor(inferencesTable.toList).doVisit(ast, null) + val shex = new ShExGeneratorVisitor(inferencesTable.asScala.toList).doVisit(ast, null) val dataset = DatasetFactory.create() new SHACLGenerator(dataset, closed).generate(shex) val outputStream = new ByteArrayOutputStream() @@ -152,10 +155,11 @@ class MappingLauncher(val username: String = "", val password: String = "", driv val dataset = DatasetFactory.create() val pushedOrPoppedFields = searchForPushedOrPoppedFields(ast) - new RDFGeneratorVisitor(dataset, varTable, username, password, generateDriversMap(), + new RDFGeneratorVisitor(dataset, varTable.toMap, username, password, generateDriversMap(), pushedOrPoppedFieldsPresent = pushedOrPoppedFields, inferenceDatatype = inferenceDatatype, - normaliseURIs = normaliseURIs).doVisit(ast, null) + normaliseURIs = normaliseURIs, + parallelCollectionConfigurator = parallelCollectionConfigurator).doVisit(ast, null) //val in = new ByteArrayInputStream(output.toString().getBytes) //val model = ModelFactory.createDefaultModel() //model.read(in, null, "TURTLE") @@ -164,31 +168,32 @@ class MappingLauncher(val username: String = "", val password: String = "", driv private def generateResultingRML(ast: AST, varTable: mutable.HashMap[Variable, VarResult], prettify: Boolean): Dataset = { val output = DatasetFactory.create() - new RMLGeneratorVisitor(output, varTable, prettify, username, password).doVisit(ast, null) + new RMLGeneratorVisitor(output, varTable.toMap, prettify, username, password).doVisit(ast, null) output } private def generateInferencesFromShExML(ast: AST, varTable: mutable.HashMap[Variable, VarResult], - inferences: mutable.ListBuffer[ShExMLInferredCardinalitiesAndDatatypes]): Unit = { + inferences: ConcurrentLinkedQueue[ShExMLInferredCardinalitiesAndDatatypes]): Unit = { logger.info("Executing RDF Generator to get more accurate inferences") val dataset = DatasetFactory.create() - new RDFGeneratorVisitor(dataset, varTable, username, password, generateDriversMap(), inferences, + new RDFGeneratorVisitor(dataset, varTable.toMap, username, password, generateDriversMap(), Some(inferences), pushedOrPoppedFieldsPresent = searchForPushedOrPoppedFields(ast), - registerDatatypesAndCardinalities = true, inferenceDatatype = inferenceDatatype, - normaliseURIs = normaliseURIs).doVisit(ast, null) + normaliseURIs = normaliseURIs, + parallelCollectionConfigurator = parallelCollectionConfigurator).doVisit(ast, null) } private def generateShapeMaps(ast: AST, varTable: mutable.HashMap[Variable, VarResult]): List[ShapeMapInference] = { - val shapeMapTable = mutable.ListBuffer.empty[ShapeMapInference] - val inferences = mutable.ListBuffer.empty[ShExMLInferredCardinalitiesAndDatatypes] + val shapeMapTable = new ConcurrentLinkedQueue[ShapeMapInference]() + val inferences = new ConcurrentLinkedQueue[ShExMLInferredCardinalitiesAndDatatypes]() val dataset = DatasetFactory.create() logger.info("Executing RDF Generator to get more accurate inferences") - new RDFGeneratorVisitor(dataset, varTable, username, password, generateDriversMap(), inferences, shapeMapTable, + new RDFGeneratorVisitor(dataset, varTable.toMap, username, password, generateDriversMap(), Some(inferences), Some(shapeMapTable), pushedOrPoppedFieldsPresent = searchForPushedOrPoppedFields(ast), inferenceDatatype = inferenceDatatype, - normaliseURIs = normaliseURIs).doVisit(ast, null) - shapeMapTable.result() + normaliseURIs = normaliseURIs, + parallelCollectionConfigurator = parallelCollectionConfigurator).doVisit(ast, null) + shapeMapTable.asScala.toList } private def generateDriversMap(): Map[String, String] = { diff --git a/src/main/scala/com/herminiogarcia/shexml/visitor/QuerySearcher.scala b/src/main/scala/com/herminiogarcia/shexml/visitor/QuerySearcher.scala index 40516ec..d05ef76 100644 --- a/src/main/scala/com/herminiogarcia/shexml/visitor/QuerySearcher.scala +++ b/src/main/scala/com/herminiogarcia/shexml/visitor/QuerySearcher.scala @@ -3,9 +3,8 @@ package com.herminiogarcia.shexml.visitor import com.herminiogarcia.shexml.ast._ import com.herminiogarcia.shexml.helper.SourceHelper -import scala.collection.mutable -class QuerySearcher(val varTable: mutable.HashMap[Variable, VarResult]) { +class QuerySearcher(val varTable: Map[Variable, VarResult]) { def getQueryFromVarTable(variable: Var): QueryClause = { varTable.get(variable) match { diff --git a/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala b/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala index 965a345..d980997 100644 --- a/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala +++ b/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala @@ -1,9 +1,8 @@ package com.herminiogarcia.shexml.visitor -import com.fasterxml.jackson.databind.{JsonNode, ObjectMapper} import com.github.tototoshi.csv.{CSVReader, DefaultCSVFormat} import com.herminiogarcia.shexml.ast.{AST, Action, ActionOrLiteral, AutoIncrement, BuiltinFunction, CSVPerRow, DataTypeGeneration, DataTypeLiteral, Declaration, Exp, FieldQuery, FilePath, FunctionCalling, Graph, Index, IteratorQuery, JdbcURL, Join, JsonPath, LangTagGeneration, LangTagLiteral, LiteralObject, LiteralObjectValue, LiteralSubject, Matcher, Matchers, ObjectElement, Predicate, PredicateObject, Prefix, QueryClause, RDFAlt, RDFBag, RDFCollection, RDFList, RDFSeq, RelativePath, ShExML, Shape, ShapeLink, ShapeVar, Sparql, SparqlColumn, Sql, SqlColumn, StringOperation, Substitution, URL, Union, Var, VarResult, Variable, XmlPath} -import com.herminiogarcia.shexml.helper.{FunctionHubExecutor, LoadedSource, SourceHelper} +import com.herminiogarcia.shexml.helper.{FunctionHubExecutor, LoadedSource, ParallelExecutionConfigurator, SourceHelper} import com.herminiogarcia.shexml.shex.{Node, ShExMLInferredCardinalitiesAndDatatypes, ShapeMapInference, ShapeMapShape} import com.herminiogarcia.shexml.visitor import com.jayway.jsonpath.{Configuration, DocumentContext} @@ -12,37 +11,38 @@ import net.sf.saxon.s9api.{Processor, XdmNode} import net.minidev.json.JSONArray import org.apache.jena.datatypes.xsd.XSDDatatype import org.apache.jena.datatypes.{RDFDatatype, TypeMapper} -import org.apache.jena.query.{Dataset, QueryExecutionFactory, QueryFactory, ResultSet} +import org.apache.jena.query.{Dataset, QueryExecutionFactory, QueryFactory, ReadWrite, ResultSet, TxnType} import org.apache.jena.rdf.model._ import org.apache.jena.riot.RDFDataMgr import org.apache.jena.util.SplitIRI +import scala.collection.concurrent import java.io.{File, StringReader} import java.sql.DriverManager +import java.util.concurrent.ConcurrentLinkedQueue import javax.xml.transform.stream.StreamSource -import scala.collection.JavaConverters._ -import scala.collection.mutable import scala.collection.immutable.HashSet import scala.util.Try +import scala.collection.JavaConverters._ /** * Created by herminio on 26/12/17. */ -class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, VarResult], username: String, password: String, +class RDFGeneratorVisitor(dataset: Dataset, varTable: Map[Variable, VarResult], username: String, password: String, driversMap: Map[String, String] = Map[String, String](), - shexInferredPropertiesTable: mutable.ListBuffer[ShExMLInferredCardinalitiesAndDatatypes] = mutable.ListBuffer.empty[ShExMLInferredCardinalitiesAndDatatypes], - shapeMapTable: mutable.ListBuffer[ShapeMapInference] = mutable.ListBuffer.empty[ShapeMapInference], + shexInferredPropertiesTable: Option[ConcurrentLinkedQueue[ShExMLInferredCardinalitiesAndDatatypes]] = None, + shapeMapTable: Option[ConcurrentLinkedQueue[ShapeMapInference]] = None, pushedOrPoppedFieldsPresent: Boolean = true, - registerDatatypesAndCardinalities: Boolean = false, inferenceDatatype: Boolean = false, - normaliseURIs: Boolean = false) + normaliseURIs: Boolean = false, + parallelCollectionConfigurator: ParallelExecutionConfigurator = new ParallelExecutionConfigurator(Map(), None)) extends DefaultVisitor[Any, Any] with JdbcDriverRegistry { - protected val prefixTable = mutable.HashMap[String, String](("rdf:", "http://www.w3.org/1999/02/22-rdf-syntax-ns#")) - protected val iteratorsCombinations = mutable.HashMap[String, List[Result]]() - protected val pushedQueries = mutable.HashMap[String, QueryClause]() + protected val prefixTable = concurrent.TrieMap[String, String](("rdf:", "http://www.w3.org/1999/02/22-rdf-syntax-ns#")) + protected val iteratorsCombinations = concurrent.TrieMap[String, List[Result]]() + protected val pushedQueries = concurrent.TrieMap[String, QueryClause]() protected val queryResultCache = new QueryResultsCache() - protected val alreadyGeneratedCollections = mutable.ListBuffer[String]() + protected val alreadyGeneratedCollections = new ConcurrentLinkedQueue[String]() protected val iteratorQueryResultsCache = new IteratorQueryResultsCache(pushedOrPoppedFieldsPresent) protected val jsonpathQueryResultsCache = new JsonPathQueryResultsCache(pushedOrPoppedFieldsPresent) protected val jsonObjectMapperCache = new JsonObjectMapperCache() @@ -51,6 +51,7 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, protected val functionHubExecuterCache = new FunctionHubExecutorCache() protected val defaultModel = dataset.getDefaultModel + private val xmlProcessor = new Processor(false) private val logger = Logger[RDFGeneratorVisitor] @@ -64,7 +65,16 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, case ShapeLink(shapeVar) => List(shapeVar) case _ => List() })) - val firstShape = shapes.filterNot(s => linkedShapes.contains(s.shapeName)).map(doVisit(_, optionalArgument)).headOption + val filteredShapes = shapes.filterNot(s => linkedShapes.contains(s.shapeName)) + val shapesHead = filteredShapes.headOption + val shapesTail = filteredShapes.tail + val firstShape = shapesHead.map(doVisit(_, optionalArgument)) + parallelCollectionConfigurator + .asParallelCollection("shapes", shapesTail) + .fold( + l => l.map(doVisit(_, optionalArgument)), + r => r.map(doVisit(_, optionalArgument)) + ) val numberOfTriples = (graphs.map(g => prefixTable.getOrElse(g.graphName.prefix, "") + g.graphName.name).map(dataset.getNamedModel(_)) :+ defaultModel).map(_.size()).sum @@ -84,7 +94,15 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, case Graph(graphName, shapes) => { logger.info(s"Generating ${shapes.size} shapes within $graphName graph") - shapes.map(doVisit(_, optionalArgument)) + val shapesHead = shapes.headOption + val shapesTail = shapes.tail + shapesHead.map(doVisit(_, optionalArgument)) + parallelCollectionConfigurator + .asParallelCollection("shapes", shapesTail) + .fold( + l => l.map(doVisit(_, optionalArgument)), + r => r.map(doVisit(_, optionalArgument)) + ) } case Shape(shapeName, action, predicateObjects, holdingGraph) => { @@ -92,7 +110,7 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, val shapePrefix = getShapePrefix(action) val graphName = holdingGraph.map(g => prefixTable.getOrElse(g.graphName.prefix, "") + g.graphName.name).getOrElse("") val output = if(holdingGraph.isEmpty) defaultModel else dataset.getNamedModel(graphName) - val predicateObjectsList = predicateObjects.map(doVisit(_, optionalArgument)) + val predicateObjectsList = predicateObjects.map(doVisit(_, optionalArgument)).toList logger.info(s"Expanded ${predicateObjects.size} predicate-object statements in ${predicateObjectsList.collect { case r: List[Result] => r.size }.sum} results") val actions = visitAction(action, predicateObjectsList, optionalArgument) val predicateObjectsWithAutoIncrements = solveAutoIncrementResults(predicateObjectsList, actions) @@ -127,8 +145,8 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, val groupedPredicateObjects = predicateObjectsList.groupBy(i => i(0)) val keys = groupedPredicateObjects.keys for (key <- keys) { - if(!alreadyGeneratedCollections.contains(key + groupedPredicateObjects(key).map(_(1)).mkString(""))) { - alreadyGeneratedCollections += key + groupedPredicateObjects(key).map(_(1)).mkString("") + if (!alreadyGeneratedCollections.contains(key + groupedPredicateObjects(key).map(_(1)).mkString(""))) { + alreadyGeneratedCollections.add(key + groupedPredicateObjects(key).map(_(1)).mkString("")) registerCardinalityAndDatatype(shapeName.name, groupedPredicateObjects(key).head, result) createTripleWithCollection(shapePrefix, action, groupedPredicateObjects(key).toList, result, output, rdfCollection) } @@ -150,7 +168,7 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, ShapeMapShape(":", splittedShapeName(1)) val node = Node(shapePrefix, normaliseURI(r)) val shapeMap = ShapeMapInference(node, shapeMapShape) - if(shapePrefix != "_:") shapeMapTable += shapeMap + if(shapePrefix != "_:") shapeMapTable.map(_.add(shapeMap)) }) }) finalActions.map(r => Result(r.id, r.rootIds, r.results.map(ir => { @@ -356,7 +374,7 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, case None => iteratorsCombinations += s"$expName$k" -> v } } - iteratorQueryResultsCache.save(iteratorQueryStringRepresentation, file.asInstanceOf[LoadedSource], values) + iteratorQueryResultsCache.save(iteratorQueryStringRepresentation, file.asInstanceOf[LoadedSource], values.toList.toMap) values } } @@ -819,13 +837,15 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, case _ => { val iteratorQueries = doIteratorQueries(iteratorVars.slice(0, iteratorVars.size - 1), "", List(""), middleArguments, null) val queries = iteratorResultsToQueries(iteratorQueries.filter(_.results.nonEmpty), query, HashSet(), fileContentOrURL) - queries.map(q => { - doVisit(q.query, middleArguments.+( - "index" -> q.index, "rootIds" -> q.rootIds, "iteratorQuery" -> q.iteratorQuery)) - .asInstanceOf[Result] - .addResultContext(ResultContext(q.index, q.query, q.iteratorQuery)) - }) - .filter(_.results.nonEmpty) + val transformationFunction: QueryWithIndex => Result = q => + doVisit(q.query, middleArguments.+( + "index" -> q.index, "rootIds" -> q.rootIds, "iteratorQuery" -> q.iteratorQuery)) + .asInstanceOf[Result] + .addResultContext(ResultContext(q.index, q.query, q.iteratorQuery)) + parallelCollectionConfigurator.asParallelCollection("queries", queries).fold( + l => l.map(transformationFunction).filter(_.results.nonEmpty).toList, + r => r.map(transformationFunction).filter(_.results.nonEmpty).toList + ) } } } @@ -1022,7 +1042,7 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, private def getMaxOccurrencesPredicateObjectList(list: List[Any]) = { - val mostCommonSize = mutable.HashMap[Int, Int]() + val mostCommonSize = concurrent.TrieMap[Int, Int]() list.filter(_ != Nil).foreach { case lr: List[Result] if lr.nonEmpty => mostCommonSize += ((lr.size, mostCommonSize.getOrElse(lr.size, 0) + 1)) case ra: ResultAutoIncrement if ra.results.nonEmpty => @@ -1041,7 +1061,7 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, } private def registerCardinalityAndDatatype(shapeName: String, predicateObject: Array[String], result: Result) = { - if(registerDatatypesAndCardinalities) { + if(shexInferredPropertiesTable.isDefined) { val datatype = result.dataType match { case Some(value) => Some(value) case None => { @@ -1052,68 +1072,80 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, None } } - shexInferredPropertiesTable += ShExMLInferredCardinalitiesAndDatatypes(shapeName, predicateObject(0), result.results.size, datatype) + shexInferredPropertiesTable.map(_.add(ShExMLInferredCardinalitiesAndDatatypes(shapeName, predicateObject(0), result.results.size, datatype))) } } private def createTriple(shapePrefix: String, action: String, predicateObject: Array[String], result: Result, output: Model): Unit = { - if(shapePrefix == "_:") { - if (predicateObject(1).startsWith("http://") || predicateObject(1).startsWith("https://") || predicateObject(1).contains("_:")) - output.add(createBNodeStatement(action, predicateObject(0), normaliseURI(predicateObject(1)))) - else - output.add(createBNodeStatementWithLiteral( - action, predicateObject(0), predicateObject(1), result.dataType, result.langTag)) - } else { - if (predicateObject(1).startsWith("http://") || predicateObject(1).startsWith("https://") || predicateObject(1).startsWith("_:")) - output.add(createStatement(prefixTable(shapePrefix) + action, predicateObject(0), normaliseURI(predicateObject(1)))) - else - output.add(createStatementWithLiteral( - prefixTable(shapePrefix) + action, predicateObject(0), predicateObject(1), result.dataType, result.langTag)) + dataset.begin(TxnType.WRITE) + try { + if(shapePrefix == "_:") { + if (predicateObject(1).startsWith("http://") || predicateObject(1).startsWith("https://") || predicateObject(1).contains("_:")) + output.add(createBNodeStatement(action, predicateObject(0), normaliseURI(predicateObject(1)))) + else + output.add(createBNodeStatementWithLiteral( + action, predicateObject(0), predicateObject(1), result.dataType, result.langTag)) + } else { + if (predicateObject(1).startsWith("http://") || predicateObject(1).startsWith("https://") || predicateObject(1).startsWith("_:")) + output.add(createStatement(prefixTable(shapePrefix) + action, predicateObject(0), normaliseURI(predicateObject(1)))) + else + output.add(createStatementWithLiteral( + prefixTable(shapePrefix) + action, predicateObject(0), predicateObject(1), result.dataType, result.langTag)) + } + dataset.commit() + } finally { + dataset.end() } } private def createTripleWithCollection(shapePrefix: String, action: String, predicateObjects: List[Array[String]], result: Result, output: Model, rdfCollection: RDFCollection): Unit = { - val predicateObject = predicateObjects.head - if(shapePrefix == "_:") { - if (predicateObject(1).startsWith("http://") || predicateObject(1).startsWith("https://") || predicateObject(1).startsWith("_:")) { - val values = predicateObjects.map(i => output.createResource(normaliseURI(i(1)))) - val collection = collectionConstructor(output, values.toIterator, rdfCollection) - output.add(createBNodeStatementWithCollection(action, predicateObject(0), collection)) - } - else { - val values = predicateObjects.map(i => { - if(result.langTag.isDefined) output.createLiteral(i(1), result.langTag.get) - else if(result.dataType.isDefined) { - val xsdType = result.dataType.map(d => prefixTable(d.split(":")(0) + ":") + d.split(":")(1)) - .map(TypeMapper.getInstance().getSafeTypeByName(_)).getOrElse(searchForXSDType(i(1))) - output.createTypedLiteral(i(1), xsdType) - } - else output.createTypedLiteral(i(1), searchForXSDType(i(1))) - }) - val collection = collectionConstructor(output, values.toIterator, rdfCollection) - output.add(createBNodeStatementWithCollection(action, predicateObject(0), collection)) - } - } else { - if (predicateObject(1).startsWith("http://") || predicateObject(1).startsWith("https://") || predicateObject(1).startsWith("_:")) { - val values = predicateObjects.map(i => output.createResource(normaliseURI(i(1)))) - val collection = collectionConstructor(output, values.toIterator, rdfCollection) - output.add(createStatementWithCollection(prefixTable(shapePrefix) + action, predicateObject(0), collection)) - } - else { - val values = predicateObjects.map(i => { - if(result.langTag.isDefined) output.createLiteral(i(1), result.langTag.get) - else if(result.dataType.isDefined) { - val xsdType = result.dataType.map(d => prefixTable(d.split(":")(0) + ":") + d.split(":")(1)) - .map(TypeMapper.getInstance().getSafeTypeByName(_)).getOrElse(searchForXSDType(i(1))) - output.createTypedLiteral(i(1), xsdType) - } - else output.createTypedLiteral(i(1), searchForXSDType(i(1))) - }) - val collection = collectionConstructor(output, values.toIterator, rdfCollection) - output.add(createStatementWithCollection( - prefixTable(shapePrefix) + action, predicateObject(0), collection)) + dataset.begin(TxnType.WRITE) + try { + val predicateObject = predicateObjects.head + if (shapePrefix == "_:") { + if (predicateObject(1).startsWith("http://") || predicateObject(1).startsWith("https://") || predicateObject(1).startsWith("_:")) { + val values = predicateObjects.map(i => output.createResource(normaliseURI(i(1)))) + val collection = collectionConstructor(output, values.toIterator, rdfCollection) + output.add(createBNodeStatementWithCollection(action, predicateObject(0), collection)) + } + else { + val values = predicateObjects.map(i => { + if (result.langTag.isDefined) output.createLiteral(i(1), result.langTag.get) + else if (result.dataType.isDefined) { + val xsdType = result.dataType.map(d => prefixTable(d.split(":")(0) + ":") + d.split(":")(1)) + .map(TypeMapper.getInstance().getSafeTypeByName(_)).getOrElse(searchForXSDType(i(1))) + output.createTypedLiteral(i(1), xsdType) + } + else output.createTypedLiteral(i(1), searchForXSDType(i(1))) + }) + val collection = collectionConstructor(output, values.toIterator, rdfCollection) + output.add(createBNodeStatementWithCollection(action, predicateObject(0), collection)) + } + } else { + if (predicateObject(1).startsWith("http://") || predicateObject(1).startsWith("https://") || predicateObject(1).startsWith("_:")) { + val values = predicateObjects.map(i => output.createResource(normaliseURI(i(1)))) + val collection = collectionConstructor(output, values.toIterator, rdfCollection) + output.add(createStatementWithCollection(prefixTable(shapePrefix) + action, predicateObject(0), collection)) + } + else { + val values = predicateObjects.map(i => { + if (result.langTag.isDefined) output.createLiteral(i(1), result.langTag.get) + else if (result.dataType.isDefined) { + val xsdType = result.dataType.map(d => prefixTable(d.split(":")(0) + ":") + d.split(":")(1)) + .map(TypeMapper.getInstance().getSafeTypeByName(_)).getOrElse(searchForXSDType(i(1))) + output.createTypedLiteral(i(1), xsdType) + } + else output.createTypedLiteral(i(1), searchForXSDType(i(1))) + }) + val collection = collectionConstructor(output, values.toIterator, rdfCollection) + output.add(createStatementWithCollection( + prefixTable(shapePrefix) + action, predicateObject(0), collection)) + } } + dataset.commit() + } finally { + dataset.end() } } @@ -1174,7 +1206,7 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, } class QueryResultsCache() { - private val table = mutable.HashMap[Int, Object]() + private val table = concurrent.TrieMap[Int, Object]() def search(query: String, file: LoadedSource): Option[Object] = { table.get((query + file.filepath).hashCode) @@ -1186,7 +1218,7 @@ class QueryResultsCache() { } def save(query: String, file: LoadedSource, resultSet: java.sql.ResultSet): Unit = { - val results = mutable.HashMap[String, List[String]]() + val results = concurrent.TrieMap[String, List[String]]() val columns = resultSet.getMetaData.getColumnCount val columnsNames = (1 to columns).map(resultSet.getMetaData.getColumnName) while(resultSet.next()) { @@ -1201,7 +1233,7 @@ class QueryResultsCache() { } def save(query: String, file: LoadedSource, resultSet: ResultSet): Unit = { - val results = mutable.HashMap[String, List[String]]() + val results = concurrent.TrieMap[String, List[String]]() val columnsNames = resultSet.getResultVars while(resultSet.hasNext) { val row = resultSet.next() @@ -1223,7 +1255,7 @@ class QueryResultsCache() { } class IteratorQueryResultsCache(pushedValues: Boolean) { - private val table = mutable.HashMap[Int, Map[String, List[Result]]]() + private val table = concurrent.TrieMap[Int, Map[String, List[Result]]]() def search(iteratorQuery: String, file: LoadedSource): Option[Map[String, List[Result]]] = { table.get((iteratorQuery + file.filepath).hashCode) @@ -1239,7 +1271,7 @@ class IteratorQueryResultsCache(pushedValues: Boolean) { } class JsonPathQueryResultsCache(pushedValues: Boolean) { - private val table = mutable.HashMap[Int, Result]() + private val table = concurrent.TrieMap[Int, Result]() def search(query: String, file: LoadedSource, index: String): Option[Result] = { table.get((query + file.filepath + index).hashCode) @@ -1254,7 +1286,7 @@ class JsonPathQueryResultsCache(pushedValues: Boolean) { } class JsonObjectMapperCache { - private val table = mutable.HashMap[Int, DocumentContext]() + private val table = concurrent.TrieMap[Int, DocumentContext]() def search(file: LoadedSource): Option[DocumentContext] = { table.get(file.filepath.hashCode) @@ -1267,7 +1299,7 @@ class JsonObjectMapperCache { } class XMLDocumentCache { - private val table = mutable.HashMap[Int, XdmNode]() + private val table = concurrent.TrieMap[Int, XdmNode]() def search(file: LoadedSource): Option[XdmNode] = { table.get(file.filepath.hashCode) @@ -1280,7 +1312,7 @@ class XMLDocumentCache { } class XpathQueryResultsCache(pushedValues: Boolean) { - private val table = mutable.HashMap[Int, Result]() + private val table = concurrent.TrieMap[Int, Result]() def search(query: String, file: LoadedSource, index: String): Option[Result] = { table.get((query + file.filepath + index).hashCode) @@ -1295,7 +1327,7 @@ class XpathQueryResultsCache(pushedValues: Boolean) { } class FunctionHubExecutorCache() { - private val table = mutable.HashMap[String, FunctionHubExecutor]() + private val table = concurrent.TrieMap[String, FunctionHubExecutor]() def search(filepath: String): Option[FunctionHubExecutor] = { table.get(filepath) diff --git a/src/main/scala/com/herminiogarcia/shexml/visitor/RMLGeneratorVisitor.scala b/src/main/scala/com/herminiogarcia/shexml/visitor/RMLGeneratorVisitor.scala index b78be84..4566e41 100644 --- a/src/main/scala/com/herminiogarcia/shexml/visitor/RMLGeneratorVisitor.scala +++ b/src/main/scala/com/herminiogarcia/shexml/visitor/RMLGeneratorVisitor.scala @@ -3,11 +3,9 @@ package com.herminiogarcia.shexml.visitor import com.herminiogarcia.shexml.ast._ import com.typesafe.scalalogging.Logger import org.apache.jena.query.Dataset -import org.apache.jena.rdf.model.{AnonId, Resource, ResourceFactory, Statement} +import org.apache.jena.rdf.model.{Resource, Statement} -import scala.collection.mutable - -class RMLGeneratorVisitor(dataset: Dataset, varTable: mutable.HashMap[Variable, VarResult], prettify: Boolean ,username: String, password: String) +class RMLGeneratorVisitor(dataset: Dataset, varTable: Map[Variable, VarResult], prettify: Boolean ,username: String, password: String) extends RDFGeneratorVisitor(dataset, varTable, username, password) with JdbcDriverRegistry { private val mapPrefix = "http://mapping.example.com/" diff --git a/src/main/scala/com/herminiogarcia/shexml/visitor/VarTableBuilderVisitor.scala b/src/main/scala/com/herminiogarcia/shexml/visitor/VarTableBuilderVisitor.scala index 07d08cd..65ad6cb 100644 --- a/src/main/scala/com/herminiogarcia/shexml/visitor/VarTableBuilderVisitor.scala +++ b/src/main/scala/com/herminiogarcia/shexml/visitor/VarTableBuilderVisitor.scala @@ -58,7 +58,7 @@ class VarTableBuilderVisitor(val variableMap: mutable.HashMap[Variable, VarResul } private def getQueryFromVarTable(variable: Var): QueryClause = { - new QuerySearcher(variableMap).getQueryFromVarTable(variable) + new QuerySearcher(variableMap.toMap).getQueryFromVarTable(variable) } override def doVisitDefault(): Unit = ??? diff --git a/src/test/scala/com/herminiogarcia/shexml/AccessFieldsOutsideIteratorsWithImportsTest.scala b/src/test/scala/com/herminiogarcia/shexml/AccessFieldsOutsideIteratorsWithImportsTest.scala index 33475ff..0b681fe 100644 --- a/src/test/scala/com/herminiogarcia/shexml/AccessFieldsOutsideIteratorsWithImportsTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/AccessFieldsOutsideIteratorsWithImportsTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class AccessFieldsOutsideIteratorsWithImportsTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class AccessFieldsOutsideIteratorsWithImportsTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -27,10 +31,14 @@ class AccessFieldsOutsideIteratorsWithImportsTest extends AnyFunSuite with Match |IMPORT """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/AutoIncrementOnFunctionTest.scala b/src/test/scala/com/herminiogarcia/shexml/AutoIncrementOnFunctionTest.scala index 6571199..9392a7b 100644 --- a/src/test/scala/com/herminiogarcia/shexml/AutoIncrementOnFunctionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/AutoIncrementOnFunctionTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class AutoIncrementOnFunctionTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class AutoIncrementOnFunctionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -42,10 +46,14 @@ class AutoIncrementOnFunctionTest extends AnyFunSuite with Matchers with RDFStat |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "1", "internalId1", "1something: 5", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/CommentIteratorExpressionTest.scala b/src/test/scala/com/herminiogarcia/shexml/CommentIteratorExpressionTest.scala index d08c33e..0f65862 100644 --- a/src/test/scala/com/herminiogarcia/shexml/CommentIteratorExpressionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/CommentIteratorExpressionTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class CommentIteratorExpressionTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class CommentIteratorExpressionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -39,10 +43,15 @@ class CommentIteratorExpressionTest extends AnyFunSuite with Matchers with RDFSt | #ex:long [performances.long] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://ex.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) assert(!output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "long", "3.717333", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/CommentTest.scala b/src/test/scala/com/herminiogarcia/shexml/CommentTest.scala index 88503bd..8ac9303 100644 --- a/src/test/scala/com/herminiogarcia/shexml/CommentTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/CommentTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class CommentTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class CommentTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -42,10 +46,15 @@ class CommentTest extends AnyFunSuite with Matchers with RDFStatementCreator { | #ex:long [long_union] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://ex.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) assert(!output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "long", "3.717333", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationPredicateTest.scala b/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationPredicateTest.scala index 4110266..04be23f 100644 --- a/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationPredicateTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationPredicateTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class ConditionalGenerationPredicateTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class ConditionalGenerationPredicateTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -31,10 +35,14 @@ class ConditionalGenerationPredicateTest extends AnyFunSuite with Matchers with |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 99 is generated without name") { assert(!output.contains(createStatementWithLiteral(prefix, "99", "name", "Incomplete film", XSDDatatype.XSDstring))) assert(output.contains(createStatementWithLiteral(prefix, "99", "countryOfOrigin", "USA", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationPredicateTestHierarchical.scala b/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationPredicateTestHierarchical.scala index 1257efd..d8e34ff 100644 --- a/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationPredicateTestHierarchical.scala +++ b/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationPredicateTestHierarchical.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class ConditionalGenerationPredicateTestHierarchical extends AnyFunSuite with Matchers with RDFStatementCreator { +class ConditionalGenerationPredicateTestHierarchical extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigNormaliseURIsFixture { private val example = """ @@ -30,10 +34,14 @@ class ConditionalGenerationPredicateTestHierarchical extends AnyFunSuite with Ma |} """.stripMargin - private val mappingLauncher = new MappingLauncher(normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is generated completely") { assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Complete film 1", XSDDatatype.XSDstring))) assert(output.contains(createStatementWithLiteral(prefix, "1", "year1", "2000", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationSubjectTestHierarchical.scala b/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationSubjectTestHierarchical.scala index 5a6a5a1..e5e3d2b 100644 --- a/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationSubjectTestHierarchical.scala +++ b/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationSubjectTestHierarchical.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class ConditionalGenerationSubjectTestHierarchical extends AnyFunSuite with Matchers with RDFStatementCreator { +class ConditionalGenerationSubjectTestHierarchical extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigNormaliseURIsFixture { private val example = """ @@ -30,10 +34,14 @@ class ConditionalGenerationSubjectTestHierarchical extends AnyFunSuite with Matc |} """.stripMargin - private val mappingLauncher = new MappingLauncher(normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is generated completely") { assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Complete film 1", XSDDatatype.XSDstring))) assert(output.contains(createStatementWithLiteral(prefix, "1", "year1", "2000", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationTest.scala b/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationTest.scala index 5c33975..bf0ecea 100644 --- a/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/ConditionalGenerationTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class ConditionalGenerationTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class ConditionalGenerationTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -48,10 +52,14 @@ class ConditionalGenerationTest extends AnyFunSuite with Matchers with RDFStatem |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 4 is generated without country") { assert(output.contains(createStatementWithLiteral(prefix, "4", "director", "Christopher Nolan", XSDDatatype.XSDstring))) assert(output.contains(createStatementWithLiteral(prefix, "4", "musicBy", "David Julyan", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/DeepHierarchyJSONTest.scala b/src/test/scala/com/herminiogarcia/shexml/DeepHierarchyJSONTest.scala index 6b5d303..cf4991a 100644 --- a/src/test/scala/com/herminiogarcia/shexml/DeepHierarchyJSONTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/DeepHierarchyJSONTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class DeepHierarchyJSONTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class DeepHierarchyJSONTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -83,10 +87,15 @@ class DeepHierarchyJSONTest extends AnyFunSuite with Matchers with RDFStatementC | :tag [tag.tag.tag.tag.tag.tag.tag.tag.tag.tag.tag] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shapes are linked correctly") { assert(output.contains(createStatement(prefix, "1", "nested", "2"))) assert(output.contains(createStatement(prefix, "2", "nested", "3"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/DeepHierarchyJSONWithUnorderedFieldsAndIteratorsTest.scala b/src/test/scala/com/herminiogarcia/shexml/DeepHierarchyJSONWithUnorderedFieldsAndIteratorsTest.scala index 7886248..1c213f5 100644 --- a/src/test/scala/com/herminiogarcia/shexml/DeepHierarchyJSONWithUnorderedFieldsAndIteratorsTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/DeepHierarchyJSONWithUnorderedFieldsAndIteratorsTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class DeepHierarchyJSONWithUnorderedFieldsAndIteratorsTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class DeepHierarchyJSONWithUnorderedFieldsAndIteratorsTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigNormaliseURIsFixture { private val example = """ @@ -103,10 +107,15 @@ class DeepHierarchyJSONWithUnorderedFieldsAndIteratorsTest extends AnyFunSuite w | :tag [tag.tag.tag.tag.tag.tag.tag.tag.tag.tag.tag] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = false, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shapes are linked correctly") { assert(output.contains(createStatement(prefix, "1", "nested", "2"))) assert(output.contains(createStatement(prefix, "2", "nested", "3"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/DeepHierarchyXMLTest.scala b/src/test/scala/com/herminiogarcia/shexml/DeepHierarchyXMLTest.scala index e72b78a..a059562 100644 --- a/src/test/scala/com/herminiogarcia/shexml/DeepHierarchyXMLTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/DeepHierarchyXMLTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class DeepHierarchyXMLTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class DeepHierarchyXMLTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -83,10 +87,15 @@ class DeepHierarchyXMLTest extends AnyFunSuite with Matchers with RDFStatementCr | :tag [tag.tag.tag.tag.tag.tag.tag.tag.tag.tag.tag] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shapes are linked correctly") { assert(output.contains(createStatement(prefix, "1", "nested", "2"))) assert(output.contains(createStatement(prefix, "2", "nested", "3"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/ExternalAndBuiltinFunctions.scala b/src/test/scala/com/herminiogarcia/shexml/ExternalAndBuiltinFunctions.scala index df428a5..ecff965 100644 --- a/src/test/scala/com/herminiogarcia/shexml/ExternalAndBuiltinFunctions.scala +++ b/src/test/scala/com/herminiogarcia/shexml/ExternalAndBuiltinFunctions.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class ExternalAndBuiltinFunctions extends AnyFunSuite with Matchers with RDFStatementCreator { +class ExternalAndBuiltinFunctions extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -92,10 +96,14 @@ class ExternalAndBuiltinFunctions extends AnyFunSuite with Matchers with RDFStat |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 transformations are done correctly") { assert(output.contains(createStatementWithLiteral(prefix, "1", "screenwritterName", "Christopher", XSDDatatype.XSDstring))) assert(output.contains(createStatementWithLiteral(prefix, "1", "titleYear", "Dunkirk2017", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/ExternalFunctionsTest.scala b/src/test/scala/com/herminiogarcia/shexml/ExternalFunctionsTest.scala index a789918..db84990 100644 --- a/src/test/scala/com/herminiogarcia/shexml/ExternalFunctionsTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/ExternalFunctionsTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class ExternalFunctionsTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class ExternalFunctionsTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -80,10 +84,14 @@ class ExternalFunctionsTest extends AnyFunSuite with Matchers with RDFStatementC |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 transformations are done correctly") { assert(output.contains(createStatementWithLiteral(prefix, "1", "screenwritterName", "Christopher", XSDDatatype.XSDstring))) assert(output.contains(createStatementWithLiteral(prefix, "1", "titleYear", "Dunkirk2017", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/ExternalFunctionsWithDashedVarsTest.scala b/src/test/scala/com/herminiogarcia/shexml/ExternalFunctionsWithDashedVarsTest.scala index b9c5ffd..9e65f19 100644 --- a/src/test/scala/com/herminiogarcia/shexml/ExternalFunctionsWithDashedVarsTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/ExternalFunctionsWithDashedVarsTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class ExternalFunctionsWithDashedVarsTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class ExternalFunctionsWithDashedVarsTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -80,10 +84,14 @@ class ExternalFunctionsWithDashedVarsTest extends AnyFunSuite with Matchers with |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 transformations are done correctly") { assert(output.contains(createStatementWithLiteral(prefix, "1", "screenwritterName", "Christopher", XSDDatatype.XSDstring))) assert(output.contains(createStatementWithLiteral(prefix, "1", "titleYear", "Dunkirk2017", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/FilmsAlt.scala b/src/test/scala/com/herminiogarcia/shexml/FilmsAlt.scala index c92ffc9..9ad428f 100644 --- a/src/test/scala/com/herminiogarcia/shexml/FilmsAlt.scala +++ b/src/test/scala/com/herminiogarcia/shexml/FilmsAlt.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsAlt extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsAlt extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -37,10 +41,14 @@ class FilmsAlt extends AnyFunSuite with Matchers with RDFStatementCreator { |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape film1 contains all the data, literal action, enhancement-#97") { assert(output.contains(createStatementWithLiteral(prefix, "film1", "name", "Dunkirk", XSDDatatype.XSDstring))) assert(output.contains(createStatementWithLiteral(prefix, "film1", "year", "2017", XSDDatatype.XSDinteger))) diff --git a/src/test/scala/com/herminiogarcia/shexml/FilmsExternalQueryMySQLTest.scala b/src/test/scala/com/herminiogarcia/shexml/FilmsExternalQueryMySQLTest.scala index e36bd2d..579299f 100644 --- a/src/test/scala/com/herminiogarcia/shexml/FilmsExternalQueryMySQLTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/FilmsExternalQueryMySQLTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsExternalQueryMySQLTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsExternalQueryMySQLTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigDatabase { private val example = """ @@ -33,10 +37,14 @@ class FilmsExternalQueryMySQLTest extends AnyFunSuite with Matchers with RDFStat |} """.stripMargin - private val mappingLauncher = new MappingLauncher("root", "root", inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 8 is translated correctly") { assert(output.contains(createStatement(prefix, "8", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "8", "name", "Tenet", "en"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/FilmsMySQLTest.scala b/src/test/scala/com/herminiogarcia/shexml/FilmsMySQLTest.scala index d000633..5051588 100644 --- a/src/test/scala/com/herminiogarcia/shexml/FilmsMySQLTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/FilmsMySQLTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsMySQLTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsMySQLTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigDatabase { private val example = """ @@ -32,10 +36,15 @@ class FilmsMySQLTest extends AnyFunSuite with Matchers with RDFStatementCreator |} """.stripMargin - private val mappingLauncher = new MappingLauncher("root", "root", inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 8 is translated correctly") { assert(output.contains(createStatement(prefix, "8", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "8", "name", "Tenet", "en"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/FilmsPostgresTest.scala b/src/test/scala/com/herminiogarcia/shexml/FilmsPostgresTest.scala index 436913c..c21dbfb 100644 --- a/src/test/scala/com/herminiogarcia/shexml/FilmsPostgresTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/FilmsPostgresTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsPostgresTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsPostgresTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigDatabase { private val example = """ @@ -32,10 +36,15 @@ class FilmsPostgresTest extends AnyFunSuite with Matchers with RDFStatementCreat |} """.stripMargin - private val mappingLauncher = new MappingLauncher("root", "root", inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 8 is translated correctly") { assert(output.contains(createStatement(prefix, "8", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "8", "name", "Tenet", "en"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/FilmsRelativePathTest.scala b/src/test/scala/com/herminiogarcia/shexml/FilmsRelativePathTest.scala index 067235b..5c27116 100644 --- a/src/test/scala/com/herminiogarcia/shexml/FilmsRelativePathTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/FilmsRelativePathTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsRelativePathTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsRelativePathTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -39,10 +43,14 @@ class FilmsRelativePathTest extends AnyFunSuite with Matchers with RDFStatementC |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) assert(output.contains(createStatement(prefix, "1", "internalId", "1"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/FilmsSparqlFileTest.scala b/src/test/scala/com/herminiogarcia/shexml/FilmsSparqlFileTest.scala index aa0f1ee..cfe845f 100644 --- a/src/test/scala/com/herminiogarcia/shexml/FilmsSparqlFileTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/FilmsSparqlFileTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsSparqlFileTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsSparqlFileTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigSparqlNormaliseURIs { private val example = """ @@ -29,10 +33,14 @@ class FilmsSparqlFileTest extends AnyFunSuite with Matchers with RDFStatementCre |} """.stripMargin - private val mappingLauncher = new MappingLauncher("root", normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Memento__film_ is translated correctly") { assert(output.contains(createStatement(prefix, "Memento__film_", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "Memento__film_", "name", "Memento", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/FilmsSparqlTest.scala b/src/test/scala/com/herminiogarcia/shexml/FilmsSparqlTest.scala index 369ba3b..de924d8 100644 --- a/src/test/scala/com/herminiogarcia/shexml/FilmsSparqlTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/FilmsSparqlTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsSparqlTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsSparqlTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigSparql { private val example = """ @@ -33,10 +37,14 @@ class FilmsSparqlTest extends AnyFunSuite with Matchers with RDFStatementCreator |} """.stripMargin - private val mappingLauncher = new MappingLauncher("root") - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Entity Q63985561 is translated correctly") { assert(output.contains(createStatement(prefix, "Q63985561", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "Q63985561", "name", "Tenet", "en"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/FilmsTestIteratorsWithMissingValues.scala b/src/test/scala/com/herminiogarcia/shexml/FilmsTestIteratorsWithMissingValues.scala index 35e2d11..f52356e 100644 --- a/src/test/scala/com/herminiogarcia/shexml/FilmsTestIteratorsWithMissingValues.scala +++ b/src/test/scala/com/herminiogarcia/shexml/FilmsTestIteratorsWithMissingValues.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsTestIteratorsWithMissingValues extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsTestIteratorsWithMissingValues extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -56,10 +60,14 @@ class FilmsTestIteratorsWithMissingValues extends AnyFunSuite with Matchers with |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", "en"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/FilmsWithNullsTest.scala b/src/test/scala/com/herminiogarcia/shexml/FilmsWithNullsTest.scala index 9df4b0c..48c4211 100644 --- a/src/test/scala/com/herminiogarcia/shexml/FilmsWithNullsTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/FilmsWithNullsTest.scala @@ -1,11 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype -import org.apache.jena.rdf.model.ResourceFactory +import org.apache.jena.rdf.model.{Model, ResourceFactory} +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsWithNullsTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsWithNullsTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -46,10 +49,14 @@ class FilmsWithNullsTest extends AnyFunSuite with Matchers with RDFStatementCrea |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", "en"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/GraphMultipleElementIteratorExpressionTest.scala b/src/test/scala/com/herminiogarcia/shexml/GraphMultipleElementIteratorExpressionTest.scala index a82d38e..e6b3ef2 100644 --- a/src/test/scala/com/herminiogarcia/shexml/GraphMultipleElementIteratorExpressionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/GraphMultipleElementIteratorExpressionTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class GraphMultipleElementIteratorExpressionTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class GraphMultipleElementIteratorExpressionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -50,11 +54,16 @@ class GraphMultipleElementIteratorExpressionTest extends AnyFunSuite with Matche |} """.stripMargin + private var output: Model = _ + private var myFilmsGraph: Model = _ private val prefix = "http://example.com/" - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val dataset = mappingLauncher.launchMapping(example) - private val output = dataset.getDefaultModel - private val myFilmsGraph = dataset.getNamedModel(prefix + "MyFilms") + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val dataset = mappingLauncher.launchMapping(example) + output = dataset.getDefaultModel + myFilmsGraph = dataset.getNamedModel(prefix + "MyFilms") + } test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMapping.scala b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMapping.scala index 3027770..cb7d205 100644 --- a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMapping.scala +++ b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMapping.scala @@ -1,13 +1,17 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMapping extends AnyFunSuite with Matchers with RDFStatementCreator { +class JsonAndXmlEventsMapping extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -44,10 +48,15 @@ class JsonAndXmlEventsMapping extends AnyFunSuite with Matchers with RDFStatemen | ex:long [long_union] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://ex.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "long", "3.717333", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingIteratorExpression.scala b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingIteratorExpression.scala index 2a9dce8..431d0d8 100644 --- a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingIteratorExpression.scala +++ b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingIteratorExpression.scala @@ -1,13 +1,17 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingIteratorExpression extends AnyFunSuite with Matchers with RDFStatementCreator { +class JsonAndXmlEventsMappingIteratorExpression extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -42,10 +46,15 @@ class JsonAndXmlEventsMappingIteratorExpression extends AnyFunSuite with Matcher | ex:long [performances.long] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://ex.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "long", "3.717333", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithBNode.scala b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithBNode.scala index 91ac05e..cb6db37 100644 --- a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithBNode.scala +++ b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithBNode.scala @@ -1,13 +1,17 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingWithBNode extends AnyFunSuite with Matchers with RDFStatementCreator { +class JsonAndXmlEventsMappingWithBNode extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -42,10 +46,15 @@ class JsonAndXmlEventsMappingWithBNode extends AnyFunSuite with Matchers with RD | ex:long [performances.long] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://ex.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteralAndBNodeSubject(output, prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteralAndBNodeSubject(output, prefix, "51.043613-3.717333", "long", "3.717333", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithBlankPrefix.scala b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithBlankPrefix.scala index 12e2b9a..2c0cddc 100644 --- a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithBlankPrefix.scala +++ b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithBlankPrefix.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class JsonAndXmlEventsMappingWithBlankPrefix extends AnyFunSuite with Matchers with RDFStatementCreator { +class JsonAndXmlEventsMappingWithBlankPrefix extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { val example = """ @@ -42,10 +46,14 @@ class JsonAndXmlEventsMappingWithBlankPrefix extends AnyFunSuite with Matchers w |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://ex.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "long", "3.717333", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression.scala b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression.scala index 69fa2e1..55784e8 100644 --- a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression.scala +++ b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression extends AnyFunSuite with Matchers with RDFStatementCreator { +class JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { val example = """ @@ -41,10 +45,14 @@ class JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression extends AnyFunSui |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://ex.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "long", "3.717333", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithExternalQuery.scala b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithExternalQuery.scala index b6005ca..e36c47c 100644 --- a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithExternalQuery.scala +++ b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithExternalQuery.scala @@ -1,13 +1,17 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingWithExternalQuery extends AnyFunSuite with Matchers with RDFStatementCreator { +class JsonAndXmlEventsMappingWithExternalQuery extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -46,10 +50,15 @@ class JsonAndXmlEventsMappingWithExternalQuery extends AnyFunSuite with Matchers | ex:long [long_union] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://ex.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "long", "3.717333", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithJoin.scala b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithJoin.scala index af01587..e38c38d 100644 --- a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithJoin.scala +++ b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithJoin.scala @@ -1,13 +1,17 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingWithJoin extends AnyFunSuite with Matchers with RDFStatementCreator { +class JsonAndXmlEventsMappingWithJoin extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { val example = """ @@ -45,10 +49,14 @@ class JsonAndXmlEventsMappingWithJoin extends AnyFunSuite with Matchers with RDF |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://ex.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "long", "3.717333", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithJoinIteratorExpression.scala b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithJoinIteratorExpression.scala index dec0694..a7afc30 100644 --- a/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithJoinIteratorExpression.scala +++ b/src/test/scala/com/herminiogarcia/shexml/JsonAndXmlEventsMappingWithJoinIteratorExpression.scala @@ -1,13 +1,17 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingWithJoinIteratorExpression extends AnyFunSuite with Matchers with RDFStatementCreator { +class JsonAndXmlEventsMappingWithJoinIteratorExpression extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { val example = """ @@ -44,10 +48,14 @@ class JsonAndXmlEventsMappingWithJoinIteratorExpression extends AnyFunSuite with |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://ex.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "long", "3.717333", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/MatcherIteratorExpressionTest.scala b/src/test/scala/com/herminiogarcia/shexml/MatcherIteratorExpressionTest.scala index 0d54bce..9ca138b 100644 --- a/src/test/scala/com/herminiogarcia/shexml/MatcherIteratorExpressionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/MatcherIteratorExpressionTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MatcherIteratorExpressionTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class MatcherIteratorExpressionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -39,10 +43,15 @@ class MatcherIteratorExpressionTest extends AnyFunSuite with Matchers with RDFSt | ex:long [performances.long] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://ex.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "long", "3.717333", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/MatcherTest.scala b/src/test/scala/com/herminiogarcia/shexml/MatcherTest.scala index db8ce1e..701b230 100644 --- a/src/test/scala/com/herminiogarcia/shexml/MatcherTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/MatcherTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MatcherTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class MatcherTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -42,10 +46,15 @@ class MatcherTest extends AnyFunSuite with Matchers with RDFStatementCreator { | ex:long [long_union] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://ex.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "long", "3.717333", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionTest.scala b/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionTest.scala index 940fa8e..f188c5a 100644 --- a/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementIteratorExpressionTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class MultipleElementIteratorExpressionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -39,10 +43,14 @@ class MultipleElementIteratorExpressionTest extends AnyFunSuite with Matchers wi |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) assert(output.contains(createStatement(prefix, "1", "internalId", "1"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionWithAutoIncrementWithStringsTest.scala b/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionWithAutoIncrementWithStringsTest.scala index 6170316..50225c6 100644 --- a/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionWithAutoIncrementWithStringsTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionWithAutoIncrementWithStringsTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementIteratorExpressionWithAutoIncrementWithStringsTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class MultipleElementIteratorExpressionWithAutoIncrementWithStringsTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -43,10 +47,14 @@ class MultipleElementIteratorExpressionWithAutoIncrementWithStringsTest extends |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "1", "internalId1", "something: 1", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionWithCSVAndDBTest.scala b/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionWithCSVAndDBTest.scala index 0bc3e23..318537b 100644 --- a/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionWithCSVAndDBTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionWithCSVAndDBTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementIteratorExpressionWithCSVAndDBTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class MultipleElementIteratorExpressionWithCSVAndDBTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -54,10 +58,14 @@ class MultipleElementIteratorExpressionWithCSVAndDBTest extends AnyFunSuite with |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", "en"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionWithCSVTest.scala b/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionWithCSVTest.scala index 92134b9..606f4c7 100644 --- a/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionWithCSVTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/MultipleElementIteratorExpressionWithCSVTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementIteratorExpressionWithCSVTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class MultipleElementIteratorExpressionWithCSVTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -45,10 +49,14 @@ class MultipleElementIteratorExpressionWithCSVTest extends AnyFunSuite with Matc |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", "en"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/MultipleElementTest.scala b/src/test/scala/com/herminiogarcia/shexml/MultipleElementTest.scala index 402cd3d..0fd5bf5 100644 --- a/src/test/scala/com/herminiogarcia/shexml/MultipleElementTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/MultipleElementTest.scala @@ -1,10 +1,14 @@ package com.herminiogarcia.shexml import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class MultipleElementTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -39,10 +43,14 @@ class MultipleElementTest extends AnyFunSuite with Matchers with RDFStatementCre |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", XSDDatatype.XSDstring))) assert(output.contains(createStatementWithLiteral(prefix, "1", "year", "2017", XSDDatatype.XSDinteger))) diff --git a/src/test/scala/com/herminiogarcia/shexml/ParallelConfigFixtures.scala b/src/test/scala/com/herminiogarcia/shexml/ParallelConfigFixtures.scala new file mode 100644 index 0000000..e998a90 --- /dev/null +++ b/src/test/scala/com/herminiogarcia/shexml/ParallelConfigFixtures.scala @@ -0,0 +1,75 @@ +package com.herminiogarcia.shexml + +import com.herminiogarcia.shexml.helper.ParallelExecutionConfigurator +import org.scalatest.{BeforeAndAfterAllConfigMap, ConfigMap, TestSuite} + + +trait ParallelConfigInferenceDatatypesNormaliseURIsFixture extends BeforeAndAfterAllConfigMap with MappingLauncherInitializer { this: TestSuite => + var mappingLauncher: MappingLauncher = _ + + override def beforeAll(configMap: ConfigMap): Unit = { + mappingLauncher = configMapToParallelConfiguration(configMap).parallelConfigurationInferenceDatatypesNormaliseURIs + super.beforeAll(configMap) + } +} + +trait ParallelConfigNormaliseURIsFixture extends BeforeAndAfterAllConfigMap with MappingLauncherInitializer { this: TestSuite => + var mappingLauncher: MappingLauncher = _ + + override def beforeAll(configMap: ConfigMap): Unit = { + mappingLauncher = configMapToParallelConfiguration(configMap).parallelConfigurationNormaliseURIs + super.beforeAll(configMap) + } +} + +trait ParallelConfigDatabase extends BeforeAndAfterAllConfigMap with MappingLauncherInitializer { this: TestSuite => + var mappingLauncher: MappingLauncher = _ + + override def beforeAll(configMap: ConfigMap): Unit = { + mappingLauncher = configMapToParallelConfiguration(configMap).parallelConfigurationDatabase + super.beforeAll(configMap) + } +} + +trait ParallelConfigSparqlNormaliseURIs extends BeforeAndAfterAllConfigMap with MappingLauncherInitializer { this: TestSuite => + var mappingLauncher: MappingLauncher = _ + + override def beforeAll(configMap: ConfigMap): Unit = { + mappingLauncher = configMapToParallelConfiguration(configMap).parallelConfigurationSparqlNormaliseURIs + super.beforeAll(configMap) + } +} + +trait ParallelConfigSparql extends BeforeAndAfterAllConfigMap with MappingLauncherInitializer { this: TestSuite => + var mappingLauncher: MappingLauncher = _ + + override def beforeAll(configMap: ConfigMap): Unit = { + mappingLauncher = configMapToParallelConfiguration(configMap).parallelConfigurationSparql + super.beforeAll(configMap) + } +} + +trait ParallelConfigValidation extends BeforeAndAfterAllConfigMap with MappingLauncherInitializer { this: TestSuite => + var parallelConfiguration: ParallelExecutionConfigurator = _ + + override def beforeAll(configMap: ConfigMap): Unit = { + parallelConfiguration = configMapToParallelConfiguration(configMap).parallelConfigurationInferenceDatatypesNormaliseURIs.parallelCollectionConfigurator + super.beforeAll(configMap) + } +} + +trait MappingLauncherInitializer { + def getParallelConfig(parallelConfig: String): ParallelConfigurations = { + if(parallelConfig == "all") ParallelConfigurations.parallelConfigurationAll + else if(parallelConfig == "shapes") ParallelConfigurations.parallelConfigurationShapes + else if(parallelConfig == "queries") ParallelConfigurations.parallelConfigurationQueries + else ParallelConfigurations.nonParallelConfiguration + } + + def configMapToParallelConfiguration(configMap: ConfigMap): ParallelConfigurations = configMap.get("parallel") match { + case Some(parallelConfig) => getParallelConfig(parallelConfig.asInstanceOf[String]) + case None => ParallelConfigurations.nonParallelConfiguration + } + + +} diff --git a/src/test/scala/com/herminiogarcia/shexml/ParallelConfigurations.scala b/src/test/scala/com/herminiogarcia/shexml/ParallelConfigurations.scala new file mode 100644 index 0000000..f634e7e --- /dev/null +++ b/src/test/scala/com/herminiogarcia/shexml/ParallelConfigurations.scala @@ -0,0 +1,44 @@ +package com.herminiogarcia.shexml + +import com.herminiogarcia.shexml.helper.ParallelExecutionConfigurator + +class ParallelConfigurations(val parallelConfiguration: ParallelExecutionConfigurator) { + + val parallelConfigurationInferenceDatatypesNormaliseURIs = new MappingLauncher( + inferenceDatatype = true, + normaliseURIs = true, + parallelCollectionConfigurator = parallelConfiguration + ) + + val parallelConfigurationNormaliseURIs = new MappingLauncher( + inferenceDatatype = false, + normaliseURIs = true, + parallelCollectionConfigurator = parallelConfiguration + ) + + val parallelConfigurationDatabase = new MappingLauncher( + "root", + "root", + inferenceDatatype = true, + normaliseURIs = true, + parallelCollectionConfigurator = parallelConfiguration + ) + + val parallelConfigurationSparqlNormaliseURIs = new MappingLauncher( + "root", + normaliseURIs = true, + parallelCollectionConfigurator = parallelConfiguration + ) + + val parallelConfigurationSparql = new MappingLauncher( + "root", + parallelCollectionConfigurator = parallelConfiguration + ) +} + +object ParallelConfigurations { + val parallelConfigurationAll = new ParallelConfigurations(parallelConfiguration = ParallelExecutionConfigurator("all", "4")) + val parallelConfigurationShapes = new ParallelConfigurations(parallelConfiguration = ParallelExecutionConfigurator("shapes", "2")) + val parallelConfigurationQueries = new ParallelConfigurations(parallelConfiguration = ParallelExecutionConfigurator("queries", "6")) + val nonParallelConfiguration = new ParallelConfigurations(parallelConfiguration = new ParallelExecutionConfigurator(Map(), None)) +} diff --git a/src/test/scala/com/herminiogarcia/shexml/PrecompilationTest.scala b/src/test/scala/com/herminiogarcia/shexml/PrecompilationTest.scala index 4c2e75e..a71472a 100644 --- a/src/test/scala/com/herminiogarcia/shexml/PrecompilationTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/PrecompilationTest.scala @@ -2,7 +2,7 @@ package com.herminiogarcia.shexml import org.scalatest.funsuite.AnyFunSuite -class PrecompilationTest extends AnyFunSuite { +class PrecompilationTest(val mappingLauncher: MappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true)) extends AnyFunSuite { private val example = """ @@ -82,7 +82,6 @@ class PrecompilationTest extends AnyFunSuite { |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) private val output = mappingLauncher.precompile(example) test("Precompiled version is generated as expected") { diff --git a/src/test/scala/com/herminiogarcia/shexml/PrecompilationWithParserErrorTest.scala b/src/test/scala/com/herminiogarcia/shexml/PrecompilationWithParserErrorTest.scala index b743139..09a061b 100644 --- a/src/test/scala/com/herminiogarcia/shexml/PrecompilationWithParserErrorTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/PrecompilationWithParserErrorTest.scala @@ -2,7 +2,7 @@ package com.herminiogarcia.shexml import org.scalatest.funsuite.AnyFunSuite -class PrecompilationWithParserErrorTest extends AnyFunSuite { +class PrecompilationWithParserErrorTest(val mappingLauncher: MappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true)) extends AnyFunSuite { private val example = """ @@ -84,7 +84,6 @@ class PrecompilationWithParserErrorTest extends AnyFunSuite { |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) private val output = mappingLauncher.precompile(example) test("Precompiled version is generated as expected") { diff --git a/src/test/scala/com/herminiogarcia/shexml/PushedValueWithMultipleEntities.scala b/src/test/scala/com/herminiogarcia/shexml/PushedValueWithMultipleEntities.scala index 67231b7..a83357a 100644 --- a/src/test/scala/com/herminiogarcia/shexml/PushedValueWithMultipleEntities.scala +++ b/src/test/scala/com/herminiogarcia/shexml/PushedValueWithMultipleEntities.scala @@ -1,10 +1,13 @@ package com.herminiogarcia.shexml -import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class PushedValueWithMultipleEntities extends AnyFunSuite with Matchers with RDFStatementCreator { +class PushedValueWithMultipleEntities extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -25,10 +28,14 @@ class PushedValueWithMultipleEntities extends AnyFunSuite with Matchers with RDF |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "one", "under", "1"))) } diff --git a/src/test/scala/com/herminiogarcia/shexml/TwoNestedIteratorWithoutFieldInBetween.scala b/src/test/scala/com/herminiogarcia/shexml/TwoNestedIteratorWithoutFieldInBetween.scala index da68874..af00acc 100644 --- a/src/test/scala/com/herminiogarcia/shexml/TwoNestedIteratorWithoutFieldInBetween.scala +++ b/src/test/scala/com/herminiogarcia/shexml/TwoNestedIteratorWithoutFieldInBetween.scala @@ -1,9 +1,13 @@ package com.herminiogarcia.shexml +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class TwoNestedIteratorWithoutFieldInBetween extends AnyFunSuite with Matchers with RDFStatementCreator { +class TwoNestedIteratorWithoutFieldInBetween extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -22,10 +26,14 @@ class TwoNestedIteratorWithoutFieldInBetween extends AnyFunSuite with Matchers w |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "one", "type", "Test"))) } diff --git a/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFAltTest.scala b/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFAltTest.scala index 85bd92e..0928a32 100644 --- a/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFAltTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFAltTest.scala @@ -1,14 +1,17 @@ package com.herminiogarcia.shexml.collectionsandcontainers -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} -import org.apache.jena.rdf.model.ResourceFactory +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} +import org.apache.jena.rdf.model.{Model, ResourceFactory} +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class RDFAltTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class RDFAltTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -41,10 +44,15 @@ class RDFAltTest extends AnyFunSuite with Matchers with RDFStatementCreator { | ex:hasAuthors ex:[labValues.articles.authors.name AS RDFAlt] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Lab shape is correctly translated") { assert(output.contains(createStatement(prefix, "AmazingLab1", "hasArticles", "article1"))) } diff --git a/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFBagTest.scala b/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFBagTest.scala index 29ff0b9..cd15d6f 100644 --- a/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFBagTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFBagTest.scala @@ -1,14 +1,17 @@ package com.herminiogarcia.shexml.collectionsandcontainers -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} -import org.apache.jena.rdf.model.ResourceFactory +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} +import org.apache.jena.rdf.model.{Model, ResourceFactory} +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class RDFBagTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class RDFBagTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -41,10 +44,15 @@ class RDFBagTest extends AnyFunSuite with Matchers with RDFStatementCreator { | ex:hasAuthors ex:[labValues.articles.authors.name AS RDFBag] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Lab shape is correctly translated") { assert(output.contains(createStatement(prefix, "AmazingLab1", "hasArticles", "article1"))) } diff --git a/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFListTest.scala b/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFListTest.scala index cf51227..101d70a 100644 --- a/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFListTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFListTest.scala @@ -1,14 +1,17 @@ package com.herminiogarcia.shexml.collectionsandcontainers -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} -import org.apache.jena.rdf.model.ResourceFactory +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} +import org.apache.jena.rdf.model.{Model, ResourceFactory} +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class RDFListTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class RDFListTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -41,10 +44,15 @@ class RDFListTest extends AnyFunSuite with Matchers with RDFStatementCreator { | ex:hasAuthors ex:[labValues.articles.authors.name AS RDFList] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Lab shape is correctly translated") { assert(output.contains(createStatement(prefix, "AmazingLab1", "hasArticles", "article1"))) } diff --git a/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFSeqTest.scala b/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFSeqTest.scala index 183bac3..7e0fc09 100644 --- a/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFSeqTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/collectionsandcontainers/RDFSeqTest.scala @@ -1,14 +1,17 @@ package com.herminiogarcia.shexml.collectionsandcontainers -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} -import org.apache.jena.rdf.model.ResourceFactory +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} +import org.apache.jena.rdf.model.{Model, ResourceFactory} +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class RDFSeqTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class RDFSeqTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -41,10 +44,15 @@ class RDFSeqTest extends AnyFunSuite with Matchers with RDFStatementCreator { | ex:hasAuthors ex:[labValues.articles.authors.name AS RDFSeq] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Lab shape is correctly translated") { assert(output.contains(createStatement(prefix, "AmazingLab1", "hasArticles", "article1"))) } diff --git a/src/test/scala/com/herminiogarcia/shexml/datatype/DataTypeGenerationFullURI.scala b/src/test/scala/com/herminiogarcia/shexml/datatype/DataTypeGenerationFullURI.scala index e7d7e12..8cbbeb6 100644 --- a/src/test/scala/com/herminiogarcia/shexml/datatype/DataTypeGenerationFullURI.scala +++ b/src/test/scala/com/herminiogarcia/shexml/datatype/DataTypeGenerationFullURI.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.datatype -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class DataTypeGenerationFullURI extends AnyFunSuite with Matchers with RDFStatementCreator { +class DataTypeGenerationFullURI extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -29,10 +33,15 @@ class DataTypeGenerationFullURI extends AnyFunSuite with Matchers with RDFStatem | ex:num [person.num] [person.dt] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Numbers and datatypes translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "Jane", "num", "3.14", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteral(prefix, "John", "num", "3", XSDDatatype.XSDinteger))) diff --git a/src/test/scala/com/herminiogarcia/shexml/datatype/DataTypeGenerationWithoutPrefix.scala b/src/test/scala/com/herminiogarcia/shexml/datatype/DataTypeGenerationWithoutPrefix.scala index 142b8c5..874474c 100644 --- a/src/test/scala/com/herminiogarcia/shexml/datatype/DataTypeGenerationWithoutPrefix.scala +++ b/src/test/scala/com/herminiogarcia/shexml/datatype/DataTypeGenerationWithoutPrefix.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.datatype -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class DataTypeGenerationWithoutPrefix extends AnyFunSuite with Matchers with RDFStatementCreator { +class DataTypeGenerationWithoutPrefix extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -30,10 +34,15 @@ class DataTypeGenerationWithoutPrefix extends AnyFunSuite with Matchers with RDF | ex:num [person.num] xsd:[person.dt] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Numbers and datatypes translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "Jane", "num", "3.14", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteral(prefix, "John", "num", "3", XSDDatatype.XSDinteger))) diff --git a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsBadConditionOnNameTest.scala b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsBadConditionOnNameTest.scala index 8392c27..1191c11 100644 --- a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsBadConditionOnNameTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsBadConditionOnNameTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.joins -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsJoinLeftWithReviewsBadConditionOnNameTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsJoinLeftWithReviewsBadConditionOnNameTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigNormaliseURIsFixture { private val example = """ @@ -61,10 +65,15 @@ class FilmsJoinLeftWithReviewsBadConditionOnNameTest extends AnyFunSuite with Ma |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = false, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Film Inception is translated correctly") { assert(output.contains(createStatement(prefix, "3", "year", "2010"))) assert(output.contains(createStatement(prefix, "3", "countryOfOrigin", "USA"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsBadConditionTest.scala b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsBadConditionTest.scala index 0b1f271..a770497 100644 --- a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsBadConditionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsBadConditionTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.joins -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsJoinLeftWithReviewsBadConditionTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsJoinLeftWithReviewsBadConditionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigNormaliseURIsFixture { private val example = """ @@ -62,10 +66,15 @@ class FilmsJoinLeftWithReviewsBadConditionTest extends AnyFunSuite with Matchers |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = false, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Film Inception is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "Inception", "name", "Inception", XSDDatatype.XSDstring))) assert(output.contains(createStatement(prefix, "Inception", "year", "2010"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsJoinOnNameTest.scala b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsJoinOnNameTest.scala index 8f24385..22fd789 100644 --- a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsJoinOnNameTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsJoinOnNameTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.joins -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsJoinLeftWithReviewsJoinOnNameTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsJoinLeftWithReviewsJoinOnNameTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigNormaliseURIsFixture { private val example = """ @@ -61,10 +65,15 @@ class FilmsJoinLeftWithReviewsJoinOnNameTest extends AnyFunSuite with Matchers w |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = false, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Film Inception is translated correctly") { assert(output.contains(createStatement(prefix, "3", "year", "2010"))) assert(output.contains(createStatement(prefix, "3", "countryOfOrigin", "USA"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsTest.scala b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsTest.scala index c4e71d9..941bf47 100644 --- a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinLeftWithReviewsTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.joins -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsJoinLeftWithReviewsTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsJoinLeftWithReviewsTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigNormaliseURIsFixture { private val example = """ @@ -62,10 +66,15 @@ class FilmsJoinLeftWithReviewsTest extends AnyFunSuite with Matchers with RDFSta |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = false, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Film Inception is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "Inception", "name", "Inception", XSDDatatype.XSDstring))) assert(output.contains(createStatement(prefix, "Inception", "year", "2010"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsBadConditionOnNameTest.scala b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsBadConditionOnNameTest.scala index 8e1bdbb..12bae01 100644 --- a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsBadConditionOnNameTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsBadConditionOnNameTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.joins -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsJoinRightWithReviewsBadConditionOnNameTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsJoinRightWithReviewsBadConditionOnNameTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigNormaliseURIsFixture { private val example = """ @@ -61,10 +65,15 @@ class FilmsJoinRightWithReviewsBadConditionOnNameTest extends AnyFunSuite with M |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = false, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Film Inception is translated correctly") { assert(output.contains(createStatement(prefix, "3", "year", "2010"))) assert(output.contains(createStatement(prefix, "3", "countryOfOrigin", "USA"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsBadConditionTest.scala b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsBadConditionTest.scala index 136de0d..993be7e 100644 --- a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsBadConditionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsBadConditionTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.joins -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsJoinRightWithReviewsBadConditionTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsJoinRightWithReviewsBadConditionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigNormaliseURIsFixture { private val example = """ @@ -62,10 +66,15 @@ class FilmsJoinRightWithReviewsBadConditionTest extends AnyFunSuite with Matcher |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = false, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Film Inception is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "Inception", "name", "Inception", XSDDatatype.XSDstring))) assert(output.contains(createStatement(prefix, "Inception", "year", "2010"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsJoinOnNameTest.scala b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsJoinOnNameTest.scala index 04b70d9..c4e7b5a 100644 --- a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsJoinOnNameTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsJoinOnNameTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.joins -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsJoinRightWithReviewsJoinOnNameTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsJoinRightWithReviewsJoinOnNameTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigNormaliseURIsFixture { private val example = """ @@ -61,10 +65,15 @@ class FilmsJoinRightWithReviewsJoinOnNameTest extends AnyFunSuite with Matchers |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = false, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Film Inception is translated correctly") { assert(output.contains(createStatement(prefix, "3", "year", "2010"))) assert(output.contains(createStatement(prefix, "3", "countryOfOrigin", "USA"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsTest.scala b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsTest.scala index 5fd46b9..840f1f6 100644 --- a/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/joins/FilmsJoinRightWithReviewsTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.joins -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsJoinRightWithReviewsTest extends AnyFunSuite with Matchers with RDFStatementCreator { +class FilmsJoinRightWithReviewsTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigNormaliseURIsFixture { private val example = """ @@ -62,10 +66,15 @@ class FilmsJoinRightWithReviewsTest extends AnyFunSuite with Matchers with RDFSt |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = false, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Film Inception is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "Inception", "name", "Inception", XSDDatatype.XSDstring))) assert(output.contains(createStatement(prefix, "Inception", "year", "2010"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/AccessFieldsOutsideIterators.scala b/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/AccessFieldsOutsideIterators.scala index d473641..e65a126 100644 --- a/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/AccessFieldsOutsideIterators.scala +++ b/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/AccessFieldsOutsideIterators.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.mappingChallenges -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class AccessFieldsOutsideIterators extends AnyFunSuite with Matchers with RDFStatementCreator { +class AccessFieldsOutsideIterators extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -66,10 +70,15 @@ class AccessFieldsOutsideIterators extends AnyFunSuite with Matchers with RDFSta """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/DataTypeAndLangTagGenerationFromData.scala b/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/DataTypeAndLangTagGenerationFromData.scala index 301ad5f..361bdca 100644 --- a/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/DataTypeAndLangTagGenerationFromData.scala +++ b/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/DataTypeAndLangTagGenerationFromData.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.mappingChallenges -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class DataTypeAndLangTagGenerationFromData extends AnyFunSuite with Matchers with RDFStatementCreator { +class DataTypeAndLangTagGenerationFromData extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -33,10 +37,15 @@ class DataTypeAndLangTagGenerationFromData extends AnyFunSuite with Matchers wit | :num [values.num] [values.dt] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Numbers and datatypes translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "Jane", "num", "3.14", XSDDatatype.XSDdecimal))) assert(output.contains(createStatementWithLiteral(prefix, "John", "num", "3", XSDDatatype.XSDinteger))) diff --git a/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/JoinChallenge.scala b/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/JoinChallenge.scala index 19c7b1d..551936a 100644 --- a/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/JoinChallenge.scala +++ b/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/JoinChallenge.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.mappingChallenges -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JoinChallenge extends AnyFunSuite with Matchers with RDFStatementCreator { +class JoinChallenge extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -34,10 +38,15 @@ class JoinChallenge extends AnyFunSuite with Matchers with RDFStatementCreator { | :lastName [familyName] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Author shape translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "1", "affiliation", "Uni1", XSDDatatype.XSDstring))) assert(output.contains(createStatementWithLiteral(prefix, "1", "lastName", "Doe", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/MultiValueReferencesHierarchicalFile.scala b/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/MultiValueReferencesHierarchicalFile.scala index 54dfd8c..0092529 100644 --- a/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/MultiValueReferencesHierarchicalFile.scala +++ b/src/test/scala/com/herminiogarcia/shexml/mappingChallenges/MultiValueReferencesHierarchicalFile.scala @@ -1,13 +1,17 @@ package com.herminiogarcia.shexml.mappingChallenges -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class MultiValueReferencesHierarchicalFile extends AnyFunSuite with Matchers with RDFStatementCreator { +class MultiValueReferencesHierarchicalFile extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { private val example = """ @@ -46,10 +50,15 @@ class MultiValueReferencesHierarchicalFile extends AnyFunSuite with Matchers wit | ex:hasAffiliation ex:[labValues.articles.authors.affiliation.label] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMapping(example).getDefaultModel + + private var output: Model = _ private val prefix = "http://example.com/" + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + test("Lab shape is correctly translated") { assert(output.contains(createStatement(prefix, "AmazingLab1", "hasArticles", "article1"))) assert(output.contains(createStatement(prefix, "AmazingLab1", "hasArticles", "article2"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/CommentIteratorExpressionTest.scala b/src/test/scala/com/herminiogarcia/shexml/rml/CommentIteratorExpressionTest.scala index 5f8c634..a1522f7 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/CommentIteratorExpressionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/CommentIteratorExpressionTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class CommentIteratorExpressionTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class CommentIteratorExpressionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -40,10 +44,15 @@ class CommentIteratorExpressionTest extends AnyFunSuite with Matchers with RDFSt | #ex:long [performances.long] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/CommentTest.scala b/src/test/scala/com/herminiogarcia/shexml/rml/CommentTest.scala index f3981f7..e3c76e0 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/CommentTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/CommentTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class CommentTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class CommentTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -43,10 +47,15 @@ class CommentTest extends AnyFunSuite with Matchers with RDFStatementCreator wit | #ex:long [long_union] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/DataTypeAndLangTagGenerationFromData.scala b/src/test/scala/com/herminiogarcia/shexml/rml/DataTypeAndLangTagGenerationFromData.scala index 684e240..41ea6ae 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/DataTypeAndLangTagGenerationFromData.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/DataTypeAndLangTagGenerationFromData.scala @@ -1,13 +1,17 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class DataTypeAndLangTagGenerationFromData extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class DataTypeAndLangTagGenerationFromData extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -32,10 +36,15 @@ class DataTypeAndLangTagGenerationFromData extends AnyFunSuite with Matchers wit | :num [values.num] #[values.dt] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Lang tags translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "Jane", "lastname", "Smith", "fr"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/FilmWithActorsTest.scala b/src/test/scala/com/herminiogarcia/shexml/rml/FilmWithActorsTest.scala index fa9fa97..26da45a 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/FilmWithActorsTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/FilmWithActorsTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmWithActorsTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class FilmWithActorsTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -70,10 +74,15 @@ class FilmWithActorsTest extends AnyFunSuite with Matchers with RDFStatementCrea |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 1 is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/FilmsExternalQueryMySQLTest.scala b/src/test/scala/com/herminiogarcia/shexml/rml/FilmsExternalQueryMySQLTest.scala index 4d78b01..dcba8f2 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/FilmsExternalQueryMySQLTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/FilmsExternalQueryMySQLTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigDatabase, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsExternalQueryMySQLTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class FilmsExternalQueryMySQLTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigDatabase with RMLTestConversion { private val example = """ @@ -34,10 +38,14 @@ class FilmsExternalQueryMySQLTest extends AnyFunSuite with Matchers with RDFStat |} """.stripMargin - private val mappingLauncher = new MappingLauncher("root", "root", inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 8 is translated correctly") { assert(output.contains(createStatement(prefix, "8", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/FilmsMySQLTest.scala b/src/test/scala/com/herminiogarcia/shexml/rml/FilmsMySQLTest.scala index 26fee8d..c7a3d82 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/FilmsMySQLTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/FilmsMySQLTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigDatabase, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsMySQLTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class FilmsMySQLTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigDatabase with RMLTestConversion { private val example = """ @@ -33,10 +37,15 @@ class FilmsMySQLTest extends AnyFunSuite with Matchers with RDFStatementCreator |} """.stripMargin - private val mappingLauncher = new MappingLauncher("root", "root", inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 8 is translated correctly") { assert(output.contains(createStatement(prefix, "8", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/FilmsPostgresTest.scala b/src/test/scala/com/herminiogarcia/shexml/rml/FilmsPostgresTest.scala index e4a7f1c..d55a05e 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/FilmsPostgresTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/FilmsPostgresTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigDatabase, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsPostgresTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class FilmsPostgresTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigDatabase with RMLTestConversion { private val example = """ @@ -33,10 +37,15 @@ class FilmsPostgresTest extends AnyFunSuite with Matchers with RDFStatementCreat |} """.stripMargin - private val mappingLauncher = new MappingLauncher("root", "root", inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 8 is translated correctly") { assert(output.contains(createStatement(prefix, "8", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/GraphMultipleElementIteratorExpressionTest.scala b/src/test/scala/com/herminiogarcia/shexml/rml/GraphMultipleElementIteratorExpressionTest.scala index 11fdf19..070d665 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/GraphMultipleElementIteratorExpressionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/GraphMultipleElementIteratorExpressionTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class GraphMultipleElementIteratorExpressionTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class GraphMultipleElementIteratorExpressionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -48,12 +52,17 @@ class GraphMultipleElementIteratorExpressionTest extends AnyFunSuite with Matche |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + private var output: Model = _ + private var graphMyFilms: Model = _ private val prefix = "http://example.com/" - private val dataset = doTranslation(result, prefix) - private val output = dataset.getDefaultModel - private val graphMyFilms = dataset.getNamedModel(prefix + "MyFilms") + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + val dataset = doTranslation(result, prefix) + output = dataset.getDefaultModel + graphMyFilms = dataset.getNamedModel(prefix + "MyFilms") + } test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMapping.scala b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMapping.scala index 5246ebb..ecc7b85 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMapping.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMapping.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMapping extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMapping extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -45,10 +49,15 @@ class JsonAndXmlEventsMapping extends AnyFunSuite with Matchers with RDFStatemen | ex:long [long_union] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingIteratorExpression.scala b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingIteratorExpression.scala index 835fdd5..1d4be09 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingIteratorExpression.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingIteratorExpression.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingIteratorExpression extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingIteratorExpression extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -43,10 +47,15 @@ class JsonAndXmlEventsMappingIteratorExpression extends AnyFunSuite with Matcher | ex:long [performances.long] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithBNode.scala b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithBNode.scala index e6738db..1f66755 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithBNode.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithBNode.scala @@ -1,13 +1,17 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingWithBNode extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingWithBNode extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -42,10 +46,15 @@ class JsonAndXmlEventsMappingWithBNode extends AnyFunSuite with Matchers with RD | ex:long [performances.long] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } /**test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteralAndBNodeSubject(output, prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithBlankPrefix.scala b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithBlankPrefix.scala index 030adbc..b6ef6b3 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithBlankPrefix.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithBlankPrefix.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class JsonAndXmlEventsMappingWithBlankPrefix extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingWithBlankPrefix extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { val example = """ @@ -43,10 +47,14 @@ class JsonAndXmlEventsMappingWithBlankPrefix extends AnyFunSuite with Matchers w |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression.scala b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression.scala index f50603a..85fb04a 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { val example = """ @@ -42,10 +46,14 @@ class JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression extends AnyFunSui |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithExternalQuery.scala b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithExternalQuery.scala index edf1bc2..bfbdb49 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithExternalQuery.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithExternalQuery.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingWithExternalQuery extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingWithExternalQuery extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -47,10 +51,15 @@ class JsonAndXmlEventsMappingWithExternalQuery extends AnyFunSuite with Matchers | ex:long [long_union] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithJoin.scala b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithJoin.scala index b465f9f..8e27fbe 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithJoin.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithJoin.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingWithJoin extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingWithJoin extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { val example = """ @@ -46,10 +50,15 @@ class JsonAndXmlEventsMappingWithJoin extends AnyFunSuite with Matchers with RDF |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithJoinIteratorExpression.scala b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithJoinIteratorExpression.scala index 32f8f0d..dfe00bd 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithJoinIteratorExpression.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/JsonAndXmlEventsMappingWithJoinIteratorExpression.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingWithJoinIteratorExpression extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingWithJoinIteratorExpression extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { val example = """ @@ -45,10 +49,14 @@ class JsonAndXmlEventsMappingWithJoinIteratorExpression extends AnyFunSuite with |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementIteratorExpressionPrettifiedTest.scala b/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementIteratorExpressionPrettifiedTest.scala index 22d21e6..6da8ec8 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementIteratorExpressionPrettifiedTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementIteratorExpressionPrettifiedTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementIteratorExpressionPrettifiedTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class MultipleElementIteratorExpressionPrettifiedTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -38,10 +42,14 @@ class MultipleElementIteratorExpressionPrettifiedTest extends AnyFunSuite with M |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementIteratorExpressionTest.scala b/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementIteratorExpressionTest.scala index 15292bc..b66a8ea 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementIteratorExpressionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementIteratorExpressionTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementIteratorExpressionTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class MultipleElementIteratorExpressionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -38,10 +42,14 @@ class MultipleElementIteratorExpressionTest extends AnyFunSuite with Matchers wi |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementIteratorExpressionWithCSVTest.scala b/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementIteratorExpressionWithCSVTest.scala index 67b6829..0342d1f 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementIteratorExpressionWithCSVTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementIteratorExpressionWithCSVTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementIteratorExpressionWithCSVTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class MultipleElementIteratorExpressionWithCSVTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -46,10 +50,14 @@ class MultipleElementIteratorExpressionWithCSVTest extends AnyFunSuite with Matc |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementTest.scala b/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementTest.scala index 94ee5ff..24c1b96 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rml/MultipleElementTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rml -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class MultipleElementTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -40,10 +44,14 @@ class MultipleElementTest extends AnyFunSuite with Matchers with RDFStatementCre |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example) + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 1 is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/CommentIteratorExpressionTest.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/CommentIteratorExpressionTest.scala index f7cf296..18e1e49 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/CommentIteratorExpressionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/CommentIteratorExpressionTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class CommentIteratorExpressionTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class CommentIteratorExpressionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -40,10 +44,15 @@ class CommentIteratorExpressionTest extends AnyFunSuite with Matchers with RDFSt | #ex:long [performances.long] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/CommentTest.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/CommentTest.scala index f1c5a2b..78228d0 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/CommentTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/CommentTest.scala @@ -1,12 +1,16 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class CommentTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class CommentTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -44,10 +48,15 @@ class CommentTest extends AnyFunSuite with Matchers with RDFStatementCreator wit | #ex:long [long_union] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/DataTypeAndLangTagGenerationFromData.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/DataTypeAndLangTagGenerationFromData.scala index 9477bb6..273c8c7 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/DataTypeAndLangTagGenerationFromData.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/DataTypeAndLangTagGenerationFromData.scala @@ -1,13 +1,17 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class DataTypeAndLangTagGenerationFromData extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class DataTypeAndLangTagGenerationFromData extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -32,10 +36,15 @@ class DataTypeAndLangTagGenerationFromData extends AnyFunSuite with Matchers wit | :num [values.num] #[values.dt] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Lang tags translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "Jane", "lastname", "Smith", "fr"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmWithActorsTest.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmWithActorsTest.scala index e9c1ae9..6a1a3e9 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmWithActorsTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmWithActorsTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmWithActorsTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class FilmWithActorsTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -70,10 +74,15 @@ class FilmWithActorsTest extends AnyFunSuite with Matchers with RDFStatementCrea |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 1 is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmsExternalQueryMySQLTest.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmsExternalQueryMySQLTest.scala index 54b1440..4650367 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmsExternalQueryMySQLTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmsExternalQueryMySQLTest.scala @@ -1,12 +1,16 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigDatabase, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsExternalQueryMySQLTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class FilmsExternalQueryMySQLTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigDatabase with RMLTestConversion { private val example = """ @@ -35,10 +39,15 @@ class FilmsExternalQueryMySQLTest extends AnyFunSuite with Matchers with RDFStat |} """.stripMargin - private val mappingLauncher = new MappingLauncher("root", "root", inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 8 is translated correctly") { assert(output.contains(createStatement(prefix, "8", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmsMySQLTest.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmsMySQLTest.scala index 5adbf0f..ed1afae 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmsMySQLTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmsMySQLTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigDatabase, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsMySQLTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class FilmsMySQLTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigDatabase with RMLTestConversion { private val example = """ @@ -33,10 +37,15 @@ class FilmsMySQLTest extends AnyFunSuite with Matchers with RDFStatementCreator |} """.stripMargin - private val mappingLauncher = new MappingLauncher("root", "root", inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 8 is translated correctly") { assert(output.contains(createStatement(prefix, "8", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmsPostgresTest.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmsPostgresTest.scala index 302a1ff..d391578 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmsPostgresTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/FilmsPostgresTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigDatabase, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class FilmsPostgresTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class FilmsPostgresTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigDatabase with RMLTestConversion { private val example = """ @@ -33,10 +37,15 @@ class FilmsPostgresTest extends AnyFunSuite with Matchers with RDFStatementCreat |} """.stripMargin - private val mappingLauncher = new MappingLauncher("root", "root", inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 8 is translated correctly") { assert(output.contains(createStatement(prefix, "8", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/GraphMultipleElementIteratorExpressionTest.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/GraphMultipleElementIteratorExpressionTest.scala index 632c2c4..2fcf03f 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/GraphMultipleElementIteratorExpressionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/GraphMultipleElementIteratorExpressionTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class GraphMultipleElementIteratorExpressionTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class GraphMultipleElementIteratorExpressionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -48,12 +52,17 @@ class GraphMultipleElementIteratorExpressionTest extends AnyFunSuite with Matche |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + private var output: Model = _ + private var graphMyFilms: Model = _ private val prefix = "http://example.com/" - private val dataset = doTranslation(result, prefix) - private val output = dataset.getDefaultModel - private val graphMyFilms = dataset.getNamedModel(prefix + "MyFilms") + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + val dataset = doTranslation(result, prefix) + output = dataset.getDefaultModel + graphMyFilms = dataset.getNamedModel(prefix + "MyFilms") + } test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMapping.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMapping.scala index 01c7e33..fd43002 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMapping.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMapping.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMapping extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMapping extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -45,10 +49,15 @@ class JsonAndXmlEventsMapping extends AnyFunSuite with Matchers with RDFStatemen | ex:long [long_union] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingIteratorExpression.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingIteratorExpression.scala index 3edb9bc..e31c48a 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingIteratorExpression.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingIteratorExpression.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingIteratorExpression extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingIteratorExpression extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -43,10 +47,15 @@ class JsonAndXmlEventsMappingIteratorExpression extends AnyFunSuite with Matcher | ex:long [performances.long] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithBNode.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithBNode.scala index 1149e07..7979494 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithBNode.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithBNode.scala @@ -1,13 +1,17 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingWithBNode extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingWithBNode extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -42,10 +46,15 @@ class JsonAndXmlEventsMappingWithBNode extends AnyFunSuite with Matchers with RD | ex:long [performances.long] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } /**test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteralAndBNodeSubject(output, prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDdecimal))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithBlankPrefix.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithBlankPrefix.scala index 7cd5cba..eea965e 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithBlankPrefix.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithBlankPrefix.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class JsonAndXmlEventsMappingWithBlankPrefix extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingWithBlankPrefix extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { val example = """ @@ -43,10 +47,15 @@ class JsonAndXmlEventsMappingWithBlankPrefix extends AnyFunSuite with Matchers w |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression.scala index 792714d..86d588e 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { val example = """ @@ -42,10 +46,15 @@ class JsonAndXmlEventsMappingWithBlankPrefixIteratorExpression extends AnyFunSui |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithExternalQuery.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithExternalQuery.scala index c1f9b23..301b0dc 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithExternalQuery.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithExternalQuery.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingWithExternalQuery extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingWithExternalQuery extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -47,10 +51,15 @@ class JsonAndXmlEventsMappingWithExternalQuery extends AnyFunSuite with Matchers | ex:long [long_union] ; |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithJoin.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithJoin.scala index c1dd29b..d469ec8 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithJoin.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithJoin.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingWithJoin extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingWithJoin extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { val example = """ @@ -46,10 +50,15 @@ class JsonAndXmlEventsMappingWithJoin extends AnyFunSuite with Matchers with RDF |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithJoinIteratorExpression.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithJoinIteratorExpression.scala index cdf612f..8ee4f1d 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithJoinIteratorExpression.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/JsonAndXmlEventsMappingWithJoinIteratorExpression.scala @@ -1,14 +1,18 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMappingWithJoinIteratorExpression extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class JsonAndXmlEventsMappingWithJoinIteratorExpression extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { val example = """ @@ -45,10 +49,15 @@ class JsonAndXmlEventsMappingWithJoinIteratorExpression extends AnyFunSuite with |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://ex.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Location shape is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "51.043613-3.717333", "lat", "51.043613", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementIteratorExpressionPrettifiedTest.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementIteratorExpressionPrettifiedTest.scala index 0f0fa07..2a5501a 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementIteratorExpressionPrettifiedTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementIteratorExpressionPrettifiedTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementIteratorExpressionPrettifiedTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class MultipleElementIteratorExpressionPrettifiedTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -38,10 +42,15 @@ class MultipleElementIteratorExpressionPrettifiedTest extends AnyFunSuite with M |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementIteratorExpressionTest.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementIteratorExpressionTest.scala index 7175109..0296a52 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementIteratorExpressionTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementIteratorExpressionTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementIteratorExpressionTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class MultipleElementIteratorExpressionTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -38,10 +42,15 @@ class MultipleElementIteratorExpressionTest extends AnyFunSuite with Matchers wi |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementIteratorExpressionWithCSVTest.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementIteratorExpressionWithCSVTest.scala index 42f30af..4931497 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementIteratorExpressionWithCSVTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementIteratorExpressionWithCSVTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementIteratorExpressionWithCSVTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class MultipleElementIteratorExpressionWithCSVTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -46,10 +50,15 @@ class MultipleElementIteratorExpressionWithCSVTest extends AnyFunSuite with Matc |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 1 is translated correctly") { assert(output.contains(createStatement(prefix, "1", "type", "Film"))) diff --git a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementTest.scala b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementTest.scala index b977ae7..3a5605d 100644 --- a/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/rmlPrettyPrint/MultipleElementTest.scala @@ -1,11 +1,15 @@ package com.herminiogarcia.shexml.rmlPrettyPrint -import com.herminiogarcia.shexml.{MappingLauncher, RDFStatementCreator} +import com.herminiogarcia.shexml.{ParallelConfigInferenceDatatypesNormaliseURIsFixture, RDFStatementCreator} import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers -class MultipleElementTest extends AnyFunSuite with Matchers with RDFStatementCreator with RMLTestConversion { +class MultipleElementTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture with RMLTestConversion { private val example = """ @@ -40,10 +44,15 @@ class MultipleElementTest extends AnyFunSuite with Matchers with RDFStatementCre |} """.stripMargin - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val result = mappingLauncher.launchRMLTranslation(example, true) + + private var output: Model = _ private val prefix = "http://example.com/" - private val output = doTranslation(result, prefix).getDefaultModel + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val result = mappingLauncher.launchRMLTranslation(example, true) + output = doTranslation(result, prefix).getDefaultModel + } test("Shape 1 is translated correctly") { assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", XSDDatatype.XSDstring))) diff --git a/src/test/scala/com/herminiogarcia/shexml/shacl/FilmsTest.scala b/src/test/scala/com/herminiogarcia/shexml/shacl/FilmsTest.scala index d0ef6f7..4c71059 100644 --- a/src/test/scala/com/herminiogarcia/shexml/shacl/FilmsTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/shacl/FilmsTest.scala @@ -1,9 +1,9 @@ package com.herminiogarcia.shexml.shacl +import com.herminiogarcia.shexml.ParallelConfigValidation import org.scalatest.funsuite.AnyFunSuite -import org.scalatest.matchers.must.Matchers -class FilmsTest extends AnyFunSuite with SHACLValidation { +class FilmsTest extends AnyFunSuite with SHACLValidation with ParallelConfigValidation { private val example = """ @@ -76,11 +76,11 @@ class FilmsTest extends AnyFunSuite with SHACLValidation { """.stripMargin test("Films validate against generated schema") { - assert(this.validate(example)) + assert(this.validate(example, parallelConfiguration = parallelConfiguration)) } test("Films validate against generated schema with closed shapes") { - assert(this.validate(example, true)) + assert(this.validate(example, true, parallelConfiguration = parallelConfiguration)) } } diff --git a/src/test/scala/com/herminiogarcia/shexml/shacl/FilmsTestWithBlankNodes.scala b/src/test/scala/com/herminiogarcia/shexml/shacl/FilmsTestWithBlankNodes.scala index 8641f47..bb591fb 100644 --- a/src/test/scala/com/herminiogarcia/shexml/shacl/FilmsTestWithBlankNodes.scala +++ b/src/test/scala/com/herminiogarcia/shexml/shacl/FilmsTestWithBlankNodes.scala @@ -1,8 +1,9 @@ package com.herminiogarcia.shexml.shacl +import com.herminiogarcia.shexml.ParallelConfigValidation import org.scalatest.funsuite.AnyFunSuite -class FilmsTestWithBlankNodes extends AnyFunSuite with SHACLValidation { +class FilmsTestWithBlankNodes extends AnyFunSuite with SHACLValidation with ParallelConfigValidation { private val example = """ @@ -75,11 +76,11 @@ class FilmsTestWithBlankNodes extends AnyFunSuite with SHACLValidation { """.stripMargin test("Films validate against generated schema") { - assert(this.validate(example)) + assert(this.validate(example, parallelConfiguration = parallelConfiguration)) } test("Films validate against generated schema with closed shapes") { - assert(this.validate(example, true)) + assert(this.validate(example, true, parallelConfiguration = parallelConfiguration)) } } diff --git a/src/test/scala/com/herminiogarcia/shexml/shacl/JsonAndXmlEventsMapping.scala b/src/test/scala/com/herminiogarcia/shexml/shacl/JsonAndXmlEventsMapping.scala index 9246a59..112fe01 100644 --- a/src/test/scala/com/herminiogarcia/shexml/shacl/JsonAndXmlEventsMapping.scala +++ b/src/test/scala/com/herminiogarcia/shexml/shacl/JsonAndXmlEventsMapping.scala @@ -1,12 +1,12 @@ package com.herminiogarcia.shexml.shacl +import com.herminiogarcia.shexml.ParallelConfigValidation import org.scalatest.funsuite.AnyFunSuite -import org.scalatest.matchers.must.Matchers /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMapping extends AnyFunSuite with SHACLValidation { +class JsonAndXmlEventsMapping extends AnyFunSuite with SHACLValidation with ParallelConfigValidation { private val example = """ @@ -46,11 +46,11 @@ class JsonAndXmlEventsMapping extends AnyFunSuite with SHACLValidation { """.stripMargin test("Events validate against created schema") { - assert(this.validate(example)) + assert(this.validate(example, parallelConfiguration = parallelConfiguration)) } test("Events validate against created schema with closed shapes") { - assert(this.validate(example, true)) + assert(this.validate(example, true, parallelConfiguration = parallelConfiguration)) } } diff --git a/src/test/scala/com/herminiogarcia/shexml/shacl/MultipleElementIteratorExpressionWithCSVAndDBTest.scala b/src/test/scala/com/herminiogarcia/shexml/shacl/MultipleElementIteratorExpressionWithCSVAndDBTest.scala index 033f4b3..2c6363e 100644 --- a/src/test/scala/com/herminiogarcia/shexml/shacl/MultipleElementIteratorExpressionWithCSVAndDBTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/shacl/MultipleElementIteratorExpressionWithCSVAndDBTest.scala @@ -1,9 +1,9 @@ package com.herminiogarcia.shexml.shacl +import com.herminiogarcia.shexml.ParallelConfigValidation import org.scalatest.funsuite.AnyFunSuite -import org.scalatest.matchers.must.Matchers -class MultipleElementIteratorExpressionWithCSVAndDBTest extends AnyFunSuite with SHACLValidation { +class MultipleElementIteratorExpressionWithCSVAndDBTest extends AnyFunSuite with SHACLValidation with ParallelConfigValidation { private val example = """ @@ -56,11 +56,11 @@ class MultipleElementIteratorExpressionWithCSVAndDBTest extends AnyFunSuite with """.stripMargin test("Films validate against generated schema") { - assert(this.validate(example)) + assert(this.validate(example, parallelConfiguration = parallelConfiguration)) } test("Films validate against generated schema with closed shapes") { - assert(this.validate(example, true)) + assert(this.validate(example, true, parallelConfiguration = parallelConfiguration)) } } diff --git a/src/test/scala/com/herminiogarcia/shexml/shacl/SHACLValidation.scala b/src/test/scala/com/herminiogarcia/shexml/shacl/SHACLValidation.scala index 3ceade6..13f9ca1 100644 --- a/src/test/scala/com/herminiogarcia/shexml/shacl/SHACLValidation.scala +++ b/src/test/scala/com/herminiogarcia/shexml/shacl/SHACLValidation.scala @@ -1,6 +1,7 @@ package com.herminiogarcia.shexml.shacl import com.herminiogarcia.shexml.MappingLauncher +import com.herminiogarcia.shexml.helper.ParallelExecutionConfigurator import org.apache.jena.query.DatasetFactory import org.apache.jena.riot.{Lang, RDFDataMgr} import org.apache.jena.shacl.ShaclValidator @@ -9,8 +10,8 @@ import java.io.ByteArrayInputStream trait SHACLValidation { - def validate(shexml: String, closed: Boolean = false): Boolean = { - val mappingLauncher = new MappingLauncher() + def validate(shexml: String, closed: Boolean = false, parallelConfiguration: ParallelExecutionConfigurator): Boolean = { + val mappingLauncher = new MappingLauncher(parallelCollectionConfigurator = parallelConfiguration) val dataGraph = mappingLauncher.launchMapping(shexml) val shaclString = mappingLauncher.launchSHACLGeneration(shexml, closed) diff --git a/src/test/scala/com/herminiogarcia/shexml/shex/FilmsWithInferredShapeMapAndBNodesTest.scala b/src/test/scala/com/herminiogarcia/shexml/shex/FilmsWithInferredShapeMapAndBNodesTest.scala index 4daae63..0bce966 100644 --- a/src/test/scala/com/herminiogarcia/shexml/shex/FilmsWithInferredShapeMapAndBNodesTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/shex/FilmsWithInferredShapeMapAndBNodesTest.scala @@ -1,9 +1,9 @@ package com.herminiogarcia.shexml.shex -import com.herminiogarcia.shexml.MappingLauncher +import com.herminiogarcia.shexml.{MappingLauncher, ParallelConfigValidation} import org.scalatest.funsuite.AnyFunSuite -class FilmsWithInferredShapeMapAndBNodesTest extends AnyFunSuite with ShExValidation { +class FilmsWithInferredShapeMapAndBNodesTest extends AnyFunSuite with ShExValidation with ParallelConfigValidation { private val example = """ @@ -76,7 +76,7 @@ class FilmsWithInferredShapeMapAndBNodesTest extends AnyFunSuite with ShExValida test("Films validate against generated schema") { val shapeMap = new MappingLauncher(normaliseURIs = true).launchShapeMapGeneration(example) - assert(this.validate(example, shapeMap)) + assert(this.validate(example, shapeMap, parallelConfiguration = parallelConfiguration)) } } diff --git a/src/test/scala/com/herminiogarcia/shexml/shex/FilmsWithInferredShapeMapTest.scala b/src/test/scala/com/herminiogarcia/shexml/shex/FilmsWithInferredShapeMapTest.scala index dfb7e47..8382964 100644 --- a/src/test/scala/com/herminiogarcia/shexml/shex/FilmsWithInferredShapeMapTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/shex/FilmsWithInferredShapeMapTest.scala @@ -1,9 +1,9 @@ package com.herminiogarcia.shexml.shex -import com.herminiogarcia.shexml.MappingLauncher +import com.herminiogarcia.shexml.{MappingLauncher, ParallelConfigValidation} import org.scalatest.funsuite.AnyFunSuite -class FilmsWithInferredShapeMapTest extends AnyFunSuite with ShExValidation { +class FilmsWithInferredShapeMapTest extends AnyFunSuite with ShExValidation with ParallelConfigValidation { private val example = """ @@ -76,7 +76,7 @@ class FilmsWithInferredShapeMapTest extends AnyFunSuite with ShExValidation { test("Films validate against generated schema") { val shapeMap = new MappingLauncher(normaliseURIs = true).launchShapeMapGeneration(example) - assert(this.validate(example, shapeMap)) + assert(this.validate(example, shapeMap, parallelConfiguration = parallelConfiguration)) } } diff --git a/src/test/scala/com/herminiogarcia/shexml/shex/JsonAndXmlEventsMapping.scala b/src/test/scala/com/herminiogarcia/shexml/shex/JsonAndXmlEventsMapping.scala index e91d677..9529321 100644 --- a/src/test/scala/com/herminiogarcia/shexml/shex/JsonAndXmlEventsMapping.scala +++ b/src/test/scala/com/herminiogarcia/shexml/shex/JsonAndXmlEventsMapping.scala @@ -1,11 +1,12 @@ package com.herminiogarcia.shexml.shex +import com.herminiogarcia.shexml.ParallelConfigValidation import org.scalatest.funsuite.AnyFunSuite /** * Created by herminio on 21/2/18. */ -class JsonAndXmlEventsMapping extends AnyFunSuite with ShExValidation { +class JsonAndXmlEventsMapping extends AnyFunSuite with ShExValidation with ParallelConfigValidation { private val example = """ @@ -47,7 +48,7 @@ class JsonAndXmlEventsMapping extends AnyFunSuite with ShExValidation { "ex:398@ex:Performance, ex:567@ex:Performance, ex:444@ex:Performance, ex:989@ex:Performance" test("Events validate against created schema") { - assert(this.validate(example, shapeMap)) + assert(this.validate(example, shapeMap, parallelConfiguration = parallelConfiguration)) } } diff --git a/src/test/scala/com/herminiogarcia/shexml/shex/MultipleElementIteratorExpressionWithCSVAndDBInferredShapeMapTest.scala b/src/test/scala/com/herminiogarcia/shexml/shex/MultipleElementIteratorExpressionWithCSVAndDBInferredShapeMapTest.scala index 1532443..d8db664 100644 --- a/src/test/scala/com/herminiogarcia/shexml/shex/MultipleElementIteratorExpressionWithCSVAndDBInferredShapeMapTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/shex/MultipleElementIteratorExpressionWithCSVAndDBInferredShapeMapTest.scala @@ -1,9 +1,9 @@ package com.herminiogarcia.shexml.shex -import com.herminiogarcia.shexml.MappingLauncher +import com.herminiogarcia.shexml.{MappingLauncher, ParallelConfigValidation} import org.scalatest.funsuite.AnyFunSuite -class MultipleElementIteratorExpressionWithCSVAndDBInferredShapeMapTest extends AnyFunSuite with ShExValidation { +class MultipleElementIteratorExpressionWithCSVAndDBInferredShapeMapTest extends AnyFunSuite with ShExValidation with ParallelConfigValidation { private val example = """ @@ -57,7 +57,7 @@ class MultipleElementIteratorExpressionWithCSVAndDBInferredShapeMapTest extends test("Films validate against generated schema") { val shapeMap = new MappingLauncher().launchShapeMapGeneration(example) - assert(this.validate(example, shapeMap)) + assert(this.validate(example, shapeMap, parallelConfiguration = parallelConfiguration)) } } diff --git a/src/test/scala/com/herminiogarcia/shexml/shex/MultipleElementIteratorExpressionWithCSVAndDBTest.scala b/src/test/scala/com/herminiogarcia/shexml/shex/MultipleElementIteratorExpressionWithCSVAndDBTest.scala index 5a15118..9de882c 100644 --- a/src/test/scala/com/herminiogarcia/shexml/shex/MultipleElementIteratorExpressionWithCSVAndDBTest.scala +++ b/src/test/scala/com/herminiogarcia/shexml/shex/MultipleElementIteratorExpressionWithCSVAndDBTest.scala @@ -1,8 +1,9 @@ package com.herminiogarcia.shexml.shex +import com.herminiogarcia.shexml.ParallelConfigValidation import org.scalatest.funsuite.AnyFunSuite -class MultipleElementIteratorExpressionWithCSVAndDBTest extends AnyFunSuite with ShExValidation { +class MultipleElementIteratorExpressionWithCSVAndDBTest extends AnyFunSuite with ShExValidation with ParallelConfigValidation { private val example = """ @@ -57,7 +58,7 @@ class MultipleElementIteratorExpressionWithCSVAndDBTest extends AnyFunSuite with "ex:6@ex:Films,ex:7@ex:Films,ex:8@ex:Films,ex:9@ex:Films" test("Films validate against generated schema") { - assert(this.validate(example, shapeMap)) + assert(this.validate(example, shapeMap, parallelConfiguration = parallelConfiguration)) } } diff --git a/src/test/scala/com/herminiogarcia/shexml/shex/ShExValidation.scala b/src/test/scala/com/herminiogarcia/shexml/shex/ShExValidation.scala index 1c1307d..84293aa 100644 --- a/src/test/scala/com/herminiogarcia/shexml/shex/ShExValidation.scala +++ b/src/test/scala/com/herminiogarcia/shexml/shex/ShExValidation.scala @@ -2,6 +2,7 @@ package com.herminiogarcia.shexml.shex import cats.effect.unsafe.implicits.global import com.herminiogarcia.shexml.MappingLauncher +import com.herminiogarcia.shexml.helper.ParallelExecutionConfigurator import es.weso.rdf.rdf4j.RDFAsRDF4jModel import es.weso.shapemaps.ShapeMap import es.weso.shex.validator.Validator @@ -13,8 +14,8 @@ import java.io.{ByteArrayInputStream, ByteArrayOutputStream} trait ShExValidation { - def validate(shexml: String, shapemap: String): Boolean = { - val mappingLauncher = new MappingLauncher(normaliseURIs = true) + def validate(shexml: String, shapemap: String, parallelConfiguration: ParallelExecutionConfigurator): Boolean = { + val mappingLauncher = new MappingLauncher(normaliseURIs = true, parallelCollectionConfigurator = parallelConfiguration) val output = mappingLauncher.launchMapping(shexml).getDefaultModel val outputStream = new ByteArrayOutputStream() output.write(outputStream, "Turtle") From 49384ebca1a185740c3798aaf5bf15b5348de24f Mon Sep 17 00:00:00 2001 From: herminiogg <2806005+herminiogg@users.noreply.github.com> Date: Mon, 11 Aug 2025 13:48:26 +0000 Subject: [PATCH 03/15] Pulled latest version of the ShExML CodeMeta file --- codemeta.json | 247 +++++++++++++++++++++----------------------------- 1 file changed, 102 insertions(+), 145 deletions(-) diff --git a/codemeta.json b/codemeta.json index ce82dac..6db2cf3 100644 --- a/codemeta.json +++ b/codemeta.json @@ -4,32 +4,110 @@ "schema" : "http://schema.org/", "id" : "@id", "type" : "@type", + "name" : { + "@id" : "schema:name" + }, + "version" : { + "@id" : "schema:version" + }, "identifier" : { + "@id" : "schema:identifier", "@type" : "@id" }, - "codeRepository" : { + "email" : { + "@id" : "schema:email" + }, + "affiliation" : { + "@id" : "schema:affiliation", + "@type" : "@id" + }, + "familyName" : { + "@id" : "schema:familyName" + }, + "givenName" : { + "@id" : "schema:givenName" + }, + "roleName" : { + "@id" : "schema:roleName" + }, + "author" : { + "@id" : "schema:author", "@type" : "@id" }, + "dateCreated" : { + "@id" : "schema:dateCreated", + "@type" : "http://www.w3.org/2001/XMLSchema#date" + }, + "softwareRequirements" : { + "@id" : "schema:softwareRequirements", + "@type" : "@id" + }, + "developmentStatus" : { + "@id" : "schema:developmentStatus" + }, "issueTracker" : { + "@id" : "https://w3id.org/codemeta/3.0/issueTracker", "@type" : "@id" }, + "referencePublication" : { + "@id" : "https://w3id.org/codemeta/3.0/referencePublication", + "@type" : "@id" + }, + "applicationCategory" : { + "@id" : "schema:applicationCategory" + }, + "dateModified" : { + "@id" : "schema:dateModified", + "@type" : "http://www.w3.org/2001/XMLSchema#date" + }, + "runtimePlatform" : { + "@id" : "schema:runtimePlatform" + }, + "codeRepository" : { + "@id" : "schema:codeRepository", + "@type" : "@id" + }, + "description" : { + "@id" : "schema:description" + }, "downloadUrl" : { + "@id" : "schema:downloadUrl", "@type" : "@id" }, "license" : { + "@id" : "schema:license", "@type" : "@id" }, - "schema:author" : { - "@type" : "@id" + "programmingLanguage" : { + "@id" : "schema:programmingLanguage" }, - "referencePublication" : { + "contributor" : { + "@id" : "schema:contributor", "@type" : "@id" + }, + "releaseNotes" : { + "@id" : "schema:releaseNotes" + }, + "SoftwareSourceCode" : { + "@id" : "schema:SoftwareSourceCode" + }, + "Person" : { + "@id" : "schema:Person" + }, + "Organization" : { + "@id" : "schema:Organization" + }, + "Role" : { + "@id" : "schema:Role" } }, "id" : "https://github.com/herminiogg/ShExML", "type" : "SoftwareSourceCode", "applicationCategory" : "Computer Science", "author" : [ { + "type" : "Role", + "roleName" : "Main author" + }, { "id" : "https://herminiogarcia.com/#me", "type" : "Person", "affiliation" : { @@ -41,155 +119,34 @@ "familyName" : "García González", "givenName" : "Herminio", "identifier" : "https://orcid.org/0000-0001-5590-4857" - }, { - "type" : "Role", - "schema:author" : "https://herminiogarcia.com/#me", - "roleName" : "Main author" } ], "codeRepository" : "https://github.com/herminiogg/ShExML", + "contributor" : { + "id" : "https://niod.knaw.nl/en/staff/mikebryant", + "type" : "Person", + "affiliation" : { + "id" : "https://niod.knaw.nl/en", + "type" : "Organization", + "name" : "NIOD Institute for War, Holocaust and Genocide Studies" + }, + "email" : "m.bryant@niod.knaw.nl", + "familyName" : "Bryant", + "givenName" : "Mike", + "identifier" : "https://orcid.org/0000-0003-0765-7390" + }, "dateCreated" : "2018-02-22", - "dateModified" : "2024-06-27", + "dateModified" : "2025-07-08", "description" : "A heterogeneous data mapping language based on Shape Expressions", "developmentStatus" : "active", "downloadUrl" : "https://api.github.com/repos/herminiogg/ShExML/downloads", - "identifier" : "https://doi.org/10.5281/zenodo.12569454", - "issueTracker" : "https://api.github.com/repos/herminiogg/ShExML/issues", + "identifier" : "https://doi.org/10.5281/zenodo.15837379", "license" : "https://api.github.com/licenses/mit", "name" : "ShExML", "programmingLanguage" : "Scala", - "referencePublication" : "https://doi.org/10.7717/peerj-cs.318", - "releaseNotes" : "## What's Changed\r\n* Solved a performance problem when executing functions over big data sources", + "releaseNotes" : "## What's Changed\r\n* Fixed a bug which prevented the generation of a subject based on a condition applied down the hierarchy.\r\n* Added the possibility to get the iteration index as part of a new builtin functions mechanism.\r\n* Iterators and fields can now be placed in any order.\r\n* Allowed the option to use dashes in the variables names.\r\n* Added the possibility to pass autoincrement ids as arguments of a function.\r\n* Added an option to precompile the ShExML input (`-pc` in the CLI) to generate a single version with all the imported files incorporated and check the input for syntactic and grammatical errors. (This should facilitate debugging in these kinds of files.)\r\n* Improved the CLI help message, removing unnecessary nesting of options and grouping them by categories.\r\n* The databases needed for some tests can now be set up locally using Docker (thanks @mikesname for this contribution).\r\n\r\n**Full Changelog**: https://github.com/herminiogg/ShExML/compare/v0.5.3...v0.5.4", "runtimePlatform" : "JVM", - "softwareRequirements" : [ { - "id" : "http://example.org/shex_3", - "type" : "SoftwareSourceCode", - "name" : "es.weso:shex_3", - "version" : "0.1.97" - }, { - "id" : "http://example.org/postgresql", - "type" : "SoftwareSourceCode", - "name" : "org.postgresql:postgresql", - "version" : "42.5.0" - }, { - "id" : "http://example.org/picocli", - "type" : "SoftwareSourceCode", - "name" : "info.picocli:picocli", - "version" : "4.0.4" - }, { - "id" : "http://example.org/srdf4j_3", - "type" : "SoftwareSourceCode", - "name" : "es.weso:srdf4j_3", - "version" : "0.1.104" - }, { - "id" : "http://example.org/rmlmapper", - "type" : "SoftwareSourceCode", - "name" : "be.ugent.rml:rmlmapper", - "version" : "4.9.0" - }, { - "id" : "http://example.org/scala-logging_3", - "type" : "SoftwareSourceCode", - "name" : "com.typesafe.scala-logging:scala-logging_3", - "version" : "3.9.5" - }, { - "id" : "http://example.org/stringdistance_2.13", - "type" : "SoftwareSourceCode", - "name" : "com.github.vickumar1981:stringdistance_2.13", - "version" : "1.2.6" - }, { - "id" : "http://example.org/srdf_3", - "type" : "SoftwareSourceCode", - "name" : "es.weso:srdf_3", - "version" : "0.1.104" - }, { - "id" : "http://example.org/jena-arq", - "type" : "SoftwareSourceCode", - "name" : "org.apache.jena:jena-arq", - "version" : "3.17.0" - }, { - "id" : "http://example.org/jena-shacl", - "type" : "SoftwareSourceCode", - "name" : "org.apache.jena:jena-shacl", - "version" : "3.17.0" - }, { - "id" : "http://example.org/scalatest_3", - "type" : "SoftwareSourceCode", - "name" : "org.scalatest:scalatest_3", - "version" : "3.2.9" - }, { - "id" : "http://example.org/mariadb-java-client", - "type" : "SoftwareSourceCode", - "name" : "org.mariadb.jdbc:mariadb-java-client", - "version" : "2.6.2" - }, { - "id" : "http://example.org/slf4j-nop", - "type" : "SoftwareSourceCode", - "name" : "org.slf4j:slf4j-nop", - "version" : "1.7.27" - }, { - "id" : "http://example.org/logback-classic", - "type" : "SoftwareSourceCode", - "name" : "ch.qos.logback:logback-classic", - "version" : "1.3.5" - }, { - "id" : "http://example.org/scala3-library_3", - "type" : "SoftwareSourceCode", - "name" : "org.scala-lang:scala3-library_3", - "version" : "3.2.0" - }, { - "id" : "http://example.org/Saxon-HE", - "type" : "SoftwareSourceCode", - "name" : "net.sf.saxon:Saxon-HE", - "version" : "12.4" - }, { - "id" : "http://example.org/sqlite-jdbc", - "type" : "SoftwareSourceCode", - "name" : "org.xerial:sqlite-jdbc", - "version" : "3.32.3.2" - }, { - "id" : "http://example.org/scala-reflect", - "type" : "SoftwareSourceCode", - "name" : "org.scala-lang:scala-reflect", - "version" : "2.13.9" - }, { - "id" : "http://example.org/scala-csv_2.13", - "type" : "SoftwareSourceCode", - "name" : "com.github.tototoshi:scala-csv_2.13", - "version" : "1.3.6" - }, { - "id" : "http://example.org/antlr4", - "type" : "SoftwareSourceCode", - "name" : "org.antlr:antlr4", - "version" : "4.9.2" - }, { - "id" : "http://example.org/json-path", - "type" : "SoftwareSourceCode", - "name" : "com.jayway.jsonpath:json-path", - "version" : "2.8.0" - }, { - "id" : "http://example.org/jena-core", - "type" : "SoftwareSourceCode", - "name" : "org.apache.jena:jena-core", - "version" : "3.17.0" - }, { - "id" : "http://example.org/jena-base", - "type" : "SoftwareSourceCode", - "name" : "org.apache.jena:jena-base", - "version" : "3.17.0" - }, { - "id" : "http://example.org/mysql-connector-java", - "type" : "SoftwareSourceCode", - "name" : "mysql:mysql-connector-java", - "version" : "8.0.21" - }, { - "id" : "http://example.org/scala-compiler", - "type" : "SoftwareSourceCode", - "name" : "org.scala-lang:scala-compiler", - "version" : "2.13.9" - }, { - "id" : "http://example.org/mssql-jdbc", - "type" : "SoftwareSourceCode", - "name" : "com.microsoft.sqlserver:mssql-jdbc", - "version" : "8.4.1.jre8" - } ], - "version" : "0.5.3" + "softwareRequirements" : [ "http://example.org/jena-shacl", "http://example.org/Saxon-HE", "http://example.org/logback-classic", "http://example.org/jena-core", "http://example.org/scala-compiler", "http://example.org/mysql-connector-java", "http://example.org/stringdistance_2.13", "http://example.org/rmlmapper", "http://example.org/jena-base", "http://example.org/srdf_3", "http://example.org/mssql-jdbc", "http://example.org/json-path", "http://example.org/picocli", "http://example.org/postgresql", "http://example.org/scala3-library_3", "http://example.org/shex_3", "http://example.org/scala-logging_3", "http://example.org/jena-arq", "http://example.org/srdf4j_3", "http://example.org/slf4j-nop", "http://example.org/antlr4", "http://example.org/mariadb-java-client", "http://example.org/sqlite-jdbc", "http://example.org/scalatest_3", "http://example.org/scala-csv_2.13", "http://example.org/scala-reflect" ], + "version" : "0.5.4", + "issueTracker" : "https://api.github.com/repos/herminiogg/ShExML/issues", + "referencePublication" : "https://doi.org/10.7717/peerj-cs.318" } From 40047a68d3bd6b2968ce1f5b53288d503e7fdfe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Mon, 11 Aug 2025 16:28:48 +0200 Subject: [PATCH 04/15] Incremented the max memory for the parallel testing in the GitHub Action workflow --- .github/workflows/scala.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml index f17e70c..4c9c2bf 100644 --- a/.github/workflows/scala.yml +++ b/.github/workflows/scala.yml @@ -20,8 +20,8 @@ jobs: - name: Run tests run: sbt --mem 2048 "+ test" - name: Run tests parallel all - run: sbt --mem 2048 "+ testOnly * -- -Dparallel=all" + run: sbt --mem 4096 "+ testOnly * -- -Dparallel=all" - name: Run tests parallel shapes - run: sbt --mem 2048 "+ testOnly * -- -Dparallel=shapes" + run: sbt --mem 4096 "+ testOnly * -- -Dparallel=shapes" - name: Run tests parallel queries - run: sbt --mem 2048 "+ testOnly * -- -Dparallel=queries" + run: sbt --mem 4096 "+ testOnly * -- -Dparallel=queries" From 9dd81fee2360959649406efeab59199ef2078c9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Mon, 11 Aug 2025 16:41:24 +0200 Subject: [PATCH 05/15] Second attemp to increment the max memory size for the GitHub Action workflow --- .github/workflows/scala.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml index 4c9c2bf..8454e9d 100644 --- a/.github/workflows/scala.yml +++ b/.github/workflows/scala.yml @@ -20,8 +20,8 @@ jobs: - name: Run tests run: sbt --mem 2048 "+ test" - name: Run tests parallel all - run: sbt --mem 4096 "+ testOnly * -- -Dparallel=all" + run: sbt --mem 8192 "+ testOnly * -- -Dparallel=all" - name: Run tests parallel shapes - run: sbt --mem 4096 "+ testOnly * -- -Dparallel=shapes" + run: sbt --mem 8192 "+ testOnly * -- -Dparallel=shapes" - name: Run tests parallel queries - run: sbt --mem 4096 "+ testOnly * -- -Dparallel=queries" + run: sbt --mem 8192 "+ testOnly * -- -Dparallel=queries" From c80e8cd8221d27e6e553a67578d99cae80ec86f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Tue, 12 Aug 2025 14:12:16 +0200 Subject: [PATCH 06/15] Added fork and grouping options to the execution of tests in the GitHub Action workflow so that resources are liberated during their execution --- .github/workflows/scala.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml index 8454e9d..da4c130 100644 --- a/.github/workflows/scala.yml +++ b/.github/workflows/scala.yml @@ -9,19 +9,19 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up JDK 8 + - name: Set up JDK 21 uses: actions/setup-java@v4 with: - java-version: '17' - distribution: 'adopt' + java-version: '21' + distribution: 'temurin' - uses: sbt/setup-sbt@v1 - name: Build the docker compose stack run: docker compose up -d - name: Run tests run: sbt --mem 2048 "+ test" - name: Run tests parallel all - run: sbt --mem 8192 "+ testOnly * -- -Dparallel=all" + run: sbt --mem 8192 "set fork := true" "set Test / testGrouping := { (Test / definedTests).value.grouped(30).map { group => Tests.Group(group.head.name + \"-batch\", group, Tests.SubProcess(ForkOptions())) }.toSeq }" "+ testOnly * -- -Dparallel=all" - name: Run tests parallel shapes - run: sbt --mem 8192 "+ testOnly * -- -Dparallel=shapes" + run: sbt --mem 8192 "set fork := true" "set Test / testGrouping := { (Test / definedTests).value.grouped(30).map { group => Tests.Group(group.head.name + \"-batch\", group, Tests.SubProcess(ForkOptions())) }.toSeq }" "+ testOnly * -- -Dparallel=shapes" - name: Run tests parallel queries - run: sbt --mem 8192 "+ testOnly * -- -Dparallel=queries" + run: sbt --mem 8192 "set fork := true" "set Test / testGrouping := { (Test / definedTests).value.grouped(30).map { group => Tests.Group(group.head.name + \"-batch\", group, Tests.SubProcess(ForkOptions())) }.toSeq }" "+ testOnly * -- -Dparallel=queries" From d93864579529b2e5d070a6260cf9740fe26588c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Tue, 12 Aug 2025 14:15:52 +0200 Subject: [PATCH 07/15] Changed to JDK 17 in the GitHub Action workflow to continue supporting Scala 2.12 --- .github/workflows/scala.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml index da4c130..8b8d71f 100644 --- a/.github/workflows/scala.yml +++ b/.github/workflows/scala.yml @@ -9,10 +9,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up JDK 21 + - name: Set up JDK 17 uses: actions/setup-java@v4 with: - java-version: '21' + java-version: '17' distribution: 'temurin' - uses: sbt/setup-sbt@v1 - name: Build the docker compose stack From dad43626b1a9dcfa74a3e18b93ae060beb9a59d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Tue, 12 Aug 2025 14:26:18 +0200 Subject: [PATCH 08/15] Reducing the batch size for the tests in the GitHub Actions workflow --- .github/workflows/scala.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml index 8b8d71f..c22c064 100644 --- a/.github/workflows/scala.yml +++ b/.github/workflows/scala.yml @@ -20,8 +20,8 @@ jobs: - name: Run tests run: sbt --mem 2048 "+ test" - name: Run tests parallel all - run: sbt --mem 8192 "set fork := true" "set Test / testGrouping := { (Test / definedTests).value.grouped(30).map { group => Tests.Group(group.head.name + \"-batch\", group, Tests.SubProcess(ForkOptions())) }.toSeq }" "+ testOnly * -- -Dparallel=all" + run: sbt --mem 8192 "set fork := true" "set Test / testGrouping := { (Test / definedTests).value.grouped(20).map { group => Tests.Group(group.head.name + \"-batch\", group, Tests.SubProcess(ForkOptions())) }.toSeq }" "+ testOnly * -- -Dparallel=all" - name: Run tests parallel shapes - run: sbt --mem 8192 "set fork := true" "set Test / testGrouping := { (Test / definedTests).value.grouped(30).map { group => Tests.Group(group.head.name + \"-batch\", group, Tests.SubProcess(ForkOptions())) }.toSeq }" "+ testOnly * -- -Dparallel=shapes" + run: sbt --mem 8192 "set fork := true" "set Test / testGrouping := { (Test / definedTests).value.grouped(20).map { group => Tests.Group(group.head.name + \"-batch\", group, Tests.SubProcess(ForkOptions())) }.toSeq }" "+ testOnly * -- -Dparallel=shapes" - name: Run tests parallel queries - run: sbt --mem 8192 "set fork := true" "set Test / testGrouping := { (Test / definedTests).value.grouped(30).map { group => Tests.Group(group.head.name + \"-batch\", group, Tests.SubProcess(ForkOptions())) }.toSeq }" "+ testOnly * -- -Dparallel=queries" + run: sbt --mem 8192 "set fork := true" "set Test / testGrouping := { (Test / definedTests).value.grouped(20).map { group => Tests.Group(group.head.name + \"-batch\", group, Tests.SubProcess(ForkOptions())) }.toSeq }" "+ testOnly * -- -Dparallel=queries" From 7f0faf952d009d4be4b1f2a3e13fcbd887dd2282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Tue, 12 Aug 2025 15:23:10 +0200 Subject: [PATCH 09/15] Refactoring of the cross-compiled classes to avoid the duplication of code as much as possible. --- .../ParallelExecutionConfigurator.scala | 34 ++++-------------- .../ParallelExecutionConfigurator.scala | 33 ++++------------- .../ParallelExecutionConfigurator.scala | 33 ++++------------- .../ParallelExecutionConfiguratorGen.scala | 36 +++++++++++++++++++ 4 files changed, 54 insertions(+), 82 deletions(-) create mode 100644 src/main/scala/com/herminiogarcia/shexml/helper/ParallelExecutionConfiguratorGen.scala diff --git a/src/main/scala-2.12/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala b/src/main/scala-2.12/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala index 189a03d..a022c65 100644 --- a/src/main/scala-2.12/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala +++ b/src/main/scala-2.12/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala @@ -1,35 +1,13 @@ package com.herminiogarcia.shexml.helper -import scala.collection.parallel.{ForkJoinTaskSupport, ParSeq} -import scala.util.Try +import scala.collection.parallel.ParSeq -class ParallelExecutionConfigurator(val parallelisationAspectsOptions: Map[String, Boolean], val numberOfThreads: Option[Int]) { +class ParallelExecutionConfigurator(override val parallelisationAspectsOptions: Map[String, Boolean], override val numberOfThreads: Option[Int]) + extends ParallelExecutionConfiguratorGen(parallelisationAspectsOptions, numberOfThreads) { - def asParallelCollection[T](aspect: String, collection: Seq[T]): Either[Seq[T], ParSeq[T]] = { - if(!parallelisationAspectsOptions.getOrElse(aspect, false)) Left(collection) - else numberOfThreads match { - case Some(number) => - collection.par - val parallelCollection = collection.par - parallelCollection.tasksupport = new ForkJoinTaskSupport(new java.util.concurrent.ForkJoinPool(number)) - Right(parallelCollection) - case None => Right(collection.par) - } + override protected def convertToParallelCollection[T](collection: Seq[T]): ParSeq[T] = { + collection.par } } -object ParallelExecutionConfigurator { - - def apply(parallelAspects: String, numberOfThreads: String): ParallelExecutionConfigurator = { - val parallelAspectsOptions = - if(parallelAspects.toLowerCase == "queries") Map[String, Boolean]("queries" -> true) - else if(parallelAspects.toLowerCase == "shapes") Map[String, Boolean]("shapes" -> true) - else Map[String, Boolean]("shapes" -> true, "queries" -> true) - new ParallelExecutionConfigurator( - parallelAspectsOptions, - Try(numberOfThreads.toInt).filter(_ > 0).toOption - ) - } - - def empty = new ParallelExecutionConfigurator(Map(), None) -} \ No newline at end of file +object ParallelExecutionConfigurator extends ParallelExecutionConfiguratorTrait \ No newline at end of file diff --git a/src/main/scala-2.13/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala b/src/main/scala-2.13/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala index 8184dde..d9b99fe 100644 --- a/src/main/scala-2.13/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala +++ b/src/main/scala-2.13/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala @@ -1,35 +1,14 @@ package com.herminiogarcia.shexml.helper import scala.collection.parallel.CollectionConverters._ -import scala.collection.parallel.{ForkJoinTaskSupport, ParSeq} +import scala.collection.parallel.ParSeq -class ParallelExecutionConfigurator(val parallelisationAspectsOptions: Map[String, Boolean], val numberOfThreads: Option[Int]) { +class ParallelExecutionConfigurator(override val parallelisationAspectsOptions: Map[String, Boolean], override val numberOfThreads: Option[Int]) + extends ParallelExecutionConfiguratorGen(parallelisationAspectsOptions, numberOfThreads) { - def asParallelCollection[T](aspect: String, collection: Seq[T]): Either[Seq[T], ParSeq[T]] = { - if(!parallelisationAspectsOptions.getOrElse(aspect, false)) Left(collection) - else numberOfThreads match { - case Some(number) => - collection.par - val parallelCollection = collection.par - parallelCollection.tasksupport = new ForkJoinTaskSupport(new java.util.concurrent.ForkJoinPool(number)) - Right(parallelCollection) - case None => Right(collection.par) - } + override protected def convertToParallelCollection[T](collection: Seq[T]): ParSeq[T] = { + collection.par } } -object ParallelExecutionConfigurator { - - def apply(parallelAspects: String, numberOfThreads: String): ParallelExecutionConfigurator = { - val parallelAspectsOptions = - if(parallelAspects.toLowerCase == "queries") Map[String, Boolean]("queries" -> true) - else if(parallelAspects.toLowerCase == "shapes") Map[String, Boolean]("shapes" -> true) - else Map[String, Boolean]("shapes" -> true, "queries" -> true) - new ParallelExecutionConfigurator( - parallelAspectsOptions, - numberOfThreads.toIntOption.filter(_ > 0) - ) - } - - def empty = new ParallelExecutionConfigurator(Map(), None) -} \ No newline at end of file +object ParallelExecutionConfigurator extends ParallelExecutionConfiguratorTrait \ No newline at end of file diff --git a/src/main/scala-3/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala b/src/main/scala-3/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala index 8184dde..d9b99fe 100644 --- a/src/main/scala-3/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala +++ b/src/main/scala-3/com/herminiogarcia/shexml/helper/ParallelExecutionConfigurator.scala @@ -1,35 +1,14 @@ package com.herminiogarcia.shexml.helper import scala.collection.parallel.CollectionConverters._ -import scala.collection.parallel.{ForkJoinTaskSupport, ParSeq} +import scala.collection.parallel.ParSeq -class ParallelExecutionConfigurator(val parallelisationAspectsOptions: Map[String, Boolean], val numberOfThreads: Option[Int]) { +class ParallelExecutionConfigurator(override val parallelisationAspectsOptions: Map[String, Boolean], override val numberOfThreads: Option[Int]) + extends ParallelExecutionConfiguratorGen(parallelisationAspectsOptions, numberOfThreads) { - def asParallelCollection[T](aspect: String, collection: Seq[T]): Either[Seq[T], ParSeq[T]] = { - if(!parallelisationAspectsOptions.getOrElse(aspect, false)) Left(collection) - else numberOfThreads match { - case Some(number) => - collection.par - val parallelCollection = collection.par - parallelCollection.tasksupport = new ForkJoinTaskSupport(new java.util.concurrent.ForkJoinPool(number)) - Right(parallelCollection) - case None => Right(collection.par) - } + override protected def convertToParallelCollection[T](collection: Seq[T]): ParSeq[T] = { + collection.par } } -object ParallelExecutionConfigurator { - - def apply(parallelAspects: String, numberOfThreads: String): ParallelExecutionConfigurator = { - val parallelAspectsOptions = - if(parallelAspects.toLowerCase == "queries") Map[String, Boolean]("queries" -> true) - else if(parallelAspects.toLowerCase == "shapes") Map[String, Boolean]("shapes" -> true) - else Map[String, Boolean]("shapes" -> true, "queries" -> true) - new ParallelExecutionConfigurator( - parallelAspectsOptions, - numberOfThreads.toIntOption.filter(_ > 0) - ) - } - - def empty = new ParallelExecutionConfigurator(Map(), None) -} \ No newline at end of file +object ParallelExecutionConfigurator extends ParallelExecutionConfiguratorTrait \ No newline at end of file diff --git a/src/main/scala/com/herminiogarcia/shexml/helper/ParallelExecutionConfiguratorGen.scala b/src/main/scala/com/herminiogarcia/shexml/helper/ParallelExecutionConfiguratorGen.scala new file mode 100644 index 0000000..b386203 --- /dev/null +++ b/src/main/scala/com/herminiogarcia/shexml/helper/ParallelExecutionConfiguratorGen.scala @@ -0,0 +1,36 @@ +package com.herminiogarcia.shexml.helper + +import scala.collection.parallel.{ForkJoinTaskSupport, ParSeq} +import scala.util.Try + +abstract class ParallelExecutionConfiguratorGen(val parallelisationAspectsOptions: Map[String, Boolean], val numberOfThreads: Option[Int]) { + + def asParallelCollection[T](aspect: String, collection: Seq[T]): Either[Seq[T], ParSeq[T]] = { + if(!parallelisationAspectsOptions.getOrElse(aspect, false)) Left(collection) + else numberOfThreads match { + case Some(number) => + val parallelCollection = convertToParallelCollection(collection) + parallelCollection.tasksupport = new ForkJoinTaskSupport(new java.util.concurrent.ForkJoinPool(number)) + Right(parallelCollection) + case None => Right(convertToParallelCollection(collection)) + } + } + + protected def convertToParallelCollection[T](collection: Seq[T]): ParSeq[T] +} + +trait ParallelExecutionConfiguratorTrait { + + def apply(parallelAspects: String, numberOfThreads: String): ParallelExecutionConfigurator = { + val parallelAspectsOptions = + if(parallelAspects.toLowerCase == "queries") Map[String, Boolean]("queries" -> true) + else if(parallelAspects.toLowerCase == "shapes") Map[String, Boolean]("shapes" -> true) + else Map[String, Boolean]("shapes" -> true, "queries" -> true) + new ParallelExecutionConfigurator( + parallelAspectsOptions, + Try(numberOfThreads.toInt).filter(_ > 0).toOption + ) + } + + def empty = new ParallelExecutionConfigurator(Map(), None) +} \ No newline at end of file From d43c75b86b584d2392e0ad1d8df80c67b01a6064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Tue, 12 Aug 2025 15:38:57 +0200 Subject: [PATCH 10/15] Increased Scala versions to the latest available ones and the 3.3 LTS. Closes #225. --- .github/workflows/scala.yml | 4 ++-- build.sbt | 6 +++--- src/main/scala/com/herminiogarcia/shexml/Main.scala | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml index c22c064..18d1329 100644 --- a/.github/workflows/scala.yml +++ b/.github/workflows/scala.yml @@ -9,10 +9,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v4 with: - java-version: '17' + java-version: '21' distribution: 'temurin' - uses: sbt/setup-sbt@v1 - name: Build the docker compose stack diff --git a/build.sbt b/build.sbt index 31829d2..dfeac84 100644 --- a/build.sbt +++ b/build.sbt @@ -4,9 +4,9 @@ lazy val shexml = project .in(file(".")) .settings( name := "ShExML", - version := "0.5.4", - scalaVersion := "3.2.0", - crossScalaVersions := Seq("2.12.17", "2.13.9", "3.2.0"), + version := "0.5.5-SNAPSHOT", + scalaVersion := "3.3.6", + crossScalaVersions := Seq("2.12.20", "2.13.16", "3.3.6"), libraryDependencies ++= Seq( "org.antlr" % "antlr4" % "4.9.2", "net.sf.saxon" % "Saxon-HE" % "12.4", diff --git a/src/main/scala/com/herminiogarcia/shexml/Main.scala b/src/main/scala/com/herminiogarcia/shexml/Main.scala index 2bf3710..d7a2c53 100644 --- a/src/main/scala/com/herminiogarcia/shexml/Main.scala +++ b/src/main/scala/com/herminiogarcia/shexml/Main.scala @@ -20,7 +20,7 @@ object Main { } } -@Command(name = "ShExML", version = Array("v0.5.4"), +@Command(name = "ShExML", version = Array("v0.5.5-SNAPSHOT"), mixinStandardHelpOptions = true, sortOptions = false, description = Array("Map and merge heterogeneous data sources with a Shape Expressions based syntax")) From c602cbe1c0aab212e35145aa138855a4bddcdf04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Wed, 13 Aug 2025 10:34:37 +0200 Subject: [PATCH 11/15] Changed the way in which relative paths with wildcards are transformed and relaxed the use of java.net.URI in the Source.fromURL method. Closes #228. --- .../shexml/helper/SourceHelper.scala | 3 +- .../shexml/visitor/RDFGeneratorVisitor.scala | 15 ++-- src/test/resources/filmsDirectory/film_1.json | 11 +++ src/test/resources/filmsDirectory/film_2.json | 11 +++ src/test/resources/filmsDirectory/film_3.json | 11 +++ src/test/resources/filmsDirectory/film_4.json | 11 +++ .../shexml/SourceRelativePathTest.scala | 57 +++++++++++++ .../SourceRelativePathWithWildcardTest.scala | 83 +++++++++++++++++++ ...PathWithWildcardWindowsBackslashTest.scala | 83 +++++++++++++++++++ 9 files changed, 274 insertions(+), 11 deletions(-) create mode 100644 src/test/resources/filmsDirectory/film_1.json create mode 100644 src/test/resources/filmsDirectory/film_2.json create mode 100644 src/test/resources/filmsDirectory/film_3.json create mode 100644 src/test/resources/filmsDirectory/film_4.json create mode 100644 src/test/scala/com/herminiogarcia/shexml/SourceRelativePathTest.scala create mode 100644 src/test/scala/com/herminiogarcia/shexml/SourceRelativePathWithWildcardTest.scala create mode 100644 src/test/scala/com/herminiogarcia/shexml/SourceRelativePathWithWildcardWindowsBackslashTest.scala diff --git a/src/main/scala/com/herminiogarcia/shexml/helper/SourceHelper.scala b/src/main/scala/com/herminiogarcia/shexml/helper/SourceHelper.scala index 7787dad..3ef1c8b 100644 --- a/src/main/scala/com/herminiogarcia/shexml/helper/SourceHelper.scala +++ b/src/main/scala/com/herminiogarcia/shexml/helper/SourceHelper.scala @@ -12,7 +12,8 @@ class SourceHelper { def getURLContent(url: String): LoadedSource = searchFileResult(url) match { case Some(result) => result case None => - val file = scala.io.Source.fromURL(url, "UTF-8") + val parsedURL = new java.net.URL(url) + val file = scala.io.Source.fromURL(parsedURL, "UTF-8") try { val content = LoadedSource(file.mkString, url) saveFileResult(url, content) diff --git a/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala b/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala index d980997..5e1f12a 100644 --- a/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala +++ b/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala @@ -997,20 +997,15 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: Map[Variable, VarResult], } private def getAllFilesContents(url: String): List[LoadedSource] = { - val slices = url.split("\\*") - val windows = slices(0).lastIndexOf("/") < slices(0).lastIndexOf("\\") - val path = if(windows) - slices(0).splitAt(slices(0).lastIndexOf("\\"))._1.replace("file:///", "") - else slices(0).splitAt(slices(0).lastIndexOf("/"))._1.replace("file://", "") - val fileBeginning = if(windows) - slices(0).splitAt(slices(0).lastIndexOf("\\"))._2.replace("\\", "") - else slices(0).splitAt(slices(0).lastIndexOf("/"))._2.replace("/", "") + val slices = url.split("\\*").map(_.replaceAll("\\\\", "/")) + val path = slices(0).splitAt(slices(0).lastIndexOf("/"))._1.replaceFirst("file:///?", "") + val fileBeginning = slices(0).splitAt(slices(0).lastIndexOf("/"))._2.replace("/", "") val fileEnding = slices(1).splitAt(slices(1).lastIndexOf("."))._1 val fileExtension = slices(1).splitAt(slices(1).lastIndexOf("."))._2 val files = new File(path).listFiles().filter(_.isFile) .filter(_.getName.endsWith(fileEnding + fileExtension)).filter(_.getName.startsWith(fileBeginning)) - val fileProtocol = if(windows) "file:///" else "file://" - files.map(file => new SourceHelper().getURLContent(fileProtocol + file.getAbsolutePath)).toList + val fileProtocol = if(path.startsWith("/")) "file://" else "file:///" + files.map(file => new SourceHelper().getURLContent(fileProtocol + file.getAbsolutePath.replaceAll("\\\\", "/"))).toList } private def visitAction(actionOrLiteral: ActionOrLiteral, predicateObjectsList: List[Any], optionalArgument: Any): List[Result] = actionOrLiteral match { diff --git a/src/test/resources/filmsDirectory/film_1.json b/src/test/resources/filmsDirectory/film_1.json new file mode 100644 index 0000000..435bd12 --- /dev/null +++ b/src/test/resources/filmsDirectory/film_1.json @@ -0,0 +1,11 @@ +{ + "films": [ + { + "id": 1, + "name": "Dunkirk", + "year": "2017", + "country": "USA", + "director": "Christopher Nolan" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/filmsDirectory/film_2.json b/src/test/resources/filmsDirectory/film_2.json new file mode 100644 index 0000000..2401c33 --- /dev/null +++ b/src/test/resources/filmsDirectory/film_2.json @@ -0,0 +1,11 @@ +{ + "films": [ + { + "id": 2, + "name": "Interstellar", + "year": "2014", + "country": "USA", + "director": ["Christopher Nolan", "Jonathan Nolan"] + } + ] +} \ No newline at end of file diff --git a/src/test/resources/filmsDirectory/film_3.json b/src/test/resources/filmsDirectory/film_3.json new file mode 100644 index 0000000..210a853 --- /dev/null +++ b/src/test/resources/filmsDirectory/film_3.json @@ -0,0 +1,11 @@ +{ + "films": [ + { + "id": 3, + "name": "Inception", + "year": "2010", + "country": "USA", + "director": "Christopher Nolan" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/filmsDirectory/film_4.json b/src/test/resources/filmsDirectory/film_4.json new file mode 100644 index 0000000..89cee5a --- /dev/null +++ b/src/test/resources/filmsDirectory/film_4.json @@ -0,0 +1,11 @@ +{ + "films": [ + { + "id": 4, + "name": "The Prestige", + "year": "2006", + "country": "USA", + "director": ["Christopher Nolan", "Jonathan Nolan"] + } + ] +} \ No newline at end of file diff --git a/src/test/scala/com/herminiogarcia/shexml/SourceRelativePathTest.scala b/src/test/scala/com/herminiogarcia/shexml/SourceRelativePathTest.scala new file mode 100644 index 0000000..b365ea0 --- /dev/null +++ b/src/test/scala/com/herminiogarcia/shexml/SourceRelativePathTest.scala @@ -0,0 +1,57 @@ +package com.herminiogarcia.shexml + +import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap +import org.scalatest.funsuite.AnyFunSuite +import org.scalatest.matchers.must.Matchers + +class SourceRelativePathTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { + + private val example = + """ + |PREFIX : + |PREFIX xs: + |SOURCE films_json_file + |ITERATOR film_json { + | FIELD id + | FIELD name + | FIELD year + | FIELD country + | FIELD directors + |} + |EXPRESSION films + | + |:Films :[films.id] { + | :type :Film ; + | :name [films.name] ; + | :year [films.year] xs:gYear ; + | :country [films.country] ; + | :director [films.directors] ; + |} + """.stripMargin + + private var output: Model = _ + private val prefix = "http://example.com/" + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + + test("Shape 1 is translated correctly") { + assert(output.contains(createStatement(prefix, "1", "type", "Film"))) + assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "1", "year", "2017", XSDDatatype.XSDgYear))) + assert(output.contains(createStatementWithLiteral(prefix, "1", "country", "USA", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "1", "director", "Christopher Nolan", XSDDatatype.XSDstring))) + } + + test("No additional triples are generated") { + val triplesCount = 5 + assert(output.size() == triplesCount) + } + +} diff --git a/src/test/scala/com/herminiogarcia/shexml/SourceRelativePathWithWildcardTest.scala b/src/test/scala/com/herminiogarcia/shexml/SourceRelativePathWithWildcardTest.scala new file mode 100644 index 0000000..16e9f86 --- /dev/null +++ b/src/test/scala/com/herminiogarcia/shexml/SourceRelativePathWithWildcardTest.scala @@ -0,0 +1,83 @@ +package com.herminiogarcia.shexml + +import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap +import org.scalatest.funsuite.AnyFunSuite +import org.scalatest.matchers.must.Matchers + +class SourceRelativePathWithWildcardTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { + + private val example = + """ + |PREFIX : + |PREFIX xs: + |SOURCE films_json_file + |ITERATOR film_json { + | FIELD id + | FIELD name + | FIELD year + | FIELD country + | FIELD directors + |} + |EXPRESSION films + | + |:Films :[films.id] { + | :type :Film ; + | :name [films.name] ; + | :year [films.year] xs:gYear ; + | :country [films.country] ; + | :director [films.directors] ; + |} + """.stripMargin + + private var output: Model = _ + private val prefix = "http://example.com/" + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + + test("Shape 1 is translated correctly") { + assert(output.contains(createStatement(prefix, "1", "type", "Film"))) + assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "1", "year", "2017", XSDDatatype.XSDgYear))) + assert(output.contains(createStatementWithLiteral(prefix, "1", "country", "USA", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "1", "director", "Christopher Nolan", XSDDatatype.XSDstring))) + } + + test("Shape 2 is translated correctly") { + assert(output.contains(createStatement(prefix, "2", "type", "Film"))) + assert(output.contains(createStatementWithLiteral(prefix, "2", "name", "Interstellar", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "2", "year", "2014", XSDDatatype.XSDgYear))) + assert(output.contains(createStatementWithLiteral(prefix, "2", "country", "USA", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "2", "director", "Christopher Nolan", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "2", "director", "Jonathan Nolan", XSDDatatype.XSDstring))) + } + + test("Shape 3 is translated correctly") { + assert(output.contains(createStatement(prefix, "3", "type", "Film"))) + assert(output.contains(createStatementWithLiteral(prefix, "3", "name", "Inception", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "3", "year", "2010", XSDDatatype.XSDgYear))) + assert(output.contains(createStatementWithLiteral(prefix, "3", "country", "USA", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "3", "director", "Christopher Nolan", XSDDatatype.XSDstring))) + } + + test("Shape 4 is translated correctly") { + assert(output.contains(createStatement(prefix, "4", "type", "Film"))) + assert(output.contains(createStatementWithLiteral(prefix, "4", "name", "The Prestige", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "4", "year", "2006", XSDDatatype.XSDgYear))) + assert(output.contains(createStatementWithLiteral(prefix, "4", "country", "USA", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "4", "director", "Christopher Nolan", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "4", "director", "Jonathan Nolan", XSDDatatype.XSDstring))) + } + + test("No additional triples are generated") { + val triplesCount = 22 + assert(output.size() == triplesCount) + } + +} diff --git a/src/test/scala/com/herminiogarcia/shexml/SourceRelativePathWithWildcardWindowsBackslashTest.scala b/src/test/scala/com/herminiogarcia/shexml/SourceRelativePathWithWildcardWindowsBackslashTest.scala new file mode 100644 index 0000000..b241a2a --- /dev/null +++ b/src/test/scala/com/herminiogarcia/shexml/SourceRelativePathWithWildcardWindowsBackslashTest.scala @@ -0,0 +1,83 @@ +package com.herminiogarcia.shexml + +import org.apache.jena.datatypes.xsd.XSDDatatype +import org.apache.jena.rdf.model.Model +import org.scalatest.ConfigMap +import org.scalatest.funsuite.AnyFunSuite +import org.scalatest.matchers.must.Matchers + +class SourceRelativePathWithWildcardWindowsBackslashTest extends AnyFunSuite + with Matchers with RDFStatementCreator + with ParallelConfigInferenceDatatypesNormaliseURIsFixture { + + private val example = + """ + |PREFIX : + |PREFIX xs: + |SOURCE films_json_file + |ITERATOR film_json { + | FIELD id + | FIELD name + | FIELD year + | FIELD country + | FIELD directors + |} + |EXPRESSION films + | + |:Films :[films.id] { + | :type :Film ; + | :name [films.name] ; + | :year [films.year] xs:gYear ; + | :country [films.country] ; + | :director [films.directors] ; + |} + """.stripMargin + + private var output: Model = _ + private val prefix = "http://example.com/" + + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + output = mappingLauncher.launchMapping(example).getDefaultModel + } + + test("Shape 1 is translated correctly") { + assert(output.contains(createStatement(prefix, "1", "type", "Film"))) + assert(output.contains(createStatementWithLiteral(prefix, "1", "name", "Dunkirk", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "1", "year", "2017", XSDDatatype.XSDgYear))) + assert(output.contains(createStatementWithLiteral(prefix, "1", "country", "USA", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "1", "director", "Christopher Nolan", XSDDatatype.XSDstring))) + } + + test("Shape 2 is translated correctly") { + assert(output.contains(createStatement(prefix, "2", "type", "Film"))) + assert(output.contains(createStatementWithLiteral(prefix, "2", "name", "Interstellar", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "2", "year", "2014", XSDDatatype.XSDgYear))) + assert(output.contains(createStatementWithLiteral(prefix, "2", "country", "USA", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "2", "director", "Christopher Nolan", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "2", "director", "Jonathan Nolan", XSDDatatype.XSDstring))) + } + + test("Shape 3 is translated correctly") { + assert(output.contains(createStatement(prefix, "3", "type", "Film"))) + assert(output.contains(createStatementWithLiteral(prefix, "3", "name", "Inception", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "3", "year", "2010", XSDDatatype.XSDgYear))) + assert(output.contains(createStatementWithLiteral(prefix, "3", "country", "USA", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "3", "director", "Christopher Nolan", XSDDatatype.XSDstring))) + } + + test("Shape 4 is translated correctly") { + assert(output.contains(createStatement(prefix, "4", "type", "Film"))) + assert(output.contains(createStatementWithLiteral(prefix, "4", "name", "The Prestige", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "4", "year", "2006", XSDDatatype.XSDgYear))) + assert(output.contains(createStatementWithLiteral(prefix, "4", "country", "USA", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "4", "director", "Christopher Nolan", XSDDatatype.XSDstring))) + assert(output.contains(createStatementWithLiteral(prefix, "4", "director", "Jonathan Nolan", XSDDatatype.XSDstring))) + } + + test("No additional triples are generated") { + val triplesCount = 22 + assert(output.size() == triplesCount) + } + +} From b9d160b2d655d7bbabf19cb786b00f884c7f3103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Fri, 5 Sep 2025 17:01:21 +0200 Subject: [PATCH 12/15] Implemented the possibility to input a file from stdin as proposed in PR #212. Closes #230. --- .../shexml/antlr/ShExMLLexer.g4 | 1 + .../shexml/antlr/ShExMLLexer.interp | 5 +- .../shexml/antlr/ShExMLLexer.java | 809 +++++++++--------- .../shexml/antlr/ShExMLLexer.tokens | 33 +- .../shexml/antlr/ShExMLParser.g4 | 2 +- .../shexml/antlr/ShExMLParser.interp | 4 +- .../shexml/antlr/ShExMLParser.java | 77 +- .../shexml/antlr/ShExMLParser.tokens | 33 +- .../shexml/MappingLauncher.scala | 21 +- .../com/herminiogarcia/shexml/ast/AST.scala | 7 +- .../shexml/helper/SourceHelper.scala | 8 +- .../shexml/parser/ASTCreatorVisitor.scala | 1 + .../shexml/visitor/RDFGeneratorVisitor.scala | 11 +- .../herminiogarcia/shexml/FilmsStdin.scala | 31 +- 14 files changed, 525 insertions(+), 518 deletions(-) diff --git a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.g4 b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.g4 index 9c62c39..f9aaeff 100644 --- a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.g4 +++ b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.g4 @@ -64,6 +64,7 @@ CSVPERROW: C S V P E R R O W ; SQL: S Q L ':' ; SCALA: S C A L A ':' ; SPARQL: S P A R Q L ':' ; +STDIN: S T D I N ; QUERY_PART: (LETTER | DIGIT | ALLOWED_CHARACTERS | '}' | '{' | '"')+ ; GREATER_SYMBOL_QUERY: '>' -> mode(DEFAULT_MODE) ; WS_QUERY: [ \t\n\r] -> skip ; diff --git a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.interp b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.interp index 0db7ea4..22a8e5e 100644 --- a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.interp +++ b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.interp @@ -74,6 +74,7 @@ null null null null +null token symbolic names: null @@ -135,6 +136,7 @@ CSVPERROW SQL SCALA SPARQL +STDIN QUERY_PART GREATER_SYMBOL_QUERY WS_QUERY @@ -211,6 +213,7 @@ CSVPERROW SQL SCALA SPARQL +STDIN QUERY_PART GREATER_SYMBOL_QUERY WS_QUERY @@ -269,4 +272,4 @@ DECLARATION_CONTENT AUTOINCREMENT_CONTENT atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 76, 1138, 8, 1, 8, 1, 8, 1, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 4, 88, 9, 88, 4, 89, 9, 89, 4, 90, 9, 90, 4, 91, 9, 91, 4, 92, 9, 92, 4, 93, 9, 93, 4, 94, 9, 94, 4, 95, 9, 95, 4, 96, 9, 96, 4, 97, 9, 97, 4, 98, 9, 98, 4, 99, 9, 99, 4, 100, 9, 100, 4, 101, 9, 101, 4, 102, 9, 102, 4, 103, 9, 103, 4, 104, 9, 104, 4, 105, 9, 105, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 5, 39, 444, 10, 39, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 6, 44, 468, 10, 44, 13, 44, 14, 44, 469, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 7, 45, 480, 10, 45, 12, 45, 14, 45, 483, 11, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 6, 46, 492, 10, 46, 13, 46, 14, 46, 493, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 48, 3, 48, 3, 48, 3, 48, 3, 48, 5, 48, 510, 10, 48, 3, 49, 3, 49, 6, 49, 514, 10, 49, 13, 49, 14, 49, 515, 3, 49, 3, 49, 3, 49, 6, 49, 521, 10, 49, 13, 49, 14, 49, 522, 7, 49, 525, 10, 49, 12, 49, 14, 49, 528, 11, 49, 3, 50, 3, 50, 7, 50, 532, 10, 50, 12, 50, 14, 50, 535, 11, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 5, 52, 556, 10, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 7, 52, 565, 10, 52, 12, 52, 14, 52, 568, 11, 52, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 6, 53, 578, 10, 53, 13, 53, 14, 53, 579, 3, 53, 3, 53, 3, 53, 3, 53, 7, 53, 586, 10, 53, 12, 53, 14, 53, 589, 11, 53, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 60, 3, 60, 6, 60, 642, 10, 60, 13, 60, 14, 60, 643, 3, 61, 3, 61, 3, 61, 3, 61, 3, 62, 3, 62, 3, 62, 3, 62, 3, 63, 3, 63, 3, 63, 3, 63, 3, 64, 3, 64, 3, 64, 3, 64, 7, 64, 662, 10, 64, 12, 64, 14, 64, 665, 11, 64, 3, 65, 3, 65, 3, 65, 7, 65, 670, 10, 65, 12, 65, 14, 65, 673, 11, 65, 3, 65, 3, 65, 3, 66, 3, 66, 3, 66, 3, 66, 3, 67, 3, 67, 3, 68, 3, 68, 3, 68, 3, 69, 3, 69, 3, 69, 3, 70, 3, 70, 3, 71, 6, 71, 692, 10, 71, 13, 71, 14, 71, 693, 3, 72, 3, 72, 3, 72, 3, 72, 7, 72, 700, 10, 72, 12, 72, 14, 72, 703, 11, 72, 3, 73, 3, 73, 3, 73, 3, 73, 3, 73, 6, 73, 710, 10, 73, 13, 73, 14, 73, 711, 3, 73, 3, 73, 3, 74, 3, 74, 3, 74, 3, 74, 3, 75, 3, 75, 3, 75, 3, 75, 3, 76, 5, 76, 725, 10, 76, 3, 77, 3, 77, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 5, 78, 734, 10, 78, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 5, 79, 1080, 10, 79, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 5, 80, 1087, 10, 80, 3, 81, 3, 81, 3, 82, 3, 82, 3, 83, 3, 83, 3, 84, 3, 84, 3, 85, 3, 85, 3, 86, 3, 86, 3, 87, 3, 87, 3, 88, 3, 88, 3, 89, 3, 89, 3, 90, 3, 90, 3, 91, 3, 91, 3, 92, 3, 92, 3, 93, 3, 93, 3, 94, 3, 94, 3, 95, 3, 95, 3, 96, 3, 96, 3, 97, 3, 97, 3, 98, 3, 98, 3, 99, 3, 99, 3, 100, 3, 100, 3, 101, 3, 101, 3, 102, 3, 102, 3, 103, 3, 103, 3, 104, 3, 104, 3, 105, 3, 105, 2, 2, 106, 6, 3, 8, 4, 10, 5, 12, 6, 14, 7, 16, 8, 18, 9, 20, 10, 22, 11, 24, 12, 26, 13, 28, 14, 30, 15, 32, 16, 34, 17, 36, 18, 38, 19, 40, 20, 42, 21, 44, 22, 46, 23, 48, 24, 50, 25, 52, 26, 54, 27, 56, 28, 58, 29, 60, 30, 62, 31, 64, 32, 66, 33, 68, 34, 70, 35, 72, 36, 74, 37, 76, 38, 78, 39, 80, 40, 82, 41, 84, 42, 86, 43, 88, 44, 90, 45, 92, 46, 94, 47, 96, 48, 98, 49, 100, 50, 102, 51, 104, 52, 106, 53, 108, 54, 110, 55, 112, 56, 114, 57, 116, 58, 118, 59, 120, 60, 122, 61, 124, 62, 126, 63, 128, 64, 130, 65, 132, 66, 134, 67, 136, 68, 138, 69, 140, 70, 142, 71, 144, 72, 146, 73, 148, 74, 150, 75, 152, 76, 154, 2, 156, 2, 158, 2, 160, 2, 162, 2, 164, 2, 166, 2, 168, 2, 170, 2, 172, 2, 174, 2, 176, 2, 178, 2, 180, 2, 182, 2, 184, 2, 186, 2, 188, 2, 190, 2, 192, 2, 194, 2, 196, 2, 198, 2, 200, 2, 202, 2, 204, 2, 206, 2, 208, 2, 210, 2, 212, 2, 6, 2, 3, 4, 5, 35, 4, 2, 67, 67, 99, 99, 4, 2, 47, 47, 97, 97, 4, 2, 12, 12, 15, 15, 5, 2, 11, 12, 15, 15, 34, 34, 5, 2, 36, 36, 125, 125, 127, 127, 7, 2, 67, 92, 99, 124, 194, 216, 218, 248, 250, 257, 3, 2, 50, 59, 8, 2, 37, 44, 46, 49, 60, 61, 63, 63, 65, 66, 93, 97, 4, 2, 68, 68, 100, 100, 4, 2, 69, 69, 101, 101, 4, 2, 70, 70, 102, 102, 4, 2, 71, 71, 103, 103, 4, 2, 72, 72, 104, 104, 4, 2, 73, 73, 105, 105, 4, 2, 74, 74, 106, 106, 4, 2, 75, 75, 107, 107, 4, 2, 76, 76, 108, 108, 4, 2, 77, 77, 109, 109, 4, 2, 78, 78, 110, 110, 4, 2, 79, 79, 111, 111, 4, 2, 80, 80, 112, 112, 4, 2, 81, 81, 113, 113, 4, 2, 82, 82, 114, 114, 4, 2, 83, 83, 115, 115, 4, 2, 84, 84, 116, 116, 4, 2, 85, 85, 117, 117, 4, 2, 86, 86, 118, 118, 4, 2, 87, 87, 119, 119, 4, 2, 88, 88, 120, 120, 4, 2, 89, 89, 121, 121, 4, 2, 90, 90, 122, 122, 4, 2, 91, 91, 123, 123, 4, 2, 92, 92, 124, 124, 2, 1194, 2, 6, 3, 2, 2, 2, 2, 8, 3, 2, 2, 2, 2, 10, 3, 2, 2, 2, 2, 12, 3, 2, 2, 2, 2, 14, 3, 2, 2, 2, 2, 16, 3, 2, 2, 2, 2, 18, 3, 2, 2, 2, 2, 20, 3, 2, 2, 2, 2, 22, 3, 2, 2, 2, 2, 24, 3, 2, 2, 2, 2, 26, 3, 2, 2, 2, 2, 28, 3, 2, 2, 2, 2, 30, 3, 2, 2, 2, 2, 32, 3, 2, 2, 2, 2, 34, 3, 2, 2, 2, 2, 36, 3, 2, 2, 2, 2, 38, 3, 2, 2, 2, 2, 40, 3, 2, 2, 2, 2, 42, 3, 2, 2, 2, 2, 44, 3, 2, 2, 2, 2, 46, 3, 2, 2, 2, 2, 48, 3, 2, 2, 2, 2, 50, 3, 2, 2, 2, 2, 52, 3, 2, 2, 2, 2, 54, 3, 2, 2, 2, 2, 56, 3, 2, 2, 2, 2, 58, 3, 2, 2, 2, 2, 60, 3, 2, 2, 2, 2, 62, 3, 2, 2, 2, 2, 64, 3, 2, 2, 2, 2, 66, 3, 2, 2, 2, 2, 68, 3, 2, 2, 2, 2, 70, 3, 2, 2, 2, 2, 72, 3, 2, 2, 2, 2, 74, 3, 2, 2, 2, 2, 76, 3, 2, 2, 2, 2, 78, 3, 2, 2, 2, 2, 80, 3, 2, 2, 2, 2, 82, 3, 2, 2, 2, 2, 84, 3, 2, 2, 2, 2, 86, 3, 2, 2, 2, 2, 88, 3, 2, 2, 2, 2, 90, 3, 2, 2, 2, 2, 92, 3, 2, 2, 2, 2, 94, 3, 2, 2, 2, 2, 96, 3, 2, 2, 2, 2, 98, 3, 2, 2, 2, 2, 100, 3, 2, 2, 2, 2, 102, 3, 2, 2, 2, 2, 104, 3, 2, 2, 2, 3, 106, 3, 2, 2, 2, 3, 108, 3, 2, 2, 2, 3, 110, 3, 2, 2, 2, 3, 112, 3, 2, 2, 2, 3, 114, 3, 2, 2, 2, 3, 116, 3, 2, 2, 2, 3, 118, 3, 2, 2, 2, 3, 120, 3, 2, 2, 2, 3, 122, 3, 2, 2, 2, 3, 124, 3, 2, 2, 2, 3, 126, 3, 2, 2, 2, 4, 128, 3, 2, 2, 2, 4, 130, 3, 2, 2, 2, 4, 132, 3, 2, 2, 2, 4, 134, 3, 2, 2, 2, 5, 136, 3, 2, 2, 2, 5, 138, 3, 2, 2, 2, 5, 140, 3, 2, 2, 2, 5, 142, 3, 2, 2, 2, 5, 144, 3, 2, 2, 2, 5, 146, 3, 2, 2, 2, 5, 148, 3, 2, 2, 2, 5, 150, 3, 2, 2, 2, 5, 152, 3, 2, 2, 2, 6, 214, 3, 2, 2, 2, 8, 223, 3, 2, 2, 2, 10, 232, 3, 2, 2, 2, 12, 240, 3, 2, 2, 2, 14, 251, 3, 2, 2, 2, 16, 263, 3, 2, 2, 2, 18, 271, 3, 2, 2, 2, 20, 286, 3, 2, 2, 2, 22, 301, 3, 2, 2, 2, 24, 317, 3, 2, 2, 2, 26, 328, 3, 2, 2, 2, 28, 334, 3, 2, 2, 2, 30, 339, 3, 2, 2, 2, 32, 352, 3, 2, 2, 2, 34, 360, 3, 2, 2, 2, 36, 363, 3, 2, 2, 2, 38, 366, 3, 2, 2, 2, 40, 369, 3, 2, 2, 2, 42, 378, 3, 2, 2, 2, 44, 386, 3, 2, 2, 2, 46, 393, 3, 2, 2, 2, 48, 400, 3, 2, 2, 2, 50, 407, 3, 2, 2, 2, 52, 409, 3, 2, 2, 2, 54, 411, 3, 2, 2, 2, 56, 413, 3, 2, 2, 2, 58, 416, 3, 2, 2, 2, 60, 418, 3, 2, 2, 2, 62, 421, 3, 2, 2, 2, 64, 423, 3, 2, 2, 2, 66, 425, 3, 2, 2, 2, 68, 427, 3, 2, 2, 2, 70, 429, 3, 2, 2, 2, 72, 431, 3, 2, 2, 2, 74, 433, 3, 2, 2, 2, 76, 435, 3, 2, 2, 2, 78, 437, 3, 2, 2, 2, 80, 443, 3, 2, 2, 2, 82, 445, 3, 2, 2, 2, 84, 447, 3, 2, 2, 2, 86, 449, 3, 2, 2, 2, 88, 451, 3, 2, 2, 2, 90, 467, 3, 2, 2, 2, 92, 481, 3, 2, 2, 2, 94, 486, 3, 2, 2, 2, 96, 497, 3, 2, 2, 2, 98, 501, 3, 2, 2, 2, 100, 511, 3, 2, 2, 2, 102, 529, 3, 2, 2, 2, 104, 538, 3, 2, 2, 2, 106, 555, 3, 2, 2, 2, 108, 569, 3, 2, 2, 2, 110, 590, 3, 2, 2, 2, 112, 600, 3, 2, 2, 2, 114, 607, 3, 2, 2, 2, 116, 617, 3, 2, 2, 2, 118, 622, 3, 2, 2, 2, 120, 629, 3, 2, 2, 2, 122, 641, 3, 2, 2, 2, 124, 645, 3, 2, 2, 2, 126, 649, 3, 2, 2, 2, 128, 653, 3, 2, 2, 2, 130, 657, 3, 2, 2, 2, 132, 671, 3, 2, 2, 2, 134, 676, 3, 2, 2, 2, 136, 680, 3, 2, 2, 2, 138, 682, 3, 2, 2, 2, 140, 685, 3, 2, 2, 2, 142, 688, 3, 2, 2, 2, 144, 691, 3, 2, 2, 2, 146, 695, 3, 2, 2, 2, 148, 704, 3, 2, 2, 2, 150, 715, 3, 2, 2, 2, 152, 719, 3, 2, 2, 2, 154, 724, 3, 2, 2, 2, 156, 726, 3, 2, 2, 2, 158, 733, 3, 2, 2, 2, 160, 1079, 3, 2, 2, 2, 162, 1086, 3, 2, 2, 2, 164, 1088, 3, 2, 2, 2, 166, 1090, 3, 2, 2, 2, 168, 1092, 3, 2, 2, 2, 170, 1094, 3, 2, 2, 2, 172, 1096, 3, 2, 2, 2, 174, 1098, 3, 2, 2, 2, 176, 1100, 3, 2, 2, 2, 178, 1102, 3, 2, 2, 2, 180, 1104, 3, 2, 2, 2, 182, 1106, 3, 2, 2, 2, 184, 1108, 3, 2, 2, 2, 186, 1110, 3, 2, 2, 2, 188, 1112, 3, 2, 2, 2, 190, 1114, 3, 2, 2, 2, 192, 1116, 3, 2, 2, 2, 194, 1118, 3, 2, 2, 2, 196, 1120, 3, 2, 2, 2, 198, 1122, 3, 2, 2, 2, 200, 1124, 3, 2, 2, 2, 202, 1126, 3, 2, 2, 2, 204, 1128, 3, 2, 2, 2, 206, 1130, 3, 2, 2, 2, 208, 1132, 3, 2, 2, 2, 210, 1134, 3, 2, 2, 2, 212, 1136, 3, 2, 2, 2, 214, 215, 5, 192, 95, 2, 215, 216, 5, 196, 97, 2, 216, 217, 5, 170, 84, 2, 217, 218, 5, 172, 85, 2, 218, 219, 5, 178, 88, 2, 219, 220, 5, 208, 103, 2, 220, 221, 3, 2, 2, 2, 221, 222, 8, 2, 2, 2, 222, 7, 3, 2, 2, 2, 223, 224, 5, 198, 98, 2, 224, 225, 5, 190, 94, 2, 225, 226, 5, 202, 100, 2, 226, 227, 5, 196, 97, 2, 227, 228, 5, 166, 82, 2, 228, 229, 5, 170, 84, 2, 229, 230, 3, 2, 2, 2, 230, 231, 8, 3, 2, 2, 231, 9, 3, 2, 2, 2, 232, 233, 5, 194, 96, 2, 233, 234, 5, 202, 100, 2, 234, 235, 5, 170, 84, 2, 235, 236, 5, 196, 97, 2, 236, 237, 5, 210, 104, 2, 237, 238, 3, 2, 2, 2, 238, 239, 8, 4, 2, 2, 239, 11, 3, 2, 2, 2, 240, 241, 5, 178, 88, 2, 241, 242, 5, 200, 99, 2, 242, 243, 5, 170, 84, 2, 243, 244, 5, 196, 97, 2, 244, 245, 5, 82, 40, 2, 245, 246, 5, 200, 99, 2, 246, 247, 5, 190, 94, 2, 247, 248, 5, 196, 97, 2, 248, 249, 3, 2, 2, 2, 249, 250, 8, 5, 2, 2, 250, 13, 3, 2, 2, 2, 251, 252, 5, 172, 85, 2, 252, 253, 5, 202, 100, 2, 253, 254, 5, 188, 93, 2, 254, 255, 5, 166, 82, 2, 255, 256, 5, 200, 99, 2, 256, 257, 5, 178, 88, 2, 257, 258, 5, 190, 94, 2, 258, 259, 5, 188, 93, 2, 259, 260, 5, 198, 98, 2, 260, 261, 3, 2, 2, 2, 261, 262, 8, 6, 2, 2, 262, 15, 3, 2, 2, 2, 263, 264, 5, 172, 85, 2, 264, 265, 5, 178, 88, 2, 265, 266, 5, 170, 84, 2, 266, 267, 5, 184, 91, 2, 267, 268, 5, 168, 83, 2, 268, 269, 3, 2, 2, 2, 269, 270, 8, 7, 2, 2, 270, 17, 3, 2, 2, 2, 271, 272, 5, 192, 95, 2, 272, 273, 5, 202, 100, 2, 273, 274, 5, 198, 98, 2, 274, 275, 5, 176, 87, 2, 275, 276, 5, 170, 84, 2, 276, 277, 5, 168, 83, 2, 277, 278, 7, 97, 2, 2, 278, 279, 5, 172, 85, 2, 279, 280, 5, 178, 88, 2, 280, 281, 5, 170, 84, 2, 281, 282, 5, 184, 91, 2, 282, 283, 5, 168, 83, 2, 283, 284, 3, 2, 2, 2, 284, 285, 8, 8, 2, 2, 285, 19, 3, 2, 2, 2, 286, 287, 5, 192, 95, 2, 287, 288, 5, 190, 94, 2, 288, 289, 5, 192, 95, 2, 289, 290, 5, 192, 95, 2, 290, 291, 5, 170, 84, 2, 291, 292, 5, 168, 83, 2, 292, 293, 7, 97, 2, 2, 293, 294, 5, 172, 85, 2, 294, 295, 5, 178, 88, 2, 295, 296, 5, 170, 84, 2, 296, 297, 5, 184, 91, 2, 297, 298, 5, 168, 83, 2, 298, 299, 3, 2, 2, 2, 299, 300, 8, 9, 2, 2, 300, 21, 3, 2, 2, 2, 301, 302, 5, 82, 40, 2, 302, 303, 5, 202, 100, 2, 303, 304, 5, 200, 99, 2, 304, 305, 5, 190, 94, 2, 305, 306, 5, 178, 88, 2, 306, 307, 5, 188, 93, 2, 307, 308, 5, 166, 82, 2, 308, 309, 5, 196, 97, 2, 309, 310, 5, 170, 84, 2, 310, 311, 5, 186, 92, 2, 311, 312, 5, 170, 84, 2, 312, 313, 5, 188, 93, 2, 313, 314, 5, 200, 99, 2, 314, 315, 3, 2, 2, 2, 315, 316, 8, 10, 3, 2, 316, 23, 3, 2, 2, 2, 317, 318, 5, 170, 84, 2, 318, 319, 5, 208, 103, 2, 319, 320, 5, 192, 95, 2, 320, 321, 5, 196, 97, 2, 321, 322, 5, 170, 84, 2, 322, 323, 5, 198, 98, 2, 323, 324, 5, 198, 98, 2, 324, 325, 5, 178, 88, 2, 325, 326, 5, 190, 94, 2, 326, 327, 5, 188, 93, 2, 327, 25, 3, 2, 2, 2, 328, 329, 5, 202, 100, 2, 329, 330, 5, 188, 93, 2, 330, 331, 5, 178, 88, 2, 331, 332, 5, 190, 94, 2, 332, 333, 5, 188, 93, 2, 333, 27, 3, 2, 2, 2, 334, 335, 5, 180, 89, 2, 335, 336, 5, 190, 94, 2, 336, 337, 5, 178, 88, 2, 337, 338, 5, 188, 93, 2, 338, 29, 3, 2, 2, 2, 339, 340, 5, 198, 98, 2, 340, 341, 5, 202, 100, 2, 341, 342, 5, 164, 81, 2, 342, 343, 5, 198, 98, 2, 343, 344, 5, 200, 99, 2, 344, 345, 5, 178, 88, 2, 345, 346, 5, 200, 99, 2, 346, 347, 5, 202, 100, 2, 347, 348, 5, 200, 99, 2, 348, 349, 5, 178, 88, 2, 349, 350, 5, 188, 93, 2, 350, 351, 5, 174, 86, 2, 351, 31, 3, 2, 2, 2, 352, 353, 5, 186, 92, 2, 353, 354, 5, 82, 40, 2, 354, 355, 5, 200, 99, 2, 355, 356, 5, 166, 82, 2, 356, 357, 5, 176, 87, 2, 357, 358, 5, 170, 84, 2, 358, 359, 5, 196, 97, 2, 359, 33, 3, 2, 2, 2, 360, 361, 5, 82, 40, 2, 361, 362, 5, 198, 98, 2, 362, 35, 3, 2, 2, 2, 363, 364, 5, 178, 88, 2, 364, 365, 5, 172, 85, 2, 365, 37, 3, 2, 2, 2, 366, 367, 5, 190, 94, 2, 367, 368, 5, 188, 93, 2, 368, 39, 3, 2, 2, 2, 369, 370, 5, 186, 92, 2, 370, 371, 5, 82, 40, 2, 371, 372, 5, 200, 99, 2, 372, 373, 5, 166, 82, 2, 373, 374, 5, 176, 87, 2, 374, 375, 5, 178, 88, 2, 375, 376, 5, 188, 93, 2, 376, 377, 5, 174, 86, 2, 377, 41, 3, 2, 2, 2, 378, 379, 5, 196, 97, 2, 379, 380, 5, 168, 83, 2, 380, 381, 5, 172, 85, 2, 381, 382, 5, 184, 91, 2, 382, 383, 5, 178, 88, 2, 383, 384, 5, 198, 98, 2, 384, 385, 5, 200, 99, 2, 385, 43, 3, 2, 2, 2, 386, 387, 5, 196, 97, 2, 387, 388, 5, 168, 83, 2, 388, 389, 5, 172, 85, 2, 389, 390, 5, 164, 81, 2, 390, 391, 5, 82, 40, 2, 391, 392, 5, 174, 86, 2, 392, 45, 3, 2, 2, 2, 393, 394, 5, 196, 97, 2, 394, 395, 5, 168, 83, 2, 395, 396, 5, 172, 85, 2, 396, 397, 5, 198, 98, 2, 397, 398, 5, 170, 84, 2, 398, 399, 5, 194, 96, 2, 399, 47, 3, 2, 2, 2, 400, 401, 5, 196, 97, 2, 401, 402, 5, 168, 83, 2, 402, 403, 5, 172, 85, 2, 403, 404, 5, 82, 40, 2, 404, 405, 5, 184, 91, 2, 405, 406, 5, 200, 99, 2, 406, 49, 3, 2, 2, 2, 407, 408, 7, 62, 2, 2, 408, 51, 3, 2, 2, 2, 409, 410, 7, 64, 2, 2, 410, 53, 3, 2, 2, 2, 411, 412, 7, 93, 2, 2, 412, 55, 3, 2, 2, 2, 413, 414, 7, 93, 2, 2, 414, 415, 7, 93, 2, 2, 415, 57, 3, 2, 2, 2, 416, 417, 7, 95, 2, 2, 417, 59, 3, 2, 2, 2, 418, 419, 7, 95, 2, 2, 419, 420, 7, 95, 2, 2, 420, 61, 3, 2, 2, 2, 421, 422, 7, 42, 2, 2, 422, 63, 3, 2, 2, 2, 423, 424, 7, 43, 2, 2, 424, 65, 3, 2, 2, 2, 425, 426, 7, 125, 2, 2, 426, 67, 3, 2, 2, 2, 427, 428, 7, 127, 2, 2, 428, 69, 3, 2, 2, 2, 429, 430, 7, 61, 2, 2, 430, 71, 3, 2, 2, 2, 431, 432, 7, 48, 2, 2, 432, 73, 3, 2, 2, 2, 433, 434, 7, 45, 2, 2, 434, 75, 3, 2, 2, 2, 435, 436, 7, 46, 2, 2, 436, 77, 3, 2, 2, 2, 437, 438, 7, 36, 2, 2, 438, 79, 3, 2, 2, 2, 439, 444, 7, 40, 2, 2, 440, 441, 7, 67, 2, 2, 441, 442, 7, 80, 2, 2, 442, 444, 7, 70, 2, 2, 443, 439, 3, 2, 2, 2, 443, 440, 3, 2, 2, 2, 444, 81, 3, 2, 2, 2, 445, 446, 9, 2, 2, 2, 446, 83, 3, 2, 2, 2, 447, 448, 7, 66, 2, 2, 448, 85, 3, 2, 2, 2, 449, 450, 7, 63, 2, 2, 450, 87, 3, 2, 2, 2, 451, 452, 5, 178, 88, 2, 452, 453, 5, 188, 93, 2, 453, 454, 5, 168, 83, 2, 454, 455, 5, 170, 84, 2, 455, 456, 5, 208, 103, 2, 456, 457, 7, 42, 2, 2, 457, 458, 7, 43, 2, 2, 458, 89, 3, 2, 2, 2, 459, 468, 5, 154, 76, 2, 460, 468, 5, 156, 77, 2, 461, 468, 9, 3, 2, 2, 462, 463, 7, 94, 2, 2, 463, 468, 7, 48, 2, 2, 464, 465, 7, 39, 2, 2, 465, 466, 7, 52, 2, 2, 466, 468, 7, 71, 2, 2, 467, 459, 3, 2, 2, 2, 467, 460, 3, 2, 2, 2, 467, 461, 3, 2, 2, 2, 467, 462, 3, 2, 2, 2, 467, 464, 3, 2, 2, 2, 468, 469, 3, 2, 2, 2, 469, 467, 3, 2, 2, 2, 469, 470, 3, 2, 2, 2, 470, 91, 3, 2, 2, 2, 471, 480, 5, 154, 76, 2, 472, 480, 5, 156, 77, 2, 473, 480, 9, 3, 2, 2, 474, 475, 7, 94, 2, 2, 475, 480, 7, 48, 2, 2, 476, 477, 7, 39, 2, 2, 477, 478, 7, 52, 2, 2, 478, 480, 7, 71, 2, 2, 479, 471, 3, 2, 2, 2, 479, 472, 3, 2, 2, 2, 479, 473, 3, 2, 2, 2, 479, 474, 3, 2, 2, 2, 479, 476, 3, 2, 2, 2, 480, 483, 3, 2, 2, 2, 481, 479, 3, 2, 2, 2, 481, 482, 3, 2, 2, 2, 482, 484, 3, 2, 2, 2, 483, 481, 3, 2, 2, 2, 484, 485, 7, 60, 2, 2, 485, 93, 3, 2, 2, 2, 486, 491, 7, 36, 2, 2, 487, 492, 5, 154, 76, 2, 488, 492, 5, 156, 77, 2, 489, 492, 5, 162, 80, 2, 490, 492, 7, 34, 2, 2, 491, 487, 3, 2, 2, 2, 491, 488, 3, 2, 2, 2, 491, 489, 3, 2, 2, 2, 491, 490, 3, 2, 2, 2, 492, 493, 3, 2, 2, 2, 493, 491, 3, 2, 2, 2, 493, 494, 3, 2, 2, 2, 494, 495, 3, 2, 2, 2, 495, 496, 7, 36, 2, 2, 496, 95, 3, 2, 2, 2, 497, 498, 5, 158, 78, 2, 498, 499, 7, 60, 2, 2, 499, 500, 5, 160, 79, 2, 500, 97, 3, 2, 2, 2, 501, 509, 7, 66, 2, 2, 502, 503, 5, 92, 45, 2, 503, 504, 5, 90, 44, 2, 504, 510, 3, 2, 2, 2, 505, 506, 7, 62, 2, 2, 506, 507, 5, 90, 44, 2, 507, 508, 7, 64, 2, 2, 508, 510, 3, 2, 2, 2, 509, 502, 3, 2, 2, 2, 509, 505, 3, 2, 2, 2, 510, 99, 3, 2, 2, 2, 511, 513, 7, 66, 2, 2, 512, 514, 5, 154, 76, 2, 513, 512, 3, 2, 2, 2, 514, 515, 3, 2, 2, 2, 515, 513, 3, 2, 2, 2, 515, 516, 3, 2, 2, 2, 516, 526, 3, 2, 2, 2, 517, 520, 7, 47, 2, 2, 518, 521, 5, 154, 76, 2, 519, 521, 5, 156, 77, 2, 520, 518, 3, 2, 2, 2, 520, 519, 3, 2, 2, 2, 521, 522, 3, 2, 2, 2, 522, 520, 3, 2, 2, 2, 522, 523, 3, 2, 2, 2, 523, 525, 3, 2, 2, 2, 524, 517, 3, 2, 2, 2, 525, 528, 3, 2, 2, 2, 526, 524, 3, 2, 2, 2, 526, 527, 3, 2, 2, 2, 527, 101, 3, 2, 2, 2, 528, 526, 3, 2, 2, 2, 529, 533, 7, 37, 2, 2, 530, 532, 10, 4, 2, 2, 531, 530, 3, 2, 2, 2, 532, 535, 3, 2, 2, 2, 533, 531, 3, 2, 2, 2, 533, 534, 3, 2, 2, 2, 534, 536, 3, 2, 2, 2, 535, 533, 3, 2, 2, 2, 536, 537, 8, 50, 4, 2, 537, 103, 3, 2, 2, 2, 538, 539, 9, 5, 2, 2, 539, 540, 3, 2, 2, 2, 540, 541, 8, 51, 4, 2, 541, 105, 3, 2, 2, 2, 542, 543, 7, 106, 2, 2, 543, 544, 7, 118, 2, 2, 544, 545, 7, 118, 2, 2, 545, 556, 7, 114, 2, 2, 546, 547, 7, 106, 2, 2, 547, 548, 7, 118, 2, 2, 548, 549, 7, 118, 2, 2, 549, 550, 7, 114, 2, 2, 550, 556, 7, 117, 2, 2, 551, 552, 7, 104, 2, 2, 552, 553, 7, 107, 2, 2, 553, 554, 7, 110, 2, 2, 554, 556, 7, 103, 2, 2, 555, 542, 3, 2, 2, 2, 555, 546, 3, 2, 2, 2, 555, 551, 3, 2, 2, 2, 556, 557, 3, 2, 2, 2, 557, 558, 7, 60, 2, 2, 558, 559, 7, 49, 2, 2, 559, 560, 7, 49, 2, 2, 560, 566, 3, 2, 2, 2, 561, 565, 5, 154, 76, 2, 562, 565, 5, 156, 77, 2, 563, 565, 5, 162, 80, 2, 564, 561, 3, 2, 2, 2, 564, 562, 3, 2, 2, 2, 564, 563, 3, 2, 2, 2, 565, 568, 3, 2, 2, 2, 566, 564, 3, 2, 2, 2, 566, 567, 3, 2, 2, 2, 567, 107, 3, 2, 2, 2, 568, 566, 3, 2, 2, 2, 569, 570, 7, 108, 2, 2, 570, 571, 7, 102, 2, 2, 571, 572, 7, 100, 2, 2, 572, 573, 7, 101, 2, 2, 573, 574, 7, 60, 2, 2, 574, 577, 3, 2, 2, 2, 575, 578, 5, 154, 76, 2, 576, 578, 5, 156, 77, 2, 577, 575, 3, 2, 2, 2, 577, 576, 3, 2, 2, 2, 578, 579, 3, 2, 2, 2, 579, 577, 3, 2, 2, 2, 579, 580, 3, 2, 2, 2, 580, 581, 3, 2, 2, 2, 581, 587, 7, 60, 2, 2, 582, 586, 5, 154, 76, 2, 583, 586, 5, 156, 77, 2, 584, 586, 5, 162, 80, 2, 585, 582, 3, 2, 2, 2, 585, 583, 3, 2, 2, 2, 585, 584, 3, 2, 2, 2, 586, 589, 3, 2, 2, 2, 587, 585, 3, 2, 2, 2, 587, 588, 3, 2, 2, 2, 588, 109, 3, 2, 2, 2, 589, 587, 3, 2, 2, 2, 590, 591, 5, 180, 89, 2, 591, 592, 5, 198, 98, 2, 592, 593, 5, 190, 94, 2, 593, 594, 5, 188, 93, 2, 594, 595, 5, 192, 95, 2, 595, 596, 5, 82, 40, 2, 596, 597, 5, 200, 99, 2, 597, 598, 5, 176, 87, 2, 598, 599, 7, 60, 2, 2, 599, 111, 3, 2, 2, 2, 600, 601, 5, 208, 103, 2, 601, 602, 5, 192, 95, 2, 602, 603, 5, 82, 40, 2, 603, 604, 5, 200, 99, 2, 604, 605, 5, 176, 87, 2, 605, 606, 7, 60, 2, 2, 606, 113, 3, 2, 2, 2, 607, 608, 5, 166, 82, 2, 608, 609, 5, 198, 98, 2, 609, 610, 5, 204, 101, 2, 610, 611, 5, 192, 95, 2, 611, 612, 5, 170, 84, 2, 612, 613, 5, 196, 97, 2, 613, 614, 5, 196, 97, 2, 614, 615, 5, 190, 94, 2, 615, 616, 5, 206, 102, 2, 616, 115, 3, 2, 2, 2, 617, 618, 5, 198, 98, 2, 618, 619, 5, 194, 96, 2, 619, 620, 5, 184, 91, 2, 620, 621, 7, 60, 2, 2, 621, 117, 3, 2, 2, 2, 622, 623, 5, 198, 98, 2, 623, 624, 5, 166, 82, 2, 624, 625, 5, 82, 40, 2, 625, 626, 5, 184, 91, 2, 626, 627, 5, 82, 40, 2, 627, 628, 7, 60, 2, 2, 628, 119, 3, 2, 2, 2, 629, 630, 5, 198, 98, 2, 630, 631, 5, 192, 95, 2, 631, 632, 5, 82, 40, 2, 632, 633, 5, 196, 97, 2, 633, 634, 5, 194, 96, 2, 634, 635, 5, 184, 91, 2, 635, 636, 7, 60, 2, 2, 636, 121, 3, 2, 2, 2, 637, 642, 5, 154, 76, 2, 638, 642, 5, 156, 77, 2, 639, 642, 5, 162, 80, 2, 640, 642, 9, 6, 2, 2, 641, 637, 3, 2, 2, 2, 641, 638, 3, 2, 2, 2, 641, 639, 3, 2, 2, 2, 641, 640, 3, 2, 2, 2, 642, 643, 3, 2, 2, 2, 643, 641, 3, 2, 2, 2, 643, 644, 3, 2, 2, 2, 644, 123, 3, 2, 2, 2, 645, 646, 7, 64, 2, 2, 646, 647, 3, 2, 2, 2, 647, 648, 8, 61, 5, 2, 648, 125, 3, 2, 2, 2, 649, 650, 9, 5, 2, 2, 650, 651, 3, 2, 2, 2, 651, 652, 8, 62, 4, 2, 652, 127, 3, 2, 2, 2, 653, 654, 7, 62, 2, 2, 654, 655, 3, 2, 2, 2, 655, 656, 8, 63, 6, 2, 656, 129, 3, 2, 2, 2, 657, 663, 5, 154, 76, 2, 658, 662, 5, 154, 76, 2, 659, 662, 5, 156, 77, 2, 660, 662, 9, 3, 2, 2, 661, 658, 3, 2, 2, 2, 661, 659, 3, 2, 2, 2, 661, 660, 3, 2, 2, 2, 662, 665, 3, 2, 2, 2, 663, 661, 3, 2, 2, 2, 663, 664, 3, 2, 2, 2, 664, 131, 3, 2, 2, 2, 665, 663, 3, 2, 2, 2, 666, 670, 5, 154, 76, 2, 667, 670, 5, 156, 77, 2, 668, 670, 9, 3, 2, 2, 669, 666, 3, 2, 2, 2, 669, 667, 3, 2, 2, 2, 669, 668, 3, 2, 2, 2, 670, 673, 3, 2, 2, 2, 671, 669, 3, 2, 2, 2, 671, 672, 3, 2, 2, 2, 672, 674, 3, 2, 2, 2, 673, 671, 3, 2, 2, 2, 674, 675, 7, 60, 2, 2, 675, 133, 3, 2, 2, 2, 676, 677, 9, 5, 2, 2, 677, 678, 3, 2, 2, 2, 678, 679, 8, 66, 4, 2, 679, 135, 3, 2, 2, 2, 680, 681, 7, 62, 2, 2, 681, 137, 3, 2, 2, 2, 682, 683, 5, 200, 99, 2, 683, 684, 5, 190, 94, 2, 684, 139, 3, 2, 2, 2, 685, 686, 5, 164, 81, 2, 686, 687, 5, 210, 104, 2, 687, 141, 3, 2, 2, 2, 688, 689, 7, 45, 2, 2, 689, 143, 3, 2, 2, 2, 690, 692, 5, 156, 77, 2, 691, 690, 3, 2, 2, 2, 692, 693, 3, 2, 2, 2, 693, 691, 3, 2, 2, 2, 693, 694, 3, 2, 2, 2, 694, 145, 3, 2, 2, 2, 695, 701, 5, 154, 76, 2, 696, 700, 5, 154, 76, 2, 697, 700, 5, 156, 77, 2, 698, 700, 9, 3, 2, 2, 699, 696, 3, 2, 2, 2, 699, 697, 3, 2, 2, 2, 699, 698, 3, 2, 2, 2, 700, 703, 3, 2, 2, 2, 701, 699, 3, 2, 2, 2, 701, 702, 3, 2, 2, 2, 702, 147, 3, 2, 2, 2, 703, 701, 3, 2, 2, 2, 704, 709, 7, 36, 2, 2, 705, 710, 5, 154, 76, 2, 706, 710, 5, 156, 77, 2, 707, 710, 5, 162, 80, 2, 708, 710, 7, 34, 2, 2, 709, 705, 3, 2, 2, 2, 709, 706, 3, 2, 2, 2, 709, 707, 3, 2, 2, 2, 709, 708, 3, 2, 2, 2, 710, 711, 3, 2, 2, 2, 711, 709, 3, 2, 2, 2, 711, 712, 3, 2, 2, 2, 712, 713, 3, 2, 2, 2, 713, 714, 7, 36, 2, 2, 714, 149, 3, 2, 2, 2, 715, 716, 7, 64, 2, 2, 716, 717, 3, 2, 2, 2, 717, 718, 8, 74, 5, 2, 718, 151, 3, 2, 2, 2, 719, 720, 9, 5, 2, 2, 720, 721, 3, 2, 2, 2, 721, 722, 8, 75, 4, 2, 722, 153, 3, 2, 2, 2, 723, 725, 9, 7, 2, 2, 724, 723, 3, 2, 2, 2, 725, 155, 3, 2, 2, 2, 726, 727, 9, 8, 2, 2, 727, 157, 3, 2, 2, 2, 728, 729, 7, 122, 2, 2, 729, 734, 7, 117, 2, 2, 730, 731, 7, 122, 2, 2, 731, 732, 7, 117, 2, 2, 732, 734, 7, 102, 2, 2, 733, 728, 3, 2, 2, 2, 733, 730, 3, 2, 2, 2, 734, 159, 3, 2, 2, 2, 735, 736, 7, 117, 2, 2, 736, 737, 7, 118, 2, 2, 737, 738, 7, 116, 2, 2, 738, 739, 7, 107, 2, 2, 739, 740, 7, 112, 2, 2, 740, 1080, 7, 105, 2, 2, 741, 742, 7, 100, 2, 2, 742, 743, 7, 113, 2, 2, 743, 744, 7, 113, 2, 2, 744, 745, 7, 110, 2, 2, 745, 746, 7, 103, 2, 2, 746, 747, 7, 99, 2, 2, 747, 1080, 7, 112, 2, 2, 748, 749, 7, 102, 2, 2, 749, 750, 7, 103, 2, 2, 750, 751, 7, 101, 2, 2, 751, 752, 7, 107, 2, 2, 752, 753, 7, 111, 2, 2, 753, 754, 7, 99, 2, 2, 754, 1080, 7, 110, 2, 2, 755, 756, 7, 107, 2, 2, 756, 757, 7, 112, 2, 2, 757, 758, 7, 118, 2, 2, 758, 759, 7, 103, 2, 2, 759, 760, 7, 105, 2, 2, 760, 761, 7, 103, 2, 2, 761, 1080, 7, 116, 2, 2, 762, 763, 7, 102, 2, 2, 763, 764, 7, 113, 2, 2, 764, 765, 7, 119, 2, 2, 765, 766, 7, 100, 2, 2, 766, 767, 7, 110, 2, 2, 767, 1080, 7, 103, 2, 2, 768, 769, 7, 104, 2, 2, 769, 770, 7, 110, 2, 2, 770, 771, 7, 113, 2, 2, 771, 772, 7, 99, 2, 2, 772, 1080, 7, 118, 2, 2, 773, 774, 7, 102, 2, 2, 774, 775, 7, 99, 2, 2, 775, 776, 7, 118, 2, 2, 776, 1080, 7, 103, 2, 2, 777, 778, 7, 118, 2, 2, 778, 779, 7, 107, 2, 2, 779, 780, 7, 111, 2, 2, 780, 1080, 7, 103, 2, 2, 781, 782, 7, 102, 2, 2, 782, 783, 7, 99, 2, 2, 783, 784, 7, 118, 2, 2, 784, 785, 7, 103, 2, 2, 785, 786, 7, 86, 2, 2, 786, 787, 7, 107, 2, 2, 787, 788, 7, 111, 2, 2, 788, 1080, 7, 103, 2, 2, 789, 790, 7, 102, 2, 2, 790, 791, 7, 99, 2, 2, 791, 792, 7, 118, 2, 2, 792, 793, 7, 103, 2, 2, 793, 794, 7, 86, 2, 2, 794, 795, 7, 107, 2, 2, 795, 796, 7, 111, 2, 2, 796, 797, 7, 103, 2, 2, 797, 798, 7, 85, 2, 2, 798, 799, 7, 118, 2, 2, 799, 800, 7, 99, 2, 2, 800, 801, 7, 111, 2, 2, 801, 1080, 7, 114, 2, 2, 802, 803, 7, 105, 2, 2, 803, 804, 7, 91, 2, 2, 804, 805, 7, 103, 2, 2, 805, 806, 7, 99, 2, 2, 806, 1080, 7, 116, 2, 2, 807, 808, 7, 105, 2, 2, 808, 809, 7, 79, 2, 2, 809, 810, 7, 113, 2, 2, 810, 811, 7, 112, 2, 2, 811, 812, 7, 118, 2, 2, 812, 1080, 7, 106, 2, 2, 813, 814, 7, 105, 2, 2, 814, 815, 7, 70, 2, 2, 815, 816, 7, 99, 2, 2, 816, 1080, 7, 123, 2, 2, 817, 818, 7, 105, 2, 2, 818, 819, 7, 91, 2, 2, 819, 820, 7, 103, 2, 2, 820, 821, 7, 99, 2, 2, 821, 822, 7, 116, 2, 2, 822, 823, 7, 79, 2, 2, 823, 824, 7, 113, 2, 2, 824, 825, 7, 112, 2, 2, 825, 826, 7, 118, 2, 2, 826, 1080, 7, 106, 2, 2, 827, 828, 7, 105, 2, 2, 828, 829, 7, 79, 2, 2, 829, 830, 7, 113, 2, 2, 830, 831, 7, 112, 2, 2, 831, 832, 7, 118, 2, 2, 832, 833, 7, 106, 2, 2, 833, 834, 7, 70, 2, 2, 834, 835, 7, 99, 2, 2, 835, 1080, 7, 123, 2, 2, 836, 837, 7, 102, 2, 2, 837, 838, 7, 119, 2, 2, 838, 839, 7, 116, 2, 2, 839, 840, 7, 99, 2, 2, 840, 841, 7, 118, 2, 2, 841, 842, 7, 107, 2, 2, 842, 843, 7, 113, 2, 2, 843, 1080, 7, 112, 2, 2, 844, 845, 7, 123, 2, 2, 845, 846, 7, 103, 2, 2, 846, 847, 7, 99, 2, 2, 847, 848, 7, 116, 2, 2, 848, 849, 7, 79, 2, 2, 849, 850, 7, 113, 2, 2, 850, 851, 7, 112, 2, 2, 851, 852, 7, 118, 2, 2, 852, 853, 7, 106, 2, 2, 853, 854, 7, 70, 2, 2, 854, 855, 7, 119, 2, 2, 855, 856, 7, 116, 2, 2, 856, 857, 7, 99, 2, 2, 857, 858, 7, 118, 2, 2, 858, 859, 7, 107, 2, 2, 859, 860, 7, 113, 2, 2, 860, 1080, 7, 112, 2, 2, 861, 862, 7, 102, 2, 2, 862, 863, 7, 99, 2, 2, 863, 864, 7, 123, 2, 2, 864, 865, 7, 86, 2, 2, 865, 866, 7, 107, 2, 2, 866, 867, 7, 111, 2, 2, 867, 868, 7, 103, 2, 2, 868, 869, 7, 70, 2, 2, 869, 870, 7, 119, 2, 2, 870, 871, 7, 116, 2, 2, 871, 872, 7, 99, 2, 2, 872, 873, 7, 118, 2, 2, 873, 874, 7, 107, 2, 2, 874, 875, 7, 113, 2, 2, 875, 1080, 7, 112, 2, 2, 876, 877, 7, 100, 2, 2, 877, 878, 7, 123, 2, 2, 878, 879, 7, 118, 2, 2, 879, 1080, 7, 103, 2, 2, 880, 881, 7, 117, 2, 2, 881, 882, 7, 106, 2, 2, 882, 883, 7, 113, 2, 2, 883, 884, 7, 116, 2, 2, 884, 1080, 7, 118, 2, 2, 885, 886, 7, 107, 2, 2, 886, 887, 7, 112, 2, 2, 887, 1080, 7, 118, 2, 2, 888, 889, 7, 110, 2, 2, 889, 890, 7, 113, 2, 2, 890, 891, 7, 112, 2, 2, 891, 1080, 7, 105, 2, 2, 892, 893, 7, 119, 2, 2, 893, 894, 7, 112, 2, 2, 894, 895, 7, 117, 2, 2, 895, 896, 7, 107, 2, 2, 896, 897, 7, 105, 2, 2, 897, 898, 7, 112, 2, 2, 898, 899, 7, 103, 2, 2, 899, 900, 7, 102, 2, 2, 900, 901, 7, 68, 2, 2, 901, 902, 7, 123, 2, 2, 902, 903, 7, 118, 2, 2, 903, 1080, 7, 103, 2, 2, 904, 905, 7, 119, 2, 2, 905, 906, 7, 112, 2, 2, 906, 907, 7, 117, 2, 2, 907, 908, 7, 107, 2, 2, 908, 909, 7, 105, 2, 2, 909, 910, 7, 112, 2, 2, 910, 911, 7, 103, 2, 2, 911, 912, 7, 102, 2, 2, 912, 913, 7, 85, 2, 2, 913, 914, 7, 106, 2, 2, 914, 915, 7, 113, 2, 2, 915, 916, 7, 116, 2, 2, 916, 1080, 7, 118, 2, 2, 917, 918, 7, 119, 2, 2, 918, 919, 7, 112, 2, 2, 919, 920, 7, 117, 2, 2, 920, 921, 7, 107, 2, 2, 921, 922, 7, 105, 2, 2, 922, 923, 7, 112, 2, 2, 923, 924, 7, 103, 2, 2, 924, 925, 7, 102, 2, 2, 925, 926, 7, 75, 2, 2, 926, 927, 7, 112, 2, 2, 927, 1080, 7, 118, 2, 2, 928, 929, 7, 119, 2, 2, 929, 930, 7, 112, 2, 2, 930, 931, 7, 117, 2, 2, 931, 932, 7, 107, 2, 2, 932, 933, 7, 105, 2, 2, 933, 934, 7, 112, 2, 2, 934, 935, 7, 103, 2, 2, 935, 936, 7, 102, 2, 2, 936, 937, 7, 78, 2, 2, 937, 938, 7, 113, 2, 2, 938, 939, 7, 112, 2, 2, 939, 1080, 7, 105, 2, 2, 940, 941, 7, 114, 2, 2, 941, 942, 7, 113, 2, 2, 942, 943, 7, 117, 2, 2, 943, 944, 7, 107, 2, 2, 944, 945, 7, 118, 2, 2, 945, 946, 7, 107, 2, 2, 946, 947, 7, 120, 2, 2, 947, 948, 7, 103, 2, 2, 948, 949, 7, 75, 2, 2, 949, 950, 7, 112, 2, 2, 950, 951, 7, 118, 2, 2, 951, 952, 7, 103, 2, 2, 952, 953, 7, 105, 2, 2, 953, 954, 7, 103, 2, 2, 954, 1080, 7, 116, 2, 2, 955, 956, 7, 112, 2, 2, 956, 957, 7, 113, 2, 2, 957, 958, 7, 112, 2, 2, 958, 959, 7, 80, 2, 2, 959, 960, 7, 103, 2, 2, 960, 961, 7, 105, 2, 2, 961, 962, 7, 99, 2, 2, 962, 963, 7, 118, 2, 2, 963, 964, 7, 107, 2, 2, 964, 965, 7, 120, 2, 2, 965, 966, 7, 103, 2, 2, 966, 967, 7, 75, 2, 2, 967, 968, 7, 112, 2, 2, 968, 969, 7, 118, 2, 2, 969, 970, 7, 103, 2, 2, 970, 971, 7, 105, 2, 2, 971, 972, 7, 103, 2, 2, 972, 1080, 7, 116, 2, 2, 973, 974, 7, 112, 2, 2, 974, 975, 7, 103, 2, 2, 975, 976, 7, 105, 2, 2, 976, 977, 7, 99, 2, 2, 977, 978, 7, 118, 2, 2, 978, 979, 7, 107, 2, 2, 979, 980, 7, 120, 2, 2, 980, 981, 7, 103, 2, 2, 981, 982, 7, 75, 2, 2, 982, 983, 7, 112, 2, 2, 983, 984, 7, 118, 2, 2, 984, 985, 7, 103, 2, 2, 985, 986, 7, 105, 2, 2, 986, 987, 7, 103, 2, 2, 987, 1080, 7, 116, 2, 2, 988, 989, 7, 112, 2, 2, 989, 990, 7, 113, 2, 2, 990, 991, 7, 112, 2, 2, 991, 992, 7, 82, 2, 2, 992, 993, 7, 113, 2, 2, 993, 994, 7, 117, 2, 2, 994, 995, 7, 107, 2, 2, 995, 996, 7, 118, 2, 2, 996, 997, 7, 107, 2, 2, 997, 998, 7, 120, 2, 2, 998, 999, 7, 103, 2, 2, 999, 1000, 7, 75, 2, 2, 1000, 1001, 7, 112, 2, 2, 1001, 1002, 7, 118, 2, 2, 1002, 1003, 7, 103, 2, 2, 1003, 1004, 7, 105, 2, 2, 1004, 1005, 7, 103, 2, 2, 1005, 1080, 7, 116, 2, 2, 1006, 1007, 7, 106, 2, 2, 1007, 1008, 7, 103, 2, 2, 1008, 1009, 7, 122, 2, 2, 1009, 1010, 7, 68, 2, 2, 1010, 1011, 7, 107, 2, 2, 1011, 1012, 7, 112, 2, 2, 1012, 1013, 7, 99, 2, 2, 1013, 1014, 7, 116, 2, 2, 1014, 1080, 7, 123, 2, 2, 1015, 1016, 7, 100, 2, 2, 1016, 1017, 7, 99, 2, 2, 1017, 1018, 7, 117, 2, 2, 1018, 1019, 7, 103, 2, 2, 1019, 1020, 7, 56, 2, 2, 1020, 1021, 7, 54, 2, 2, 1021, 1022, 7, 68, 2, 2, 1022, 1023, 7, 107, 2, 2, 1023, 1024, 7, 112, 2, 2, 1024, 1025, 7, 99, 2, 2, 1025, 1026, 7, 116, 2, 2, 1026, 1080, 7, 123, 2, 2, 1027, 1028, 7, 99, 2, 2, 1028, 1029, 7, 112, 2, 2, 1029, 1030, 7, 123, 2, 2, 1030, 1031, 7, 87, 2, 2, 1031, 1032, 7, 84, 2, 2, 1032, 1080, 7, 75, 2, 2, 1033, 1034, 7, 110, 2, 2, 1034, 1035, 7, 99, 2, 2, 1035, 1036, 7, 112, 2, 2, 1036, 1037, 7, 105, 2, 2, 1037, 1038, 7, 119, 2, 2, 1038, 1039, 7, 99, 2, 2, 1039, 1040, 7, 105, 2, 2, 1040, 1080, 7, 103, 2, 2, 1041, 1042, 7, 112, 2, 2, 1042, 1043, 7, 113, 2, 2, 1043, 1044, 7, 116, 2, 2, 1044, 1045, 7, 111, 2, 2, 1045, 1046, 7, 99, 2, 2, 1046, 1047, 7, 110, 2, 2, 1047, 1048, 7, 107, 2, 2, 1048, 1049, 7, 124, 2, 2, 1049, 1050, 7, 103, 2, 2, 1050, 1051, 7, 102, 2, 2, 1051, 1052, 7, 85, 2, 2, 1052, 1053, 7, 118, 2, 2, 1053, 1054, 7, 116, 2, 2, 1054, 1055, 7, 107, 2, 2, 1055, 1056, 7, 112, 2, 2, 1056, 1080, 7, 105, 2, 2, 1057, 1058, 7, 118, 2, 2, 1058, 1059, 7, 113, 2, 2, 1059, 1060, 7, 109, 2, 2, 1060, 1061, 7, 103, 2, 2, 1061, 1080, 7, 112, 2, 2, 1062, 1063, 7, 80, 2, 2, 1063, 1064, 7, 79, 2, 2, 1064, 1065, 7, 86, 2, 2, 1065, 1066, 7, 81, 2, 2, 1066, 1067, 7, 77, 2, 2, 1067, 1068, 7, 71, 2, 2, 1068, 1080, 7, 80, 2, 2, 1069, 1070, 7, 80, 2, 2, 1070, 1071, 7, 99, 2, 2, 1071, 1072, 7, 111, 2, 2, 1072, 1080, 7, 103, 2, 2, 1073, 1074, 7, 80, 2, 2, 1074, 1075, 7, 69, 2, 2, 1075, 1076, 7, 80, 2, 2, 1076, 1077, 7, 99, 2, 2, 1077, 1078, 7, 111, 2, 2, 1078, 1080, 7, 103, 2, 2, 1079, 735, 3, 2, 2, 2, 1079, 741, 3, 2, 2, 2, 1079, 748, 3, 2, 2, 2, 1079, 755, 3, 2, 2, 2, 1079, 762, 3, 2, 2, 2, 1079, 768, 3, 2, 2, 2, 1079, 773, 3, 2, 2, 2, 1079, 777, 3, 2, 2, 2, 1079, 781, 3, 2, 2, 2, 1079, 789, 3, 2, 2, 2, 1079, 802, 3, 2, 2, 2, 1079, 807, 3, 2, 2, 2, 1079, 813, 3, 2, 2, 2, 1079, 817, 3, 2, 2, 2, 1079, 827, 3, 2, 2, 2, 1079, 836, 3, 2, 2, 2, 1079, 844, 3, 2, 2, 2, 1079, 861, 3, 2, 2, 2, 1079, 876, 3, 2, 2, 2, 1079, 880, 3, 2, 2, 2, 1079, 885, 3, 2, 2, 2, 1079, 888, 3, 2, 2, 2, 1079, 892, 3, 2, 2, 2, 1079, 904, 3, 2, 2, 2, 1079, 917, 3, 2, 2, 2, 1079, 928, 3, 2, 2, 2, 1079, 940, 3, 2, 2, 2, 1079, 955, 3, 2, 2, 2, 1079, 973, 3, 2, 2, 2, 1079, 988, 3, 2, 2, 2, 1079, 1006, 3, 2, 2, 2, 1079, 1015, 3, 2, 2, 2, 1079, 1027, 3, 2, 2, 2, 1079, 1033, 3, 2, 2, 2, 1079, 1041, 3, 2, 2, 2, 1079, 1057, 3, 2, 2, 2, 1079, 1062, 3, 2, 2, 2, 1079, 1069, 3, 2, 2, 2, 1079, 1073, 3, 2, 2, 2, 1080, 161, 3, 2, 2, 2, 1081, 1087, 9, 9, 2, 2, 1082, 1083, 7, 94, 2, 2, 1083, 1087, 7, 62, 2, 2, 1084, 1085, 7, 94, 2, 2, 1085, 1087, 7, 64, 2, 2, 1086, 1081, 3, 2, 2, 2, 1086, 1082, 3, 2, 2, 2, 1086, 1084, 3, 2, 2, 2, 1087, 163, 3, 2, 2, 2, 1088, 1089, 9, 10, 2, 2, 1089, 165, 3, 2, 2, 2, 1090, 1091, 9, 11, 2, 2, 1091, 167, 3, 2, 2, 2, 1092, 1093, 9, 12, 2, 2, 1093, 169, 3, 2, 2, 2, 1094, 1095, 9, 13, 2, 2, 1095, 171, 3, 2, 2, 2, 1096, 1097, 9, 14, 2, 2, 1097, 173, 3, 2, 2, 2, 1098, 1099, 9, 15, 2, 2, 1099, 175, 3, 2, 2, 2, 1100, 1101, 9, 16, 2, 2, 1101, 177, 3, 2, 2, 2, 1102, 1103, 9, 17, 2, 2, 1103, 179, 3, 2, 2, 2, 1104, 1105, 9, 18, 2, 2, 1105, 181, 3, 2, 2, 2, 1106, 1107, 9, 19, 2, 2, 1107, 183, 3, 2, 2, 2, 1108, 1109, 9, 20, 2, 2, 1109, 185, 3, 2, 2, 2, 1110, 1111, 9, 21, 2, 2, 1111, 187, 3, 2, 2, 2, 1112, 1113, 9, 22, 2, 2, 1113, 189, 3, 2, 2, 2, 1114, 1115, 9, 23, 2, 2, 1115, 191, 3, 2, 2, 2, 1116, 1117, 9, 24, 2, 2, 1117, 193, 3, 2, 2, 2, 1118, 1119, 9, 25, 2, 2, 1119, 195, 3, 2, 2, 2, 1120, 1121, 9, 26, 2, 2, 1121, 197, 3, 2, 2, 2, 1122, 1123, 9, 27, 2, 2, 1123, 199, 3, 2, 2, 2, 1124, 1125, 9, 28, 2, 2, 1125, 201, 3, 2, 2, 2, 1126, 1127, 9, 29, 2, 2, 1127, 203, 3, 2, 2, 2, 1128, 1129, 9, 30, 2, 2, 1129, 205, 3, 2, 2, 2, 1130, 1131, 9, 31, 2, 2, 1131, 207, 3, 2, 2, 2, 1132, 1133, 9, 32, 2, 2, 1133, 209, 3, 2, 2, 2, 1134, 1135, 9, 33, 2, 2, 1135, 211, 3, 2, 2, 2, 1136, 1137, 9, 34, 2, 2, 1137, 213, 3, 2, 2, 2, 41, 2, 3, 4, 5, 443, 467, 469, 479, 481, 491, 493, 509, 515, 520, 522, 526, 533, 555, 564, 566, 577, 579, 585, 587, 641, 643, 661, 663, 669, 671, 693, 699, 701, 709, 711, 724, 733, 1079, 1086, 7, 4, 4, 2, 4, 5, 2, 8, 2, 2, 4, 2, 2, 4, 3, 2] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 77, 1146, 8, 1, 8, 1, 8, 1, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 4, 88, 9, 88, 4, 89, 9, 89, 4, 90, 9, 90, 4, 91, 9, 91, 4, 92, 9, 92, 4, 93, 9, 93, 4, 94, 9, 94, 4, 95, 9, 95, 4, 96, 9, 96, 4, 97, 9, 97, 4, 98, 9, 98, 4, 99, 9, 99, 4, 100, 9, 100, 4, 101, 9, 101, 4, 102, 9, 102, 4, 103, 9, 103, 4, 104, 9, 104, 4, 105, 9, 105, 4, 106, 9, 106, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 5, 39, 446, 10, 39, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 6, 44, 470, 10, 44, 13, 44, 14, 44, 471, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 7, 45, 482, 10, 45, 12, 45, 14, 45, 485, 11, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 6, 46, 494, 10, 46, 13, 46, 14, 46, 495, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 48, 3, 48, 3, 48, 3, 48, 3, 48, 5, 48, 512, 10, 48, 3, 49, 3, 49, 6, 49, 516, 10, 49, 13, 49, 14, 49, 517, 3, 49, 3, 49, 3, 49, 6, 49, 523, 10, 49, 13, 49, 14, 49, 524, 7, 49, 527, 10, 49, 12, 49, 14, 49, 530, 11, 49, 3, 50, 3, 50, 7, 50, 534, 10, 50, 12, 50, 14, 50, 537, 11, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 5, 52, 558, 10, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 7, 52, 567, 10, 52, 12, 52, 14, 52, 570, 11, 52, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 6, 53, 580, 10, 53, 13, 53, 14, 53, 581, 3, 53, 3, 53, 3, 53, 3, 53, 7, 53, 588, 10, 53, 12, 53, 14, 53, 591, 11, 53, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 61, 3, 61, 3, 61, 3, 61, 6, 61, 650, 10, 61, 13, 61, 14, 61, 651, 3, 62, 3, 62, 3, 62, 3, 62, 3, 63, 3, 63, 3, 63, 3, 63, 3, 64, 3, 64, 3, 64, 3, 64, 3, 65, 3, 65, 3, 65, 3, 65, 7, 65, 670, 10, 65, 12, 65, 14, 65, 673, 11, 65, 3, 66, 3, 66, 3, 66, 7, 66, 678, 10, 66, 12, 66, 14, 66, 681, 11, 66, 3, 66, 3, 66, 3, 67, 3, 67, 3, 67, 3, 67, 3, 68, 3, 68, 3, 69, 3, 69, 3, 69, 3, 70, 3, 70, 3, 70, 3, 71, 3, 71, 3, 72, 6, 72, 700, 10, 72, 13, 72, 14, 72, 701, 3, 73, 3, 73, 3, 73, 3, 73, 7, 73, 708, 10, 73, 12, 73, 14, 73, 711, 11, 73, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 6, 74, 718, 10, 74, 13, 74, 14, 74, 719, 3, 74, 3, 74, 3, 75, 3, 75, 3, 75, 3, 75, 3, 76, 3, 76, 3, 76, 3, 76, 3, 77, 5, 77, 733, 10, 77, 3, 78, 3, 78, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 5, 79, 742, 10, 79, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 5, 80, 1088, 10, 80, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 5, 81, 1095, 10, 81, 3, 82, 3, 82, 3, 83, 3, 83, 3, 84, 3, 84, 3, 85, 3, 85, 3, 86, 3, 86, 3, 87, 3, 87, 3, 88, 3, 88, 3, 89, 3, 89, 3, 90, 3, 90, 3, 91, 3, 91, 3, 92, 3, 92, 3, 93, 3, 93, 3, 94, 3, 94, 3, 95, 3, 95, 3, 96, 3, 96, 3, 97, 3, 97, 3, 98, 3, 98, 3, 99, 3, 99, 3, 100, 3, 100, 3, 101, 3, 101, 3, 102, 3, 102, 3, 103, 3, 103, 3, 104, 3, 104, 3, 105, 3, 105, 3, 106, 3, 106, 2, 2, 107, 6, 3, 8, 4, 10, 5, 12, 6, 14, 7, 16, 8, 18, 9, 20, 10, 22, 11, 24, 12, 26, 13, 28, 14, 30, 15, 32, 16, 34, 17, 36, 18, 38, 19, 40, 20, 42, 21, 44, 22, 46, 23, 48, 24, 50, 25, 52, 26, 54, 27, 56, 28, 58, 29, 60, 30, 62, 31, 64, 32, 66, 33, 68, 34, 70, 35, 72, 36, 74, 37, 76, 38, 78, 39, 80, 40, 82, 41, 84, 42, 86, 43, 88, 44, 90, 45, 92, 46, 94, 47, 96, 48, 98, 49, 100, 50, 102, 51, 104, 52, 106, 53, 108, 54, 110, 55, 112, 56, 114, 57, 116, 58, 118, 59, 120, 60, 122, 61, 124, 62, 126, 63, 128, 64, 130, 65, 132, 66, 134, 67, 136, 68, 138, 69, 140, 70, 142, 71, 144, 72, 146, 73, 148, 74, 150, 75, 152, 76, 154, 77, 156, 2, 158, 2, 160, 2, 162, 2, 164, 2, 166, 2, 168, 2, 170, 2, 172, 2, 174, 2, 176, 2, 178, 2, 180, 2, 182, 2, 184, 2, 186, 2, 188, 2, 190, 2, 192, 2, 194, 2, 196, 2, 198, 2, 200, 2, 202, 2, 204, 2, 206, 2, 208, 2, 210, 2, 212, 2, 214, 2, 6, 2, 3, 4, 5, 35, 4, 2, 67, 67, 99, 99, 4, 2, 47, 47, 97, 97, 4, 2, 12, 12, 15, 15, 5, 2, 11, 12, 15, 15, 34, 34, 5, 2, 36, 36, 125, 125, 127, 127, 7, 2, 67, 92, 99, 124, 194, 216, 218, 248, 250, 257, 3, 2, 50, 59, 8, 2, 37, 44, 46, 49, 60, 61, 63, 63, 65, 66, 93, 97, 4, 2, 68, 68, 100, 100, 4, 2, 69, 69, 101, 101, 4, 2, 70, 70, 102, 102, 4, 2, 71, 71, 103, 103, 4, 2, 72, 72, 104, 104, 4, 2, 73, 73, 105, 105, 4, 2, 74, 74, 106, 106, 4, 2, 75, 75, 107, 107, 4, 2, 76, 76, 108, 108, 4, 2, 77, 77, 109, 109, 4, 2, 78, 78, 110, 110, 4, 2, 79, 79, 111, 111, 4, 2, 80, 80, 112, 112, 4, 2, 81, 81, 113, 113, 4, 2, 82, 82, 114, 114, 4, 2, 83, 83, 115, 115, 4, 2, 84, 84, 116, 116, 4, 2, 85, 85, 117, 117, 4, 2, 86, 86, 118, 118, 4, 2, 87, 87, 119, 119, 4, 2, 88, 88, 120, 120, 4, 2, 89, 89, 121, 121, 4, 2, 90, 90, 122, 122, 4, 2, 91, 91, 123, 123, 4, 2, 92, 92, 124, 124, 2, 1202, 2, 6, 3, 2, 2, 2, 2, 8, 3, 2, 2, 2, 2, 10, 3, 2, 2, 2, 2, 12, 3, 2, 2, 2, 2, 14, 3, 2, 2, 2, 2, 16, 3, 2, 2, 2, 2, 18, 3, 2, 2, 2, 2, 20, 3, 2, 2, 2, 2, 22, 3, 2, 2, 2, 2, 24, 3, 2, 2, 2, 2, 26, 3, 2, 2, 2, 2, 28, 3, 2, 2, 2, 2, 30, 3, 2, 2, 2, 2, 32, 3, 2, 2, 2, 2, 34, 3, 2, 2, 2, 2, 36, 3, 2, 2, 2, 2, 38, 3, 2, 2, 2, 2, 40, 3, 2, 2, 2, 2, 42, 3, 2, 2, 2, 2, 44, 3, 2, 2, 2, 2, 46, 3, 2, 2, 2, 2, 48, 3, 2, 2, 2, 2, 50, 3, 2, 2, 2, 2, 52, 3, 2, 2, 2, 2, 54, 3, 2, 2, 2, 2, 56, 3, 2, 2, 2, 2, 58, 3, 2, 2, 2, 2, 60, 3, 2, 2, 2, 2, 62, 3, 2, 2, 2, 2, 64, 3, 2, 2, 2, 2, 66, 3, 2, 2, 2, 2, 68, 3, 2, 2, 2, 2, 70, 3, 2, 2, 2, 2, 72, 3, 2, 2, 2, 2, 74, 3, 2, 2, 2, 2, 76, 3, 2, 2, 2, 2, 78, 3, 2, 2, 2, 2, 80, 3, 2, 2, 2, 2, 82, 3, 2, 2, 2, 2, 84, 3, 2, 2, 2, 2, 86, 3, 2, 2, 2, 2, 88, 3, 2, 2, 2, 2, 90, 3, 2, 2, 2, 2, 92, 3, 2, 2, 2, 2, 94, 3, 2, 2, 2, 2, 96, 3, 2, 2, 2, 2, 98, 3, 2, 2, 2, 2, 100, 3, 2, 2, 2, 2, 102, 3, 2, 2, 2, 2, 104, 3, 2, 2, 2, 3, 106, 3, 2, 2, 2, 3, 108, 3, 2, 2, 2, 3, 110, 3, 2, 2, 2, 3, 112, 3, 2, 2, 2, 3, 114, 3, 2, 2, 2, 3, 116, 3, 2, 2, 2, 3, 118, 3, 2, 2, 2, 3, 120, 3, 2, 2, 2, 3, 122, 3, 2, 2, 2, 3, 124, 3, 2, 2, 2, 3, 126, 3, 2, 2, 2, 3, 128, 3, 2, 2, 2, 4, 130, 3, 2, 2, 2, 4, 132, 3, 2, 2, 2, 4, 134, 3, 2, 2, 2, 4, 136, 3, 2, 2, 2, 5, 138, 3, 2, 2, 2, 5, 140, 3, 2, 2, 2, 5, 142, 3, 2, 2, 2, 5, 144, 3, 2, 2, 2, 5, 146, 3, 2, 2, 2, 5, 148, 3, 2, 2, 2, 5, 150, 3, 2, 2, 2, 5, 152, 3, 2, 2, 2, 5, 154, 3, 2, 2, 2, 6, 216, 3, 2, 2, 2, 8, 225, 3, 2, 2, 2, 10, 234, 3, 2, 2, 2, 12, 242, 3, 2, 2, 2, 14, 253, 3, 2, 2, 2, 16, 265, 3, 2, 2, 2, 18, 273, 3, 2, 2, 2, 20, 288, 3, 2, 2, 2, 22, 303, 3, 2, 2, 2, 24, 319, 3, 2, 2, 2, 26, 330, 3, 2, 2, 2, 28, 336, 3, 2, 2, 2, 30, 341, 3, 2, 2, 2, 32, 354, 3, 2, 2, 2, 34, 362, 3, 2, 2, 2, 36, 365, 3, 2, 2, 2, 38, 368, 3, 2, 2, 2, 40, 371, 3, 2, 2, 2, 42, 380, 3, 2, 2, 2, 44, 388, 3, 2, 2, 2, 46, 395, 3, 2, 2, 2, 48, 402, 3, 2, 2, 2, 50, 409, 3, 2, 2, 2, 52, 411, 3, 2, 2, 2, 54, 413, 3, 2, 2, 2, 56, 415, 3, 2, 2, 2, 58, 418, 3, 2, 2, 2, 60, 420, 3, 2, 2, 2, 62, 423, 3, 2, 2, 2, 64, 425, 3, 2, 2, 2, 66, 427, 3, 2, 2, 2, 68, 429, 3, 2, 2, 2, 70, 431, 3, 2, 2, 2, 72, 433, 3, 2, 2, 2, 74, 435, 3, 2, 2, 2, 76, 437, 3, 2, 2, 2, 78, 439, 3, 2, 2, 2, 80, 445, 3, 2, 2, 2, 82, 447, 3, 2, 2, 2, 84, 449, 3, 2, 2, 2, 86, 451, 3, 2, 2, 2, 88, 453, 3, 2, 2, 2, 90, 469, 3, 2, 2, 2, 92, 483, 3, 2, 2, 2, 94, 488, 3, 2, 2, 2, 96, 499, 3, 2, 2, 2, 98, 503, 3, 2, 2, 2, 100, 513, 3, 2, 2, 2, 102, 531, 3, 2, 2, 2, 104, 540, 3, 2, 2, 2, 106, 557, 3, 2, 2, 2, 108, 571, 3, 2, 2, 2, 110, 592, 3, 2, 2, 2, 112, 602, 3, 2, 2, 2, 114, 609, 3, 2, 2, 2, 116, 619, 3, 2, 2, 2, 118, 624, 3, 2, 2, 2, 120, 631, 3, 2, 2, 2, 122, 639, 3, 2, 2, 2, 124, 649, 3, 2, 2, 2, 126, 653, 3, 2, 2, 2, 128, 657, 3, 2, 2, 2, 130, 661, 3, 2, 2, 2, 132, 665, 3, 2, 2, 2, 134, 679, 3, 2, 2, 2, 136, 684, 3, 2, 2, 2, 138, 688, 3, 2, 2, 2, 140, 690, 3, 2, 2, 2, 142, 693, 3, 2, 2, 2, 144, 696, 3, 2, 2, 2, 146, 699, 3, 2, 2, 2, 148, 703, 3, 2, 2, 2, 150, 712, 3, 2, 2, 2, 152, 723, 3, 2, 2, 2, 154, 727, 3, 2, 2, 2, 156, 732, 3, 2, 2, 2, 158, 734, 3, 2, 2, 2, 160, 741, 3, 2, 2, 2, 162, 1087, 3, 2, 2, 2, 164, 1094, 3, 2, 2, 2, 166, 1096, 3, 2, 2, 2, 168, 1098, 3, 2, 2, 2, 170, 1100, 3, 2, 2, 2, 172, 1102, 3, 2, 2, 2, 174, 1104, 3, 2, 2, 2, 176, 1106, 3, 2, 2, 2, 178, 1108, 3, 2, 2, 2, 180, 1110, 3, 2, 2, 2, 182, 1112, 3, 2, 2, 2, 184, 1114, 3, 2, 2, 2, 186, 1116, 3, 2, 2, 2, 188, 1118, 3, 2, 2, 2, 190, 1120, 3, 2, 2, 2, 192, 1122, 3, 2, 2, 2, 194, 1124, 3, 2, 2, 2, 196, 1126, 3, 2, 2, 2, 198, 1128, 3, 2, 2, 2, 200, 1130, 3, 2, 2, 2, 202, 1132, 3, 2, 2, 2, 204, 1134, 3, 2, 2, 2, 206, 1136, 3, 2, 2, 2, 208, 1138, 3, 2, 2, 2, 210, 1140, 3, 2, 2, 2, 212, 1142, 3, 2, 2, 2, 214, 1144, 3, 2, 2, 2, 216, 217, 5, 194, 96, 2, 217, 218, 5, 198, 98, 2, 218, 219, 5, 172, 85, 2, 219, 220, 5, 174, 86, 2, 220, 221, 5, 180, 89, 2, 221, 222, 5, 210, 104, 2, 222, 223, 3, 2, 2, 2, 223, 224, 8, 2, 2, 2, 224, 7, 3, 2, 2, 2, 225, 226, 5, 200, 99, 2, 226, 227, 5, 192, 95, 2, 227, 228, 5, 204, 101, 2, 228, 229, 5, 198, 98, 2, 229, 230, 5, 168, 83, 2, 230, 231, 5, 172, 85, 2, 231, 232, 3, 2, 2, 2, 232, 233, 8, 3, 2, 2, 233, 9, 3, 2, 2, 2, 234, 235, 5, 196, 97, 2, 235, 236, 5, 204, 101, 2, 236, 237, 5, 172, 85, 2, 237, 238, 5, 198, 98, 2, 238, 239, 5, 212, 105, 2, 239, 240, 3, 2, 2, 2, 240, 241, 8, 4, 2, 2, 241, 11, 3, 2, 2, 2, 242, 243, 5, 180, 89, 2, 243, 244, 5, 202, 100, 2, 244, 245, 5, 172, 85, 2, 245, 246, 5, 198, 98, 2, 246, 247, 5, 82, 40, 2, 247, 248, 5, 202, 100, 2, 248, 249, 5, 192, 95, 2, 249, 250, 5, 198, 98, 2, 250, 251, 3, 2, 2, 2, 251, 252, 8, 5, 2, 2, 252, 13, 3, 2, 2, 2, 253, 254, 5, 174, 86, 2, 254, 255, 5, 204, 101, 2, 255, 256, 5, 190, 94, 2, 256, 257, 5, 168, 83, 2, 257, 258, 5, 202, 100, 2, 258, 259, 5, 180, 89, 2, 259, 260, 5, 192, 95, 2, 260, 261, 5, 190, 94, 2, 261, 262, 5, 200, 99, 2, 262, 263, 3, 2, 2, 2, 263, 264, 8, 6, 2, 2, 264, 15, 3, 2, 2, 2, 265, 266, 5, 174, 86, 2, 266, 267, 5, 180, 89, 2, 267, 268, 5, 172, 85, 2, 268, 269, 5, 186, 92, 2, 269, 270, 5, 170, 84, 2, 270, 271, 3, 2, 2, 2, 271, 272, 8, 7, 2, 2, 272, 17, 3, 2, 2, 2, 273, 274, 5, 194, 96, 2, 274, 275, 5, 204, 101, 2, 275, 276, 5, 200, 99, 2, 276, 277, 5, 178, 88, 2, 277, 278, 5, 172, 85, 2, 278, 279, 5, 170, 84, 2, 279, 280, 7, 97, 2, 2, 280, 281, 5, 174, 86, 2, 281, 282, 5, 180, 89, 2, 282, 283, 5, 172, 85, 2, 283, 284, 5, 186, 92, 2, 284, 285, 5, 170, 84, 2, 285, 286, 3, 2, 2, 2, 286, 287, 8, 8, 2, 2, 287, 19, 3, 2, 2, 2, 288, 289, 5, 194, 96, 2, 289, 290, 5, 192, 95, 2, 290, 291, 5, 194, 96, 2, 291, 292, 5, 194, 96, 2, 292, 293, 5, 172, 85, 2, 293, 294, 5, 170, 84, 2, 294, 295, 7, 97, 2, 2, 295, 296, 5, 174, 86, 2, 296, 297, 5, 180, 89, 2, 297, 298, 5, 172, 85, 2, 298, 299, 5, 186, 92, 2, 299, 300, 5, 170, 84, 2, 300, 301, 3, 2, 2, 2, 301, 302, 8, 9, 2, 2, 302, 21, 3, 2, 2, 2, 303, 304, 5, 82, 40, 2, 304, 305, 5, 204, 101, 2, 305, 306, 5, 202, 100, 2, 306, 307, 5, 192, 95, 2, 307, 308, 5, 180, 89, 2, 308, 309, 5, 190, 94, 2, 309, 310, 5, 168, 83, 2, 310, 311, 5, 198, 98, 2, 311, 312, 5, 172, 85, 2, 312, 313, 5, 188, 93, 2, 313, 314, 5, 172, 85, 2, 314, 315, 5, 190, 94, 2, 315, 316, 5, 202, 100, 2, 316, 317, 3, 2, 2, 2, 317, 318, 8, 10, 3, 2, 318, 23, 3, 2, 2, 2, 319, 320, 5, 172, 85, 2, 320, 321, 5, 210, 104, 2, 321, 322, 5, 194, 96, 2, 322, 323, 5, 198, 98, 2, 323, 324, 5, 172, 85, 2, 324, 325, 5, 200, 99, 2, 325, 326, 5, 200, 99, 2, 326, 327, 5, 180, 89, 2, 327, 328, 5, 192, 95, 2, 328, 329, 5, 190, 94, 2, 329, 25, 3, 2, 2, 2, 330, 331, 5, 204, 101, 2, 331, 332, 5, 190, 94, 2, 332, 333, 5, 180, 89, 2, 333, 334, 5, 192, 95, 2, 334, 335, 5, 190, 94, 2, 335, 27, 3, 2, 2, 2, 336, 337, 5, 182, 90, 2, 337, 338, 5, 192, 95, 2, 338, 339, 5, 180, 89, 2, 339, 340, 5, 190, 94, 2, 340, 29, 3, 2, 2, 2, 341, 342, 5, 200, 99, 2, 342, 343, 5, 204, 101, 2, 343, 344, 5, 166, 82, 2, 344, 345, 5, 200, 99, 2, 345, 346, 5, 202, 100, 2, 346, 347, 5, 180, 89, 2, 347, 348, 5, 202, 100, 2, 348, 349, 5, 204, 101, 2, 349, 350, 5, 202, 100, 2, 350, 351, 5, 180, 89, 2, 351, 352, 5, 190, 94, 2, 352, 353, 5, 176, 87, 2, 353, 31, 3, 2, 2, 2, 354, 355, 5, 188, 93, 2, 355, 356, 5, 82, 40, 2, 356, 357, 5, 202, 100, 2, 357, 358, 5, 168, 83, 2, 358, 359, 5, 178, 88, 2, 359, 360, 5, 172, 85, 2, 360, 361, 5, 198, 98, 2, 361, 33, 3, 2, 2, 2, 362, 363, 5, 82, 40, 2, 363, 364, 5, 200, 99, 2, 364, 35, 3, 2, 2, 2, 365, 366, 5, 180, 89, 2, 366, 367, 5, 174, 86, 2, 367, 37, 3, 2, 2, 2, 368, 369, 5, 192, 95, 2, 369, 370, 5, 190, 94, 2, 370, 39, 3, 2, 2, 2, 371, 372, 5, 188, 93, 2, 372, 373, 5, 82, 40, 2, 373, 374, 5, 202, 100, 2, 374, 375, 5, 168, 83, 2, 375, 376, 5, 178, 88, 2, 376, 377, 5, 180, 89, 2, 377, 378, 5, 190, 94, 2, 378, 379, 5, 176, 87, 2, 379, 41, 3, 2, 2, 2, 380, 381, 5, 198, 98, 2, 381, 382, 5, 170, 84, 2, 382, 383, 5, 174, 86, 2, 383, 384, 5, 186, 92, 2, 384, 385, 5, 180, 89, 2, 385, 386, 5, 200, 99, 2, 386, 387, 5, 202, 100, 2, 387, 43, 3, 2, 2, 2, 388, 389, 5, 198, 98, 2, 389, 390, 5, 170, 84, 2, 390, 391, 5, 174, 86, 2, 391, 392, 5, 166, 82, 2, 392, 393, 5, 82, 40, 2, 393, 394, 5, 176, 87, 2, 394, 45, 3, 2, 2, 2, 395, 396, 5, 198, 98, 2, 396, 397, 5, 170, 84, 2, 397, 398, 5, 174, 86, 2, 398, 399, 5, 200, 99, 2, 399, 400, 5, 172, 85, 2, 400, 401, 5, 196, 97, 2, 401, 47, 3, 2, 2, 2, 402, 403, 5, 198, 98, 2, 403, 404, 5, 170, 84, 2, 404, 405, 5, 174, 86, 2, 405, 406, 5, 82, 40, 2, 406, 407, 5, 186, 92, 2, 407, 408, 5, 202, 100, 2, 408, 49, 3, 2, 2, 2, 409, 410, 7, 62, 2, 2, 410, 51, 3, 2, 2, 2, 411, 412, 7, 64, 2, 2, 412, 53, 3, 2, 2, 2, 413, 414, 7, 93, 2, 2, 414, 55, 3, 2, 2, 2, 415, 416, 7, 93, 2, 2, 416, 417, 7, 93, 2, 2, 417, 57, 3, 2, 2, 2, 418, 419, 7, 95, 2, 2, 419, 59, 3, 2, 2, 2, 420, 421, 7, 95, 2, 2, 421, 422, 7, 95, 2, 2, 422, 61, 3, 2, 2, 2, 423, 424, 7, 42, 2, 2, 424, 63, 3, 2, 2, 2, 425, 426, 7, 43, 2, 2, 426, 65, 3, 2, 2, 2, 427, 428, 7, 125, 2, 2, 428, 67, 3, 2, 2, 2, 429, 430, 7, 127, 2, 2, 430, 69, 3, 2, 2, 2, 431, 432, 7, 61, 2, 2, 432, 71, 3, 2, 2, 2, 433, 434, 7, 48, 2, 2, 434, 73, 3, 2, 2, 2, 435, 436, 7, 45, 2, 2, 436, 75, 3, 2, 2, 2, 437, 438, 7, 46, 2, 2, 438, 77, 3, 2, 2, 2, 439, 440, 7, 36, 2, 2, 440, 79, 3, 2, 2, 2, 441, 446, 7, 40, 2, 2, 442, 443, 7, 67, 2, 2, 443, 444, 7, 80, 2, 2, 444, 446, 7, 70, 2, 2, 445, 441, 3, 2, 2, 2, 445, 442, 3, 2, 2, 2, 446, 81, 3, 2, 2, 2, 447, 448, 9, 2, 2, 2, 448, 83, 3, 2, 2, 2, 449, 450, 7, 66, 2, 2, 450, 85, 3, 2, 2, 2, 451, 452, 7, 63, 2, 2, 452, 87, 3, 2, 2, 2, 453, 454, 5, 180, 89, 2, 454, 455, 5, 190, 94, 2, 455, 456, 5, 170, 84, 2, 456, 457, 5, 172, 85, 2, 457, 458, 5, 210, 104, 2, 458, 459, 7, 42, 2, 2, 459, 460, 7, 43, 2, 2, 460, 89, 3, 2, 2, 2, 461, 470, 5, 156, 77, 2, 462, 470, 5, 158, 78, 2, 463, 470, 9, 3, 2, 2, 464, 465, 7, 94, 2, 2, 465, 470, 7, 48, 2, 2, 466, 467, 7, 39, 2, 2, 467, 468, 7, 52, 2, 2, 468, 470, 7, 71, 2, 2, 469, 461, 3, 2, 2, 2, 469, 462, 3, 2, 2, 2, 469, 463, 3, 2, 2, 2, 469, 464, 3, 2, 2, 2, 469, 466, 3, 2, 2, 2, 470, 471, 3, 2, 2, 2, 471, 469, 3, 2, 2, 2, 471, 472, 3, 2, 2, 2, 472, 91, 3, 2, 2, 2, 473, 482, 5, 156, 77, 2, 474, 482, 5, 158, 78, 2, 475, 482, 9, 3, 2, 2, 476, 477, 7, 94, 2, 2, 477, 482, 7, 48, 2, 2, 478, 479, 7, 39, 2, 2, 479, 480, 7, 52, 2, 2, 480, 482, 7, 71, 2, 2, 481, 473, 3, 2, 2, 2, 481, 474, 3, 2, 2, 2, 481, 475, 3, 2, 2, 2, 481, 476, 3, 2, 2, 2, 481, 478, 3, 2, 2, 2, 482, 485, 3, 2, 2, 2, 483, 481, 3, 2, 2, 2, 483, 484, 3, 2, 2, 2, 484, 486, 3, 2, 2, 2, 485, 483, 3, 2, 2, 2, 486, 487, 7, 60, 2, 2, 487, 93, 3, 2, 2, 2, 488, 493, 7, 36, 2, 2, 489, 494, 5, 156, 77, 2, 490, 494, 5, 158, 78, 2, 491, 494, 5, 164, 81, 2, 492, 494, 7, 34, 2, 2, 493, 489, 3, 2, 2, 2, 493, 490, 3, 2, 2, 2, 493, 491, 3, 2, 2, 2, 493, 492, 3, 2, 2, 2, 494, 495, 3, 2, 2, 2, 495, 493, 3, 2, 2, 2, 495, 496, 3, 2, 2, 2, 496, 497, 3, 2, 2, 2, 497, 498, 7, 36, 2, 2, 498, 95, 3, 2, 2, 2, 499, 500, 5, 160, 79, 2, 500, 501, 7, 60, 2, 2, 501, 502, 5, 162, 80, 2, 502, 97, 3, 2, 2, 2, 503, 511, 7, 66, 2, 2, 504, 505, 5, 92, 45, 2, 505, 506, 5, 90, 44, 2, 506, 512, 3, 2, 2, 2, 507, 508, 7, 62, 2, 2, 508, 509, 5, 90, 44, 2, 509, 510, 7, 64, 2, 2, 510, 512, 3, 2, 2, 2, 511, 504, 3, 2, 2, 2, 511, 507, 3, 2, 2, 2, 512, 99, 3, 2, 2, 2, 513, 515, 7, 66, 2, 2, 514, 516, 5, 156, 77, 2, 515, 514, 3, 2, 2, 2, 516, 517, 3, 2, 2, 2, 517, 515, 3, 2, 2, 2, 517, 518, 3, 2, 2, 2, 518, 528, 3, 2, 2, 2, 519, 522, 7, 47, 2, 2, 520, 523, 5, 156, 77, 2, 521, 523, 5, 158, 78, 2, 522, 520, 3, 2, 2, 2, 522, 521, 3, 2, 2, 2, 523, 524, 3, 2, 2, 2, 524, 522, 3, 2, 2, 2, 524, 525, 3, 2, 2, 2, 525, 527, 3, 2, 2, 2, 526, 519, 3, 2, 2, 2, 527, 530, 3, 2, 2, 2, 528, 526, 3, 2, 2, 2, 528, 529, 3, 2, 2, 2, 529, 101, 3, 2, 2, 2, 530, 528, 3, 2, 2, 2, 531, 535, 7, 37, 2, 2, 532, 534, 10, 4, 2, 2, 533, 532, 3, 2, 2, 2, 534, 537, 3, 2, 2, 2, 535, 533, 3, 2, 2, 2, 535, 536, 3, 2, 2, 2, 536, 538, 3, 2, 2, 2, 537, 535, 3, 2, 2, 2, 538, 539, 8, 50, 4, 2, 539, 103, 3, 2, 2, 2, 540, 541, 9, 5, 2, 2, 541, 542, 3, 2, 2, 2, 542, 543, 8, 51, 4, 2, 543, 105, 3, 2, 2, 2, 544, 545, 7, 106, 2, 2, 545, 546, 7, 118, 2, 2, 546, 547, 7, 118, 2, 2, 547, 558, 7, 114, 2, 2, 548, 549, 7, 106, 2, 2, 549, 550, 7, 118, 2, 2, 550, 551, 7, 118, 2, 2, 551, 552, 7, 114, 2, 2, 552, 558, 7, 117, 2, 2, 553, 554, 7, 104, 2, 2, 554, 555, 7, 107, 2, 2, 555, 556, 7, 110, 2, 2, 556, 558, 7, 103, 2, 2, 557, 544, 3, 2, 2, 2, 557, 548, 3, 2, 2, 2, 557, 553, 3, 2, 2, 2, 558, 559, 3, 2, 2, 2, 559, 560, 7, 60, 2, 2, 560, 561, 7, 49, 2, 2, 561, 562, 7, 49, 2, 2, 562, 568, 3, 2, 2, 2, 563, 567, 5, 156, 77, 2, 564, 567, 5, 158, 78, 2, 565, 567, 5, 164, 81, 2, 566, 563, 3, 2, 2, 2, 566, 564, 3, 2, 2, 2, 566, 565, 3, 2, 2, 2, 567, 570, 3, 2, 2, 2, 568, 566, 3, 2, 2, 2, 568, 569, 3, 2, 2, 2, 569, 107, 3, 2, 2, 2, 570, 568, 3, 2, 2, 2, 571, 572, 7, 108, 2, 2, 572, 573, 7, 102, 2, 2, 573, 574, 7, 100, 2, 2, 574, 575, 7, 101, 2, 2, 575, 576, 7, 60, 2, 2, 576, 579, 3, 2, 2, 2, 577, 580, 5, 156, 77, 2, 578, 580, 5, 158, 78, 2, 579, 577, 3, 2, 2, 2, 579, 578, 3, 2, 2, 2, 580, 581, 3, 2, 2, 2, 581, 579, 3, 2, 2, 2, 581, 582, 3, 2, 2, 2, 582, 583, 3, 2, 2, 2, 583, 589, 7, 60, 2, 2, 584, 588, 5, 156, 77, 2, 585, 588, 5, 158, 78, 2, 586, 588, 5, 164, 81, 2, 587, 584, 3, 2, 2, 2, 587, 585, 3, 2, 2, 2, 587, 586, 3, 2, 2, 2, 588, 591, 3, 2, 2, 2, 589, 587, 3, 2, 2, 2, 589, 590, 3, 2, 2, 2, 590, 109, 3, 2, 2, 2, 591, 589, 3, 2, 2, 2, 592, 593, 5, 182, 90, 2, 593, 594, 5, 200, 99, 2, 594, 595, 5, 192, 95, 2, 595, 596, 5, 190, 94, 2, 596, 597, 5, 194, 96, 2, 597, 598, 5, 82, 40, 2, 598, 599, 5, 202, 100, 2, 599, 600, 5, 178, 88, 2, 600, 601, 7, 60, 2, 2, 601, 111, 3, 2, 2, 2, 602, 603, 5, 210, 104, 2, 603, 604, 5, 194, 96, 2, 604, 605, 5, 82, 40, 2, 605, 606, 5, 202, 100, 2, 606, 607, 5, 178, 88, 2, 607, 608, 7, 60, 2, 2, 608, 113, 3, 2, 2, 2, 609, 610, 5, 168, 83, 2, 610, 611, 5, 200, 99, 2, 611, 612, 5, 206, 102, 2, 612, 613, 5, 194, 96, 2, 613, 614, 5, 172, 85, 2, 614, 615, 5, 198, 98, 2, 615, 616, 5, 198, 98, 2, 616, 617, 5, 192, 95, 2, 617, 618, 5, 208, 103, 2, 618, 115, 3, 2, 2, 2, 619, 620, 5, 200, 99, 2, 620, 621, 5, 196, 97, 2, 621, 622, 5, 186, 92, 2, 622, 623, 7, 60, 2, 2, 623, 117, 3, 2, 2, 2, 624, 625, 5, 200, 99, 2, 625, 626, 5, 168, 83, 2, 626, 627, 5, 82, 40, 2, 627, 628, 5, 186, 92, 2, 628, 629, 5, 82, 40, 2, 629, 630, 7, 60, 2, 2, 630, 119, 3, 2, 2, 2, 631, 632, 5, 200, 99, 2, 632, 633, 5, 194, 96, 2, 633, 634, 5, 82, 40, 2, 634, 635, 5, 198, 98, 2, 635, 636, 5, 196, 97, 2, 636, 637, 5, 186, 92, 2, 637, 638, 7, 60, 2, 2, 638, 121, 3, 2, 2, 2, 639, 640, 5, 200, 99, 2, 640, 641, 5, 202, 100, 2, 641, 642, 5, 170, 84, 2, 642, 643, 5, 180, 89, 2, 643, 644, 5, 190, 94, 2, 644, 123, 3, 2, 2, 2, 645, 650, 5, 156, 77, 2, 646, 650, 5, 158, 78, 2, 647, 650, 5, 164, 81, 2, 648, 650, 9, 6, 2, 2, 649, 645, 3, 2, 2, 2, 649, 646, 3, 2, 2, 2, 649, 647, 3, 2, 2, 2, 649, 648, 3, 2, 2, 2, 650, 651, 3, 2, 2, 2, 651, 649, 3, 2, 2, 2, 651, 652, 3, 2, 2, 2, 652, 125, 3, 2, 2, 2, 653, 654, 7, 64, 2, 2, 654, 655, 3, 2, 2, 2, 655, 656, 8, 62, 5, 2, 656, 127, 3, 2, 2, 2, 657, 658, 9, 5, 2, 2, 658, 659, 3, 2, 2, 2, 659, 660, 8, 63, 4, 2, 660, 129, 3, 2, 2, 2, 661, 662, 7, 62, 2, 2, 662, 663, 3, 2, 2, 2, 663, 664, 8, 64, 6, 2, 664, 131, 3, 2, 2, 2, 665, 671, 5, 156, 77, 2, 666, 670, 5, 156, 77, 2, 667, 670, 5, 158, 78, 2, 668, 670, 9, 3, 2, 2, 669, 666, 3, 2, 2, 2, 669, 667, 3, 2, 2, 2, 669, 668, 3, 2, 2, 2, 670, 673, 3, 2, 2, 2, 671, 669, 3, 2, 2, 2, 671, 672, 3, 2, 2, 2, 672, 133, 3, 2, 2, 2, 673, 671, 3, 2, 2, 2, 674, 678, 5, 156, 77, 2, 675, 678, 5, 158, 78, 2, 676, 678, 9, 3, 2, 2, 677, 674, 3, 2, 2, 2, 677, 675, 3, 2, 2, 2, 677, 676, 3, 2, 2, 2, 678, 681, 3, 2, 2, 2, 679, 677, 3, 2, 2, 2, 679, 680, 3, 2, 2, 2, 680, 682, 3, 2, 2, 2, 681, 679, 3, 2, 2, 2, 682, 683, 7, 60, 2, 2, 683, 135, 3, 2, 2, 2, 684, 685, 9, 5, 2, 2, 685, 686, 3, 2, 2, 2, 686, 687, 8, 67, 4, 2, 687, 137, 3, 2, 2, 2, 688, 689, 7, 62, 2, 2, 689, 139, 3, 2, 2, 2, 690, 691, 5, 202, 100, 2, 691, 692, 5, 192, 95, 2, 692, 141, 3, 2, 2, 2, 693, 694, 5, 166, 82, 2, 694, 695, 5, 212, 105, 2, 695, 143, 3, 2, 2, 2, 696, 697, 7, 45, 2, 2, 697, 145, 3, 2, 2, 2, 698, 700, 5, 158, 78, 2, 699, 698, 3, 2, 2, 2, 700, 701, 3, 2, 2, 2, 701, 699, 3, 2, 2, 2, 701, 702, 3, 2, 2, 2, 702, 147, 3, 2, 2, 2, 703, 709, 5, 156, 77, 2, 704, 708, 5, 156, 77, 2, 705, 708, 5, 158, 78, 2, 706, 708, 9, 3, 2, 2, 707, 704, 3, 2, 2, 2, 707, 705, 3, 2, 2, 2, 707, 706, 3, 2, 2, 2, 708, 711, 3, 2, 2, 2, 709, 707, 3, 2, 2, 2, 709, 710, 3, 2, 2, 2, 710, 149, 3, 2, 2, 2, 711, 709, 3, 2, 2, 2, 712, 717, 7, 36, 2, 2, 713, 718, 5, 156, 77, 2, 714, 718, 5, 158, 78, 2, 715, 718, 5, 164, 81, 2, 716, 718, 7, 34, 2, 2, 717, 713, 3, 2, 2, 2, 717, 714, 3, 2, 2, 2, 717, 715, 3, 2, 2, 2, 717, 716, 3, 2, 2, 2, 718, 719, 3, 2, 2, 2, 719, 717, 3, 2, 2, 2, 719, 720, 3, 2, 2, 2, 720, 721, 3, 2, 2, 2, 721, 722, 7, 36, 2, 2, 722, 151, 3, 2, 2, 2, 723, 724, 7, 64, 2, 2, 724, 725, 3, 2, 2, 2, 725, 726, 8, 75, 5, 2, 726, 153, 3, 2, 2, 2, 727, 728, 9, 5, 2, 2, 728, 729, 3, 2, 2, 2, 729, 730, 8, 76, 4, 2, 730, 155, 3, 2, 2, 2, 731, 733, 9, 7, 2, 2, 732, 731, 3, 2, 2, 2, 733, 157, 3, 2, 2, 2, 734, 735, 9, 8, 2, 2, 735, 159, 3, 2, 2, 2, 736, 737, 7, 122, 2, 2, 737, 742, 7, 117, 2, 2, 738, 739, 7, 122, 2, 2, 739, 740, 7, 117, 2, 2, 740, 742, 7, 102, 2, 2, 741, 736, 3, 2, 2, 2, 741, 738, 3, 2, 2, 2, 742, 161, 3, 2, 2, 2, 743, 744, 7, 117, 2, 2, 744, 745, 7, 118, 2, 2, 745, 746, 7, 116, 2, 2, 746, 747, 7, 107, 2, 2, 747, 748, 7, 112, 2, 2, 748, 1088, 7, 105, 2, 2, 749, 750, 7, 100, 2, 2, 750, 751, 7, 113, 2, 2, 751, 752, 7, 113, 2, 2, 752, 753, 7, 110, 2, 2, 753, 754, 7, 103, 2, 2, 754, 755, 7, 99, 2, 2, 755, 1088, 7, 112, 2, 2, 756, 757, 7, 102, 2, 2, 757, 758, 7, 103, 2, 2, 758, 759, 7, 101, 2, 2, 759, 760, 7, 107, 2, 2, 760, 761, 7, 111, 2, 2, 761, 762, 7, 99, 2, 2, 762, 1088, 7, 110, 2, 2, 763, 764, 7, 107, 2, 2, 764, 765, 7, 112, 2, 2, 765, 766, 7, 118, 2, 2, 766, 767, 7, 103, 2, 2, 767, 768, 7, 105, 2, 2, 768, 769, 7, 103, 2, 2, 769, 1088, 7, 116, 2, 2, 770, 771, 7, 102, 2, 2, 771, 772, 7, 113, 2, 2, 772, 773, 7, 119, 2, 2, 773, 774, 7, 100, 2, 2, 774, 775, 7, 110, 2, 2, 775, 1088, 7, 103, 2, 2, 776, 777, 7, 104, 2, 2, 777, 778, 7, 110, 2, 2, 778, 779, 7, 113, 2, 2, 779, 780, 7, 99, 2, 2, 780, 1088, 7, 118, 2, 2, 781, 782, 7, 102, 2, 2, 782, 783, 7, 99, 2, 2, 783, 784, 7, 118, 2, 2, 784, 1088, 7, 103, 2, 2, 785, 786, 7, 118, 2, 2, 786, 787, 7, 107, 2, 2, 787, 788, 7, 111, 2, 2, 788, 1088, 7, 103, 2, 2, 789, 790, 7, 102, 2, 2, 790, 791, 7, 99, 2, 2, 791, 792, 7, 118, 2, 2, 792, 793, 7, 103, 2, 2, 793, 794, 7, 86, 2, 2, 794, 795, 7, 107, 2, 2, 795, 796, 7, 111, 2, 2, 796, 1088, 7, 103, 2, 2, 797, 798, 7, 102, 2, 2, 798, 799, 7, 99, 2, 2, 799, 800, 7, 118, 2, 2, 800, 801, 7, 103, 2, 2, 801, 802, 7, 86, 2, 2, 802, 803, 7, 107, 2, 2, 803, 804, 7, 111, 2, 2, 804, 805, 7, 103, 2, 2, 805, 806, 7, 85, 2, 2, 806, 807, 7, 118, 2, 2, 807, 808, 7, 99, 2, 2, 808, 809, 7, 111, 2, 2, 809, 1088, 7, 114, 2, 2, 810, 811, 7, 105, 2, 2, 811, 812, 7, 91, 2, 2, 812, 813, 7, 103, 2, 2, 813, 814, 7, 99, 2, 2, 814, 1088, 7, 116, 2, 2, 815, 816, 7, 105, 2, 2, 816, 817, 7, 79, 2, 2, 817, 818, 7, 113, 2, 2, 818, 819, 7, 112, 2, 2, 819, 820, 7, 118, 2, 2, 820, 1088, 7, 106, 2, 2, 821, 822, 7, 105, 2, 2, 822, 823, 7, 70, 2, 2, 823, 824, 7, 99, 2, 2, 824, 1088, 7, 123, 2, 2, 825, 826, 7, 105, 2, 2, 826, 827, 7, 91, 2, 2, 827, 828, 7, 103, 2, 2, 828, 829, 7, 99, 2, 2, 829, 830, 7, 116, 2, 2, 830, 831, 7, 79, 2, 2, 831, 832, 7, 113, 2, 2, 832, 833, 7, 112, 2, 2, 833, 834, 7, 118, 2, 2, 834, 1088, 7, 106, 2, 2, 835, 836, 7, 105, 2, 2, 836, 837, 7, 79, 2, 2, 837, 838, 7, 113, 2, 2, 838, 839, 7, 112, 2, 2, 839, 840, 7, 118, 2, 2, 840, 841, 7, 106, 2, 2, 841, 842, 7, 70, 2, 2, 842, 843, 7, 99, 2, 2, 843, 1088, 7, 123, 2, 2, 844, 845, 7, 102, 2, 2, 845, 846, 7, 119, 2, 2, 846, 847, 7, 116, 2, 2, 847, 848, 7, 99, 2, 2, 848, 849, 7, 118, 2, 2, 849, 850, 7, 107, 2, 2, 850, 851, 7, 113, 2, 2, 851, 1088, 7, 112, 2, 2, 852, 853, 7, 123, 2, 2, 853, 854, 7, 103, 2, 2, 854, 855, 7, 99, 2, 2, 855, 856, 7, 116, 2, 2, 856, 857, 7, 79, 2, 2, 857, 858, 7, 113, 2, 2, 858, 859, 7, 112, 2, 2, 859, 860, 7, 118, 2, 2, 860, 861, 7, 106, 2, 2, 861, 862, 7, 70, 2, 2, 862, 863, 7, 119, 2, 2, 863, 864, 7, 116, 2, 2, 864, 865, 7, 99, 2, 2, 865, 866, 7, 118, 2, 2, 866, 867, 7, 107, 2, 2, 867, 868, 7, 113, 2, 2, 868, 1088, 7, 112, 2, 2, 869, 870, 7, 102, 2, 2, 870, 871, 7, 99, 2, 2, 871, 872, 7, 123, 2, 2, 872, 873, 7, 86, 2, 2, 873, 874, 7, 107, 2, 2, 874, 875, 7, 111, 2, 2, 875, 876, 7, 103, 2, 2, 876, 877, 7, 70, 2, 2, 877, 878, 7, 119, 2, 2, 878, 879, 7, 116, 2, 2, 879, 880, 7, 99, 2, 2, 880, 881, 7, 118, 2, 2, 881, 882, 7, 107, 2, 2, 882, 883, 7, 113, 2, 2, 883, 1088, 7, 112, 2, 2, 884, 885, 7, 100, 2, 2, 885, 886, 7, 123, 2, 2, 886, 887, 7, 118, 2, 2, 887, 1088, 7, 103, 2, 2, 888, 889, 7, 117, 2, 2, 889, 890, 7, 106, 2, 2, 890, 891, 7, 113, 2, 2, 891, 892, 7, 116, 2, 2, 892, 1088, 7, 118, 2, 2, 893, 894, 7, 107, 2, 2, 894, 895, 7, 112, 2, 2, 895, 1088, 7, 118, 2, 2, 896, 897, 7, 110, 2, 2, 897, 898, 7, 113, 2, 2, 898, 899, 7, 112, 2, 2, 899, 1088, 7, 105, 2, 2, 900, 901, 7, 119, 2, 2, 901, 902, 7, 112, 2, 2, 902, 903, 7, 117, 2, 2, 903, 904, 7, 107, 2, 2, 904, 905, 7, 105, 2, 2, 905, 906, 7, 112, 2, 2, 906, 907, 7, 103, 2, 2, 907, 908, 7, 102, 2, 2, 908, 909, 7, 68, 2, 2, 909, 910, 7, 123, 2, 2, 910, 911, 7, 118, 2, 2, 911, 1088, 7, 103, 2, 2, 912, 913, 7, 119, 2, 2, 913, 914, 7, 112, 2, 2, 914, 915, 7, 117, 2, 2, 915, 916, 7, 107, 2, 2, 916, 917, 7, 105, 2, 2, 917, 918, 7, 112, 2, 2, 918, 919, 7, 103, 2, 2, 919, 920, 7, 102, 2, 2, 920, 921, 7, 85, 2, 2, 921, 922, 7, 106, 2, 2, 922, 923, 7, 113, 2, 2, 923, 924, 7, 116, 2, 2, 924, 1088, 7, 118, 2, 2, 925, 926, 7, 119, 2, 2, 926, 927, 7, 112, 2, 2, 927, 928, 7, 117, 2, 2, 928, 929, 7, 107, 2, 2, 929, 930, 7, 105, 2, 2, 930, 931, 7, 112, 2, 2, 931, 932, 7, 103, 2, 2, 932, 933, 7, 102, 2, 2, 933, 934, 7, 75, 2, 2, 934, 935, 7, 112, 2, 2, 935, 1088, 7, 118, 2, 2, 936, 937, 7, 119, 2, 2, 937, 938, 7, 112, 2, 2, 938, 939, 7, 117, 2, 2, 939, 940, 7, 107, 2, 2, 940, 941, 7, 105, 2, 2, 941, 942, 7, 112, 2, 2, 942, 943, 7, 103, 2, 2, 943, 944, 7, 102, 2, 2, 944, 945, 7, 78, 2, 2, 945, 946, 7, 113, 2, 2, 946, 947, 7, 112, 2, 2, 947, 1088, 7, 105, 2, 2, 948, 949, 7, 114, 2, 2, 949, 950, 7, 113, 2, 2, 950, 951, 7, 117, 2, 2, 951, 952, 7, 107, 2, 2, 952, 953, 7, 118, 2, 2, 953, 954, 7, 107, 2, 2, 954, 955, 7, 120, 2, 2, 955, 956, 7, 103, 2, 2, 956, 957, 7, 75, 2, 2, 957, 958, 7, 112, 2, 2, 958, 959, 7, 118, 2, 2, 959, 960, 7, 103, 2, 2, 960, 961, 7, 105, 2, 2, 961, 962, 7, 103, 2, 2, 962, 1088, 7, 116, 2, 2, 963, 964, 7, 112, 2, 2, 964, 965, 7, 113, 2, 2, 965, 966, 7, 112, 2, 2, 966, 967, 7, 80, 2, 2, 967, 968, 7, 103, 2, 2, 968, 969, 7, 105, 2, 2, 969, 970, 7, 99, 2, 2, 970, 971, 7, 118, 2, 2, 971, 972, 7, 107, 2, 2, 972, 973, 7, 120, 2, 2, 973, 974, 7, 103, 2, 2, 974, 975, 7, 75, 2, 2, 975, 976, 7, 112, 2, 2, 976, 977, 7, 118, 2, 2, 977, 978, 7, 103, 2, 2, 978, 979, 7, 105, 2, 2, 979, 980, 7, 103, 2, 2, 980, 1088, 7, 116, 2, 2, 981, 982, 7, 112, 2, 2, 982, 983, 7, 103, 2, 2, 983, 984, 7, 105, 2, 2, 984, 985, 7, 99, 2, 2, 985, 986, 7, 118, 2, 2, 986, 987, 7, 107, 2, 2, 987, 988, 7, 120, 2, 2, 988, 989, 7, 103, 2, 2, 989, 990, 7, 75, 2, 2, 990, 991, 7, 112, 2, 2, 991, 992, 7, 118, 2, 2, 992, 993, 7, 103, 2, 2, 993, 994, 7, 105, 2, 2, 994, 995, 7, 103, 2, 2, 995, 1088, 7, 116, 2, 2, 996, 997, 7, 112, 2, 2, 997, 998, 7, 113, 2, 2, 998, 999, 7, 112, 2, 2, 999, 1000, 7, 82, 2, 2, 1000, 1001, 7, 113, 2, 2, 1001, 1002, 7, 117, 2, 2, 1002, 1003, 7, 107, 2, 2, 1003, 1004, 7, 118, 2, 2, 1004, 1005, 7, 107, 2, 2, 1005, 1006, 7, 120, 2, 2, 1006, 1007, 7, 103, 2, 2, 1007, 1008, 7, 75, 2, 2, 1008, 1009, 7, 112, 2, 2, 1009, 1010, 7, 118, 2, 2, 1010, 1011, 7, 103, 2, 2, 1011, 1012, 7, 105, 2, 2, 1012, 1013, 7, 103, 2, 2, 1013, 1088, 7, 116, 2, 2, 1014, 1015, 7, 106, 2, 2, 1015, 1016, 7, 103, 2, 2, 1016, 1017, 7, 122, 2, 2, 1017, 1018, 7, 68, 2, 2, 1018, 1019, 7, 107, 2, 2, 1019, 1020, 7, 112, 2, 2, 1020, 1021, 7, 99, 2, 2, 1021, 1022, 7, 116, 2, 2, 1022, 1088, 7, 123, 2, 2, 1023, 1024, 7, 100, 2, 2, 1024, 1025, 7, 99, 2, 2, 1025, 1026, 7, 117, 2, 2, 1026, 1027, 7, 103, 2, 2, 1027, 1028, 7, 56, 2, 2, 1028, 1029, 7, 54, 2, 2, 1029, 1030, 7, 68, 2, 2, 1030, 1031, 7, 107, 2, 2, 1031, 1032, 7, 112, 2, 2, 1032, 1033, 7, 99, 2, 2, 1033, 1034, 7, 116, 2, 2, 1034, 1088, 7, 123, 2, 2, 1035, 1036, 7, 99, 2, 2, 1036, 1037, 7, 112, 2, 2, 1037, 1038, 7, 123, 2, 2, 1038, 1039, 7, 87, 2, 2, 1039, 1040, 7, 84, 2, 2, 1040, 1088, 7, 75, 2, 2, 1041, 1042, 7, 110, 2, 2, 1042, 1043, 7, 99, 2, 2, 1043, 1044, 7, 112, 2, 2, 1044, 1045, 7, 105, 2, 2, 1045, 1046, 7, 119, 2, 2, 1046, 1047, 7, 99, 2, 2, 1047, 1048, 7, 105, 2, 2, 1048, 1088, 7, 103, 2, 2, 1049, 1050, 7, 112, 2, 2, 1050, 1051, 7, 113, 2, 2, 1051, 1052, 7, 116, 2, 2, 1052, 1053, 7, 111, 2, 2, 1053, 1054, 7, 99, 2, 2, 1054, 1055, 7, 110, 2, 2, 1055, 1056, 7, 107, 2, 2, 1056, 1057, 7, 124, 2, 2, 1057, 1058, 7, 103, 2, 2, 1058, 1059, 7, 102, 2, 2, 1059, 1060, 7, 85, 2, 2, 1060, 1061, 7, 118, 2, 2, 1061, 1062, 7, 116, 2, 2, 1062, 1063, 7, 107, 2, 2, 1063, 1064, 7, 112, 2, 2, 1064, 1088, 7, 105, 2, 2, 1065, 1066, 7, 118, 2, 2, 1066, 1067, 7, 113, 2, 2, 1067, 1068, 7, 109, 2, 2, 1068, 1069, 7, 103, 2, 2, 1069, 1088, 7, 112, 2, 2, 1070, 1071, 7, 80, 2, 2, 1071, 1072, 7, 79, 2, 2, 1072, 1073, 7, 86, 2, 2, 1073, 1074, 7, 81, 2, 2, 1074, 1075, 7, 77, 2, 2, 1075, 1076, 7, 71, 2, 2, 1076, 1088, 7, 80, 2, 2, 1077, 1078, 7, 80, 2, 2, 1078, 1079, 7, 99, 2, 2, 1079, 1080, 7, 111, 2, 2, 1080, 1088, 7, 103, 2, 2, 1081, 1082, 7, 80, 2, 2, 1082, 1083, 7, 69, 2, 2, 1083, 1084, 7, 80, 2, 2, 1084, 1085, 7, 99, 2, 2, 1085, 1086, 7, 111, 2, 2, 1086, 1088, 7, 103, 2, 2, 1087, 743, 3, 2, 2, 2, 1087, 749, 3, 2, 2, 2, 1087, 756, 3, 2, 2, 2, 1087, 763, 3, 2, 2, 2, 1087, 770, 3, 2, 2, 2, 1087, 776, 3, 2, 2, 2, 1087, 781, 3, 2, 2, 2, 1087, 785, 3, 2, 2, 2, 1087, 789, 3, 2, 2, 2, 1087, 797, 3, 2, 2, 2, 1087, 810, 3, 2, 2, 2, 1087, 815, 3, 2, 2, 2, 1087, 821, 3, 2, 2, 2, 1087, 825, 3, 2, 2, 2, 1087, 835, 3, 2, 2, 2, 1087, 844, 3, 2, 2, 2, 1087, 852, 3, 2, 2, 2, 1087, 869, 3, 2, 2, 2, 1087, 884, 3, 2, 2, 2, 1087, 888, 3, 2, 2, 2, 1087, 893, 3, 2, 2, 2, 1087, 896, 3, 2, 2, 2, 1087, 900, 3, 2, 2, 2, 1087, 912, 3, 2, 2, 2, 1087, 925, 3, 2, 2, 2, 1087, 936, 3, 2, 2, 2, 1087, 948, 3, 2, 2, 2, 1087, 963, 3, 2, 2, 2, 1087, 981, 3, 2, 2, 2, 1087, 996, 3, 2, 2, 2, 1087, 1014, 3, 2, 2, 2, 1087, 1023, 3, 2, 2, 2, 1087, 1035, 3, 2, 2, 2, 1087, 1041, 3, 2, 2, 2, 1087, 1049, 3, 2, 2, 2, 1087, 1065, 3, 2, 2, 2, 1087, 1070, 3, 2, 2, 2, 1087, 1077, 3, 2, 2, 2, 1087, 1081, 3, 2, 2, 2, 1088, 163, 3, 2, 2, 2, 1089, 1095, 9, 9, 2, 2, 1090, 1091, 7, 94, 2, 2, 1091, 1095, 7, 62, 2, 2, 1092, 1093, 7, 94, 2, 2, 1093, 1095, 7, 64, 2, 2, 1094, 1089, 3, 2, 2, 2, 1094, 1090, 3, 2, 2, 2, 1094, 1092, 3, 2, 2, 2, 1095, 165, 3, 2, 2, 2, 1096, 1097, 9, 10, 2, 2, 1097, 167, 3, 2, 2, 2, 1098, 1099, 9, 11, 2, 2, 1099, 169, 3, 2, 2, 2, 1100, 1101, 9, 12, 2, 2, 1101, 171, 3, 2, 2, 2, 1102, 1103, 9, 13, 2, 2, 1103, 173, 3, 2, 2, 2, 1104, 1105, 9, 14, 2, 2, 1105, 175, 3, 2, 2, 2, 1106, 1107, 9, 15, 2, 2, 1107, 177, 3, 2, 2, 2, 1108, 1109, 9, 16, 2, 2, 1109, 179, 3, 2, 2, 2, 1110, 1111, 9, 17, 2, 2, 1111, 181, 3, 2, 2, 2, 1112, 1113, 9, 18, 2, 2, 1113, 183, 3, 2, 2, 2, 1114, 1115, 9, 19, 2, 2, 1115, 185, 3, 2, 2, 2, 1116, 1117, 9, 20, 2, 2, 1117, 187, 3, 2, 2, 2, 1118, 1119, 9, 21, 2, 2, 1119, 189, 3, 2, 2, 2, 1120, 1121, 9, 22, 2, 2, 1121, 191, 3, 2, 2, 2, 1122, 1123, 9, 23, 2, 2, 1123, 193, 3, 2, 2, 2, 1124, 1125, 9, 24, 2, 2, 1125, 195, 3, 2, 2, 2, 1126, 1127, 9, 25, 2, 2, 1127, 197, 3, 2, 2, 2, 1128, 1129, 9, 26, 2, 2, 1129, 199, 3, 2, 2, 2, 1130, 1131, 9, 27, 2, 2, 1131, 201, 3, 2, 2, 2, 1132, 1133, 9, 28, 2, 2, 1133, 203, 3, 2, 2, 2, 1134, 1135, 9, 29, 2, 2, 1135, 205, 3, 2, 2, 2, 1136, 1137, 9, 30, 2, 2, 1137, 207, 3, 2, 2, 2, 1138, 1139, 9, 31, 2, 2, 1139, 209, 3, 2, 2, 2, 1140, 1141, 9, 32, 2, 2, 1141, 211, 3, 2, 2, 2, 1142, 1143, 9, 33, 2, 2, 1143, 213, 3, 2, 2, 2, 1144, 1145, 9, 34, 2, 2, 1145, 215, 3, 2, 2, 2, 41, 2, 3, 4, 5, 445, 469, 471, 481, 483, 493, 495, 511, 517, 522, 524, 528, 535, 557, 566, 568, 579, 581, 587, 589, 649, 651, 669, 671, 677, 679, 701, 707, 709, 717, 719, 732, 741, 1087, 1094, 7, 4, 4, 2, 4, 5, 2, 8, 2, 2, 4, 2, 2, 4, 3, 2] \ No newline at end of file diff --git a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.java b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.java index 409813b..c2b8d9c 100644 --- a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.java +++ b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.java @@ -28,11 +28,11 @@ public class ShExMLLexer extends Lexer { QUOTE=37, AND=38, A=39, AT=40, EQUAL=41, INDEX=42, STRING_OR_VAR=43, URI_VAR=44, STRINGOPERATOR=45, XMLSCHEMADATATYPE=46, SHAPELINK=47, LANGTAG=48, COMMENT=49, WS=50, URL=51, JDBC_URL=52, JSONPATH=53, XMLPATH=54, CSVPERROW=55, SQL=56, - SCALA=57, SPARQL=58, QUERY_PART=59, GREATER_SYMBOL_QUERY=60, WS_QUERY=61, - LESS_SYMBOL_QUERY=62, STRING_OR_VAR_QUERY=63, URI_VAR_QUERY=64, WS_DECLARATION=65, - LESS_SYMBOL_AUTOINCREMENT=66, TO=67, BY=68, ADD_AUTOINCREMENT=69, DIGITS=70, - STRING_OR_VAR_AUTOINCREMENT=71, STRINGOPERATOR_AUTOINCREMENT=72, GREATER_SYMBOL_AUTOINCREMENT=73, - WS_AUTOINCREMENT=74; + SCALA=57, SPARQL=58, STDIN=59, QUERY_PART=60, GREATER_SYMBOL_QUERY=61, + WS_QUERY=62, LESS_SYMBOL_QUERY=63, STRING_OR_VAR_QUERY=64, URI_VAR_QUERY=65, + WS_DECLARATION=66, LESS_SYMBOL_AUTOINCREMENT=67, TO=68, BY=69, ADD_AUTOINCREMENT=70, + DIGITS=71, STRING_OR_VAR_AUTOINCREMENT=72, STRINGOPERATOR_AUTOINCREMENT=73, + GREATER_SYMBOL_AUTOINCREMENT=74, WS_AUTOINCREMENT=75; public static final int QUERY_CONTENT=1, DECLARATION_CONTENT=2, AUTOINCREMENT_CONTENT=3; public static String[] channelNames = { @@ -54,7 +54,7 @@ private static String[] makeRuleNames() { "AND", "A", "AT", "EQUAL", "INDEX", "STRING_OR_VAR", "URI_VAR", "STRINGOPERATOR", "XMLSCHEMADATATYPE", "SHAPELINK", "LANGTAG", "COMMENT", "WS", "URL", "JDBC_URL", "JSONPATH", "XMLPATH", "CSVPERROW", "SQL", "SCALA", "SPARQL", - "QUERY_PART", "GREATER_SYMBOL_QUERY", "WS_QUERY", "LESS_SYMBOL_QUERY", + "STDIN", "QUERY_PART", "GREATER_SYMBOL_QUERY", "WS_QUERY", "LESS_SYMBOL_QUERY", "STRING_OR_VAR_QUERY", "URI_VAR_QUERY", "WS_DECLARATION", "LESS_SYMBOL_AUTOINCREMENT", "TO", "BY", "ADD_AUTOINCREMENT", "DIGITS", "STRING_OR_VAR_AUTOINCREMENT", "STRINGOPERATOR_AUTOINCREMENT", "GREATER_SYMBOL_AUTOINCREMENT", "WS_AUTOINCREMENT", @@ -85,11 +85,11 @@ private static String[] makeSymbolicNames() { "COMMA", "QUOTE", "AND", "A", "AT", "EQUAL", "INDEX", "STRING_OR_VAR", "URI_VAR", "STRINGOPERATOR", "XMLSCHEMADATATYPE", "SHAPELINK", "LANGTAG", "COMMENT", "WS", "URL", "JDBC_URL", "JSONPATH", "XMLPATH", "CSVPERROW", - "SQL", "SCALA", "SPARQL", "QUERY_PART", "GREATER_SYMBOL_QUERY", "WS_QUERY", - "LESS_SYMBOL_QUERY", "STRING_OR_VAR_QUERY", "URI_VAR_QUERY", "WS_DECLARATION", - "LESS_SYMBOL_AUTOINCREMENT", "TO", "BY", "ADD_AUTOINCREMENT", "DIGITS", - "STRING_OR_VAR_AUTOINCREMENT", "STRINGOPERATOR_AUTOINCREMENT", "GREATER_SYMBOL_AUTOINCREMENT", - "WS_AUTOINCREMENT" + "SQL", "SCALA", "SPARQL", "STDIN", "QUERY_PART", "GREATER_SYMBOL_QUERY", + "WS_QUERY", "LESS_SYMBOL_QUERY", "STRING_OR_VAR_QUERY", "URI_VAR_QUERY", + "WS_DECLARATION", "LESS_SYMBOL_AUTOINCREMENT", "TO", "BY", "ADD_AUTOINCREMENT", + "DIGITS", "STRING_OR_VAR_AUTOINCREMENT", "STRINGOPERATOR_AUTOINCREMENT", + "GREATER_SYMBOL_AUTOINCREMENT", "WS_AUTOINCREMENT" }; } private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); @@ -151,7 +151,7 @@ public ShExMLLexer(CharStream input) { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2L\u0472\b\1\b\1\b"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2M\u047a\b\1\b\1\b"+ "\1\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t"+ "\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21"+ "\t\21\4\22\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30"+ @@ -163,400 +163,403 @@ public ShExMLLexer(CharStream input) { "\tG\4H\tH\4I\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR"+ "\4S\tS\4T\tT\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4"+ "^\t^\4_\t_\4`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\4i\t"+ - "i\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3"+ - "\3\3\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3"+ - "\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7"+ - "\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3"+ - "\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t"+ - "\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13"+ - "\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f"+ - "\3\f\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16"+ - "\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20"+ - "\3\20\3\21\3\21\3\21\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23"+ - "\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25"+ - "\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27"+ - "\3\27\3\27\3\27\3\30\3\30\3\31\3\31\3\32\3\32\3\33\3\33\3\33\3\34\3\34"+ - "\3\35\3\35\3\35\3\36\3\36\3\37\3\37\3 \3 \3!\3!\3\"\3\"\3#\3#\3$\3$\3"+ - "%\3%\3&\3&\3\'\3\'\3\'\3\'\5\'\u01bc\n\'\3(\3(\3)\3)\3*\3*\3+\3+\3+\3"+ - "+\3+\3+\3+\3+\3,\3,\3,\3,\3,\3,\3,\3,\6,\u01d4\n,\r,\16,\u01d5\3-\3-\3"+ - "-\3-\3-\3-\3-\3-\7-\u01e0\n-\f-\16-\u01e3\13-\3-\3-\3.\3.\3.\3.\3.\6."+ - "\u01ec\n.\r.\16.\u01ed\3.\3.\3/\3/\3/\3/\3\60\3\60\3\60\3\60\3\60\3\60"+ - "\3\60\3\60\5\60\u01fe\n\60\3\61\3\61\6\61\u0202\n\61\r\61\16\61\u0203"+ - "\3\61\3\61\3\61\6\61\u0209\n\61\r\61\16\61\u020a\7\61\u020d\n\61\f\61"+ - "\16\61\u0210\13\61\3\62\3\62\7\62\u0214\n\62\f\62\16\62\u0217\13\62\3"+ + "i\4j\tj\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3"+ + "\3\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5"+ + "\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3"+ + "\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b"+ + "\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3"+ + "\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+ + "\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3"+ + "\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16"+ + "\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3\20"+ + "\3\20\3\20\3\21\3\21\3\21\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23"+ + "\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25"+ + "\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27"+ + "\3\27\3\27\3\27\3\27\3\30\3\30\3\31\3\31\3\32\3\32\3\33\3\33\3\33\3\34"+ + "\3\34\3\35\3\35\3\35\3\36\3\36\3\37\3\37\3 \3 \3!\3!\3\"\3\"\3#\3#\3$"+ + "\3$\3%\3%\3&\3&\3\'\3\'\3\'\3\'\5\'\u01be\n\'\3(\3(\3)\3)\3*\3*\3+\3+"+ + "\3+\3+\3+\3+\3+\3+\3,\3,\3,\3,\3,\3,\3,\3,\6,\u01d6\n,\r,\16,\u01d7\3"+ + "-\3-\3-\3-\3-\3-\3-\3-\7-\u01e2\n-\f-\16-\u01e5\13-\3-\3-\3.\3.\3.\3."+ + "\3.\6.\u01ee\n.\r.\16.\u01ef\3.\3.\3/\3/\3/\3/\3\60\3\60\3\60\3\60\3\60"+ + "\3\60\3\60\3\60\5\60\u0200\n\60\3\61\3\61\6\61\u0204\n\61\r\61\16\61\u0205"+ + "\3\61\3\61\3\61\6\61\u020b\n\61\r\61\16\61\u020c\7\61\u020f\n\61\f\61"+ + "\16\61\u0212\13\61\3\62\3\62\7\62\u0216\n\62\f\62\16\62\u0219\13\62\3"+ "\62\3\62\3\63\3\63\3\63\3\63\3\64\3\64\3\64\3\64\3\64\3\64\3\64\3\64\3"+ - "\64\3\64\3\64\3\64\3\64\5\64\u022c\n\64\3\64\3\64\3\64\3\64\3\64\3\64"+ - "\3\64\7\64\u0235\n\64\f\64\16\64\u0238\13\64\3\65\3\65\3\65\3\65\3\65"+ - "\3\65\3\65\3\65\6\65\u0242\n\65\r\65\16\65\u0243\3\65\3\65\3\65\3\65\7"+ - "\65\u024a\n\65\f\65\16\65\u024d\13\65\3\66\3\66\3\66\3\66\3\66\3\66\3"+ + "\64\3\64\3\64\3\64\3\64\5\64\u022e\n\64\3\64\3\64\3\64\3\64\3\64\3\64"+ + "\3\64\7\64\u0237\n\64\f\64\16\64\u023a\13\64\3\65\3\65\3\65\3\65\3\65"+ + "\3\65\3\65\3\65\6\65\u0244\n\65\r\65\16\65\u0245\3\65\3\65\3\65\3\65\7"+ + "\65\u024c\n\65\f\65\16\65\u024f\13\65\3\66\3\66\3\66\3\66\3\66\3\66\3"+ "\66\3\66\3\66\3\66\3\67\3\67\3\67\3\67\3\67\3\67\3\67\38\38\38\38\38\3"+ "8\38\38\38\38\39\39\39\39\39\3:\3:\3:\3:\3:\3:\3:\3;\3;\3;\3;\3;\3;\3"+ - ";\3;\3<\3<\3<\3<\6<\u0282\n<\r<\16<\u0283\3=\3=\3=\3=\3>\3>\3>\3>\3?\3"+ - "?\3?\3?\3@\3@\3@\3@\7@\u0296\n@\f@\16@\u0299\13@\3A\3A\3A\7A\u029e\nA"+ - "\fA\16A\u02a1\13A\3A\3A\3B\3B\3B\3B\3C\3C\3D\3D\3D\3E\3E\3E\3F\3F\3G\6"+ - "G\u02b4\nG\rG\16G\u02b5\3H\3H\3H\3H\7H\u02bc\nH\fH\16H\u02bf\13H\3I\3"+ - "I\3I\3I\3I\6I\u02c6\nI\rI\16I\u02c7\3I\3I\3J\3J\3J\3J\3K\3K\3K\3K\3L\5"+ - "L\u02d5\nL\3M\3M\3N\3N\3N\3N\3N\5N\u02de\nN\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+ - "O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\5O\u0438\nO\3P\3P\3P\3P\3P\5"+ - "P\u043f\nP\3Q\3Q\3R\3R\3S\3S\3T\3T\3U\3U\3V\3V\3W\3W\3X\3X\3Y\3Y\3Z\3"+ - "Z\3[\3[\3\\\3\\\3]\3]\3^\3^\3_\3_\3`\3`\3a\3a\3b\3b\3c\3c\3d\3d\3e\3e"+ - "\3f\3f\3g\3g\3h\3h\3i\3i\2\2j\6\3\b\4\n\5\f\6\16\7\20\b\22\t\24\n\26\13"+ - "\30\f\32\r\34\16\36\17 \20\"\21$\22&\23(\24*\25,\26.\27\60\30\62\31\64"+ - "\32\66\338\34:\35<\36>\37@ B!D\"F#H$J%L&N\'P(R)T*V+X,Z-\\.^/`\60b\61d"+ - "\62f\63h\64j\65l\66n\67p8r9t:v;x~?\u0080@\u0082A\u0084B\u0086C\u0088"+ - "D\u008aE\u008cF\u008eG\u0090H\u0092I\u0094J\u0096K\u0098L\u009a\2\u009c"+ - "\2\u009e\2\u00a0\2\u00a2\2\u00a4\2\u00a6\2\u00a8\2\u00aa\2\u00ac\2\u00ae"+ - "\2\u00b0\2\u00b2\2\u00b4\2\u00b6\2\u00b8\2\u00ba\2\u00bc\2\u00be\2\u00c0"+ - "\2\u00c2\2\u00c4\2\u00c6\2\u00c8\2\u00ca\2\u00cc\2\u00ce\2\u00d0\2\u00d2"+ - "\2\u00d4\2\6\2\3\4\5#\4\2CCcc\4\2//aa\4\2\f\f\17\17\5\2\13\f\17\17\"\""+ - "\5\2$$}}\177\177\7\2C\\c|\u00c2\u00d8\u00da\u00f8\u00fa\u0101\3\2\62;"+ - "\b\2%,.\61<=??AB]a\4\2DDdd\4\2EEee\4\2FFff\4\2GGgg\4\2HHhh\4\2IIii\4\2"+ - "JJjj\4\2KKkk\4\2LLll\4\2MMmm\4\2NNnn\4\2OOoo\4\2PPpp\4\2QQqq\4\2RRrr\4"+ - "\2SSss\4\2TTtt\4\2UUuu\4\2VVvv\4\2WWww\4\2XXxx\4\2YYyy\4\2ZZzz\4\2[[{"+ - "{\4\2\\\\||\2\u04aa\2\6\3\2\2\2\2\b\3\2\2\2\2\n\3\2\2\2\2\f\3\2\2\2\2"+ - "\16\3\2\2\2\2\20\3\2\2\2\2\22\3\2\2\2\2\24\3\2\2\2\2\26\3\2\2\2\2\30\3"+ - "\2\2\2\2\32\3\2\2\2\2\34\3\2\2\2\2\36\3\2\2\2\2 \3\2\2\2\2\"\3\2\2\2\2"+ - "$\3\2\2\2\2&\3\2\2\2\2(\3\2\2\2\2*\3\2\2\2\2,\3\2\2\2\2.\3\2\2\2\2\60"+ - "\3\2\2\2\2\62\3\2\2\2\2\64\3\2\2\2\2\66\3\2\2\2\28\3\2\2\2\2:\3\2\2\2"+ - "\2<\3\2\2\2\2>\3\2\2\2\2@\3\2\2\2\2B\3\2\2\2\2D\3\2\2\2\2F\3\2\2\2\2H"+ - "\3\2\2\2\2J\3\2\2\2\2L\3\2\2\2\2N\3\2\2\2\2P\3\2\2\2\2R\3\2\2\2\2T\3\2"+ - "\2\2\2V\3\2\2\2\2X\3\2\2\2\2Z\3\2\2\2\2\\\3\2\2\2\2^\3\2\2\2\2`\3\2\2"+ - "\2\2b\3\2\2\2\2d\3\2\2\2\2f\3\2\2\2\2h\3\2\2\2\3j\3\2\2\2\3l\3\2\2\2\3"+ - "n\3\2\2\2\3p\3\2\2\2\3r\3\2\2\2\3t\3\2\2\2\3v\3\2\2\2\3x\3\2\2\2\3z\3"+ - "\2\2\2\3|\3\2\2\2\3~\3\2\2\2\4\u0080\3\2\2\2\4\u0082\3\2\2\2\4\u0084\3"+ - "\2\2\2\4\u0086\3\2\2\2\5\u0088\3\2\2\2\5\u008a\3\2\2\2\5\u008c\3\2\2\2"+ - "\5\u008e\3\2\2\2\5\u0090\3\2\2\2\5\u0092\3\2\2\2\5\u0094\3\2\2\2\5\u0096"+ - "\3\2\2\2\5\u0098\3\2\2\2\6\u00d6\3\2\2\2\b\u00df\3\2\2\2\n\u00e8\3\2\2"+ - "\2\f\u00f0\3\2\2\2\16\u00fb\3\2\2\2\20\u0107\3\2\2\2\22\u010f\3\2\2\2"+ - "\24\u011e\3\2\2\2\26\u012d\3\2\2\2\30\u013d\3\2\2\2\32\u0148\3\2\2\2\34"+ - "\u014e\3\2\2\2\36\u0153\3\2\2\2 \u0160\3\2\2\2\"\u0168\3\2\2\2$\u016b"+ - "\3\2\2\2&\u016e\3\2\2\2(\u0171\3\2\2\2*\u017a\3\2\2\2,\u0182\3\2\2\2."+ - "\u0189\3\2\2\2\60\u0190\3\2\2\2\62\u0197\3\2\2\2\64\u0199\3\2\2\2\66\u019b"+ - "\3\2\2\28\u019d\3\2\2\2:\u01a0\3\2\2\2<\u01a2\3\2\2\2>\u01a5\3\2\2\2@"+ - "\u01a7\3\2\2\2B\u01a9\3\2\2\2D\u01ab\3\2\2\2F\u01ad\3\2\2\2H\u01af\3\2"+ - "\2\2J\u01b1\3\2\2\2L\u01b3\3\2\2\2N\u01b5\3\2\2\2P\u01bb\3\2\2\2R\u01bd"+ - "\3\2\2\2T\u01bf\3\2\2\2V\u01c1\3\2\2\2X\u01c3\3\2\2\2Z\u01d3\3\2\2\2\\"+ - "\u01e1\3\2\2\2^\u01e6\3\2\2\2`\u01f1\3\2\2\2b\u01f5\3\2\2\2d\u01ff\3\2"+ - "\2\2f\u0211\3\2\2\2h\u021a\3\2\2\2j\u022b\3\2\2\2l\u0239\3\2\2\2n\u024e"+ - "\3\2\2\2p\u0258\3\2\2\2r\u025f\3\2\2\2t\u0269\3\2\2\2v\u026e\3\2\2\2x"+ - "\u0275\3\2\2\2z\u0281\3\2\2\2|\u0285\3\2\2\2~\u0289\3\2\2\2\u0080\u028d"+ - "\3\2\2\2\u0082\u0291\3\2\2\2\u0084\u029f\3\2\2\2\u0086\u02a4\3\2\2\2\u0088"+ - "\u02a8\3\2\2\2\u008a\u02aa\3\2\2\2\u008c\u02ad\3\2\2\2\u008e\u02b0\3\2"+ - "\2\2\u0090\u02b3\3\2\2\2\u0092\u02b7\3\2\2\2\u0094\u02c0\3\2\2\2\u0096"+ - "\u02cb\3\2\2\2\u0098\u02cf\3\2\2\2\u009a\u02d4\3\2\2\2\u009c\u02d6\3\2"+ - "\2\2\u009e\u02dd\3\2\2\2\u00a0\u0437\3\2\2\2\u00a2\u043e\3\2\2\2\u00a4"+ - "\u0440\3\2\2\2\u00a6\u0442\3\2\2\2\u00a8\u0444\3\2\2\2\u00aa\u0446\3\2"+ - "\2\2\u00ac\u0448\3\2\2\2\u00ae\u044a\3\2\2\2\u00b0\u044c\3\2\2\2\u00b2"+ - "\u044e\3\2\2\2\u00b4\u0450\3\2\2\2\u00b6\u0452\3\2\2\2\u00b8\u0454\3\2"+ - "\2\2\u00ba\u0456\3\2\2\2\u00bc\u0458\3\2\2\2\u00be\u045a\3\2\2\2\u00c0"+ - "\u045c\3\2\2\2\u00c2\u045e\3\2\2\2\u00c4\u0460\3\2\2\2\u00c6\u0462\3\2"+ - "\2\2\u00c8\u0464\3\2\2\2\u00ca\u0466\3\2\2\2\u00cc\u0468\3\2\2\2\u00ce"+ - "\u046a\3\2\2\2\u00d0\u046c\3\2\2\2\u00d2\u046e\3\2\2\2\u00d4\u0470\3\2"+ - "\2\2\u00d6\u00d7\5\u00c0_\2\u00d7\u00d8\5\u00c4a\2\u00d8\u00d9\5\u00aa"+ - "T\2\u00d9\u00da\5\u00acU\2\u00da\u00db\5\u00b2X\2\u00db\u00dc\5\u00d0"+ - "g\2\u00dc\u00dd\3\2\2\2\u00dd\u00de\b\2\2\2\u00de\7\3\2\2\2\u00df\u00e0"+ - "\5\u00c6b\2\u00e0\u00e1\5\u00be^\2\u00e1\u00e2\5\u00cad\2\u00e2\u00e3"+ - "\5\u00c4a\2\u00e3\u00e4\5\u00a6R\2\u00e4\u00e5\5\u00aaT\2\u00e5\u00e6"+ - "\3\2\2\2\u00e6\u00e7\b\3\2\2\u00e7\t\3\2\2\2\u00e8\u00e9\5\u00c2`\2\u00e9"+ - "\u00ea\5\u00cad\2\u00ea\u00eb\5\u00aaT\2\u00eb\u00ec\5\u00c4a\2\u00ec"+ - "\u00ed\5\u00d2h\2\u00ed\u00ee\3\2\2\2\u00ee\u00ef\b\4\2\2\u00ef\13\3\2"+ - "\2\2\u00f0\u00f1\5\u00b2X\2\u00f1\u00f2\5\u00c8c\2\u00f2\u00f3\5\u00aa"+ - "T\2\u00f3\u00f4\5\u00c4a\2\u00f4\u00f5\5R(\2\u00f5\u00f6\5\u00c8c\2\u00f6"+ - "\u00f7\5\u00be^\2\u00f7\u00f8\5\u00c4a\2\u00f8\u00f9\3\2\2\2\u00f9\u00fa"+ - "\b\5\2\2\u00fa\r\3\2\2\2\u00fb\u00fc\5\u00acU\2\u00fc\u00fd\5\u00cad\2"+ - "\u00fd\u00fe\5\u00bc]\2\u00fe\u00ff\5\u00a6R\2\u00ff\u0100\5\u00c8c\2"+ - "\u0100\u0101\5\u00b2X\2\u0101\u0102\5\u00be^\2\u0102\u0103\5\u00bc]\2"+ - "\u0103\u0104\5\u00c6b\2\u0104\u0105\3\2\2\2\u0105\u0106\b\6\2\2\u0106"+ - "\17\3\2\2\2\u0107\u0108\5\u00acU\2\u0108\u0109\5\u00b2X\2\u0109\u010a"+ - "\5\u00aaT\2\u010a\u010b\5\u00b8[\2\u010b\u010c\5\u00a8S\2\u010c\u010d"+ - "\3\2\2\2\u010d\u010e\b\7\2\2\u010e\21\3\2\2\2\u010f\u0110\5\u00c0_\2\u0110"+ - "\u0111\5\u00cad\2\u0111\u0112\5\u00c6b\2\u0112\u0113\5\u00b0W\2\u0113"+ - "\u0114\5\u00aaT\2\u0114\u0115\5\u00a8S\2\u0115\u0116\7a\2\2\u0116\u0117"+ - "\5\u00acU\2\u0117\u0118\5\u00b2X\2\u0118\u0119\5\u00aaT\2\u0119\u011a"+ - "\5\u00b8[\2\u011a\u011b\5\u00a8S\2\u011b\u011c\3\2\2\2\u011c\u011d\b\b"+ - "\2\2\u011d\23\3\2\2\2\u011e\u011f\5\u00c0_\2\u011f\u0120\5\u00be^\2\u0120"+ - "\u0121\5\u00c0_\2\u0121\u0122\5\u00c0_\2\u0122\u0123\5\u00aaT\2\u0123"+ - "\u0124\5\u00a8S\2\u0124\u0125\7a\2\2\u0125\u0126\5\u00acU\2\u0126\u0127"+ - "\5\u00b2X\2\u0127\u0128\5\u00aaT\2\u0128\u0129\5\u00b8[\2\u0129\u012a"+ - "\5\u00a8S\2\u012a\u012b\3\2\2\2\u012b\u012c\b\t\2\2\u012c\25\3\2\2\2\u012d"+ - "\u012e\5R(\2\u012e\u012f\5\u00cad\2\u012f\u0130\5\u00c8c\2\u0130\u0131"+ - "\5\u00be^\2\u0131\u0132\5\u00b2X\2\u0132\u0133\5\u00bc]\2\u0133\u0134"+ - "\5\u00a6R\2\u0134\u0135\5\u00c4a\2\u0135\u0136\5\u00aaT\2\u0136\u0137"+ - "\5\u00ba\\\2\u0137\u0138\5\u00aaT\2\u0138\u0139\5\u00bc]\2\u0139\u013a"+ - "\5\u00c8c\2\u013a\u013b\3\2\2\2\u013b\u013c\b\n\3\2\u013c\27\3\2\2\2\u013d"+ - "\u013e\5\u00aaT\2\u013e\u013f\5\u00d0g\2\u013f\u0140\5\u00c0_\2\u0140"+ - "\u0141\5\u00c4a\2\u0141\u0142\5\u00aaT\2\u0142\u0143\5\u00c6b\2\u0143"+ - "\u0144\5\u00c6b\2\u0144\u0145\5\u00b2X\2\u0145\u0146\5\u00be^\2\u0146"+ - "\u0147\5\u00bc]\2\u0147\31\3\2\2\2\u0148\u0149\5\u00cad\2\u0149\u014a"+ - "\5\u00bc]\2\u014a\u014b\5\u00b2X\2\u014b\u014c\5\u00be^\2\u014c\u014d"+ - "\5\u00bc]\2\u014d\33\3\2\2\2\u014e\u014f\5\u00b4Y\2\u014f\u0150\5\u00be"+ - "^\2\u0150\u0151\5\u00b2X\2\u0151\u0152\5\u00bc]\2\u0152\35\3\2\2\2\u0153"+ - "\u0154\5\u00c6b\2\u0154\u0155\5\u00cad\2\u0155\u0156\5\u00a4Q\2\u0156"+ - "\u0157\5\u00c6b\2\u0157\u0158\5\u00c8c\2\u0158\u0159\5\u00b2X\2\u0159"+ - "\u015a\5\u00c8c\2\u015a\u015b\5\u00cad\2\u015b\u015c\5\u00c8c\2\u015c"+ - "\u015d\5\u00b2X\2\u015d\u015e\5\u00bc]\2\u015e\u015f\5\u00aeV\2\u015f"+ - "\37\3\2\2\2\u0160\u0161\5\u00ba\\\2\u0161\u0162\5R(\2\u0162\u0163\5\u00c8"+ - "c\2\u0163\u0164\5\u00a6R\2\u0164\u0165\5\u00b0W\2\u0165\u0166\5\u00aa"+ - "T\2\u0166\u0167\5\u00c4a\2\u0167!\3\2\2\2\u0168\u0169\5R(\2\u0169\u016a"+ - "\5\u00c6b\2\u016a#\3\2\2\2\u016b\u016c\5\u00b2X\2\u016c\u016d\5\u00ac"+ - "U\2\u016d%\3\2\2\2\u016e\u016f\5\u00be^\2\u016f\u0170\5\u00bc]\2\u0170"+ - "\'\3\2\2\2\u0171\u0172\5\u00ba\\\2\u0172\u0173\5R(\2\u0173\u0174\5\u00c8"+ - "c\2\u0174\u0175\5\u00a6R\2\u0175\u0176\5\u00b0W\2\u0176\u0177\5\u00b2"+ - "X\2\u0177\u0178\5\u00bc]\2\u0178\u0179\5\u00aeV\2\u0179)\3\2\2\2\u017a"+ - "\u017b\5\u00c4a\2\u017b\u017c\5\u00a8S\2\u017c\u017d\5\u00acU\2\u017d"+ - "\u017e\5\u00b8[\2\u017e\u017f\5\u00b2X\2\u017f\u0180\5\u00c6b\2\u0180"+ - "\u0181\5\u00c8c\2\u0181+\3\2\2\2\u0182\u0183\5\u00c4a\2\u0183\u0184\5"+ - "\u00a8S\2\u0184\u0185\5\u00acU\2\u0185\u0186\5\u00a4Q\2\u0186\u0187\5"+ - "R(\2\u0187\u0188\5\u00aeV\2\u0188-\3\2\2\2\u0189\u018a\5\u00c4a\2\u018a"+ - "\u018b\5\u00a8S\2\u018b\u018c\5\u00acU\2\u018c\u018d\5\u00c6b\2\u018d"+ - "\u018e\5\u00aaT\2\u018e\u018f\5\u00c2`\2\u018f/\3\2\2\2\u0190\u0191\5"+ - "\u00c4a\2\u0191\u0192\5\u00a8S\2\u0192\u0193\5\u00acU\2\u0193\u0194\5"+ - "R(\2\u0194\u0195\5\u00b8[\2\u0195\u0196\5\u00c8c\2\u0196\61\3\2\2\2\u0197"+ - "\u0198\7>\2\2\u0198\63\3\2\2\2\u0199\u019a\7@\2\2\u019a\65\3\2\2\2\u019b"+ - "\u019c\7]\2\2\u019c\67\3\2\2\2\u019d\u019e\7]\2\2\u019e\u019f\7]\2\2\u019f"+ - "9\3\2\2\2\u01a0\u01a1\7_\2\2\u01a1;\3\2\2\2\u01a2\u01a3\7_\2\2\u01a3\u01a4"+ - "\7_\2\2\u01a4=\3\2\2\2\u01a5\u01a6\7*\2\2\u01a6?\3\2\2\2\u01a7\u01a8\7"+ - "+\2\2\u01a8A\3\2\2\2\u01a9\u01aa\7}\2\2\u01aaC\3\2\2\2\u01ab\u01ac\7\177"+ - "\2\2\u01acE\3\2\2\2\u01ad\u01ae\7=\2\2\u01aeG\3\2\2\2\u01af\u01b0\7\60"+ - "\2\2\u01b0I\3\2\2\2\u01b1\u01b2\7-\2\2\u01b2K\3\2\2\2\u01b3\u01b4\7.\2"+ - "\2\u01b4M\3\2\2\2\u01b5\u01b6\7$\2\2\u01b6O\3\2\2\2\u01b7\u01bc\7(\2\2"+ - "\u01b8\u01b9\7C\2\2\u01b9\u01ba\7P\2\2\u01ba\u01bc\7F\2\2\u01bb\u01b7"+ - "\3\2\2\2\u01bb\u01b8\3\2\2\2\u01bcQ\3\2\2\2\u01bd\u01be\t\2\2\2\u01be"+ - "S\3\2\2\2\u01bf\u01c0\7B\2\2\u01c0U\3\2\2\2\u01c1\u01c2\7?\2\2\u01c2W"+ - "\3\2\2\2\u01c3\u01c4\5\u00b2X\2\u01c4\u01c5\5\u00bc]\2\u01c5\u01c6\5\u00a8"+ - "S\2\u01c6\u01c7\5\u00aaT\2\u01c7\u01c8\5\u00d0g\2\u01c8\u01c9\7*\2\2\u01c9"+ - "\u01ca\7+\2\2\u01caY\3\2\2\2\u01cb\u01d4\5\u009aL\2\u01cc\u01d4\5\u009c"+ - "M\2\u01cd\u01d4\t\3\2\2\u01ce\u01cf\7^\2\2\u01cf\u01d4\7\60\2\2\u01d0"+ - "\u01d1\7\'\2\2\u01d1\u01d2\7\64\2\2\u01d2\u01d4\7G\2\2\u01d3\u01cb\3\2"+ - "\2\2\u01d3\u01cc\3\2\2\2\u01d3\u01cd\3\2\2\2\u01d3\u01ce\3\2\2\2\u01d3"+ - "\u01d0\3\2\2\2\u01d4\u01d5\3\2\2\2\u01d5\u01d3\3\2\2\2\u01d5\u01d6\3\2"+ - "\2\2\u01d6[\3\2\2\2\u01d7\u01e0\5\u009aL\2\u01d8\u01e0\5\u009cM\2\u01d9"+ - "\u01e0\t\3\2\2\u01da\u01db\7^\2\2\u01db\u01e0\7\60\2\2\u01dc\u01dd\7\'"+ - "\2\2\u01dd\u01de\7\64\2\2\u01de\u01e0\7G\2\2\u01df\u01d7\3\2\2\2\u01df"+ - "\u01d8\3\2\2\2\u01df\u01d9\3\2\2\2\u01df\u01da\3\2\2\2\u01df\u01dc\3\2"+ - "\2\2\u01e0\u01e3\3\2\2\2\u01e1\u01df\3\2\2\2\u01e1\u01e2\3\2\2\2\u01e2"+ - "\u01e4\3\2\2\2\u01e3\u01e1\3\2\2\2\u01e4\u01e5\7<\2\2\u01e5]\3\2\2\2\u01e6"+ - "\u01eb\7$\2\2\u01e7\u01ec\5\u009aL\2\u01e8\u01ec\5\u009cM\2\u01e9\u01ec"+ - "\5\u00a2P\2\u01ea\u01ec\7\"\2\2\u01eb\u01e7\3\2\2\2\u01eb\u01e8\3\2\2"+ - "\2\u01eb\u01e9\3\2\2\2\u01eb\u01ea\3\2\2\2\u01ec\u01ed\3\2\2\2\u01ed\u01eb"+ - "\3\2\2\2\u01ed\u01ee\3\2\2\2\u01ee\u01ef\3\2\2\2\u01ef\u01f0\7$\2\2\u01f0"+ - "_\3\2\2\2\u01f1\u01f2\5\u009eN\2\u01f2\u01f3\7<\2\2\u01f3\u01f4\5\u00a0"+ - "O\2\u01f4a\3\2\2\2\u01f5\u01fd\7B\2\2\u01f6\u01f7\5\\-\2\u01f7\u01f8\5"+ - "Z,\2\u01f8\u01fe\3\2\2\2\u01f9\u01fa\7>\2\2\u01fa\u01fb\5Z,\2\u01fb\u01fc"+ - "\7@\2\2\u01fc\u01fe\3\2\2\2\u01fd\u01f6\3\2\2\2\u01fd\u01f9\3\2\2\2\u01fe"+ - "c\3\2\2\2\u01ff\u0201\7B\2\2\u0200\u0202\5\u009aL\2\u0201\u0200\3\2\2"+ - "\2\u0202\u0203\3\2\2\2\u0203\u0201\3\2\2\2\u0203\u0204\3\2\2\2\u0204\u020e"+ - "\3\2\2\2\u0205\u0208\7/\2\2\u0206\u0209\5\u009aL\2\u0207\u0209\5\u009c"+ - "M\2\u0208\u0206\3\2\2\2\u0208\u0207\3\2\2\2\u0209\u020a\3\2\2\2\u020a"+ - "\u0208\3\2\2\2\u020a\u020b\3\2\2\2\u020b\u020d\3\2\2\2\u020c\u0205\3\2"+ - "\2\2\u020d\u0210\3\2\2\2\u020e\u020c\3\2\2\2\u020e\u020f\3\2\2\2\u020f"+ - "e\3\2\2\2\u0210\u020e\3\2\2\2\u0211\u0215\7%\2\2\u0212\u0214\n\4\2\2\u0213"+ - "\u0212\3\2\2\2\u0214\u0217\3\2\2\2\u0215\u0213\3\2\2\2\u0215\u0216\3\2"+ - "\2\2\u0216\u0218\3\2\2\2\u0217\u0215\3\2\2\2\u0218\u0219\b\62\4\2\u0219"+ - "g\3\2\2\2\u021a\u021b\t\5\2\2\u021b\u021c\3\2\2\2\u021c\u021d\b\63\4\2"+ - "\u021di\3\2\2\2\u021e\u021f\7j\2\2\u021f\u0220\7v\2\2\u0220\u0221\7v\2"+ - "\2\u0221\u022c\7r\2\2\u0222\u0223\7j\2\2\u0223\u0224\7v\2\2\u0224\u0225"+ - "\7v\2\2\u0225\u0226\7r\2\2\u0226\u022c\7u\2\2\u0227\u0228\7h\2\2\u0228"+ - "\u0229\7k\2\2\u0229\u022a\7n\2\2\u022a\u022c\7g\2\2\u022b\u021e\3\2\2"+ - "\2\u022b\u0222\3\2\2\2\u022b\u0227\3\2\2\2\u022c\u022d\3\2\2\2\u022d\u022e"+ - "\7<\2\2\u022e\u022f\7\61\2\2\u022f\u0230\7\61\2\2\u0230\u0236\3\2\2\2"+ - "\u0231\u0235\5\u009aL\2\u0232\u0235\5\u009cM\2\u0233\u0235\5\u00a2P\2"+ - "\u0234\u0231\3\2\2\2\u0234\u0232\3\2\2\2\u0234\u0233\3\2\2\2\u0235\u0238"+ - "\3\2\2\2\u0236\u0234\3\2\2\2\u0236\u0237\3\2\2\2\u0237k\3\2\2\2\u0238"+ - "\u0236\3\2\2\2\u0239\u023a\7l\2\2\u023a\u023b\7f\2\2\u023b\u023c\7d\2"+ - "\2\u023c\u023d\7e\2\2\u023d\u023e\7<\2\2\u023e\u0241\3\2\2\2\u023f\u0242"+ - "\5\u009aL\2\u0240\u0242\5\u009cM\2\u0241\u023f\3\2\2\2\u0241\u0240\3\2"+ - "\2\2\u0242\u0243\3\2\2\2\u0243\u0241\3\2\2\2\u0243\u0244\3\2\2\2\u0244"+ - "\u0245\3\2\2\2\u0245\u024b\7<\2\2\u0246\u024a\5\u009aL\2\u0247\u024a\5"+ - "\u009cM\2\u0248\u024a\5\u00a2P\2\u0249\u0246\3\2\2\2\u0249\u0247\3\2\2"+ - "\2\u0249\u0248\3\2\2\2\u024a\u024d\3\2\2\2\u024b\u0249\3\2\2\2\u024b\u024c"+ - "\3\2\2\2\u024cm\3\2\2\2\u024d\u024b\3\2\2\2\u024e\u024f\5\u00b4Y\2\u024f"+ - "\u0250\5\u00c6b\2\u0250\u0251\5\u00be^\2\u0251\u0252\5\u00bc]\2\u0252"+ - "\u0253\5\u00c0_\2\u0253\u0254\5R(\2\u0254\u0255\5\u00c8c\2\u0255\u0256"+ - "\5\u00b0W\2\u0256\u0257\7<\2\2\u0257o\3\2\2\2\u0258\u0259\5\u00d0g\2\u0259"+ - "\u025a\5\u00c0_\2\u025a\u025b\5R(\2\u025b\u025c\5\u00c8c\2\u025c\u025d"+ - "\5\u00b0W\2\u025d\u025e\7<\2\2\u025eq\3\2\2\2\u025f\u0260\5\u00a6R\2\u0260"+ - "\u0261\5\u00c6b\2\u0261\u0262\5\u00cce\2\u0262\u0263\5\u00c0_\2\u0263"+ - "\u0264\5\u00aaT\2\u0264\u0265\5\u00c4a\2\u0265\u0266\5\u00c4a\2\u0266"+ - "\u0267\5\u00be^\2\u0267\u0268\5\u00cef\2\u0268s\3\2\2\2\u0269\u026a\5"+ - "\u00c6b\2\u026a\u026b\5\u00c2`\2\u026b\u026c\5\u00b8[\2\u026c\u026d\7"+ - "<\2\2\u026du\3\2\2\2\u026e\u026f\5\u00c6b\2\u026f\u0270\5\u00a6R\2\u0270"+ - "\u0271\5R(\2\u0271\u0272\5\u00b8[\2\u0272\u0273\5R(\2\u0273\u0274\7<\2"+ - "\2\u0274w\3\2\2\2\u0275\u0276\5\u00c6b\2\u0276\u0277\5\u00c0_\2\u0277"+ - "\u0278\5R(\2\u0278\u0279\5\u00c4a\2\u0279\u027a\5\u00c2`\2\u027a\u027b"+ - "\5\u00b8[\2\u027b\u027c\7<\2\2\u027cy\3\2\2\2\u027d\u0282\5\u009aL\2\u027e"+ - "\u0282\5\u009cM\2\u027f\u0282\5\u00a2P\2\u0280\u0282\t\6\2\2\u0281\u027d"+ - "\3\2\2\2\u0281\u027e\3\2\2\2\u0281\u027f\3\2\2\2\u0281\u0280\3\2\2\2\u0282"+ - "\u0283\3\2\2\2\u0283\u0281\3\2\2\2\u0283\u0284\3\2\2\2\u0284{\3\2\2\2"+ - "\u0285\u0286\7@\2\2\u0286\u0287\3\2\2\2\u0287\u0288\b=\5\2\u0288}\3\2"+ - "\2\2\u0289\u028a\t\5\2\2\u028a\u028b\3\2\2\2\u028b\u028c\b>\4\2\u028c"+ - "\177\3\2\2\2\u028d\u028e\7>\2\2\u028e\u028f\3\2\2\2\u028f\u0290\b?\6\2"+ - "\u0290\u0081\3\2\2\2\u0291\u0297\5\u009aL\2\u0292\u0296\5\u009aL\2\u0293"+ - "\u0296\5\u009cM\2\u0294\u0296\t\3\2\2\u0295\u0292\3\2\2\2\u0295\u0293"+ - "\3\2\2\2\u0295\u0294\3\2\2\2\u0296\u0299\3\2\2\2\u0297\u0295\3\2\2\2\u0297"+ - "\u0298\3\2\2\2\u0298\u0083\3\2\2\2\u0299\u0297\3\2\2\2\u029a\u029e\5\u009a"+ - "L\2\u029b\u029e\5\u009cM\2\u029c\u029e\t\3\2\2\u029d\u029a\3\2\2\2\u029d"+ - "\u029b\3\2\2\2\u029d\u029c\3\2\2\2\u029e\u02a1\3\2\2\2\u029f\u029d\3\2"+ - "\2\2\u029f\u02a0\3\2\2\2\u02a0\u02a2\3\2\2\2\u02a1\u029f\3\2\2\2\u02a2"+ - "\u02a3\7<\2\2\u02a3\u0085\3\2\2\2\u02a4\u02a5\t\5\2\2\u02a5\u02a6\3\2"+ - "\2\2\u02a6\u02a7\bB\4\2\u02a7\u0087\3\2\2\2\u02a8\u02a9\7>\2\2\u02a9\u0089"+ - "\3\2\2\2\u02aa\u02ab\5\u00c8c\2\u02ab\u02ac\5\u00be^\2\u02ac\u008b\3\2"+ - "\2\2\u02ad\u02ae\5\u00a4Q\2\u02ae\u02af\5\u00d2h\2\u02af\u008d\3\2\2\2"+ - "\u02b0\u02b1\7-\2\2\u02b1\u008f\3\2\2\2\u02b2\u02b4\5\u009cM\2\u02b3\u02b2"+ - "\3\2\2\2\u02b4\u02b5\3\2\2\2\u02b5\u02b3\3\2\2\2\u02b5\u02b6\3\2\2\2\u02b6"+ - "\u0091\3\2\2\2\u02b7\u02bd\5\u009aL\2\u02b8\u02bc\5\u009aL\2\u02b9\u02bc"+ - "\5\u009cM\2\u02ba\u02bc\t\3\2\2\u02bb\u02b8\3\2\2\2\u02bb\u02b9\3\2\2"+ - "\2\u02bb\u02ba\3\2\2\2\u02bc\u02bf\3\2\2\2\u02bd\u02bb\3\2\2\2\u02bd\u02be"+ - "\3\2\2\2\u02be\u0093\3\2\2\2\u02bf\u02bd\3\2\2\2\u02c0\u02c5\7$\2\2\u02c1"+ - "\u02c6\5\u009aL\2\u02c2\u02c6\5\u009cM\2\u02c3\u02c6\5\u00a2P\2\u02c4"+ - "\u02c6\7\"\2\2\u02c5\u02c1\3\2\2\2\u02c5\u02c2\3\2\2\2\u02c5\u02c3\3\2"+ - "\2\2\u02c5\u02c4\3\2\2\2\u02c6\u02c7\3\2\2\2\u02c7\u02c5\3\2\2\2\u02c7"+ - "\u02c8\3\2\2\2\u02c8\u02c9\3\2\2\2\u02c9\u02ca\7$\2\2\u02ca\u0095\3\2"+ - "\2\2\u02cb\u02cc\7@\2\2\u02cc\u02cd\3\2\2\2\u02cd\u02ce\bJ\5\2\u02ce\u0097"+ - "\3\2\2\2\u02cf\u02d0\t\5\2\2\u02d0\u02d1\3\2\2\2\u02d1\u02d2\bK\4\2\u02d2"+ - "\u0099\3\2\2\2\u02d3\u02d5\t\7\2\2\u02d4\u02d3\3\2\2\2\u02d5\u009b\3\2"+ - "\2\2\u02d6\u02d7\t\b\2\2\u02d7\u009d\3\2\2\2\u02d8\u02d9\7z\2\2\u02d9"+ - "\u02de\7u\2\2\u02da\u02db\7z\2\2\u02db\u02dc\7u\2\2\u02dc\u02de\7f\2\2"+ - "\u02dd\u02d8\3\2\2\2\u02dd\u02da\3\2\2\2\u02de\u009f\3\2\2\2\u02df\u02e0"+ - "\7u\2\2\u02e0\u02e1\7v\2\2\u02e1\u02e2\7t\2\2\u02e2\u02e3\7k\2\2\u02e3"+ - "\u02e4\7p\2\2\u02e4\u0438\7i\2\2\u02e5\u02e6\7d\2\2\u02e6\u02e7\7q\2\2"+ - "\u02e7\u02e8\7q\2\2\u02e8\u02e9\7n\2\2\u02e9\u02ea\7g\2\2\u02ea\u02eb"+ - "\7c\2\2\u02eb\u0438\7p\2\2\u02ec\u02ed\7f\2\2\u02ed\u02ee\7g\2\2\u02ee"+ - "\u02ef\7e\2\2\u02ef\u02f0\7k\2\2\u02f0\u02f1\7o\2\2\u02f1\u02f2\7c\2\2"+ - "\u02f2\u0438\7n\2\2\u02f3\u02f4\7k\2\2\u02f4\u02f5\7p\2\2\u02f5\u02f6"+ - "\7v\2\2\u02f6\u02f7\7g\2\2\u02f7\u02f8\7i\2\2\u02f8\u02f9\7g\2\2\u02f9"+ - "\u0438\7t\2\2\u02fa\u02fb\7f\2\2\u02fb\u02fc\7q\2\2\u02fc\u02fd\7w\2\2"+ - "\u02fd\u02fe\7d\2\2\u02fe\u02ff\7n\2\2\u02ff\u0438\7g\2\2\u0300\u0301"+ - "\7h\2\2\u0301\u0302\7n\2\2\u0302\u0303\7q\2\2\u0303\u0304\7c\2\2\u0304"+ - "\u0438\7v\2\2\u0305\u0306\7f\2\2\u0306\u0307\7c\2\2\u0307\u0308\7v\2\2"+ - "\u0308\u0438\7g\2\2\u0309\u030a\7v\2\2\u030a\u030b\7k\2\2\u030b\u030c"+ - "\7o\2\2\u030c\u0438\7g\2\2\u030d\u030e\7f\2\2\u030e\u030f\7c\2\2\u030f"+ - "\u0310\7v\2\2\u0310\u0311\7g\2\2\u0311\u0312\7V\2\2\u0312\u0313\7k\2\2"+ - "\u0313\u0314\7o\2\2\u0314\u0438\7g\2\2\u0315\u0316\7f\2\2\u0316\u0317"+ - "\7c\2\2\u0317\u0318\7v\2\2\u0318\u0319\7g\2\2\u0319\u031a\7V\2\2\u031a"+ - "\u031b\7k\2\2\u031b\u031c\7o\2\2\u031c\u031d\7g\2\2\u031d\u031e\7U\2\2"+ - "\u031e\u031f\7v\2\2\u031f\u0320\7c\2\2\u0320\u0321\7o\2\2\u0321\u0438"+ - "\7r\2\2\u0322\u0323\7i\2\2\u0323\u0324\7[\2\2\u0324\u0325\7g\2\2\u0325"+ - "\u0326\7c\2\2\u0326\u0438\7t\2\2\u0327\u0328\7i\2\2\u0328\u0329\7O\2\2"+ - "\u0329\u032a\7q\2\2\u032a\u032b\7p\2\2\u032b\u032c\7v\2\2\u032c\u0438"+ - "\7j\2\2\u032d\u032e\7i\2\2\u032e\u032f\7F\2\2\u032f\u0330\7c\2\2\u0330"+ - "\u0438\7{\2\2\u0331\u0332\7i\2\2\u0332\u0333\7[\2\2\u0333\u0334\7g\2\2"+ - "\u0334\u0335\7c\2\2\u0335\u0336\7t\2\2\u0336\u0337\7O\2\2\u0337\u0338"+ - "\7q\2\2\u0338\u0339\7p\2\2\u0339\u033a\7v\2\2\u033a\u0438\7j\2\2\u033b"+ - "\u033c\7i\2\2\u033c\u033d\7O\2\2\u033d\u033e\7q\2\2\u033e\u033f\7p\2\2"+ - "\u033f\u0340\7v\2\2\u0340\u0341\7j\2\2\u0341\u0342\7F\2\2\u0342\u0343"+ - "\7c\2\2\u0343\u0438\7{\2\2\u0344\u0345\7f\2\2\u0345\u0346\7w\2\2\u0346"+ - "\u0347\7t\2\2\u0347\u0348\7c\2\2\u0348\u0349\7v\2\2\u0349\u034a\7k\2\2"+ - "\u034a\u034b\7q\2\2\u034b\u0438\7p\2\2\u034c\u034d\7{\2\2\u034d\u034e"+ - "\7g\2\2\u034e\u034f\7c\2\2\u034f\u0350\7t\2\2\u0350\u0351\7O\2\2\u0351"+ - "\u0352\7q\2\2\u0352\u0353\7p\2\2\u0353\u0354\7v\2\2\u0354\u0355\7j\2\2"+ - "\u0355\u0356\7F\2\2\u0356\u0357\7w\2\2\u0357\u0358\7t\2\2\u0358\u0359"+ - "\7c\2\2\u0359\u035a\7v\2\2\u035a\u035b\7k\2\2\u035b\u035c\7q\2\2\u035c"+ - "\u0438\7p\2\2\u035d\u035e\7f\2\2\u035e\u035f\7c\2\2\u035f\u0360\7{\2\2"+ - "\u0360\u0361\7V\2\2\u0361\u0362\7k\2\2\u0362\u0363\7o\2\2\u0363\u0364"+ - "\7g\2\2\u0364\u0365\7F\2\2\u0365\u0366\7w\2\2\u0366\u0367\7t\2\2\u0367"+ - "\u0368\7c\2\2\u0368\u0369\7v\2\2\u0369\u036a\7k\2\2\u036a\u036b\7q\2\2"+ - "\u036b\u0438\7p\2\2\u036c\u036d\7d\2\2\u036d\u036e\7{\2\2\u036e\u036f"+ - "\7v\2\2\u036f\u0438\7g\2\2\u0370\u0371\7u\2\2\u0371\u0372\7j\2\2\u0372"+ - "\u0373\7q\2\2\u0373\u0374\7t\2\2\u0374\u0438\7v\2\2\u0375\u0376\7k\2\2"+ - "\u0376\u0377\7p\2\2\u0377\u0438\7v\2\2\u0378\u0379\7n\2\2\u0379\u037a"+ - "\7q\2\2\u037a\u037b\7p\2\2\u037b\u0438\7i\2\2\u037c\u037d\7w\2\2\u037d"+ - "\u037e\7p\2\2\u037e\u037f\7u\2\2\u037f\u0380\7k\2\2\u0380\u0381\7i\2\2"+ - "\u0381\u0382\7p\2\2\u0382\u0383\7g\2\2\u0383\u0384\7f\2\2\u0384\u0385"+ - "\7D\2\2\u0385\u0386\7{\2\2\u0386\u0387\7v\2\2\u0387\u0438\7g\2\2\u0388"+ - "\u0389\7w\2\2\u0389\u038a\7p\2\2\u038a\u038b\7u\2\2\u038b\u038c\7k\2\2"+ - "\u038c\u038d\7i\2\2\u038d\u038e\7p\2\2\u038e\u038f\7g\2\2\u038f\u0390"+ - "\7f\2\2\u0390\u0391\7U\2\2\u0391\u0392\7j\2\2\u0392\u0393\7q\2\2\u0393"+ - "\u0394\7t\2\2\u0394\u0438\7v\2\2\u0395\u0396\7w\2\2\u0396\u0397\7p\2\2"+ - "\u0397\u0398\7u\2\2\u0398\u0399\7k\2\2\u0399\u039a\7i\2\2\u039a\u039b"+ - "\7p\2\2\u039b\u039c\7g\2\2\u039c\u039d\7f\2\2\u039d\u039e\7K\2\2\u039e"+ - "\u039f\7p\2\2\u039f\u0438\7v\2\2\u03a0\u03a1\7w\2\2\u03a1\u03a2\7p\2\2"+ - "\u03a2\u03a3\7u\2\2\u03a3\u03a4\7k\2\2\u03a4\u03a5\7i\2\2\u03a5\u03a6"+ - "\7p\2\2\u03a6\u03a7\7g\2\2\u03a7\u03a8\7f\2\2\u03a8\u03a9\7N\2\2\u03a9"+ - "\u03aa\7q\2\2\u03aa\u03ab\7p\2\2\u03ab\u0438\7i\2\2\u03ac\u03ad\7r\2\2"+ - "\u03ad\u03ae\7q\2\2\u03ae\u03af\7u\2\2\u03af\u03b0\7k\2\2\u03b0\u03b1"+ - "\7v\2\2\u03b1\u03b2\7k\2\2\u03b2\u03b3\7x\2\2\u03b3\u03b4\7g\2\2\u03b4"+ - "\u03b5\7K\2\2\u03b5\u03b6\7p\2\2\u03b6\u03b7\7v\2\2\u03b7\u03b8\7g\2\2"+ - "\u03b8\u03b9\7i\2\2\u03b9\u03ba\7g\2\2\u03ba\u0438\7t\2\2\u03bb\u03bc"+ - "\7p\2\2\u03bc\u03bd\7q\2\2\u03bd\u03be\7p\2\2\u03be\u03bf\7P\2\2\u03bf"+ - "\u03c0\7g\2\2\u03c0\u03c1\7i\2\2\u03c1\u03c2\7c\2\2\u03c2\u03c3\7v\2\2"+ - "\u03c3\u03c4\7k\2\2\u03c4\u03c5\7x\2\2\u03c5\u03c6\7g\2\2\u03c6\u03c7"+ - "\7K\2\2\u03c7\u03c8\7p\2\2\u03c8\u03c9\7v\2\2\u03c9\u03ca\7g\2\2\u03ca"+ - "\u03cb\7i\2\2\u03cb\u03cc\7g\2\2\u03cc\u0438\7t\2\2\u03cd\u03ce\7p\2\2"+ - "\u03ce\u03cf\7g\2\2\u03cf\u03d0\7i\2\2\u03d0\u03d1\7c\2\2\u03d1\u03d2"+ - "\7v\2\2\u03d2\u03d3\7k\2\2\u03d3\u03d4\7x\2\2\u03d4\u03d5\7g\2\2\u03d5"+ - "\u03d6\7K\2\2\u03d6\u03d7\7p\2\2\u03d7\u03d8\7v\2\2\u03d8\u03d9\7g\2\2"+ - "\u03d9\u03da\7i\2\2\u03da\u03db\7g\2\2\u03db\u0438\7t\2\2\u03dc\u03dd"+ - "\7p\2\2\u03dd\u03de\7q\2\2\u03de\u03df\7p\2\2\u03df\u03e0\7R\2\2\u03e0"+ - "\u03e1\7q\2\2\u03e1\u03e2\7u\2\2\u03e2\u03e3\7k\2\2\u03e3\u03e4\7v\2\2"+ - "\u03e4\u03e5\7k\2\2\u03e5\u03e6\7x\2\2\u03e6\u03e7\7g\2\2\u03e7\u03e8"+ - "\7K\2\2\u03e8\u03e9\7p\2\2\u03e9\u03ea\7v\2\2\u03ea\u03eb\7g\2\2\u03eb"+ - "\u03ec\7i\2\2\u03ec\u03ed\7g\2\2\u03ed\u0438\7t\2\2\u03ee\u03ef\7j\2\2"+ - "\u03ef\u03f0\7g\2\2\u03f0\u03f1\7z\2\2\u03f1\u03f2\7D\2\2\u03f2\u03f3"+ - "\7k\2\2\u03f3\u03f4\7p\2\2\u03f4\u03f5\7c\2\2\u03f5\u03f6\7t\2\2\u03f6"+ - "\u0438\7{\2\2\u03f7\u03f8\7d\2\2\u03f8\u03f9\7c\2\2\u03f9\u03fa\7u\2\2"+ - "\u03fa\u03fb\7g\2\2\u03fb\u03fc\78\2\2\u03fc\u03fd\7\66\2\2\u03fd\u03fe"+ - "\7D\2\2\u03fe\u03ff\7k\2\2\u03ff\u0400\7p\2\2\u0400\u0401\7c\2\2\u0401"+ - "\u0402\7t\2\2\u0402\u0438\7{\2\2\u0403\u0404\7c\2\2\u0404\u0405\7p\2\2"+ - "\u0405\u0406\7{\2\2\u0406\u0407\7W\2\2\u0407\u0408\7T\2\2\u0408\u0438"+ - "\7K\2\2\u0409\u040a\7n\2\2\u040a\u040b\7c\2\2\u040b\u040c\7p\2\2\u040c"+ - "\u040d\7i\2\2\u040d\u040e\7w\2\2\u040e\u040f\7c\2\2\u040f\u0410\7i\2\2"+ - "\u0410\u0438\7g\2\2\u0411\u0412\7p\2\2\u0412\u0413\7q\2\2\u0413\u0414"+ - "\7t\2\2\u0414\u0415\7o\2\2\u0415\u0416\7c\2\2\u0416\u0417\7n\2\2\u0417"+ - "\u0418\7k\2\2\u0418\u0419\7|\2\2\u0419\u041a\7g\2\2\u041a\u041b\7f\2\2"+ - "\u041b\u041c\7U\2\2\u041c\u041d\7v\2\2\u041d\u041e\7t\2\2\u041e\u041f"+ - "\7k\2\2\u041f\u0420\7p\2\2\u0420\u0438\7i\2\2\u0421\u0422\7v\2\2\u0422"+ - "\u0423\7q\2\2\u0423\u0424\7m\2\2\u0424\u0425\7g\2\2\u0425\u0438\7p\2\2"+ - "\u0426\u0427\7P\2\2\u0427\u0428\7O\2\2\u0428\u0429\7V\2\2\u0429\u042a"+ - "\7Q\2\2\u042a\u042b\7M\2\2\u042b\u042c\7G\2\2\u042c\u0438\7P\2\2\u042d"+ - "\u042e\7P\2\2\u042e\u042f\7c\2\2\u042f\u0430\7o\2\2\u0430\u0438\7g\2\2"+ - "\u0431\u0432\7P\2\2\u0432\u0433\7E\2\2\u0433\u0434\7P\2\2\u0434\u0435"+ - "\7c\2\2\u0435\u0436\7o\2\2\u0436\u0438\7g\2\2\u0437\u02df\3\2\2\2\u0437"+ - "\u02e5\3\2\2\2\u0437\u02ec\3\2\2\2\u0437\u02f3\3\2\2\2\u0437\u02fa\3\2"+ - "\2\2\u0437\u0300\3\2\2\2\u0437\u0305\3\2\2\2\u0437\u0309\3\2\2\2\u0437"+ - "\u030d\3\2\2\2\u0437\u0315\3\2\2\2\u0437\u0322\3\2\2\2\u0437\u0327\3\2"+ - "\2\2\u0437\u032d\3\2\2\2\u0437\u0331\3\2\2\2\u0437\u033b\3\2\2\2\u0437"+ - "\u0344\3\2\2\2\u0437\u034c\3\2\2\2\u0437\u035d\3\2\2\2\u0437\u036c\3\2"+ - "\2\2\u0437\u0370\3\2\2\2\u0437\u0375\3\2\2\2\u0437\u0378\3\2\2\2\u0437"+ - "\u037c\3\2\2\2\u0437\u0388\3\2\2\2\u0437\u0395\3\2\2\2\u0437\u03a0\3\2"+ - "\2\2\u0437\u03ac\3\2\2\2\u0437\u03bb\3\2\2\2\u0437\u03cd\3\2\2\2\u0437"+ - "\u03dc\3\2\2\2\u0437\u03ee\3\2\2\2\u0437\u03f7\3\2\2\2\u0437\u0403\3\2"+ - "\2\2\u0437\u0409\3\2\2\2\u0437\u0411\3\2\2\2\u0437\u0421\3\2\2\2\u0437"+ - "\u0426\3\2\2\2\u0437\u042d\3\2\2\2\u0437\u0431\3\2\2\2\u0438\u00a1\3\2"+ - "\2\2\u0439\u043f\t\t\2\2\u043a\u043b\7^\2\2\u043b\u043f\7>\2\2\u043c\u043d"+ - "\7^\2\2\u043d\u043f\7@\2\2\u043e\u0439\3\2\2\2\u043e\u043a\3\2\2\2\u043e"+ - "\u043c\3\2\2\2\u043f\u00a3\3\2\2\2\u0440\u0441\t\n\2\2\u0441\u00a5\3\2"+ - "\2\2\u0442\u0443\t\13\2\2\u0443\u00a7\3\2\2\2\u0444\u0445\t\f\2\2\u0445"+ - "\u00a9\3\2\2\2\u0446\u0447\t\r\2\2\u0447\u00ab\3\2\2\2\u0448\u0449\t\16"+ - "\2\2\u0449\u00ad\3\2\2\2\u044a\u044b\t\17\2\2\u044b\u00af\3\2\2\2\u044c"+ - "\u044d\t\20\2\2\u044d\u00b1\3\2\2\2\u044e\u044f\t\21\2\2\u044f\u00b3\3"+ - "\2\2\2\u0450\u0451\t\22\2\2\u0451\u00b5\3\2\2\2\u0452\u0453\t\23\2\2\u0453"+ - "\u00b7\3\2\2\2\u0454\u0455\t\24\2\2\u0455\u00b9\3\2\2\2\u0456\u0457\t"+ - "\25\2\2\u0457\u00bb\3\2\2\2\u0458\u0459\t\26\2\2\u0459\u00bd\3\2\2\2\u045a"+ - "\u045b\t\27\2\2\u045b\u00bf\3\2\2\2\u045c\u045d\t\30\2\2\u045d\u00c1\3"+ - "\2\2\2\u045e\u045f\t\31\2\2\u045f\u00c3\3\2\2\2\u0460\u0461\t\32\2\2\u0461"+ - "\u00c5\3\2\2\2\u0462\u0463\t\33\2\2\u0463\u00c7\3\2\2\2\u0464\u0465\t"+ - "\34\2\2\u0465\u00c9\3\2\2\2\u0466\u0467\t\35\2\2\u0467\u00cb\3\2\2\2\u0468"+ - "\u0469\t\36\2\2\u0469\u00cd\3\2\2\2\u046a\u046b\t\37\2\2\u046b\u00cf\3"+ - "\2\2\2\u046c\u046d\t \2\2\u046d\u00d1\3\2\2\2\u046e\u046f\t!\2\2\u046f"+ - "\u00d3\3\2\2\2\u0470\u0471\t\"\2\2\u0471\u00d5\3\2\2\2)\2\3\4\5\u01bb"+ - "\u01d3\u01d5\u01df\u01e1\u01eb\u01ed\u01fd\u0203\u0208\u020a\u020e\u0215"+ - "\u022b\u0234\u0236\u0241\u0243\u0249\u024b\u0281\u0283\u0295\u0297\u029d"+ - "\u029f\u02b5\u02bb\u02bd\u02c5\u02c7\u02d4\u02dd\u0437\u043e\7\4\4\2\4"+ + ";\3;\3<\3<\3<\3<\3<\3<\3=\3=\3=\3=\6=\u028a\n=\r=\16=\u028b\3>\3>\3>\3"+ + ">\3?\3?\3?\3?\3@\3@\3@\3@\3A\3A\3A\3A\7A\u029e\nA\fA\16A\u02a1\13A\3B"+ + "\3B\3B\7B\u02a6\nB\fB\16B\u02a9\13B\3B\3B\3C\3C\3C\3C\3D\3D\3E\3E\3E\3"+ + "F\3F\3F\3G\3G\3H\6H\u02bc\nH\rH\16H\u02bd\3I\3I\3I\3I\7I\u02c4\nI\fI\16"+ + "I\u02c7\13I\3J\3J\3J\3J\3J\6J\u02ce\nJ\rJ\16J\u02cf\3J\3J\3K\3K\3K\3K"+ + "\3L\3L\3L\3L\3M\5M\u02dd\nM\3N\3N\3O\3O\3O\3O\3O\5O\u02e6\nO\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+ + "\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\5P\u0440\nP"+ + "\3Q\3Q\3Q\3Q\3Q\5Q\u0447\nQ\3R\3R\3S\3S\3T\3T\3U\3U\3V\3V\3W\3W\3X\3X"+ + "\3Y\3Y\3Z\3Z\3[\3[\3\\\3\\\3]\3]\3^\3^\3_\3_\3`\3`\3a\3a\3b\3b\3c\3c\3"+ + "d\3d\3e\3e\3f\3f\3g\3g\3h\3h\3i\3i\3j\3j\2\2k\6\3\b\4\n\5\f\6\16\7\20"+ + "\b\22\t\24\n\26\13\30\f\32\r\34\16\36\17 \20\"\21$\22&\23(\24*\25,\26"+ + ".\27\60\30\62\31\64\32\66\338\34:\35<\36>\37@ B!D\"F#H$J%L&N\'P(R)T*V"+ + "+X,Z-\\.^/`\60b\61d\62f\63h\64j\65l\66n\67p8r9t:v;x~?\u0080@\u0082"+ + "A\u0084B\u0086C\u0088D\u008aE\u008cF\u008eG\u0090H\u0092I\u0094J\u0096"+ + "K\u0098L\u009aM\u009c\2\u009e\2\u00a0\2\u00a2\2\u00a4\2\u00a6\2\u00a8"+ + "\2\u00aa\2\u00ac\2\u00ae\2\u00b0\2\u00b2\2\u00b4\2\u00b6\2\u00b8\2\u00ba"+ + "\2\u00bc\2\u00be\2\u00c0\2\u00c2\2\u00c4\2\u00c6\2\u00c8\2\u00ca\2\u00cc"+ + "\2\u00ce\2\u00d0\2\u00d2\2\u00d4\2\u00d6\2\6\2\3\4\5#\4\2CCcc\4\2//aa"+ + "\4\2\f\f\17\17\5\2\13\f\17\17\"\"\5\2$$}}\177\177\7\2C\\c|\u00c2\u00d8"+ + "\u00da\u00f8\u00fa\u0101\3\2\62;\b\2%,.\61<=??AB]a\4\2DDdd\4\2EEee\4\2"+ + "FFff\4\2GGgg\4\2HHhh\4\2IIii\4\2JJjj\4\2KKkk\4\2LLll\4\2MMmm\4\2NNnn\4"+ + "\2OOoo\4\2PPpp\4\2QQqq\4\2RRrr\4\2SSss\4\2TTtt\4\2UUuu\4\2VVvv\4\2WWw"+ + "w\4\2XXxx\4\2YYyy\4\2ZZzz\4\2[[{{\4\2\\\\||\2\u04b2\2\6\3\2\2\2\2\b\3"+ + "\2\2\2\2\n\3\2\2\2\2\f\3\2\2\2\2\16\3\2\2\2\2\20\3\2\2\2\2\22\3\2\2\2"+ + "\2\24\3\2\2\2\2\26\3\2\2\2\2\30\3\2\2\2\2\32\3\2\2\2\2\34\3\2\2\2\2\36"+ + "\3\2\2\2\2 \3\2\2\2\2\"\3\2\2\2\2$\3\2\2\2\2&\3\2\2\2\2(\3\2\2\2\2*\3"+ + "\2\2\2\2,\3\2\2\2\2.\3\2\2\2\2\60\3\2\2\2\2\62\3\2\2\2\2\64\3\2\2\2\2"+ + "\66\3\2\2\2\28\3\2\2\2\2:\3\2\2\2\2<\3\2\2\2\2>\3\2\2\2\2@\3\2\2\2\2B"+ + "\3\2\2\2\2D\3\2\2\2\2F\3\2\2\2\2H\3\2\2\2\2J\3\2\2\2\2L\3\2\2\2\2N\3\2"+ + "\2\2\2P\3\2\2\2\2R\3\2\2\2\2T\3\2\2\2\2V\3\2\2\2\2X\3\2\2\2\2Z\3\2\2\2"+ + "\2\\\3\2\2\2\2^\3\2\2\2\2`\3\2\2\2\2b\3\2\2\2\2d\3\2\2\2\2f\3\2\2\2\2"+ + "h\3\2\2\2\3j\3\2\2\2\3l\3\2\2\2\3n\3\2\2\2\3p\3\2\2\2\3r\3\2\2\2\3t\3"+ + "\2\2\2\3v\3\2\2\2\3x\3\2\2\2\3z\3\2\2\2\3|\3\2\2\2\3~\3\2\2\2\3\u0080"+ + "\3\2\2\2\4\u0082\3\2\2\2\4\u0084\3\2\2\2\4\u0086\3\2\2\2\4\u0088\3\2\2"+ + "\2\5\u008a\3\2\2\2\5\u008c\3\2\2\2\5\u008e\3\2\2\2\5\u0090\3\2\2\2\5\u0092"+ + "\3\2\2\2\5\u0094\3\2\2\2\5\u0096\3\2\2\2\5\u0098\3\2\2\2\5\u009a\3\2\2"+ + "\2\6\u00d8\3\2\2\2\b\u00e1\3\2\2\2\n\u00ea\3\2\2\2\f\u00f2\3\2\2\2\16"+ + "\u00fd\3\2\2\2\20\u0109\3\2\2\2\22\u0111\3\2\2\2\24\u0120\3\2\2\2\26\u012f"+ + "\3\2\2\2\30\u013f\3\2\2\2\32\u014a\3\2\2\2\34\u0150\3\2\2\2\36\u0155\3"+ + "\2\2\2 \u0162\3\2\2\2\"\u016a\3\2\2\2$\u016d\3\2\2\2&\u0170\3\2\2\2(\u0173"+ + "\3\2\2\2*\u017c\3\2\2\2,\u0184\3\2\2\2.\u018b\3\2\2\2\60\u0192\3\2\2\2"+ + "\62\u0199\3\2\2\2\64\u019b\3\2\2\2\66\u019d\3\2\2\28\u019f\3\2\2\2:\u01a2"+ + "\3\2\2\2<\u01a4\3\2\2\2>\u01a7\3\2\2\2@\u01a9\3\2\2\2B\u01ab\3\2\2\2D"+ + "\u01ad\3\2\2\2F\u01af\3\2\2\2H\u01b1\3\2\2\2J\u01b3\3\2\2\2L\u01b5\3\2"+ + "\2\2N\u01b7\3\2\2\2P\u01bd\3\2\2\2R\u01bf\3\2\2\2T\u01c1\3\2\2\2V\u01c3"+ + "\3\2\2\2X\u01c5\3\2\2\2Z\u01d5\3\2\2\2\\\u01e3\3\2\2\2^\u01e8\3\2\2\2"+ + "`\u01f3\3\2\2\2b\u01f7\3\2\2\2d\u0201\3\2\2\2f\u0213\3\2\2\2h\u021c\3"+ + "\2\2\2j\u022d\3\2\2\2l\u023b\3\2\2\2n\u0250\3\2\2\2p\u025a\3\2\2\2r\u0261"+ + "\3\2\2\2t\u026b\3\2\2\2v\u0270\3\2\2\2x\u0277\3\2\2\2z\u027f\3\2\2\2|"+ + "\u0289\3\2\2\2~\u028d\3\2\2\2\u0080\u0291\3\2\2\2\u0082\u0295\3\2\2\2"+ + "\u0084\u0299\3\2\2\2\u0086\u02a7\3\2\2\2\u0088\u02ac\3\2\2\2\u008a\u02b0"+ + "\3\2\2\2\u008c\u02b2\3\2\2\2\u008e\u02b5\3\2\2\2\u0090\u02b8\3\2\2\2\u0092"+ + "\u02bb\3\2\2\2\u0094\u02bf\3\2\2\2\u0096\u02c8\3\2\2\2\u0098\u02d3\3\2"+ + "\2\2\u009a\u02d7\3\2\2\2\u009c\u02dc\3\2\2\2\u009e\u02de\3\2\2\2\u00a0"+ + "\u02e5\3\2\2\2\u00a2\u043f\3\2\2\2\u00a4\u0446\3\2\2\2\u00a6\u0448\3\2"+ + "\2\2\u00a8\u044a\3\2\2\2\u00aa\u044c\3\2\2\2\u00ac\u044e\3\2\2\2\u00ae"+ + "\u0450\3\2\2\2\u00b0\u0452\3\2\2\2\u00b2\u0454\3\2\2\2\u00b4\u0456\3\2"+ + "\2\2\u00b6\u0458\3\2\2\2\u00b8\u045a\3\2\2\2\u00ba\u045c\3\2\2\2\u00bc"+ + "\u045e\3\2\2\2\u00be\u0460\3\2\2\2\u00c0\u0462\3\2\2\2\u00c2\u0464\3\2"+ + "\2\2\u00c4\u0466\3\2\2\2\u00c6\u0468\3\2\2\2\u00c8\u046a\3\2\2\2\u00ca"+ + "\u046c\3\2\2\2\u00cc\u046e\3\2\2\2\u00ce\u0470\3\2\2\2\u00d0\u0472\3\2"+ + "\2\2\u00d2\u0474\3\2\2\2\u00d4\u0476\3\2\2\2\u00d6\u0478\3\2\2\2\u00d8"+ + "\u00d9\5\u00c2`\2\u00d9\u00da\5\u00c6b\2\u00da\u00db\5\u00acU\2\u00db"+ + "\u00dc\5\u00aeV\2\u00dc\u00dd\5\u00b4Y\2\u00dd\u00de\5\u00d2h\2\u00de"+ + "\u00df\3\2\2\2\u00df\u00e0\b\2\2\2\u00e0\7\3\2\2\2\u00e1\u00e2\5\u00c8"+ + "c\2\u00e2\u00e3\5\u00c0_\2\u00e3\u00e4\5\u00cce\2\u00e4\u00e5\5\u00c6"+ + "b\2\u00e5\u00e6\5\u00a8S\2\u00e6\u00e7\5\u00acU\2\u00e7\u00e8\3\2\2\2"+ + "\u00e8\u00e9\b\3\2\2\u00e9\t\3\2\2\2\u00ea\u00eb\5\u00c4a\2\u00eb\u00ec"+ + "\5\u00cce\2\u00ec\u00ed\5\u00acU\2\u00ed\u00ee\5\u00c6b\2\u00ee\u00ef"+ + "\5\u00d4i\2\u00ef\u00f0\3\2\2\2\u00f0\u00f1\b\4\2\2\u00f1\13\3\2\2\2\u00f2"+ + "\u00f3\5\u00b4Y\2\u00f3\u00f4\5\u00cad\2\u00f4\u00f5\5\u00acU\2\u00f5"+ + "\u00f6\5\u00c6b\2\u00f6\u00f7\5R(\2\u00f7\u00f8\5\u00cad\2\u00f8\u00f9"+ + "\5\u00c0_\2\u00f9\u00fa\5\u00c6b\2\u00fa\u00fb\3\2\2\2\u00fb\u00fc\b\5"+ + "\2\2\u00fc\r\3\2\2\2\u00fd\u00fe\5\u00aeV\2\u00fe\u00ff\5\u00cce\2\u00ff"+ + "\u0100\5\u00be^\2\u0100\u0101\5\u00a8S\2\u0101\u0102\5\u00cad\2\u0102"+ + "\u0103\5\u00b4Y\2\u0103\u0104\5\u00c0_\2\u0104\u0105\5\u00be^\2\u0105"+ + "\u0106\5\u00c8c\2\u0106\u0107\3\2\2\2\u0107\u0108\b\6\2\2\u0108\17\3\2"+ + "\2\2\u0109\u010a\5\u00aeV\2\u010a\u010b\5\u00b4Y\2\u010b\u010c\5\u00ac"+ + "U\2\u010c\u010d\5\u00ba\\\2\u010d\u010e\5\u00aaT\2\u010e\u010f\3\2\2\2"+ + "\u010f\u0110\b\7\2\2\u0110\21\3\2\2\2\u0111\u0112\5\u00c2`\2\u0112\u0113"+ + "\5\u00cce\2\u0113\u0114\5\u00c8c\2\u0114\u0115\5\u00b2X\2\u0115\u0116"+ + "\5\u00acU\2\u0116\u0117\5\u00aaT\2\u0117\u0118\7a\2\2\u0118\u0119\5\u00ae"+ + "V\2\u0119\u011a\5\u00b4Y\2\u011a\u011b\5\u00acU\2\u011b\u011c\5\u00ba"+ + "\\\2\u011c\u011d\5\u00aaT\2\u011d\u011e\3\2\2\2\u011e\u011f\b\b\2\2\u011f"+ + "\23\3\2\2\2\u0120\u0121\5\u00c2`\2\u0121\u0122\5\u00c0_\2\u0122\u0123"+ + "\5\u00c2`\2\u0123\u0124\5\u00c2`\2\u0124\u0125\5\u00acU\2\u0125\u0126"+ + "\5\u00aaT\2\u0126\u0127\7a\2\2\u0127\u0128\5\u00aeV\2\u0128\u0129\5\u00b4"+ + "Y\2\u0129\u012a\5\u00acU\2\u012a\u012b\5\u00ba\\\2\u012b\u012c\5\u00aa"+ + "T\2\u012c\u012d\3\2\2\2\u012d\u012e\b\t\2\2\u012e\25\3\2\2\2\u012f\u0130"+ + "\5R(\2\u0130\u0131\5\u00cce\2\u0131\u0132\5\u00cad\2\u0132\u0133\5\u00c0"+ + "_\2\u0133\u0134\5\u00b4Y\2\u0134\u0135\5\u00be^\2\u0135\u0136\5\u00a8"+ + "S\2\u0136\u0137\5\u00c6b\2\u0137\u0138\5\u00acU\2\u0138\u0139\5\u00bc"+ + "]\2\u0139\u013a\5\u00acU\2\u013a\u013b\5\u00be^\2\u013b\u013c\5\u00ca"+ + "d\2\u013c\u013d\3\2\2\2\u013d\u013e\b\n\3\2\u013e\27\3\2\2\2\u013f\u0140"+ + "\5\u00acU\2\u0140\u0141\5\u00d2h\2\u0141\u0142\5\u00c2`\2\u0142\u0143"+ + "\5\u00c6b\2\u0143\u0144\5\u00acU\2\u0144\u0145\5\u00c8c\2\u0145\u0146"+ + "\5\u00c8c\2\u0146\u0147\5\u00b4Y\2\u0147\u0148\5\u00c0_\2\u0148\u0149"+ + "\5\u00be^\2\u0149\31\3\2\2\2\u014a\u014b\5\u00cce\2\u014b\u014c\5\u00be"+ + "^\2\u014c\u014d\5\u00b4Y\2\u014d\u014e\5\u00c0_\2\u014e\u014f\5\u00be"+ + "^\2\u014f\33\3\2\2\2\u0150\u0151\5\u00b6Z\2\u0151\u0152\5\u00c0_\2\u0152"+ + "\u0153\5\u00b4Y\2\u0153\u0154\5\u00be^\2\u0154\35\3\2\2\2\u0155\u0156"+ + "\5\u00c8c\2\u0156\u0157\5\u00cce\2\u0157\u0158\5\u00a6R\2\u0158\u0159"+ + "\5\u00c8c\2\u0159\u015a\5\u00cad\2\u015a\u015b\5\u00b4Y\2\u015b\u015c"+ + "\5\u00cad\2\u015c\u015d\5\u00cce\2\u015d\u015e\5\u00cad\2\u015e\u015f"+ + "\5\u00b4Y\2\u015f\u0160\5\u00be^\2\u0160\u0161\5\u00b0W\2\u0161\37\3\2"+ + "\2\2\u0162\u0163\5\u00bc]\2\u0163\u0164\5R(\2\u0164\u0165\5\u00cad\2\u0165"+ + "\u0166\5\u00a8S\2\u0166\u0167\5\u00b2X\2\u0167\u0168\5\u00acU\2\u0168"+ + "\u0169\5\u00c6b\2\u0169!\3\2\2\2\u016a\u016b\5R(\2\u016b\u016c\5\u00c8"+ + "c\2\u016c#\3\2\2\2\u016d\u016e\5\u00b4Y\2\u016e\u016f\5\u00aeV\2\u016f"+ + "%\3\2\2\2\u0170\u0171\5\u00c0_\2\u0171\u0172\5\u00be^\2\u0172\'\3\2\2"+ + "\2\u0173\u0174\5\u00bc]\2\u0174\u0175\5R(\2\u0175\u0176\5\u00cad\2\u0176"+ + "\u0177\5\u00a8S\2\u0177\u0178\5\u00b2X\2\u0178\u0179\5\u00b4Y\2\u0179"+ + "\u017a\5\u00be^\2\u017a\u017b\5\u00b0W\2\u017b)\3\2\2\2\u017c\u017d\5"+ + "\u00c6b\2\u017d\u017e\5\u00aaT\2\u017e\u017f\5\u00aeV\2\u017f\u0180\5"+ + "\u00ba\\\2\u0180\u0181\5\u00b4Y\2\u0181\u0182\5\u00c8c\2\u0182\u0183\5"+ + "\u00cad\2\u0183+\3\2\2\2\u0184\u0185\5\u00c6b\2\u0185\u0186\5\u00aaT\2"+ + "\u0186\u0187\5\u00aeV\2\u0187\u0188\5\u00a6R\2\u0188\u0189\5R(\2\u0189"+ + "\u018a\5\u00b0W\2\u018a-\3\2\2\2\u018b\u018c\5\u00c6b\2\u018c\u018d\5"+ + "\u00aaT\2\u018d\u018e\5\u00aeV\2\u018e\u018f\5\u00c8c\2\u018f\u0190\5"+ + "\u00acU\2\u0190\u0191\5\u00c4a\2\u0191/\3\2\2\2\u0192\u0193\5\u00c6b\2"+ + "\u0193\u0194\5\u00aaT\2\u0194\u0195\5\u00aeV\2\u0195\u0196\5R(\2\u0196"+ + "\u0197\5\u00ba\\\2\u0197\u0198\5\u00cad\2\u0198\61\3\2\2\2\u0199\u019a"+ + "\7>\2\2\u019a\63\3\2\2\2\u019b\u019c\7@\2\2\u019c\65\3\2\2\2\u019d\u019e"+ + "\7]\2\2\u019e\67\3\2\2\2\u019f\u01a0\7]\2\2\u01a0\u01a1\7]\2\2\u01a19"+ + "\3\2\2\2\u01a2\u01a3\7_\2\2\u01a3;\3\2\2\2\u01a4\u01a5\7_\2\2\u01a5\u01a6"+ + "\7_\2\2\u01a6=\3\2\2\2\u01a7\u01a8\7*\2\2\u01a8?\3\2\2\2\u01a9\u01aa\7"+ + "+\2\2\u01aaA\3\2\2\2\u01ab\u01ac\7}\2\2\u01acC\3\2\2\2\u01ad\u01ae\7\177"+ + "\2\2\u01aeE\3\2\2\2\u01af\u01b0\7=\2\2\u01b0G\3\2\2\2\u01b1\u01b2\7\60"+ + "\2\2\u01b2I\3\2\2\2\u01b3\u01b4\7-\2\2\u01b4K\3\2\2\2\u01b5\u01b6\7.\2"+ + "\2\u01b6M\3\2\2\2\u01b7\u01b8\7$\2\2\u01b8O\3\2\2\2\u01b9\u01be\7(\2\2"+ + "\u01ba\u01bb\7C\2\2\u01bb\u01bc\7P\2\2\u01bc\u01be\7F\2\2\u01bd\u01b9"+ + "\3\2\2\2\u01bd\u01ba\3\2\2\2\u01beQ\3\2\2\2\u01bf\u01c0\t\2\2\2\u01c0"+ + "S\3\2\2\2\u01c1\u01c2\7B\2\2\u01c2U\3\2\2\2\u01c3\u01c4\7?\2\2\u01c4W"+ + "\3\2\2\2\u01c5\u01c6\5\u00b4Y\2\u01c6\u01c7\5\u00be^\2\u01c7\u01c8\5\u00aa"+ + "T\2\u01c8\u01c9\5\u00acU\2\u01c9\u01ca\5\u00d2h\2\u01ca\u01cb\7*\2\2\u01cb"+ + "\u01cc\7+\2\2\u01ccY\3\2\2\2\u01cd\u01d6\5\u009cM\2\u01ce\u01d6\5\u009e"+ + "N\2\u01cf\u01d6\t\3\2\2\u01d0\u01d1\7^\2\2\u01d1\u01d6\7\60\2\2\u01d2"+ + "\u01d3\7\'\2\2\u01d3\u01d4\7\64\2\2\u01d4\u01d6\7G\2\2\u01d5\u01cd\3\2"+ + "\2\2\u01d5\u01ce\3\2\2\2\u01d5\u01cf\3\2\2\2\u01d5\u01d0\3\2\2\2\u01d5"+ + "\u01d2\3\2\2\2\u01d6\u01d7\3\2\2\2\u01d7\u01d5\3\2\2\2\u01d7\u01d8\3\2"+ + "\2\2\u01d8[\3\2\2\2\u01d9\u01e2\5\u009cM\2\u01da\u01e2\5\u009eN\2\u01db"+ + "\u01e2\t\3\2\2\u01dc\u01dd\7^\2\2\u01dd\u01e2\7\60\2\2\u01de\u01df\7\'"+ + "\2\2\u01df\u01e0\7\64\2\2\u01e0\u01e2\7G\2\2\u01e1\u01d9\3\2\2\2\u01e1"+ + "\u01da\3\2\2\2\u01e1\u01db\3\2\2\2\u01e1\u01dc\3\2\2\2\u01e1\u01de\3\2"+ + "\2\2\u01e2\u01e5\3\2\2\2\u01e3\u01e1\3\2\2\2\u01e3\u01e4\3\2\2\2\u01e4"+ + "\u01e6\3\2\2\2\u01e5\u01e3\3\2\2\2\u01e6\u01e7\7<\2\2\u01e7]\3\2\2\2\u01e8"+ + "\u01ed\7$\2\2\u01e9\u01ee\5\u009cM\2\u01ea\u01ee\5\u009eN\2\u01eb\u01ee"+ + "\5\u00a4Q\2\u01ec\u01ee\7\"\2\2\u01ed\u01e9\3\2\2\2\u01ed\u01ea\3\2\2"+ + "\2\u01ed\u01eb\3\2\2\2\u01ed\u01ec\3\2\2\2\u01ee\u01ef\3\2\2\2\u01ef\u01ed"+ + "\3\2\2\2\u01ef\u01f0\3\2\2\2\u01f0\u01f1\3\2\2\2\u01f1\u01f2\7$\2\2\u01f2"+ + "_\3\2\2\2\u01f3\u01f4\5\u00a0O\2\u01f4\u01f5\7<\2\2\u01f5\u01f6\5\u00a2"+ + "P\2\u01f6a\3\2\2\2\u01f7\u01ff\7B\2\2\u01f8\u01f9\5\\-\2\u01f9\u01fa\5"+ + "Z,\2\u01fa\u0200\3\2\2\2\u01fb\u01fc\7>\2\2\u01fc\u01fd\5Z,\2\u01fd\u01fe"+ + "\7@\2\2\u01fe\u0200\3\2\2\2\u01ff\u01f8\3\2\2\2\u01ff\u01fb\3\2\2\2\u0200"+ + "c\3\2\2\2\u0201\u0203\7B\2\2\u0202\u0204\5\u009cM\2\u0203\u0202\3\2\2"+ + "\2\u0204\u0205\3\2\2\2\u0205\u0203\3\2\2\2\u0205\u0206\3\2\2\2\u0206\u0210"+ + "\3\2\2\2\u0207\u020a\7/\2\2\u0208\u020b\5\u009cM\2\u0209\u020b\5\u009e"+ + "N\2\u020a\u0208\3\2\2\2\u020a\u0209\3\2\2\2\u020b\u020c\3\2\2\2\u020c"+ + "\u020a\3\2\2\2\u020c\u020d\3\2\2\2\u020d\u020f\3\2\2\2\u020e\u0207\3\2"+ + "\2\2\u020f\u0212\3\2\2\2\u0210\u020e\3\2\2\2\u0210\u0211\3\2\2\2\u0211"+ + "e\3\2\2\2\u0212\u0210\3\2\2\2\u0213\u0217\7%\2\2\u0214\u0216\n\4\2\2\u0215"+ + "\u0214\3\2\2\2\u0216\u0219\3\2\2\2\u0217\u0215\3\2\2\2\u0217\u0218\3\2"+ + "\2\2\u0218\u021a\3\2\2\2\u0219\u0217\3\2\2\2\u021a\u021b\b\62\4\2\u021b"+ + "g\3\2\2\2\u021c\u021d\t\5\2\2\u021d\u021e\3\2\2\2\u021e\u021f\b\63\4\2"+ + "\u021fi\3\2\2\2\u0220\u0221\7j\2\2\u0221\u0222\7v\2\2\u0222\u0223\7v\2"+ + "\2\u0223\u022e\7r\2\2\u0224\u0225\7j\2\2\u0225\u0226\7v\2\2\u0226\u0227"+ + "\7v\2\2\u0227\u0228\7r\2\2\u0228\u022e\7u\2\2\u0229\u022a\7h\2\2\u022a"+ + "\u022b\7k\2\2\u022b\u022c\7n\2\2\u022c\u022e\7g\2\2\u022d\u0220\3\2\2"+ + "\2\u022d\u0224\3\2\2\2\u022d\u0229\3\2\2\2\u022e\u022f\3\2\2\2\u022f\u0230"+ + "\7<\2\2\u0230\u0231\7\61\2\2\u0231\u0232\7\61\2\2\u0232\u0238\3\2\2\2"+ + "\u0233\u0237\5\u009cM\2\u0234\u0237\5\u009eN\2\u0235\u0237\5\u00a4Q\2"+ + "\u0236\u0233\3\2\2\2\u0236\u0234\3\2\2\2\u0236\u0235\3\2\2\2\u0237\u023a"+ + "\3\2\2\2\u0238\u0236\3\2\2\2\u0238\u0239\3\2\2\2\u0239k\3\2\2\2\u023a"+ + "\u0238\3\2\2\2\u023b\u023c\7l\2\2\u023c\u023d\7f\2\2\u023d\u023e\7d\2"+ + "\2\u023e\u023f\7e\2\2\u023f\u0240\7<\2\2\u0240\u0243\3\2\2\2\u0241\u0244"+ + "\5\u009cM\2\u0242\u0244\5\u009eN\2\u0243\u0241\3\2\2\2\u0243\u0242\3\2"+ + "\2\2\u0244\u0245\3\2\2\2\u0245\u0243\3\2\2\2\u0245\u0246\3\2\2\2\u0246"+ + "\u0247\3\2\2\2\u0247\u024d\7<\2\2\u0248\u024c\5\u009cM\2\u0249\u024c\5"+ + "\u009eN\2\u024a\u024c\5\u00a4Q\2\u024b\u0248\3\2\2\2\u024b\u0249\3\2\2"+ + "\2\u024b\u024a\3\2\2\2\u024c\u024f\3\2\2\2\u024d\u024b\3\2\2\2\u024d\u024e"+ + "\3\2\2\2\u024em\3\2\2\2\u024f\u024d\3\2\2\2\u0250\u0251\5\u00b6Z\2\u0251"+ + "\u0252\5\u00c8c\2\u0252\u0253\5\u00c0_\2\u0253\u0254\5\u00be^\2\u0254"+ + "\u0255\5\u00c2`\2\u0255\u0256\5R(\2\u0256\u0257\5\u00cad\2\u0257\u0258"+ + "\5\u00b2X\2\u0258\u0259\7<\2\2\u0259o\3\2\2\2\u025a\u025b\5\u00d2h\2\u025b"+ + "\u025c\5\u00c2`\2\u025c\u025d\5R(\2\u025d\u025e\5\u00cad\2\u025e\u025f"+ + "\5\u00b2X\2\u025f\u0260\7<\2\2\u0260q\3\2\2\2\u0261\u0262\5\u00a8S\2\u0262"+ + "\u0263\5\u00c8c\2\u0263\u0264\5\u00cef\2\u0264\u0265\5\u00c2`\2\u0265"+ + "\u0266\5\u00acU\2\u0266\u0267\5\u00c6b\2\u0267\u0268\5\u00c6b\2\u0268"+ + "\u0269\5\u00c0_\2\u0269\u026a\5\u00d0g\2\u026as\3\2\2\2\u026b\u026c\5"+ + "\u00c8c\2\u026c\u026d\5\u00c4a\2\u026d\u026e\5\u00ba\\\2\u026e\u026f\7"+ + "<\2\2\u026fu\3\2\2\2\u0270\u0271\5\u00c8c\2\u0271\u0272\5\u00a8S\2\u0272"+ + "\u0273\5R(\2\u0273\u0274\5\u00ba\\\2\u0274\u0275\5R(\2\u0275\u0276\7<"+ + "\2\2\u0276w\3\2\2\2\u0277\u0278\5\u00c8c\2\u0278\u0279\5\u00c2`\2\u0279"+ + "\u027a\5R(\2\u027a\u027b\5\u00c6b\2\u027b\u027c\5\u00c4a\2\u027c\u027d"+ + "\5\u00ba\\\2\u027d\u027e\7<\2\2\u027ey\3\2\2\2\u027f\u0280\5\u00c8c\2"+ + "\u0280\u0281\5\u00cad\2\u0281\u0282\5\u00aaT\2\u0282\u0283\5\u00b4Y\2"+ + "\u0283\u0284\5\u00be^\2\u0284{\3\2\2\2\u0285\u028a\5\u009cM\2\u0286\u028a"+ + "\5\u009eN\2\u0287\u028a\5\u00a4Q\2\u0288\u028a\t\6\2\2\u0289\u0285\3\2"+ + "\2\2\u0289\u0286\3\2\2\2\u0289\u0287\3\2\2\2\u0289\u0288\3\2\2\2\u028a"+ + "\u028b\3\2\2\2\u028b\u0289\3\2\2\2\u028b\u028c\3\2\2\2\u028c}\3\2\2\2"+ + "\u028d\u028e\7@\2\2\u028e\u028f\3\2\2\2\u028f\u0290\b>\5\2\u0290\177\3"+ + "\2\2\2\u0291\u0292\t\5\2\2\u0292\u0293\3\2\2\2\u0293\u0294\b?\4\2\u0294"+ + "\u0081\3\2\2\2\u0295\u0296\7>\2\2\u0296\u0297\3\2\2\2\u0297\u0298\b@\6"+ + "\2\u0298\u0083\3\2\2\2\u0299\u029f\5\u009cM\2\u029a\u029e\5\u009cM\2\u029b"+ + "\u029e\5\u009eN\2\u029c\u029e\t\3\2\2\u029d\u029a\3\2\2\2\u029d\u029b"+ + "\3\2\2\2\u029d\u029c\3\2\2\2\u029e\u02a1\3\2\2\2\u029f\u029d\3\2\2\2\u029f"+ + "\u02a0\3\2\2\2\u02a0\u0085\3\2\2\2\u02a1\u029f\3\2\2\2\u02a2\u02a6\5\u009c"+ + "M\2\u02a3\u02a6\5\u009eN\2\u02a4\u02a6\t\3\2\2\u02a5\u02a2\3\2\2\2\u02a5"+ + "\u02a3\3\2\2\2\u02a5\u02a4\3\2\2\2\u02a6\u02a9\3\2\2\2\u02a7\u02a5\3\2"+ + "\2\2\u02a7\u02a8\3\2\2\2\u02a8\u02aa\3\2\2\2\u02a9\u02a7\3\2\2\2\u02aa"+ + "\u02ab\7<\2\2\u02ab\u0087\3\2\2\2\u02ac\u02ad\t\5\2\2\u02ad\u02ae\3\2"+ + "\2\2\u02ae\u02af\bC\4\2\u02af\u0089\3\2\2\2\u02b0\u02b1\7>\2\2\u02b1\u008b"+ + "\3\2\2\2\u02b2\u02b3\5\u00cad\2\u02b3\u02b4\5\u00c0_\2\u02b4\u008d\3\2"+ + "\2\2\u02b5\u02b6\5\u00a6R\2\u02b6\u02b7\5\u00d4i\2\u02b7\u008f\3\2\2\2"+ + "\u02b8\u02b9\7-\2\2\u02b9\u0091\3\2\2\2\u02ba\u02bc\5\u009eN\2\u02bb\u02ba"+ + "\3\2\2\2\u02bc\u02bd\3\2\2\2\u02bd\u02bb\3\2\2\2\u02bd\u02be\3\2\2\2\u02be"+ + "\u0093\3\2\2\2\u02bf\u02c5\5\u009cM\2\u02c0\u02c4\5\u009cM\2\u02c1\u02c4"+ + "\5\u009eN\2\u02c2\u02c4\t\3\2\2\u02c3\u02c0\3\2\2\2\u02c3\u02c1\3\2\2"+ + "\2\u02c3\u02c2\3\2\2\2\u02c4\u02c7\3\2\2\2\u02c5\u02c3\3\2\2\2\u02c5\u02c6"+ + "\3\2\2\2\u02c6\u0095\3\2\2\2\u02c7\u02c5\3\2\2\2\u02c8\u02cd\7$\2\2\u02c9"+ + "\u02ce\5\u009cM\2\u02ca\u02ce\5\u009eN\2\u02cb\u02ce\5\u00a4Q\2\u02cc"+ + "\u02ce\7\"\2\2\u02cd\u02c9\3\2\2\2\u02cd\u02ca\3\2\2\2\u02cd\u02cb\3\2"+ + "\2\2\u02cd\u02cc\3\2\2\2\u02ce\u02cf\3\2\2\2\u02cf\u02cd\3\2\2\2\u02cf"+ + "\u02d0\3\2\2\2\u02d0\u02d1\3\2\2\2\u02d1\u02d2\7$\2\2\u02d2\u0097\3\2"+ + "\2\2\u02d3\u02d4\7@\2\2\u02d4\u02d5\3\2\2\2\u02d5\u02d6\bK\5\2\u02d6\u0099"+ + "\3\2\2\2\u02d7\u02d8\t\5\2\2\u02d8\u02d9\3\2\2\2\u02d9\u02da\bL\4\2\u02da"+ + "\u009b\3\2\2\2\u02db\u02dd\t\7\2\2\u02dc\u02db\3\2\2\2\u02dd\u009d\3\2"+ + "\2\2\u02de\u02df\t\b\2\2\u02df\u009f\3\2\2\2\u02e0\u02e1\7z\2\2\u02e1"+ + "\u02e6\7u\2\2\u02e2\u02e3\7z\2\2\u02e3\u02e4\7u\2\2\u02e4\u02e6\7f\2\2"+ + "\u02e5\u02e0\3\2\2\2\u02e5\u02e2\3\2\2\2\u02e6\u00a1\3\2\2\2\u02e7\u02e8"+ + "\7u\2\2\u02e8\u02e9\7v\2\2\u02e9\u02ea\7t\2\2\u02ea\u02eb\7k\2\2\u02eb"+ + "\u02ec\7p\2\2\u02ec\u0440\7i\2\2\u02ed\u02ee\7d\2\2\u02ee\u02ef\7q\2\2"+ + "\u02ef\u02f0\7q\2\2\u02f0\u02f1\7n\2\2\u02f1\u02f2\7g\2\2\u02f2\u02f3"+ + "\7c\2\2\u02f3\u0440\7p\2\2\u02f4\u02f5\7f\2\2\u02f5\u02f6\7g\2\2\u02f6"+ + "\u02f7\7e\2\2\u02f7\u02f8\7k\2\2\u02f8\u02f9\7o\2\2\u02f9\u02fa\7c\2\2"+ + "\u02fa\u0440\7n\2\2\u02fb\u02fc\7k\2\2\u02fc\u02fd\7p\2\2\u02fd\u02fe"+ + "\7v\2\2\u02fe\u02ff\7g\2\2\u02ff\u0300\7i\2\2\u0300\u0301\7g\2\2\u0301"+ + "\u0440\7t\2\2\u0302\u0303\7f\2\2\u0303\u0304\7q\2\2\u0304\u0305\7w\2\2"+ + "\u0305\u0306\7d\2\2\u0306\u0307\7n\2\2\u0307\u0440\7g\2\2\u0308\u0309"+ + "\7h\2\2\u0309\u030a\7n\2\2\u030a\u030b\7q\2\2\u030b\u030c\7c\2\2\u030c"+ + "\u0440\7v\2\2\u030d\u030e\7f\2\2\u030e\u030f\7c\2\2\u030f\u0310\7v\2\2"+ + "\u0310\u0440\7g\2\2\u0311\u0312\7v\2\2\u0312\u0313\7k\2\2\u0313\u0314"+ + "\7o\2\2\u0314\u0440\7g\2\2\u0315\u0316\7f\2\2\u0316\u0317\7c\2\2\u0317"+ + "\u0318\7v\2\2\u0318\u0319\7g\2\2\u0319\u031a\7V\2\2\u031a\u031b\7k\2\2"+ + "\u031b\u031c\7o\2\2\u031c\u0440\7g\2\2\u031d\u031e\7f\2\2\u031e\u031f"+ + "\7c\2\2\u031f\u0320\7v\2\2\u0320\u0321\7g\2\2\u0321\u0322\7V\2\2\u0322"+ + "\u0323\7k\2\2\u0323\u0324\7o\2\2\u0324\u0325\7g\2\2\u0325\u0326\7U\2\2"+ + "\u0326\u0327\7v\2\2\u0327\u0328\7c\2\2\u0328\u0329\7o\2\2\u0329\u0440"+ + "\7r\2\2\u032a\u032b\7i\2\2\u032b\u032c\7[\2\2\u032c\u032d\7g\2\2\u032d"+ + "\u032e\7c\2\2\u032e\u0440\7t\2\2\u032f\u0330\7i\2\2\u0330\u0331\7O\2\2"+ + "\u0331\u0332\7q\2\2\u0332\u0333\7p\2\2\u0333\u0334\7v\2\2\u0334\u0440"+ + "\7j\2\2\u0335\u0336\7i\2\2\u0336\u0337\7F\2\2\u0337\u0338\7c\2\2\u0338"+ + "\u0440\7{\2\2\u0339\u033a\7i\2\2\u033a\u033b\7[\2\2\u033b\u033c\7g\2\2"+ + "\u033c\u033d\7c\2\2\u033d\u033e\7t\2\2\u033e\u033f\7O\2\2\u033f\u0340"+ + "\7q\2\2\u0340\u0341\7p\2\2\u0341\u0342\7v\2\2\u0342\u0440\7j\2\2\u0343"+ + "\u0344\7i\2\2\u0344\u0345\7O\2\2\u0345\u0346\7q\2\2\u0346\u0347\7p\2\2"+ + "\u0347\u0348\7v\2\2\u0348\u0349\7j\2\2\u0349\u034a\7F\2\2\u034a\u034b"+ + "\7c\2\2\u034b\u0440\7{\2\2\u034c\u034d\7f\2\2\u034d\u034e\7w\2\2\u034e"+ + "\u034f\7t\2\2\u034f\u0350\7c\2\2\u0350\u0351\7v\2\2\u0351\u0352\7k\2\2"+ + "\u0352\u0353\7q\2\2\u0353\u0440\7p\2\2\u0354\u0355\7{\2\2\u0355\u0356"+ + "\7g\2\2\u0356\u0357\7c\2\2\u0357\u0358\7t\2\2\u0358\u0359\7O\2\2\u0359"+ + "\u035a\7q\2\2\u035a\u035b\7p\2\2\u035b\u035c\7v\2\2\u035c\u035d\7j\2\2"+ + "\u035d\u035e\7F\2\2\u035e\u035f\7w\2\2\u035f\u0360\7t\2\2\u0360\u0361"+ + "\7c\2\2\u0361\u0362\7v\2\2\u0362\u0363\7k\2\2\u0363\u0364\7q\2\2\u0364"+ + "\u0440\7p\2\2\u0365\u0366\7f\2\2\u0366\u0367\7c\2\2\u0367\u0368\7{\2\2"+ + "\u0368\u0369\7V\2\2\u0369\u036a\7k\2\2\u036a\u036b\7o\2\2\u036b\u036c"+ + "\7g\2\2\u036c\u036d\7F\2\2\u036d\u036e\7w\2\2\u036e\u036f\7t\2\2\u036f"+ + "\u0370\7c\2\2\u0370\u0371\7v\2\2\u0371\u0372\7k\2\2\u0372\u0373\7q\2\2"+ + "\u0373\u0440\7p\2\2\u0374\u0375\7d\2\2\u0375\u0376\7{\2\2\u0376\u0377"+ + "\7v\2\2\u0377\u0440\7g\2\2\u0378\u0379\7u\2\2\u0379\u037a\7j\2\2\u037a"+ + "\u037b\7q\2\2\u037b\u037c\7t\2\2\u037c\u0440\7v\2\2\u037d\u037e\7k\2\2"+ + "\u037e\u037f\7p\2\2\u037f\u0440\7v\2\2\u0380\u0381\7n\2\2\u0381\u0382"+ + "\7q\2\2\u0382\u0383\7p\2\2\u0383\u0440\7i\2\2\u0384\u0385\7w\2\2\u0385"+ + "\u0386\7p\2\2\u0386\u0387\7u\2\2\u0387\u0388\7k\2\2\u0388\u0389\7i\2\2"+ + "\u0389\u038a\7p\2\2\u038a\u038b\7g\2\2\u038b\u038c\7f\2\2\u038c\u038d"+ + "\7D\2\2\u038d\u038e\7{\2\2\u038e\u038f\7v\2\2\u038f\u0440\7g\2\2\u0390"+ + "\u0391\7w\2\2\u0391\u0392\7p\2\2\u0392\u0393\7u\2\2\u0393\u0394\7k\2\2"+ + "\u0394\u0395\7i\2\2\u0395\u0396\7p\2\2\u0396\u0397\7g\2\2\u0397\u0398"+ + "\7f\2\2\u0398\u0399\7U\2\2\u0399\u039a\7j\2\2\u039a\u039b\7q\2\2\u039b"+ + "\u039c\7t\2\2\u039c\u0440\7v\2\2\u039d\u039e\7w\2\2\u039e\u039f\7p\2\2"+ + "\u039f\u03a0\7u\2\2\u03a0\u03a1\7k\2\2\u03a1\u03a2\7i\2\2\u03a2\u03a3"+ + "\7p\2\2\u03a3\u03a4\7g\2\2\u03a4\u03a5\7f\2\2\u03a5\u03a6\7K\2\2\u03a6"+ + "\u03a7\7p\2\2\u03a7\u0440\7v\2\2\u03a8\u03a9\7w\2\2\u03a9\u03aa\7p\2\2"+ + "\u03aa\u03ab\7u\2\2\u03ab\u03ac\7k\2\2\u03ac\u03ad\7i\2\2\u03ad\u03ae"+ + "\7p\2\2\u03ae\u03af\7g\2\2\u03af\u03b0\7f\2\2\u03b0\u03b1\7N\2\2\u03b1"+ + "\u03b2\7q\2\2\u03b2\u03b3\7p\2\2\u03b3\u0440\7i\2\2\u03b4\u03b5\7r\2\2"+ + "\u03b5\u03b6\7q\2\2\u03b6\u03b7\7u\2\2\u03b7\u03b8\7k\2\2\u03b8\u03b9"+ + "\7v\2\2\u03b9\u03ba\7k\2\2\u03ba\u03bb\7x\2\2\u03bb\u03bc\7g\2\2\u03bc"+ + "\u03bd\7K\2\2\u03bd\u03be\7p\2\2\u03be\u03bf\7v\2\2\u03bf\u03c0\7g\2\2"+ + "\u03c0\u03c1\7i\2\2\u03c1\u03c2\7g\2\2\u03c2\u0440\7t\2\2\u03c3\u03c4"+ + "\7p\2\2\u03c4\u03c5\7q\2\2\u03c5\u03c6\7p\2\2\u03c6\u03c7\7P\2\2\u03c7"+ + "\u03c8\7g\2\2\u03c8\u03c9\7i\2\2\u03c9\u03ca\7c\2\2\u03ca\u03cb\7v\2\2"+ + "\u03cb\u03cc\7k\2\2\u03cc\u03cd\7x\2\2\u03cd\u03ce\7g\2\2\u03ce\u03cf"+ + "\7K\2\2\u03cf\u03d0\7p\2\2\u03d0\u03d1\7v\2\2\u03d1\u03d2\7g\2\2\u03d2"+ + "\u03d3\7i\2\2\u03d3\u03d4\7g\2\2\u03d4\u0440\7t\2\2\u03d5\u03d6\7p\2\2"+ + "\u03d6\u03d7\7g\2\2\u03d7\u03d8\7i\2\2\u03d8\u03d9\7c\2\2\u03d9\u03da"+ + "\7v\2\2\u03da\u03db\7k\2\2\u03db\u03dc\7x\2\2\u03dc\u03dd\7g\2\2\u03dd"+ + "\u03de\7K\2\2\u03de\u03df\7p\2\2\u03df\u03e0\7v\2\2\u03e0\u03e1\7g\2\2"+ + "\u03e1\u03e2\7i\2\2\u03e2\u03e3\7g\2\2\u03e3\u0440\7t\2\2\u03e4\u03e5"+ + "\7p\2\2\u03e5\u03e6\7q\2\2\u03e6\u03e7\7p\2\2\u03e7\u03e8\7R\2\2\u03e8"+ + "\u03e9\7q\2\2\u03e9\u03ea\7u\2\2\u03ea\u03eb\7k\2\2\u03eb\u03ec\7v\2\2"+ + "\u03ec\u03ed\7k\2\2\u03ed\u03ee\7x\2\2\u03ee\u03ef\7g\2\2\u03ef\u03f0"+ + "\7K\2\2\u03f0\u03f1\7p\2\2\u03f1\u03f2\7v\2\2\u03f2\u03f3\7g\2\2\u03f3"+ + "\u03f4\7i\2\2\u03f4\u03f5\7g\2\2\u03f5\u0440\7t\2\2\u03f6\u03f7\7j\2\2"+ + "\u03f7\u03f8\7g\2\2\u03f8\u03f9\7z\2\2\u03f9\u03fa\7D\2\2\u03fa\u03fb"+ + "\7k\2\2\u03fb\u03fc\7p\2\2\u03fc\u03fd\7c\2\2\u03fd\u03fe\7t\2\2\u03fe"+ + "\u0440\7{\2\2\u03ff\u0400\7d\2\2\u0400\u0401\7c\2\2\u0401\u0402\7u\2\2"+ + "\u0402\u0403\7g\2\2\u0403\u0404\78\2\2\u0404\u0405\7\66\2\2\u0405\u0406"+ + "\7D\2\2\u0406\u0407\7k\2\2\u0407\u0408\7p\2\2\u0408\u0409\7c\2\2\u0409"+ + "\u040a\7t\2\2\u040a\u0440\7{\2\2\u040b\u040c\7c\2\2\u040c\u040d\7p\2\2"+ + "\u040d\u040e\7{\2\2\u040e\u040f\7W\2\2\u040f\u0410\7T\2\2\u0410\u0440"+ + "\7K\2\2\u0411\u0412\7n\2\2\u0412\u0413\7c\2\2\u0413\u0414\7p\2\2\u0414"+ + "\u0415\7i\2\2\u0415\u0416\7w\2\2\u0416\u0417\7c\2\2\u0417\u0418\7i\2\2"+ + "\u0418\u0440\7g\2\2\u0419\u041a\7p\2\2\u041a\u041b\7q\2\2\u041b\u041c"+ + "\7t\2\2\u041c\u041d\7o\2\2\u041d\u041e\7c\2\2\u041e\u041f\7n\2\2\u041f"+ + "\u0420\7k\2\2\u0420\u0421\7|\2\2\u0421\u0422\7g\2\2\u0422\u0423\7f\2\2"+ + "\u0423\u0424\7U\2\2\u0424\u0425\7v\2\2\u0425\u0426\7t\2\2\u0426\u0427"+ + "\7k\2\2\u0427\u0428\7p\2\2\u0428\u0440\7i\2\2\u0429\u042a\7v\2\2\u042a"+ + "\u042b\7q\2\2\u042b\u042c\7m\2\2\u042c\u042d\7g\2\2\u042d\u0440\7p\2\2"+ + "\u042e\u042f\7P\2\2\u042f\u0430\7O\2\2\u0430\u0431\7V\2\2\u0431\u0432"+ + "\7Q\2\2\u0432\u0433\7M\2\2\u0433\u0434\7G\2\2\u0434\u0440\7P\2\2\u0435"+ + "\u0436\7P\2\2\u0436\u0437\7c\2\2\u0437\u0438\7o\2\2\u0438\u0440\7g\2\2"+ + "\u0439\u043a\7P\2\2\u043a\u043b\7E\2\2\u043b\u043c\7P\2\2\u043c\u043d"+ + "\7c\2\2\u043d\u043e\7o\2\2\u043e\u0440\7g\2\2\u043f\u02e7\3\2\2\2\u043f"+ + "\u02ed\3\2\2\2\u043f\u02f4\3\2\2\2\u043f\u02fb\3\2\2\2\u043f\u0302\3\2"+ + "\2\2\u043f\u0308\3\2\2\2\u043f\u030d\3\2\2\2\u043f\u0311\3\2\2\2\u043f"+ + "\u0315\3\2\2\2\u043f\u031d\3\2\2\2\u043f\u032a\3\2\2\2\u043f\u032f\3\2"+ + "\2\2\u043f\u0335\3\2\2\2\u043f\u0339\3\2\2\2\u043f\u0343\3\2\2\2\u043f"+ + "\u034c\3\2\2\2\u043f\u0354\3\2\2\2\u043f\u0365\3\2\2\2\u043f\u0374\3\2"+ + "\2\2\u043f\u0378\3\2\2\2\u043f\u037d\3\2\2\2\u043f\u0380\3\2\2\2\u043f"+ + "\u0384\3\2\2\2\u043f\u0390\3\2\2\2\u043f\u039d\3\2\2\2\u043f\u03a8\3\2"+ + "\2\2\u043f\u03b4\3\2\2\2\u043f\u03c3\3\2\2\2\u043f\u03d5\3\2\2\2\u043f"+ + "\u03e4\3\2\2\2\u043f\u03f6\3\2\2\2\u043f\u03ff\3\2\2\2\u043f\u040b\3\2"+ + "\2\2\u043f\u0411\3\2\2\2\u043f\u0419\3\2\2\2\u043f\u0429\3\2\2\2\u043f"+ + "\u042e\3\2\2\2\u043f\u0435\3\2\2\2\u043f\u0439\3\2\2\2\u0440\u00a3\3\2"+ + "\2\2\u0441\u0447\t\t\2\2\u0442\u0443\7^\2\2\u0443\u0447\7>\2\2\u0444\u0445"+ + "\7^\2\2\u0445\u0447\7@\2\2\u0446\u0441\3\2\2\2\u0446\u0442\3\2\2\2\u0446"+ + "\u0444\3\2\2\2\u0447\u00a5\3\2\2\2\u0448\u0449\t\n\2\2\u0449\u00a7\3\2"+ + "\2\2\u044a\u044b\t\13\2\2\u044b\u00a9\3\2\2\2\u044c\u044d\t\f\2\2\u044d"+ + "\u00ab\3\2\2\2\u044e\u044f\t\r\2\2\u044f\u00ad\3\2\2\2\u0450\u0451\t\16"+ + "\2\2\u0451\u00af\3\2\2\2\u0452\u0453\t\17\2\2\u0453\u00b1\3\2\2\2\u0454"+ + "\u0455\t\20\2\2\u0455\u00b3\3\2\2\2\u0456\u0457\t\21\2\2\u0457\u00b5\3"+ + "\2\2\2\u0458\u0459\t\22\2\2\u0459\u00b7\3\2\2\2\u045a\u045b\t\23\2\2\u045b"+ + "\u00b9\3\2\2\2\u045c\u045d\t\24\2\2\u045d\u00bb\3\2\2\2\u045e\u045f\t"+ + "\25\2\2\u045f\u00bd\3\2\2\2\u0460\u0461\t\26\2\2\u0461\u00bf\3\2\2\2\u0462"+ + "\u0463\t\27\2\2\u0463\u00c1\3\2\2\2\u0464\u0465\t\30\2\2\u0465\u00c3\3"+ + "\2\2\2\u0466\u0467\t\31\2\2\u0467\u00c5\3\2\2\2\u0468\u0469\t\32\2\2\u0469"+ + "\u00c7\3\2\2\2\u046a\u046b\t\33\2\2\u046b\u00c9\3\2\2\2\u046c\u046d\t"+ + "\34\2\2\u046d\u00cb\3\2\2\2\u046e\u046f\t\35\2\2\u046f\u00cd\3\2\2\2\u0470"+ + "\u0471\t\36\2\2\u0471\u00cf\3\2\2\2\u0472\u0473\t\37\2\2\u0473\u00d1\3"+ + "\2\2\2\u0474\u0475\t \2\2\u0475\u00d3\3\2\2\2\u0476\u0477\t!\2\2\u0477"+ + "\u00d5\3\2\2\2\u0478\u0479\t\"\2\2\u0479\u00d7\3\2\2\2)\2\3\4\5\u01bd"+ + "\u01d5\u01d7\u01e1\u01e3\u01ed\u01ef\u01ff\u0205\u020a\u020c\u0210\u0217"+ + "\u022d\u0236\u0238\u0243\u0245\u024b\u024d\u0289\u028b\u029d\u029f\u02a5"+ + "\u02a7\u02bd\u02c3\u02c5\u02cd\u02cf\u02dc\u02e5\u043f\u0446\7\4\4\2\4"+ "\5\2\b\2\2\4\2\2\4\3\2"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); diff --git a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.tokens b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.tokens index 686041f..d273e53 100644 --- a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.tokens +++ b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLLexer.tokens @@ -56,22 +56,23 @@ CSVPERROW=55 SQL=56 SCALA=57 SPARQL=58 -QUERY_PART=59 -GREATER_SYMBOL_QUERY=60 -WS_QUERY=61 -LESS_SYMBOL_QUERY=62 -STRING_OR_VAR_QUERY=63 -URI_VAR_QUERY=64 -WS_DECLARATION=65 -LESS_SYMBOL_AUTOINCREMENT=66 -TO=67 -BY=68 -ADD_AUTOINCREMENT=69 -DIGITS=70 -STRING_OR_VAR_AUTOINCREMENT=71 -STRINGOPERATOR_AUTOINCREMENT=72 -GREATER_SYMBOL_AUTOINCREMENT=73 -WS_AUTOINCREMENT=74 +STDIN=59 +QUERY_PART=60 +GREATER_SYMBOL_QUERY=61 +WS_QUERY=62 +LESS_SYMBOL_QUERY=63 +STRING_OR_VAR_QUERY=64 +URI_VAR_QUERY=65 +WS_DECLARATION=66 +LESS_SYMBOL_AUTOINCREMENT=67 +TO=68 +BY=69 +ADD_AUTOINCREMENT=70 +DIGITS=71 +STRING_OR_VAR_AUTOINCREMENT=72 +STRINGOPERATOR_AUTOINCREMENT=73 +GREATER_SYMBOL_AUTOINCREMENT=74 +WS_AUTOINCREMENT=75 '['=25 '[['=26 ']'=27 diff --git a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.g4 b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.g4 index 6981b57..e6badb3 100644 --- a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.g4 +++ b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.g4 @@ -9,7 +9,7 @@ options{tokenVocab=ShExMLLexer;} shExML: decl* (shape | graph)* ; decl: (source | prefix | query | expression | matcher | iterator | autoincrement | functions) ; prefix: PREFIX variable LESS_SYMBOL_QUERY URL GREATER_SYMBOL_QUERY ; -source: SOURCE variable LESS_SYMBOL_QUERY (URL | JDBC_URL | QUERY_PART) GREATER_SYMBOL_QUERY ; +source: SOURCE variable LESS_SYMBOL_QUERY (URL | JDBC_URL | QUERY_PART | STDIN) GREATER_SYMBOL_QUERY ; query: QUERY variable LESS_SYMBOL_QUERY (URL | queryClause) GREATER_SYMBOL_QUERY ; functions: FUNCTIONS variable LESS_SYMBOL_QUERY SCALA (URL | QUERY_PART) GREATER_SYMBOL_QUERY ; iterator: ITERATOR variable LESS_SYMBOL_QUERY (queryClause | QUERY_PART+) GREATER_SYMBOL_QUERY '{' (field | nestedIterator)* '}' ; diff --git a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.interp b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.interp index 410e952..9320e8d 100644 --- a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.interp +++ b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.interp @@ -74,6 +74,7 @@ null null null null +null token symbolic names: null @@ -135,6 +136,7 @@ CSVPERROW SQL SCALA SPARQL +STDIN QUERY_PART GREATER_SYMBOL_QUERY WS_QUERY @@ -202,4 +204,4 @@ variable atn: -[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 76, 470, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 3, 2, 7, 2, 96, 10, 2, 12, 2, 14, 2, 99, 11, 2, 3, 2, 3, 2, 7, 2, 103, 10, 2, 12, 2, 14, 2, 106, 11, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 116, 10, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 135, 10, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 6, 8, 151, 10, 8, 13, 8, 14, 8, 152, 5, 8, 155, 10, 8, 3, 8, 3, 8, 3, 8, 3, 8, 7, 8, 161, 10, 8, 12, 8, 14, 8, 164, 11, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 6, 9, 172, 10, 9, 13, 9, 14, 9, 173, 3, 9, 3, 9, 3, 9, 3, 9, 7, 9, 180, 10, 9, 12, 9, 14, 9, 183, 11, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 6, 10, 191, 10, 10, 13, 10, 14, 10, 192, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 5, 11, 202, 10, 11, 3, 11, 3, 11, 3, 11, 5, 11, 207, 10, 11, 3, 11, 3, 11, 5, 11, 211, 10, 11, 3, 11, 3, 11, 5, 11, 215, 10, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 7, 14, 242, 10, 14, 12, 14, 14, 14, 245, 11, 14, 3, 15, 3, 15, 3, 15, 3, 15, 5, 15, 251, 10, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 5, 16, 258, 10, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 271, 10, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 5, 19, 278, 10, 19, 3, 20, 3, 20, 3, 21, 3, 21, 6, 21, 284, 10, 21, 13, 21, 14, 21, 285, 3, 21, 3, 21, 6, 21, 290, 10, 21, 13, 21, 14, 21, 291, 3, 21, 3, 21, 3, 21, 6, 21, 297, 10, 21, 13, 21, 14, 21, 298, 3, 21, 3, 21, 6, 21, 303, 10, 21, 13, 21, 14, 21, 304, 5, 21, 307, 10, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 5, 25, 329, 10, 25, 3, 26, 3, 26, 3, 26, 5, 26, 334, 10, 26, 3, 27, 3, 27, 3, 27, 6, 27, 339, 10, 27, 13, 27, 14, 27, 340, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 351, 10, 28, 12, 28, 14, 28, 354, 11, 28, 3, 28, 5, 28, 357, 10, 28, 3, 28, 3, 28, 3, 29, 3, 29, 5, 29, 363, 10, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 5, 31, 373, 10, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 5, 32, 381, 10, 32, 3, 33, 3, 33, 3, 33, 5, 33, 386, 10, 33, 3, 34, 5, 34, 389, 10, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 35, 5, 35, 397, 10, 35, 3, 35, 3, 35, 5, 35, 401, 10, 35, 3, 35, 3, 35, 5, 35, 405, 10, 35, 3, 35, 3, 35, 3, 35, 5, 35, 410, 10, 35, 3, 36, 3, 36, 3, 36, 5, 36, 415, 10, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 38, 3, 38, 5, 38, 426, 10, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 5, 38, 433, 10, 38, 5, 38, 435, 10, 38, 3, 39, 3, 39, 3, 40, 3, 40, 5, 40, 441, 10, 40, 3, 41, 3, 41, 3, 41, 5, 41, 446, 10, 41, 3, 42, 3, 42, 3, 43, 3, 43, 5, 43, 452, 10, 43, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 5, 45, 462, 10, 45, 3, 46, 3, 46, 5, 46, 466, 10, 46, 3, 47, 3, 47, 3, 47, 2, 3, 26, 48, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 2, 8, 4, 2, 53, 54, 61, 61, 4, 2, 53, 53, 61, 61, 3, 2, 8, 10, 4, 2, 45, 45, 47, 47, 3, 2, 21, 24, 5, 2, 45, 46, 65, 66, 73, 73, 2, 489, 2, 97, 3, 2, 2, 2, 4, 115, 3, 2, 2, 2, 6, 117, 3, 2, 2, 2, 8, 123, 3, 2, 2, 2, 10, 129, 3, 2, 2, 2, 12, 138, 3, 2, 2, 2, 14, 145, 3, 2, 2, 2, 16, 167, 3, 2, 2, 2, 18, 186, 3, 2, 2, 2, 20, 196, 3, 2, 2, 2, 22, 218, 3, 2, 2, 2, 24, 224, 3, 2, 2, 2, 26, 230, 3, 2, 2, 2, 28, 250, 3, 2, 2, 2, 30, 257, 3, 2, 2, 2, 32, 259, 3, 2, 2, 2, 34, 265, 3, 2, 2, 2, 36, 277, 3, 2, 2, 2, 38, 279, 3, 2, 2, 2, 40, 306, 3, 2, 2, 2, 42, 308, 3, 2, 2, 2, 44, 314, 3, 2, 2, 2, 46, 322, 3, 2, 2, 2, 48, 328, 3, 2, 2, 2, 50, 333, 3, 2, 2, 2, 52, 335, 3, 2, 2, 2, 54, 344, 3, 2, 2, 2, 56, 362, 3, 2, 2, 2, 58, 364, 3, 2, 2, 2, 60, 367, 3, 2, 2, 2, 62, 376, 3, 2, 2, 2, 64, 382, 3, 2, 2, 2, 66, 388, 3, 2, 2, 2, 68, 409, 3, 2, 2, 2, 70, 414, 3, 2, 2, 2, 72, 416, 3, 2, 2, 2, 74, 434, 3, 2, 2, 2, 76, 436, 3, 2, 2, 2, 78, 440, 3, 2, 2, 2, 80, 445, 3, 2, 2, 2, 82, 447, 3, 2, 2, 2, 84, 451, 3, 2, 2, 2, 86, 453, 3, 2, 2, 2, 88, 461, 3, 2, 2, 2, 90, 465, 3, 2, 2, 2, 92, 467, 3, 2, 2, 2, 94, 96, 5, 4, 3, 2, 95, 94, 3, 2, 2, 2, 96, 99, 3, 2, 2, 2, 97, 95, 3, 2, 2, 2, 97, 98, 3, 2, 2, 2, 98, 104, 3, 2, 2, 2, 99, 97, 3, 2, 2, 2, 100, 103, 5, 54, 28, 2, 101, 103, 5, 52, 27, 2, 102, 100, 3, 2, 2, 2, 102, 101, 3, 2, 2, 2, 103, 106, 3, 2, 2, 2, 104, 102, 3, 2, 2, 2, 104, 105, 3, 2, 2, 2, 105, 3, 3, 2, 2, 2, 106, 104, 3, 2, 2, 2, 107, 116, 5, 8, 5, 2, 108, 116, 5, 6, 4, 2, 109, 116, 5, 10, 6, 2, 110, 116, 5, 22, 12, 2, 111, 116, 5, 24, 13, 2, 112, 116, 5, 14, 8, 2, 113, 116, 5, 20, 11, 2, 114, 116, 5, 12, 7, 2, 115, 107, 3, 2, 2, 2, 115, 108, 3, 2, 2, 2, 115, 109, 3, 2, 2, 2, 115, 110, 3, 2, 2, 2, 115, 111, 3, 2, 2, 2, 115, 112, 3, 2, 2, 2, 115, 113, 3, 2, 2, 2, 115, 114, 3, 2, 2, 2, 116, 5, 3, 2, 2, 2, 117, 118, 7, 3, 2, 2, 118, 119, 5, 92, 47, 2, 119, 120, 7, 64, 2, 2, 120, 121, 7, 53, 2, 2, 121, 122, 7, 62, 2, 2, 122, 7, 3, 2, 2, 2, 123, 124, 7, 4, 2, 2, 124, 125, 5, 92, 47, 2, 125, 126, 7, 64, 2, 2, 126, 127, 9, 2, 2, 2, 127, 128, 7, 62, 2, 2, 128, 9, 3, 2, 2, 2, 129, 130, 7, 5, 2, 2, 130, 131, 5, 92, 47, 2, 131, 134, 7, 64, 2, 2, 132, 135, 7, 53, 2, 2, 133, 135, 5, 40, 21, 2, 134, 132, 3, 2, 2, 2, 134, 133, 3, 2, 2, 2, 135, 136, 3, 2, 2, 2, 136, 137, 7, 62, 2, 2, 137, 11, 3, 2, 2, 2, 138, 139, 7, 7, 2, 2, 139, 140, 5, 92, 47, 2, 140, 141, 7, 64, 2, 2, 141, 142, 7, 59, 2, 2, 142, 143, 9, 3, 2, 2, 143, 144, 7, 62, 2, 2, 144, 13, 3, 2, 2, 2, 145, 146, 7, 6, 2, 2, 146, 147, 5, 92, 47, 2, 147, 154, 7, 64, 2, 2, 148, 155, 5, 40, 21, 2, 149, 151, 7, 61, 2, 2, 150, 149, 3, 2, 2, 2, 151, 152, 3, 2, 2, 2, 152, 150, 3, 2, 2, 2, 152, 153, 3, 2, 2, 2, 153, 155, 3, 2, 2, 2, 154, 148, 3, 2, 2, 2, 154, 150, 3, 2, 2, 2, 155, 156, 3, 2, 2, 2, 156, 157, 7, 62, 2, 2, 157, 162, 7, 33, 2, 2, 158, 161, 5, 18, 10, 2, 159, 161, 5, 16, 9, 2, 160, 158, 3, 2, 2, 2, 160, 159, 3, 2, 2, 2, 161, 164, 3, 2, 2, 2, 162, 160, 3, 2, 2, 2, 162, 163, 3, 2, 2, 2, 163, 165, 3, 2, 2, 2, 164, 162, 3, 2, 2, 2, 165, 166, 7, 34, 2, 2, 166, 15, 3, 2, 2, 2, 167, 168, 7, 6, 2, 2, 168, 169, 5, 92, 47, 2, 169, 171, 7, 64, 2, 2, 170, 172, 7, 61, 2, 2, 171, 170, 3, 2, 2, 2, 172, 173, 3, 2, 2, 2, 173, 171, 3, 2, 2, 2, 173, 174, 3, 2, 2, 2, 174, 175, 3, 2, 2, 2, 175, 176, 7, 62, 2, 2, 176, 181, 7, 33, 2, 2, 177, 180, 5, 18, 10, 2, 178, 180, 5, 16, 9, 2, 179, 177, 3, 2, 2, 2, 179, 178, 3, 2, 2, 2, 180, 183, 3, 2, 2, 2, 181, 179, 3, 2, 2, 2, 181, 182, 3, 2, 2, 2, 182, 184, 3, 2, 2, 2, 183, 181, 3, 2, 2, 2, 184, 185, 7, 34, 2, 2, 185, 17, 3, 2, 2, 2, 186, 187, 9, 4, 2, 2, 187, 188, 5, 92, 47, 2, 188, 190, 7, 64, 2, 2, 189, 191, 7, 61, 2, 2, 190, 189, 3, 2, 2, 2, 191, 192, 3, 2, 2, 2, 192, 190, 3, 2, 2, 2, 192, 193, 3, 2, 2, 2, 193, 194, 3, 2, 2, 2, 194, 195, 7, 62, 2, 2, 195, 19, 3, 2, 2, 2, 196, 197, 7, 11, 2, 2, 197, 198, 5, 92, 47, 2, 198, 201, 7, 68, 2, 2, 199, 200, 7, 74, 2, 2, 200, 202, 7, 71, 2, 2, 201, 199, 3, 2, 2, 2, 201, 202, 3, 2, 2, 2, 202, 203, 3, 2, 2, 2, 203, 206, 7, 72, 2, 2, 204, 205, 7, 69, 2, 2, 205, 207, 7, 72, 2, 2, 206, 204, 3, 2, 2, 2, 206, 207, 3, 2, 2, 2, 207, 210, 3, 2, 2, 2, 208, 209, 7, 70, 2, 2, 209, 211, 7, 72, 2, 2, 210, 208, 3, 2, 2, 2, 210, 211, 3, 2, 2, 2, 211, 214, 3, 2, 2, 2, 212, 213, 7, 71, 2, 2, 213, 215, 7, 74, 2, 2, 214, 212, 3, 2, 2, 2, 214, 215, 3, 2, 2, 2, 215, 216, 3, 2, 2, 2, 216, 217, 7, 75, 2, 2, 217, 21, 3, 2, 2, 2, 218, 219, 7, 12, 2, 2, 219, 220, 5, 92, 47, 2, 220, 221, 7, 25, 2, 2, 221, 222, 5, 30, 16, 2, 222, 223, 7, 26, 2, 2, 223, 23, 3, 2, 2, 2, 224, 225, 7, 16, 2, 2, 225, 226, 5, 92, 47, 2, 226, 227, 7, 25, 2, 2, 227, 228, 5, 26, 14, 2, 228, 229, 7, 26, 2, 2, 229, 25, 3, 2, 2, 2, 230, 231, 8, 14, 1, 2, 231, 232, 5, 28, 15, 2, 232, 233, 7, 17, 2, 2, 233, 234, 9, 5, 2, 2, 234, 243, 3, 2, 2, 2, 235, 236, 12, 3, 2, 2, 236, 237, 7, 40, 2, 2, 237, 238, 5, 28, 15, 2, 238, 239, 7, 17, 2, 2, 239, 240, 9, 5, 2, 2, 240, 242, 3, 2, 2, 2, 241, 235, 3, 2, 2, 2, 242, 245, 3, 2, 2, 2, 243, 241, 3, 2, 2, 2, 243, 244, 3, 2, 2, 2, 244, 27, 3, 2, 2, 2, 245, 243, 3, 2, 2, 2, 246, 247, 9, 5, 2, 2, 247, 248, 7, 38, 2, 2, 248, 251, 5, 28, 15, 2, 249, 251, 9, 5, 2, 2, 250, 246, 3, 2, 2, 2, 250, 249, 3, 2, 2, 2, 251, 29, 3, 2, 2, 2, 252, 258, 5, 46, 24, 2, 253, 258, 5, 44, 23, 2, 254, 258, 5, 42, 22, 2, 255, 258, 5, 32, 17, 2, 256, 258, 5, 34, 18, 2, 257, 252, 3, 2, 2, 2, 257, 253, 3, 2, 2, 2, 257, 254, 3, 2, 2, 2, 257, 255, 3, 2, 2, 2, 257, 256, 3, 2, 2, 2, 258, 31, 3, 2, 2, 2, 259, 260, 5, 34, 18, 2, 260, 261, 7, 37, 2, 2, 261, 262, 7, 47, 2, 2, 262, 263, 7, 37, 2, 2, 263, 264, 5, 34, 18, 2, 264, 33, 3, 2, 2, 2, 265, 266, 5, 92, 47, 2, 266, 267, 7, 36, 2, 2, 267, 270, 5, 36, 19, 2, 268, 269, 7, 36, 2, 2, 269, 271, 5, 38, 20, 2, 270, 268, 3, 2, 2, 2, 270, 271, 3, 2, 2, 2, 271, 35, 3, 2, 2, 2, 272, 278, 5, 92, 47, 2, 273, 274, 5, 92, 47, 2, 274, 275, 7, 36, 2, 2, 275, 276, 5, 36, 19, 2, 276, 278, 3, 2, 2, 2, 277, 272, 3, 2, 2, 2, 277, 273, 3, 2, 2, 2, 278, 37, 3, 2, 2, 2, 279, 280, 7, 44, 2, 2, 280, 39, 3, 2, 2, 2, 281, 283, 7, 55, 2, 2, 282, 284, 7, 61, 2, 2, 283, 282, 3, 2, 2, 2, 284, 285, 3, 2, 2, 2, 285, 283, 3, 2, 2, 2, 285, 286, 3, 2, 2, 2, 286, 307, 3, 2, 2, 2, 287, 289, 7, 56, 2, 2, 288, 290, 7, 61, 2, 2, 289, 288, 3, 2, 2, 2, 290, 291, 3, 2, 2, 2, 291, 289, 3, 2, 2, 2, 291, 292, 3, 2, 2, 2, 292, 307, 3, 2, 2, 2, 293, 307, 7, 57, 2, 2, 294, 296, 7, 58, 2, 2, 295, 297, 7, 61, 2, 2, 296, 295, 3, 2, 2, 2, 297, 298, 3, 2, 2, 2, 298, 296, 3, 2, 2, 2, 298, 299, 3, 2, 2, 2, 299, 307, 3, 2, 2, 2, 300, 302, 7, 60, 2, 2, 301, 303, 7, 61, 2, 2, 302, 301, 3, 2, 2, 2, 303, 304, 3, 2, 2, 2, 304, 302, 3, 2, 2, 2, 304, 305, 3, 2, 2, 2, 305, 307, 3, 2, 2, 2, 306, 281, 3, 2, 2, 2, 306, 287, 3, 2, 2, 2, 306, 293, 3, 2, 2, 2, 306, 294, 3, 2, 2, 2, 306, 300, 3, 2, 2, 2, 307, 41, 3, 2, 2, 2, 308, 309, 5, 34, 18, 2, 309, 310, 7, 13, 2, 2, 310, 311, 5, 34, 18, 2, 311, 312, 7, 15, 2, 2, 312, 313, 5, 34, 18, 2, 313, 43, 3, 2, 2, 2, 314, 315, 5, 34, 18, 2, 315, 316, 7, 14, 2, 2, 316, 317, 5, 34, 18, 2, 317, 318, 7, 19, 2, 2, 318, 319, 5, 34, 18, 2, 319, 320, 7, 43, 2, 2, 320, 321, 5, 34, 18, 2, 321, 45, 3, 2, 2, 2, 322, 323, 5, 48, 25, 2, 323, 324, 7, 13, 2, 2, 324, 325, 5, 50, 26, 2, 325, 47, 3, 2, 2, 2, 326, 329, 5, 34, 18, 2, 327, 329, 5, 32, 17, 2, 328, 326, 3, 2, 2, 2, 328, 327, 3, 2, 2, 2, 329, 49, 3, 2, 2, 2, 330, 334, 5, 34, 18, 2, 331, 334, 5, 46, 24, 2, 332, 334, 5, 32, 17, 2, 333, 330, 3, 2, 2, 2, 333, 331, 3, 2, 2, 2, 333, 332, 3, 2, 2, 2, 334, 51, 3, 2, 2, 2, 335, 336, 5, 86, 44, 2, 336, 338, 7, 28, 2, 2, 337, 339, 5, 54, 28, 2, 338, 337, 3, 2, 2, 2, 339, 340, 3, 2, 2, 2, 340, 338, 3, 2, 2, 2, 340, 341, 3, 2, 2, 2, 341, 342, 3, 2, 2, 2, 342, 343, 7, 30, 2, 2, 343, 53, 3, 2, 2, 2, 344, 345, 5, 88, 45, 2, 345, 346, 5, 56, 29, 2, 346, 352, 7, 33, 2, 2, 347, 348, 5, 62, 32, 2, 348, 349, 7, 35, 2, 2, 349, 351, 3, 2, 2, 2, 350, 347, 3, 2, 2, 2, 351, 354, 3, 2, 2, 2, 352, 350, 3, 2, 2, 2, 352, 353, 3, 2, 2, 2, 353, 356, 3, 2, 2, 2, 354, 352, 3, 2, 2, 2, 355, 357, 5, 62, 32, 2, 356, 355, 3, 2, 2, 2, 356, 357, 3, 2, 2, 2, 357, 358, 3, 2, 2, 2, 358, 359, 7, 34, 2, 2, 359, 55, 3, 2, 2, 2, 360, 363, 5, 60, 31, 2, 361, 363, 5, 58, 30, 2, 362, 360, 3, 2, 2, 2, 362, 361, 3, 2, 2, 2, 363, 57, 3, 2, 2, 2, 364, 365, 5, 90, 46, 2, 365, 366, 5, 92, 47, 2, 366, 59, 3, 2, 2, 2, 367, 368, 5, 90, 46, 2, 368, 369, 7, 27, 2, 2, 369, 372, 5, 70, 36, 2, 370, 371, 7, 18, 2, 2, 371, 373, 5, 70, 36, 2, 372, 370, 3, 2, 2, 2, 372, 373, 3, 2, 2, 2, 373, 374, 3, 2, 2, 2, 374, 375, 7, 29, 2, 2, 375, 61, 3, 2, 2, 2, 376, 380, 5, 84, 43, 2, 377, 381, 5, 64, 33, 2, 378, 381, 5, 82, 42, 2, 379, 381, 5, 86, 44, 2, 380, 377, 3, 2, 2, 2, 380, 378, 3, 2, 2, 2, 380, 379, 3, 2, 2, 2, 381, 63, 3, 2, 2, 2, 382, 385, 5, 66, 34, 2, 383, 386, 5, 78, 40, 2, 384, 386, 5, 80, 41, 2, 385, 383, 3, 2, 2, 2, 385, 384, 3, 2, 2, 2, 385, 386, 3, 2, 2, 2, 386, 65, 3, 2, 2, 2, 387, 389, 5, 90, 46, 2, 388, 387, 3, 2, 2, 2, 388, 389, 3, 2, 2, 2, 389, 390, 3, 2, 2, 2, 390, 391, 5, 68, 35, 2, 391, 67, 3, 2, 2, 2, 392, 393, 7, 27, 2, 2, 393, 396, 5, 70, 36, 2, 394, 395, 7, 20, 2, 2, 395, 397, 5, 92, 47, 2, 396, 394, 3, 2, 2, 2, 396, 397, 3, 2, 2, 2, 397, 400, 3, 2, 2, 2, 398, 399, 7, 18, 2, 2, 399, 401, 5, 70, 36, 2, 400, 398, 3, 2, 2, 2, 400, 401, 3, 2, 2, 2, 401, 404, 3, 2, 2, 2, 402, 403, 7, 17, 2, 2, 403, 405, 5, 76, 39, 2, 404, 402, 3, 2, 2, 2, 404, 405, 3, 2, 2, 2, 405, 406, 3, 2, 2, 2, 406, 407, 7, 29, 2, 2, 407, 410, 3, 2, 2, 2, 408, 410, 7, 47, 2, 2, 409, 392, 3, 2, 2, 2, 409, 408, 3, 2, 2, 2, 410, 69, 3, 2, 2, 2, 411, 415, 5, 30, 16, 2, 412, 415, 5, 92, 47, 2, 413, 415, 5, 72, 37, 2, 414, 411, 3, 2, 2, 2, 414, 412, 3, 2, 2, 2, 414, 413, 3, 2, 2, 2, 415, 71, 3, 2, 2, 2, 416, 417, 5, 92, 47, 2, 417, 418, 7, 36, 2, 2, 418, 419, 5, 92, 47, 2, 419, 420, 7, 31, 2, 2, 420, 421, 5, 74, 38, 2, 421, 422, 7, 32, 2, 2, 422, 73, 3, 2, 2, 2, 423, 426, 5, 30, 16, 2, 424, 426, 5, 92, 47, 2, 425, 423, 3, 2, 2, 2, 425, 424, 3, 2, 2, 2, 426, 427, 3, 2, 2, 2, 427, 428, 7, 38, 2, 2, 428, 429, 5, 74, 38, 2, 429, 435, 3, 2, 2, 2, 430, 433, 5, 30, 16, 2, 431, 433, 5, 92, 47, 2, 432, 430, 3, 2, 2, 2, 432, 431, 3, 2, 2, 2, 433, 435, 3, 2, 2, 2, 434, 425, 3, 2, 2, 2, 434, 432, 3, 2, 2, 2, 435, 75, 3, 2, 2, 2, 436, 437, 9, 6, 2, 2, 437, 77, 3, 2, 2, 2, 438, 441, 7, 48, 2, 2, 439, 441, 5, 66, 34, 2, 440, 438, 3, 2, 2, 2, 440, 439, 3, 2, 2, 2, 441, 79, 3, 2, 2, 2, 442, 446, 7, 50, 2, 2, 443, 444, 7, 42, 2, 2, 444, 446, 5, 68, 35, 2, 445, 442, 3, 2, 2, 2, 445, 443, 3, 2, 2, 2, 446, 81, 3, 2, 2, 2, 447, 448, 7, 49, 2, 2, 448, 83, 3, 2, 2, 2, 449, 452, 5, 86, 44, 2, 450, 452, 7, 41, 2, 2, 451, 449, 3, 2, 2, 2, 451, 450, 3, 2, 2, 2, 452, 85, 3, 2, 2, 2, 453, 454, 5, 90, 46, 2, 454, 455, 5, 92, 47, 2, 455, 87, 3, 2, 2, 2, 456, 462, 5, 84, 43, 2, 457, 458, 7, 25, 2, 2, 458, 459, 5, 92, 47, 2, 459, 460, 7, 26, 2, 2, 460, 462, 3, 2, 2, 2, 461, 456, 3, 2, 2, 2, 461, 457, 3, 2, 2, 2, 462, 89, 3, 2, 2, 2, 463, 466, 5, 92, 47, 2, 464, 466, 7, 53, 2, 2, 465, 463, 3, 2, 2, 2, 465, 464, 3, 2, 2, 2, 466, 91, 3, 2, 2, 2, 467, 468, 9, 7, 2, 2, 468, 93, 3, 2, 2, 2, 52, 97, 102, 104, 115, 134, 152, 154, 160, 162, 173, 179, 181, 192, 201, 206, 210, 214, 243, 250, 257, 270, 277, 285, 291, 298, 304, 306, 328, 333, 340, 352, 356, 362, 372, 380, 385, 388, 396, 400, 404, 409, 414, 425, 432, 434, 440, 445, 451, 461, 465] \ No newline at end of file +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 77, 470, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 3, 2, 7, 2, 96, 10, 2, 12, 2, 14, 2, 99, 11, 2, 3, 2, 3, 2, 7, 2, 103, 10, 2, 12, 2, 14, 2, 106, 11, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 116, 10, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 135, 10, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 6, 8, 151, 10, 8, 13, 8, 14, 8, 152, 5, 8, 155, 10, 8, 3, 8, 3, 8, 3, 8, 3, 8, 7, 8, 161, 10, 8, 12, 8, 14, 8, 164, 11, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 6, 9, 172, 10, 9, 13, 9, 14, 9, 173, 3, 9, 3, 9, 3, 9, 3, 9, 7, 9, 180, 10, 9, 12, 9, 14, 9, 183, 11, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 6, 10, 191, 10, 10, 13, 10, 14, 10, 192, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 5, 11, 202, 10, 11, 3, 11, 3, 11, 3, 11, 5, 11, 207, 10, 11, 3, 11, 3, 11, 5, 11, 211, 10, 11, 3, 11, 3, 11, 5, 11, 215, 10, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 7, 14, 242, 10, 14, 12, 14, 14, 14, 245, 11, 14, 3, 15, 3, 15, 3, 15, 3, 15, 5, 15, 251, 10, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 5, 16, 258, 10, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 271, 10, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 5, 19, 278, 10, 19, 3, 20, 3, 20, 3, 21, 3, 21, 6, 21, 284, 10, 21, 13, 21, 14, 21, 285, 3, 21, 3, 21, 6, 21, 290, 10, 21, 13, 21, 14, 21, 291, 3, 21, 3, 21, 3, 21, 6, 21, 297, 10, 21, 13, 21, 14, 21, 298, 3, 21, 3, 21, 6, 21, 303, 10, 21, 13, 21, 14, 21, 304, 5, 21, 307, 10, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 5, 25, 329, 10, 25, 3, 26, 3, 26, 3, 26, 5, 26, 334, 10, 26, 3, 27, 3, 27, 3, 27, 6, 27, 339, 10, 27, 13, 27, 14, 27, 340, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 351, 10, 28, 12, 28, 14, 28, 354, 11, 28, 3, 28, 5, 28, 357, 10, 28, 3, 28, 3, 28, 3, 29, 3, 29, 5, 29, 363, 10, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 5, 31, 373, 10, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 5, 32, 381, 10, 32, 3, 33, 3, 33, 3, 33, 5, 33, 386, 10, 33, 3, 34, 5, 34, 389, 10, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 35, 5, 35, 397, 10, 35, 3, 35, 3, 35, 5, 35, 401, 10, 35, 3, 35, 3, 35, 5, 35, 405, 10, 35, 3, 35, 3, 35, 3, 35, 5, 35, 410, 10, 35, 3, 36, 3, 36, 3, 36, 5, 36, 415, 10, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 38, 3, 38, 5, 38, 426, 10, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 5, 38, 433, 10, 38, 5, 38, 435, 10, 38, 3, 39, 3, 39, 3, 40, 3, 40, 5, 40, 441, 10, 40, 3, 41, 3, 41, 3, 41, 5, 41, 446, 10, 41, 3, 42, 3, 42, 3, 43, 3, 43, 5, 43, 452, 10, 43, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 5, 45, 462, 10, 45, 3, 46, 3, 46, 5, 46, 466, 10, 46, 3, 47, 3, 47, 3, 47, 2, 3, 26, 48, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 2, 8, 4, 2, 53, 54, 61, 62, 4, 2, 53, 53, 62, 62, 3, 2, 8, 10, 4, 2, 45, 45, 47, 47, 3, 2, 21, 24, 5, 2, 45, 46, 66, 67, 74, 74, 2, 489, 2, 97, 3, 2, 2, 2, 4, 115, 3, 2, 2, 2, 6, 117, 3, 2, 2, 2, 8, 123, 3, 2, 2, 2, 10, 129, 3, 2, 2, 2, 12, 138, 3, 2, 2, 2, 14, 145, 3, 2, 2, 2, 16, 167, 3, 2, 2, 2, 18, 186, 3, 2, 2, 2, 20, 196, 3, 2, 2, 2, 22, 218, 3, 2, 2, 2, 24, 224, 3, 2, 2, 2, 26, 230, 3, 2, 2, 2, 28, 250, 3, 2, 2, 2, 30, 257, 3, 2, 2, 2, 32, 259, 3, 2, 2, 2, 34, 265, 3, 2, 2, 2, 36, 277, 3, 2, 2, 2, 38, 279, 3, 2, 2, 2, 40, 306, 3, 2, 2, 2, 42, 308, 3, 2, 2, 2, 44, 314, 3, 2, 2, 2, 46, 322, 3, 2, 2, 2, 48, 328, 3, 2, 2, 2, 50, 333, 3, 2, 2, 2, 52, 335, 3, 2, 2, 2, 54, 344, 3, 2, 2, 2, 56, 362, 3, 2, 2, 2, 58, 364, 3, 2, 2, 2, 60, 367, 3, 2, 2, 2, 62, 376, 3, 2, 2, 2, 64, 382, 3, 2, 2, 2, 66, 388, 3, 2, 2, 2, 68, 409, 3, 2, 2, 2, 70, 414, 3, 2, 2, 2, 72, 416, 3, 2, 2, 2, 74, 434, 3, 2, 2, 2, 76, 436, 3, 2, 2, 2, 78, 440, 3, 2, 2, 2, 80, 445, 3, 2, 2, 2, 82, 447, 3, 2, 2, 2, 84, 451, 3, 2, 2, 2, 86, 453, 3, 2, 2, 2, 88, 461, 3, 2, 2, 2, 90, 465, 3, 2, 2, 2, 92, 467, 3, 2, 2, 2, 94, 96, 5, 4, 3, 2, 95, 94, 3, 2, 2, 2, 96, 99, 3, 2, 2, 2, 97, 95, 3, 2, 2, 2, 97, 98, 3, 2, 2, 2, 98, 104, 3, 2, 2, 2, 99, 97, 3, 2, 2, 2, 100, 103, 5, 54, 28, 2, 101, 103, 5, 52, 27, 2, 102, 100, 3, 2, 2, 2, 102, 101, 3, 2, 2, 2, 103, 106, 3, 2, 2, 2, 104, 102, 3, 2, 2, 2, 104, 105, 3, 2, 2, 2, 105, 3, 3, 2, 2, 2, 106, 104, 3, 2, 2, 2, 107, 116, 5, 8, 5, 2, 108, 116, 5, 6, 4, 2, 109, 116, 5, 10, 6, 2, 110, 116, 5, 22, 12, 2, 111, 116, 5, 24, 13, 2, 112, 116, 5, 14, 8, 2, 113, 116, 5, 20, 11, 2, 114, 116, 5, 12, 7, 2, 115, 107, 3, 2, 2, 2, 115, 108, 3, 2, 2, 2, 115, 109, 3, 2, 2, 2, 115, 110, 3, 2, 2, 2, 115, 111, 3, 2, 2, 2, 115, 112, 3, 2, 2, 2, 115, 113, 3, 2, 2, 2, 115, 114, 3, 2, 2, 2, 116, 5, 3, 2, 2, 2, 117, 118, 7, 3, 2, 2, 118, 119, 5, 92, 47, 2, 119, 120, 7, 65, 2, 2, 120, 121, 7, 53, 2, 2, 121, 122, 7, 63, 2, 2, 122, 7, 3, 2, 2, 2, 123, 124, 7, 4, 2, 2, 124, 125, 5, 92, 47, 2, 125, 126, 7, 65, 2, 2, 126, 127, 9, 2, 2, 2, 127, 128, 7, 63, 2, 2, 128, 9, 3, 2, 2, 2, 129, 130, 7, 5, 2, 2, 130, 131, 5, 92, 47, 2, 131, 134, 7, 65, 2, 2, 132, 135, 7, 53, 2, 2, 133, 135, 5, 40, 21, 2, 134, 132, 3, 2, 2, 2, 134, 133, 3, 2, 2, 2, 135, 136, 3, 2, 2, 2, 136, 137, 7, 63, 2, 2, 137, 11, 3, 2, 2, 2, 138, 139, 7, 7, 2, 2, 139, 140, 5, 92, 47, 2, 140, 141, 7, 65, 2, 2, 141, 142, 7, 59, 2, 2, 142, 143, 9, 3, 2, 2, 143, 144, 7, 63, 2, 2, 144, 13, 3, 2, 2, 2, 145, 146, 7, 6, 2, 2, 146, 147, 5, 92, 47, 2, 147, 154, 7, 65, 2, 2, 148, 155, 5, 40, 21, 2, 149, 151, 7, 62, 2, 2, 150, 149, 3, 2, 2, 2, 151, 152, 3, 2, 2, 2, 152, 150, 3, 2, 2, 2, 152, 153, 3, 2, 2, 2, 153, 155, 3, 2, 2, 2, 154, 148, 3, 2, 2, 2, 154, 150, 3, 2, 2, 2, 155, 156, 3, 2, 2, 2, 156, 157, 7, 63, 2, 2, 157, 162, 7, 33, 2, 2, 158, 161, 5, 18, 10, 2, 159, 161, 5, 16, 9, 2, 160, 158, 3, 2, 2, 2, 160, 159, 3, 2, 2, 2, 161, 164, 3, 2, 2, 2, 162, 160, 3, 2, 2, 2, 162, 163, 3, 2, 2, 2, 163, 165, 3, 2, 2, 2, 164, 162, 3, 2, 2, 2, 165, 166, 7, 34, 2, 2, 166, 15, 3, 2, 2, 2, 167, 168, 7, 6, 2, 2, 168, 169, 5, 92, 47, 2, 169, 171, 7, 65, 2, 2, 170, 172, 7, 62, 2, 2, 171, 170, 3, 2, 2, 2, 172, 173, 3, 2, 2, 2, 173, 171, 3, 2, 2, 2, 173, 174, 3, 2, 2, 2, 174, 175, 3, 2, 2, 2, 175, 176, 7, 63, 2, 2, 176, 181, 7, 33, 2, 2, 177, 180, 5, 18, 10, 2, 178, 180, 5, 16, 9, 2, 179, 177, 3, 2, 2, 2, 179, 178, 3, 2, 2, 2, 180, 183, 3, 2, 2, 2, 181, 179, 3, 2, 2, 2, 181, 182, 3, 2, 2, 2, 182, 184, 3, 2, 2, 2, 183, 181, 3, 2, 2, 2, 184, 185, 7, 34, 2, 2, 185, 17, 3, 2, 2, 2, 186, 187, 9, 4, 2, 2, 187, 188, 5, 92, 47, 2, 188, 190, 7, 65, 2, 2, 189, 191, 7, 62, 2, 2, 190, 189, 3, 2, 2, 2, 191, 192, 3, 2, 2, 2, 192, 190, 3, 2, 2, 2, 192, 193, 3, 2, 2, 2, 193, 194, 3, 2, 2, 2, 194, 195, 7, 63, 2, 2, 195, 19, 3, 2, 2, 2, 196, 197, 7, 11, 2, 2, 197, 198, 5, 92, 47, 2, 198, 201, 7, 69, 2, 2, 199, 200, 7, 75, 2, 2, 200, 202, 7, 72, 2, 2, 201, 199, 3, 2, 2, 2, 201, 202, 3, 2, 2, 2, 202, 203, 3, 2, 2, 2, 203, 206, 7, 73, 2, 2, 204, 205, 7, 70, 2, 2, 205, 207, 7, 73, 2, 2, 206, 204, 3, 2, 2, 2, 206, 207, 3, 2, 2, 2, 207, 210, 3, 2, 2, 2, 208, 209, 7, 71, 2, 2, 209, 211, 7, 73, 2, 2, 210, 208, 3, 2, 2, 2, 210, 211, 3, 2, 2, 2, 211, 214, 3, 2, 2, 2, 212, 213, 7, 72, 2, 2, 213, 215, 7, 75, 2, 2, 214, 212, 3, 2, 2, 2, 214, 215, 3, 2, 2, 2, 215, 216, 3, 2, 2, 2, 216, 217, 7, 76, 2, 2, 217, 21, 3, 2, 2, 2, 218, 219, 7, 12, 2, 2, 219, 220, 5, 92, 47, 2, 220, 221, 7, 25, 2, 2, 221, 222, 5, 30, 16, 2, 222, 223, 7, 26, 2, 2, 223, 23, 3, 2, 2, 2, 224, 225, 7, 16, 2, 2, 225, 226, 5, 92, 47, 2, 226, 227, 7, 25, 2, 2, 227, 228, 5, 26, 14, 2, 228, 229, 7, 26, 2, 2, 229, 25, 3, 2, 2, 2, 230, 231, 8, 14, 1, 2, 231, 232, 5, 28, 15, 2, 232, 233, 7, 17, 2, 2, 233, 234, 9, 5, 2, 2, 234, 243, 3, 2, 2, 2, 235, 236, 12, 3, 2, 2, 236, 237, 7, 40, 2, 2, 237, 238, 5, 28, 15, 2, 238, 239, 7, 17, 2, 2, 239, 240, 9, 5, 2, 2, 240, 242, 3, 2, 2, 2, 241, 235, 3, 2, 2, 2, 242, 245, 3, 2, 2, 2, 243, 241, 3, 2, 2, 2, 243, 244, 3, 2, 2, 2, 244, 27, 3, 2, 2, 2, 245, 243, 3, 2, 2, 2, 246, 247, 9, 5, 2, 2, 247, 248, 7, 38, 2, 2, 248, 251, 5, 28, 15, 2, 249, 251, 9, 5, 2, 2, 250, 246, 3, 2, 2, 2, 250, 249, 3, 2, 2, 2, 251, 29, 3, 2, 2, 2, 252, 258, 5, 46, 24, 2, 253, 258, 5, 44, 23, 2, 254, 258, 5, 42, 22, 2, 255, 258, 5, 32, 17, 2, 256, 258, 5, 34, 18, 2, 257, 252, 3, 2, 2, 2, 257, 253, 3, 2, 2, 2, 257, 254, 3, 2, 2, 2, 257, 255, 3, 2, 2, 2, 257, 256, 3, 2, 2, 2, 258, 31, 3, 2, 2, 2, 259, 260, 5, 34, 18, 2, 260, 261, 7, 37, 2, 2, 261, 262, 7, 47, 2, 2, 262, 263, 7, 37, 2, 2, 263, 264, 5, 34, 18, 2, 264, 33, 3, 2, 2, 2, 265, 266, 5, 92, 47, 2, 266, 267, 7, 36, 2, 2, 267, 270, 5, 36, 19, 2, 268, 269, 7, 36, 2, 2, 269, 271, 5, 38, 20, 2, 270, 268, 3, 2, 2, 2, 270, 271, 3, 2, 2, 2, 271, 35, 3, 2, 2, 2, 272, 278, 5, 92, 47, 2, 273, 274, 5, 92, 47, 2, 274, 275, 7, 36, 2, 2, 275, 276, 5, 36, 19, 2, 276, 278, 3, 2, 2, 2, 277, 272, 3, 2, 2, 2, 277, 273, 3, 2, 2, 2, 278, 37, 3, 2, 2, 2, 279, 280, 7, 44, 2, 2, 280, 39, 3, 2, 2, 2, 281, 283, 7, 55, 2, 2, 282, 284, 7, 62, 2, 2, 283, 282, 3, 2, 2, 2, 284, 285, 3, 2, 2, 2, 285, 283, 3, 2, 2, 2, 285, 286, 3, 2, 2, 2, 286, 307, 3, 2, 2, 2, 287, 289, 7, 56, 2, 2, 288, 290, 7, 62, 2, 2, 289, 288, 3, 2, 2, 2, 290, 291, 3, 2, 2, 2, 291, 289, 3, 2, 2, 2, 291, 292, 3, 2, 2, 2, 292, 307, 3, 2, 2, 2, 293, 307, 7, 57, 2, 2, 294, 296, 7, 58, 2, 2, 295, 297, 7, 62, 2, 2, 296, 295, 3, 2, 2, 2, 297, 298, 3, 2, 2, 2, 298, 296, 3, 2, 2, 2, 298, 299, 3, 2, 2, 2, 299, 307, 3, 2, 2, 2, 300, 302, 7, 60, 2, 2, 301, 303, 7, 62, 2, 2, 302, 301, 3, 2, 2, 2, 303, 304, 3, 2, 2, 2, 304, 302, 3, 2, 2, 2, 304, 305, 3, 2, 2, 2, 305, 307, 3, 2, 2, 2, 306, 281, 3, 2, 2, 2, 306, 287, 3, 2, 2, 2, 306, 293, 3, 2, 2, 2, 306, 294, 3, 2, 2, 2, 306, 300, 3, 2, 2, 2, 307, 41, 3, 2, 2, 2, 308, 309, 5, 34, 18, 2, 309, 310, 7, 13, 2, 2, 310, 311, 5, 34, 18, 2, 311, 312, 7, 15, 2, 2, 312, 313, 5, 34, 18, 2, 313, 43, 3, 2, 2, 2, 314, 315, 5, 34, 18, 2, 315, 316, 7, 14, 2, 2, 316, 317, 5, 34, 18, 2, 317, 318, 7, 19, 2, 2, 318, 319, 5, 34, 18, 2, 319, 320, 7, 43, 2, 2, 320, 321, 5, 34, 18, 2, 321, 45, 3, 2, 2, 2, 322, 323, 5, 48, 25, 2, 323, 324, 7, 13, 2, 2, 324, 325, 5, 50, 26, 2, 325, 47, 3, 2, 2, 2, 326, 329, 5, 34, 18, 2, 327, 329, 5, 32, 17, 2, 328, 326, 3, 2, 2, 2, 328, 327, 3, 2, 2, 2, 329, 49, 3, 2, 2, 2, 330, 334, 5, 34, 18, 2, 331, 334, 5, 46, 24, 2, 332, 334, 5, 32, 17, 2, 333, 330, 3, 2, 2, 2, 333, 331, 3, 2, 2, 2, 333, 332, 3, 2, 2, 2, 334, 51, 3, 2, 2, 2, 335, 336, 5, 86, 44, 2, 336, 338, 7, 28, 2, 2, 337, 339, 5, 54, 28, 2, 338, 337, 3, 2, 2, 2, 339, 340, 3, 2, 2, 2, 340, 338, 3, 2, 2, 2, 340, 341, 3, 2, 2, 2, 341, 342, 3, 2, 2, 2, 342, 343, 7, 30, 2, 2, 343, 53, 3, 2, 2, 2, 344, 345, 5, 88, 45, 2, 345, 346, 5, 56, 29, 2, 346, 352, 7, 33, 2, 2, 347, 348, 5, 62, 32, 2, 348, 349, 7, 35, 2, 2, 349, 351, 3, 2, 2, 2, 350, 347, 3, 2, 2, 2, 351, 354, 3, 2, 2, 2, 352, 350, 3, 2, 2, 2, 352, 353, 3, 2, 2, 2, 353, 356, 3, 2, 2, 2, 354, 352, 3, 2, 2, 2, 355, 357, 5, 62, 32, 2, 356, 355, 3, 2, 2, 2, 356, 357, 3, 2, 2, 2, 357, 358, 3, 2, 2, 2, 358, 359, 7, 34, 2, 2, 359, 55, 3, 2, 2, 2, 360, 363, 5, 60, 31, 2, 361, 363, 5, 58, 30, 2, 362, 360, 3, 2, 2, 2, 362, 361, 3, 2, 2, 2, 363, 57, 3, 2, 2, 2, 364, 365, 5, 90, 46, 2, 365, 366, 5, 92, 47, 2, 366, 59, 3, 2, 2, 2, 367, 368, 5, 90, 46, 2, 368, 369, 7, 27, 2, 2, 369, 372, 5, 70, 36, 2, 370, 371, 7, 18, 2, 2, 371, 373, 5, 70, 36, 2, 372, 370, 3, 2, 2, 2, 372, 373, 3, 2, 2, 2, 373, 374, 3, 2, 2, 2, 374, 375, 7, 29, 2, 2, 375, 61, 3, 2, 2, 2, 376, 380, 5, 84, 43, 2, 377, 381, 5, 64, 33, 2, 378, 381, 5, 82, 42, 2, 379, 381, 5, 86, 44, 2, 380, 377, 3, 2, 2, 2, 380, 378, 3, 2, 2, 2, 380, 379, 3, 2, 2, 2, 381, 63, 3, 2, 2, 2, 382, 385, 5, 66, 34, 2, 383, 386, 5, 78, 40, 2, 384, 386, 5, 80, 41, 2, 385, 383, 3, 2, 2, 2, 385, 384, 3, 2, 2, 2, 385, 386, 3, 2, 2, 2, 386, 65, 3, 2, 2, 2, 387, 389, 5, 90, 46, 2, 388, 387, 3, 2, 2, 2, 388, 389, 3, 2, 2, 2, 389, 390, 3, 2, 2, 2, 390, 391, 5, 68, 35, 2, 391, 67, 3, 2, 2, 2, 392, 393, 7, 27, 2, 2, 393, 396, 5, 70, 36, 2, 394, 395, 7, 20, 2, 2, 395, 397, 5, 92, 47, 2, 396, 394, 3, 2, 2, 2, 396, 397, 3, 2, 2, 2, 397, 400, 3, 2, 2, 2, 398, 399, 7, 18, 2, 2, 399, 401, 5, 70, 36, 2, 400, 398, 3, 2, 2, 2, 400, 401, 3, 2, 2, 2, 401, 404, 3, 2, 2, 2, 402, 403, 7, 17, 2, 2, 403, 405, 5, 76, 39, 2, 404, 402, 3, 2, 2, 2, 404, 405, 3, 2, 2, 2, 405, 406, 3, 2, 2, 2, 406, 407, 7, 29, 2, 2, 407, 410, 3, 2, 2, 2, 408, 410, 7, 47, 2, 2, 409, 392, 3, 2, 2, 2, 409, 408, 3, 2, 2, 2, 410, 69, 3, 2, 2, 2, 411, 415, 5, 30, 16, 2, 412, 415, 5, 92, 47, 2, 413, 415, 5, 72, 37, 2, 414, 411, 3, 2, 2, 2, 414, 412, 3, 2, 2, 2, 414, 413, 3, 2, 2, 2, 415, 71, 3, 2, 2, 2, 416, 417, 5, 92, 47, 2, 417, 418, 7, 36, 2, 2, 418, 419, 5, 92, 47, 2, 419, 420, 7, 31, 2, 2, 420, 421, 5, 74, 38, 2, 421, 422, 7, 32, 2, 2, 422, 73, 3, 2, 2, 2, 423, 426, 5, 30, 16, 2, 424, 426, 5, 92, 47, 2, 425, 423, 3, 2, 2, 2, 425, 424, 3, 2, 2, 2, 426, 427, 3, 2, 2, 2, 427, 428, 7, 38, 2, 2, 428, 429, 5, 74, 38, 2, 429, 435, 3, 2, 2, 2, 430, 433, 5, 30, 16, 2, 431, 433, 5, 92, 47, 2, 432, 430, 3, 2, 2, 2, 432, 431, 3, 2, 2, 2, 433, 435, 3, 2, 2, 2, 434, 425, 3, 2, 2, 2, 434, 432, 3, 2, 2, 2, 435, 75, 3, 2, 2, 2, 436, 437, 9, 6, 2, 2, 437, 77, 3, 2, 2, 2, 438, 441, 7, 48, 2, 2, 439, 441, 5, 66, 34, 2, 440, 438, 3, 2, 2, 2, 440, 439, 3, 2, 2, 2, 441, 79, 3, 2, 2, 2, 442, 446, 7, 50, 2, 2, 443, 444, 7, 42, 2, 2, 444, 446, 5, 68, 35, 2, 445, 442, 3, 2, 2, 2, 445, 443, 3, 2, 2, 2, 446, 81, 3, 2, 2, 2, 447, 448, 7, 49, 2, 2, 448, 83, 3, 2, 2, 2, 449, 452, 5, 86, 44, 2, 450, 452, 7, 41, 2, 2, 451, 449, 3, 2, 2, 2, 451, 450, 3, 2, 2, 2, 452, 85, 3, 2, 2, 2, 453, 454, 5, 90, 46, 2, 454, 455, 5, 92, 47, 2, 455, 87, 3, 2, 2, 2, 456, 462, 5, 84, 43, 2, 457, 458, 7, 25, 2, 2, 458, 459, 5, 92, 47, 2, 459, 460, 7, 26, 2, 2, 460, 462, 3, 2, 2, 2, 461, 456, 3, 2, 2, 2, 461, 457, 3, 2, 2, 2, 462, 89, 3, 2, 2, 2, 463, 466, 5, 92, 47, 2, 464, 466, 7, 53, 2, 2, 465, 463, 3, 2, 2, 2, 465, 464, 3, 2, 2, 2, 466, 91, 3, 2, 2, 2, 467, 468, 9, 7, 2, 2, 468, 93, 3, 2, 2, 2, 52, 97, 102, 104, 115, 134, 152, 154, 160, 162, 173, 179, 181, 192, 201, 206, 210, 214, 243, 250, 257, 270, 277, 285, 291, 298, 304, 306, 328, 333, 340, 352, 356, 362, 372, 380, 385, 388, 396, 400, 404, 409, 414, 425, 432, 434, 440, 445, 451, 461, 465] \ No newline at end of file diff --git a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.java b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.java index ca7041b..e401c69 100644 --- a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.java +++ b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.java @@ -28,11 +28,11 @@ public class ShExMLParser extends Parser { QUOTE=37, AND=38, A=39, AT=40, EQUAL=41, INDEX=42, STRING_OR_VAR=43, URI_VAR=44, STRINGOPERATOR=45, XMLSCHEMADATATYPE=46, SHAPELINK=47, LANGTAG=48, COMMENT=49, WS=50, URL=51, JDBC_URL=52, JSONPATH=53, XMLPATH=54, CSVPERROW=55, SQL=56, - SCALA=57, SPARQL=58, QUERY_PART=59, GREATER_SYMBOL_QUERY=60, WS_QUERY=61, - LESS_SYMBOL_QUERY=62, STRING_OR_VAR_QUERY=63, URI_VAR_QUERY=64, WS_DECLARATION=65, - LESS_SYMBOL_AUTOINCREMENT=66, TO=67, BY=68, ADD_AUTOINCREMENT=69, DIGITS=70, - STRING_OR_VAR_AUTOINCREMENT=71, STRINGOPERATOR_AUTOINCREMENT=72, GREATER_SYMBOL_AUTOINCREMENT=73, - WS_AUTOINCREMENT=74; + SCALA=57, SPARQL=58, STDIN=59, QUERY_PART=60, GREATER_SYMBOL_QUERY=61, + WS_QUERY=62, LESS_SYMBOL_QUERY=63, STRING_OR_VAR_QUERY=64, URI_VAR_QUERY=65, + WS_DECLARATION=66, LESS_SYMBOL_AUTOINCREMENT=67, TO=68, BY=69, ADD_AUTOINCREMENT=70, + DIGITS=71, STRING_OR_VAR_AUTOINCREMENT=72, STRINGOPERATOR_AUTOINCREMENT=73, + GREATER_SYMBOL_AUTOINCREMENT=74, WS_AUTOINCREMENT=75; public static final int RULE_shExML = 0, RULE_decl = 1, RULE_prefix = 2, RULE_source = 3, RULE_query = 4, RULE_functions = 5, RULE_iterator = 6, RULE_nestedIterator = 7, RULE_field = 8, @@ -83,11 +83,11 @@ private static String[] makeSymbolicNames() { "COMMA", "QUOTE", "AND", "A", "AT", "EQUAL", "INDEX", "STRING_OR_VAR", "URI_VAR", "STRINGOPERATOR", "XMLSCHEMADATATYPE", "SHAPELINK", "LANGTAG", "COMMENT", "WS", "URL", "JDBC_URL", "JSONPATH", "XMLPATH", "CSVPERROW", - "SQL", "SCALA", "SPARQL", "QUERY_PART", "GREATER_SYMBOL_QUERY", "WS_QUERY", - "LESS_SYMBOL_QUERY", "STRING_OR_VAR_QUERY", "URI_VAR_QUERY", "WS_DECLARATION", - "LESS_SYMBOL_AUTOINCREMENT", "TO", "BY", "ADD_AUTOINCREMENT", "DIGITS", - "STRING_OR_VAR_AUTOINCREMENT", "STRINGOPERATOR_AUTOINCREMENT", "GREATER_SYMBOL_AUTOINCREMENT", - "WS_AUTOINCREMENT" + "SQL", "SCALA", "SPARQL", "STDIN", "QUERY_PART", "GREATER_SYMBOL_QUERY", + "WS_QUERY", "LESS_SYMBOL_QUERY", "STRING_OR_VAR_QUERY", "URI_VAR_QUERY", + "WS_DECLARATION", "LESS_SYMBOL_AUTOINCREMENT", "TO", "BY", "ADD_AUTOINCREMENT", + "DIGITS", "STRING_OR_VAR_AUTOINCREMENT", "STRINGOPERATOR_AUTOINCREMENT", + "GREATER_SYMBOL_AUTOINCREMENT", "WS_AUTOINCREMENT" }; } private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); @@ -422,6 +422,7 @@ public VariableContext variable() { public TerminalNode URL() { return getToken(ShExMLParser.URL, 0); } public TerminalNode JDBC_URL() { return getToken(ShExMLParser.JDBC_URL, 0); } public TerminalNode QUERY_PART() { return getToken(ShExMLParser.QUERY_PART, 0); } + public TerminalNode STDIN() { return getToken(ShExMLParser.STDIN, 0); } public SourceContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -456,7 +457,7 @@ public final SourceContext source() throws RecognitionException { match(LESS_SYMBOL_QUERY); setState(124); _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << URL) | (1L << JDBC_URL) | (1L << QUERY_PART))) != 0)) ) { + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << URL) | (1L << JDBC_URL) | (1L << STDIN) | (1L << QUERY_PART))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -3627,7 +3628,7 @@ private boolean matchers_sempred(MatchersContext _localctx, int predIndex) { } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3L\u01d6\4\2\t\2\4"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3M\u01d6\4\2\t\2\4"+ "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+ "\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ @@ -3662,8 +3663,8 @@ private boolean matchers_sempred(MatchersContext _localctx, int predIndex) { "\n&\5&\u01b3\n&\3\'\3\'\3(\3(\5(\u01b9\n(\3)\3)\3)\5)\u01be\n)\3*\3*\3"+ "+\3+\5+\u01c4\n+\3,\3,\3,\3-\3-\3-\3-\3-\5-\u01ce\n-\3.\3.\5.\u01d2\n"+ ".\3/\3/\3/\2\3\32\60\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60"+ - "\62\64\668:<>@BDFHJLNPRTVXZ\\\2\b\4\2\65\66==\4\2\65\65==\3\2\b\n\4\2"+ - "--//\3\2\25\30\5\2-.ABII\2\u01e9\2a\3\2\2\2\4s\3\2\2\2\6u\3\2\2\2\b{\3"+ + "\62\64\668:<>@BDFHJLNPRTVXZ\\\2\b\4\2\65\66=>\4\2\65\65>>\3\2\b\n\4\2"+ + "--//\3\2\25\30\5\2-.BCJJ\2\u01e9\2a\3\2\2\2\4s\3\2\2\2\6u\3\2\2\2\b{\3"+ "\2\2\2\n\u0081\3\2\2\2\f\u008a\3\2\2\2\16\u0091\3\2\2\2\20\u00a7\3\2\2"+ "\2\22\u00ba\3\2\2\2\24\u00c4\3\2\2\2\26\u00da\3\2\2\2\30\u00e0\3\2\2\2"+ "\32\u00e6\3\2\2\2\34\u00fa\3\2\2\2\36\u0101\3\2\2\2 \u0103\3\2\2\2\"\u0109"+ @@ -3678,37 +3679,37 @@ private boolean matchers_sempred(MatchersContext _localctx, int predIndex) { "\2\2gj\3\2\2\2hf\3\2\2\2hi\3\2\2\2i\3\3\2\2\2jh\3\2\2\2kt\5\b\5\2lt\5"+ "\6\4\2mt\5\n\6\2nt\5\26\f\2ot\5\30\r\2pt\5\16\b\2qt\5\24\13\2rt\5\f\7"+ "\2sk\3\2\2\2sl\3\2\2\2sm\3\2\2\2sn\3\2\2\2so\3\2\2\2sp\3\2\2\2sq\3\2\2"+ - "\2sr\3\2\2\2t\5\3\2\2\2uv\7\3\2\2vw\5\\/\2wx\7@\2\2xy\7\65\2\2yz\7>\2"+ - "\2z\7\3\2\2\2{|\7\4\2\2|}\5\\/\2}~\7@\2\2~\177\t\2\2\2\177\u0080\7>\2"+ + "\2sr\3\2\2\2t\5\3\2\2\2uv\7\3\2\2vw\5\\/\2wx\7A\2\2xy\7\65\2\2yz\7?\2"+ + "\2z\7\3\2\2\2{|\7\4\2\2|}\5\\/\2}~\7A\2\2~\177\t\2\2\2\177\u0080\7?\2"+ "\2\u0080\t\3\2\2\2\u0081\u0082\7\5\2\2\u0082\u0083\5\\/\2\u0083\u0086"+ - "\7@\2\2\u0084\u0087\7\65\2\2\u0085\u0087\5(\25\2\u0086\u0084\3\2\2\2\u0086"+ - "\u0085\3\2\2\2\u0087\u0088\3\2\2\2\u0088\u0089\7>\2\2\u0089\13\3\2\2\2"+ - "\u008a\u008b\7\7\2\2\u008b\u008c\5\\/\2\u008c\u008d\7@\2\2\u008d\u008e"+ - "\7;\2\2\u008e\u008f\t\3\2\2\u008f\u0090\7>\2\2\u0090\r\3\2\2\2\u0091\u0092"+ - "\7\6\2\2\u0092\u0093\5\\/\2\u0093\u009a\7@\2\2\u0094\u009b\5(\25\2\u0095"+ - "\u0097\7=\2\2\u0096\u0095\3\2\2\2\u0097\u0098\3\2\2\2\u0098\u0096\3\2"+ + "\7A\2\2\u0084\u0087\7\65\2\2\u0085\u0087\5(\25\2\u0086\u0084\3\2\2\2\u0086"+ + "\u0085\3\2\2\2\u0087\u0088\3\2\2\2\u0088\u0089\7?\2\2\u0089\13\3\2\2\2"+ + "\u008a\u008b\7\7\2\2\u008b\u008c\5\\/\2\u008c\u008d\7A\2\2\u008d\u008e"+ + "\7;\2\2\u008e\u008f\t\3\2\2\u008f\u0090\7?\2\2\u0090\r\3\2\2\2\u0091\u0092"+ + "\7\6\2\2\u0092\u0093\5\\/\2\u0093\u009a\7A\2\2\u0094\u009b\5(\25\2\u0095"+ + "\u0097\7>\2\2\u0096\u0095\3\2\2\2\u0097\u0098\3\2\2\2\u0098\u0096\3\2"+ "\2\2\u0098\u0099\3\2\2\2\u0099\u009b\3\2\2\2\u009a\u0094\3\2\2\2\u009a"+ - "\u0096\3\2\2\2\u009b\u009c\3\2\2\2\u009c\u009d\7>\2\2\u009d\u00a2\7!\2"+ + "\u0096\3\2\2\2\u009b\u009c\3\2\2\2\u009c\u009d\7?\2\2\u009d\u00a2\7!\2"+ "\2\u009e\u00a1\5\22\n\2\u009f\u00a1\5\20\t\2\u00a0\u009e\3\2\2\2\u00a0"+ "\u009f\3\2\2\2\u00a1\u00a4\3\2\2\2\u00a2\u00a0\3\2\2\2\u00a2\u00a3\3\2"+ "\2\2\u00a3\u00a5\3\2\2\2\u00a4\u00a2\3\2\2\2\u00a5\u00a6\7\"\2\2\u00a6"+ - "\17\3\2\2\2\u00a7\u00a8\7\6\2\2\u00a8\u00a9\5\\/\2\u00a9\u00ab\7@\2\2"+ - "\u00aa\u00ac\7=\2\2\u00ab\u00aa\3\2\2\2\u00ac\u00ad\3\2\2\2\u00ad\u00ab"+ - "\3\2\2\2\u00ad\u00ae\3\2\2\2\u00ae\u00af\3\2\2\2\u00af\u00b0\7>\2\2\u00b0"+ + "\17\3\2\2\2\u00a7\u00a8\7\6\2\2\u00a8\u00a9\5\\/\2\u00a9\u00ab\7A\2\2"+ + "\u00aa\u00ac\7>\2\2\u00ab\u00aa\3\2\2\2\u00ac\u00ad\3\2\2\2\u00ad\u00ab"+ + "\3\2\2\2\u00ad\u00ae\3\2\2\2\u00ae\u00af\3\2\2\2\u00af\u00b0\7?\2\2\u00b0"+ "\u00b5\7!\2\2\u00b1\u00b4\5\22\n\2\u00b2\u00b4\5\20\t\2\u00b3\u00b1\3"+ "\2\2\2\u00b3\u00b2\3\2\2\2\u00b4\u00b7\3\2\2\2\u00b5\u00b3\3\2\2\2\u00b5"+ "\u00b6\3\2\2\2\u00b6\u00b8\3\2\2\2\u00b7\u00b5\3\2\2\2\u00b8\u00b9\7\""+ "\2\2\u00b9\21\3\2\2\2\u00ba\u00bb\t\4\2\2\u00bb\u00bc\5\\/\2\u00bc\u00be"+ - "\7@\2\2\u00bd\u00bf\7=\2\2\u00be\u00bd\3\2\2\2\u00bf\u00c0\3\2\2\2\u00c0"+ - "\u00be\3\2\2\2\u00c0\u00c1\3\2\2\2\u00c1\u00c2\3\2\2\2\u00c2\u00c3\7>"+ + "\7A\2\2\u00bd\u00bf\7>\2\2\u00be\u00bd\3\2\2\2\u00bf\u00c0\3\2\2\2\u00c0"+ + "\u00be\3\2\2\2\u00c0\u00c1\3\2\2\2\u00c1\u00c2\3\2\2\2\u00c2\u00c3\7?"+ "\2\2\u00c3\23\3\2\2\2\u00c4\u00c5\7\13\2\2\u00c5\u00c6\5\\/\2\u00c6\u00c9"+ - "\7D\2\2\u00c7\u00c8\7J\2\2\u00c8\u00ca\7G\2\2\u00c9\u00c7\3\2\2\2\u00c9"+ - "\u00ca\3\2\2\2\u00ca\u00cb\3\2\2\2\u00cb\u00ce\7H\2\2\u00cc\u00cd\7E\2"+ - "\2\u00cd\u00cf\7H\2\2\u00ce\u00cc\3\2\2\2\u00ce\u00cf\3\2\2\2\u00cf\u00d2"+ - "\3\2\2\2\u00d0\u00d1\7F\2\2\u00d1\u00d3\7H\2\2\u00d2\u00d0\3\2\2\2\u00d2"+ - "\u00d3\3\2\2\2\u00d3\u00d6\3\2\2\2\u00d4\u00d5\7G\2\2\u00d5\u00d7\7J\2"+ + "\7E\2\2\u00c7\u00c8\7K\2\2\u00c8\u00ca\7H\2\2\u00c9\u00c7\3\2\2\2\u00c9"+ + "\u00ca\3\2\2\2\u00ca\u00cb\3\2\2\2\u00cb\u00ce\7I\2\2\u00cc\u00cd\7F\2"+ + "\2\u00cd\u00cf\7I\2\2\u00ce\u00cc\3\2\2\2\u00ce\u00cf\3\2\2\2\u00cf\u00d2"+ + "\3\2\2\2\u00d0\u00d1\7G\2\2\u00d1\u00d3\7I\2\2\u00d2\u00d0\3\2\2\2\u00d2"+ + "\u00d3\3\2\2\2\u00d3\u00d6\3\2\2\2\u00d4\u00d5\7H\2\2\u00d5\u00d7\7K\2"+ "\2\u00d6\u00d4\3\2\2\2\u00d6\u00d7\3\2\2\2\u00d7\u00d8\3\2\2\2\u00d8\u00d9"+ - "\7K\2\2\u00d9\25\3\2\2\2\u00da\u00db\7\f\2\2\u00db\u00dc\5\\/\2\u00dc"+ + "\7L\2\2\u00d9\25\3\2\2\2\u00da\u00db\7\f\2\2\u00db\u00dc\5\\/\2\u00dc"+ "\u00dd\7\31\2\2\u00dd\u00de\5\36\20\2\u00de\u00df\7\32\2\2\u00df\27\3"+ "\2\2\2\u00e0\u00e1\7\20\2\2\u00e1\u00e2\5\\/\2\u00e2\u00e3\7\31\2\2\u00e3"+ "\u00e4\5\32\16\2\u00e4\u00e5\7\32\2\2\u00e5\31\3\2\2\2\u00e6\u00e7\b\16"+ @@ -3728,13 +3729,13 @@ private boolean matchers_sempred(MatchersContext _localctx, int predIndex) { "\u010f\3\2\2\2\u010f#\3\2\2\2\u0110\u0116\5\\/\2\u0111\u0112\5\\/\2\u0112"+ "\u0113\7$\2\2\u0113\u0114\5$\23\2\u0114\u0116\3\2\2\2\u0115\u0110\3\2"+ "\2\2\u0115\u0111\3\2\2\2\u0116%\3\2\2\2\u0117\u0118\7,\2\2\u0118\'\3\2"+ - "\2\2\u0119\u011b\7\67\2\2\u011a\u011c\7=\2\2\u011b\u011a\3\2\2\2\u011c"+ + "\2\2\u0119\u011b\7\67\2\2\u011a\u011c\7>\2\2\u011b\u011a\3\2\2\2\u011c"+ "\u011d\3\2\2\2\u011d\u011b\3\2\2\2\u011d\u011e\3\2\2\2\u011e\u0133\3\2"+ - "\2\2\u011f\u0121\78\2\2\u0120\u0122\7=\2\2\u0121\u0120\3\2\2\2\u0122\u0123"+ + "\2\2\u011f\u0121\78\2\2\u0120\u0122\7>\2\2\u0121\u0120\3\2\2\2\u0122\u0123"+ "\3\2\2\2\u0123\u0121\3\2\2\2\u0123\u0124\3\2\2\2\u0124\u0133\3\2\2\2\u0125"+ - "\u0133\79\2\2\u0126\u0128\7:\2\2\u0127\u0129\7=\2\2\u0128\u0127\3\2\2"+ + "\u0133\79\2\2\u0126\u0128\7:\2\2\u0127\u0129\7>\2\2\u0128\u0127\3\2\2"+ "\2\u0129\u012a\3\2\2\2\u012a\u0128\3\2\2\2\u012a\u012b\3\2\2\2\u012b\u0133"+ - "\3\2\2\2\u012c\u012e\7<\2\2\u012d\u012f\7=\2\2\u012e\u012d\3\2\2\2\u012f"+ + "\3\2\2\2\u012c\u012e\7<\2\2\u012d\u012f\7>\2\2\u012e\u012d\3\2\2\2\u012f"+ "\u0130\3\2\2\2\u0130\u012e\3\2\2\2\u0130\u0131\3\2\2\2\u0131\u0133\3\2"+ "\2\2\u0132\u0119\3\2\2\2\u0132\u011f\3\2\2\2\u0132\u0125\3\2\2\2\u0132"+ "\u0126\3\2\2\2\u0132\u012c\3\2\2\2\u0133)\3\2\2\2\u0134\u0135\5\"\22\2"+ diff --git a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.tokens b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.tokens index 686041f..d273e53 100644 --- a/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.tokens +++ b/src/main/java/com/herminiogarcia/shexml/antlr/ShExMLParser.tokens @@ -56,22 +56,23 @@ CSVPERROW=55 SQL=56 SCALA=57 SPARQL=58 -QUERY_PART=59 -GREATER_SYMBOL_QUERY=60 -WS_QUERY=61 -LESS_SYMBOL_QUERY=62 -STRING_OR_VAR_QUERY=63 -URI_VAR_QUERY=64 -WS_DECLARATION=65 -LESS_SYMBOL_AUTOINCREMENT=66 -TO=67 -BY=68 -ADD_AUTOINCREMENT=69 -DIGITS=70 -STRING_OR_VAR_AUTOINCREMENT=71 -STRINGOPERATOR_AUTOINCREMENT=72 -GREATER_SYMBOL_AUTOINCREMENT=73 -WS_AUTOINCREMENT=74 +STDIN=59 +QUERY_PART=60 +GREATER_SYMBOL_QUERY=61 +WS_QUERY=62 +LESS_SYMBOL_QUERY=63 +STRING_OR_VAR_QUERY=64 +URI_VAR_QUERY=65 +WS_DECLARATION=66 +LESS_SYMBOL_AUTOINCREMENT=67 +TO=68 +BY=69 +ADD_AUTOINCREMENT=70 +DIGITS=71 +STRING_OR_VAR_AUTOINCREMENT=72 +STRINGOPERATOR_AUTOINCREMENT=73 +GREATER_SYMBOL_AUTOINCREMENT=74 +WS_AUTOINCREMENT=75 '['=25 '[['=26 ']'=27 diff --git a/src/main/scala/com/herminiogarcia/shexml/MappingLauncher.scala b/src/main/scala/com/herminiogarcia/shexml/MappingLauncher.scala index 9f50f32..70b1c0d 100644 --- a/src/main/scala/com/herminiogarcia/shexml/MappingLauncher.scala +++ b/src/main/scala/com/herminiogarcia/shexml/MappingLauncher.scala @@ -1,6 +1,5 @@ package com.herminiogarcia.shexml -import com.fasterxml.jackson.databind.{JsonNode, ObjectMapper} import com.herminiogarcia.shexml.antlr.{ShExMLLexer, ShExMLParser} import com.herminiogarcia.shexml.ast._ import com.herminiogarcia.shexml.helper.{OrphanBNodeRemover, ParallelExecutionConfigurator, SourceHelper} @@ -11,7 +10,7 @@ import org.antlr.v4.runtime.{CharStreams, CommonTokenStream} import org.apache.jena.query.{Dataset, DatasetFactory} import org.apache.jena.riot.{RDFDataMgr, RDFFormat, RDFLanguages} import com.typesafe.scalalogging.Logger -import java.io.{ByteArrayInputStream, ByteArrayOutputStream} +import java.io.ByteArrayOutputStream import scala.collection.JavaConverters._ import java.util.concurrent.ConcurrentLinkedQueue import scala.collection.mutable @@ -51,24 +50,6 @@ class MappingLauncher(val username: String = "", val password: String = "", driv generateResultingRDF(ast, varTable) } - def launchMappingFromJsonData(mappingCode: String, data: JsonNode): Dataset = { - logger.info(s"Launching mapping with data") - logger.debug(s"Mapping rules $mappingCode") - val lexer = createLexer(mappingCode) - val parser = createParser(lexer) - val ast = createAST(parser) - val varTable = createVarTable(ast) - try { - val bytes = new ObjectMapper().writeValueAsBytes(data) - logger.trace(s"Data: ${data.toString}") - val inputBytes = new ByteArrayInputStream(bytes) - System.setIn(inputBytes) - generateResultingRDF(ast, varTable) - } finally { - System.setIn(System.in) - } - } - def launchRMLTranslation(mappingCode: String, prettify: Boolean = false): String = { logger.info(s"Launching ShExML to RML translation with prettify option to $prettify") logger.debug(s"Mapping rules $mappingCode") diff --git a/src/main/scala/com/herminiogarcia/shexml/ast/AST.scala b/src/main/scala/com/herminiogarcia/shexml/ast/AST.scala index b71a751..6cfcded 100644 --- a/src/main/scala/com/herminiogarcia/shexml/ast/AST.scala +++ b/src/main/scala/com/herminiogarcia/shexml/ast/AST.scala @@ -17,7 +17,7 @@ case class LiteralSubject(prefix: Var, value: String) extends ActionOrLiteral sealed trait DeclarationStatement extends AST case class Prefix(name: Var, url: URL) extends DeclarationStatement -case class Source(name: Var, path: FilePath) extends DeclarationStatement +case class Source(name: Var, path: FilePathOrStdin) extends DeclarationStatement case class Query(name: Var, query: QueryOrURL) extends DeclarationStatement case class Functions(name: Var, query: FilePath) extends DeclarationStatement case class Iterator(name: Var, queryClause: QueryOrVar, fields: List[Field], iterators: List[NestedIterator]) extends Iterators with DeclarationStatement with VarResult @@ -98,12 +98,15 @@ sealed trait Iterators extends AST { def iterators: List[NestedIterator] } -sealed trait FilePath extends VarResult { +sealed trait FilePathOrStdin extends VarResult + +sealed trait FilePath extends FilePathOrStdin { def value: String } case class URL(value: String) extends FilePath with QueryOrURL case class JdbcURL(value: String) extends FilePath case class RelativePath(value: String) extends FilePath +case class Stdin() extends FilePathOrStdin case class ReplacedStrings(strings: List[String]) extends AST case class ComposedVariable(variables: List[Var]) extends AST case class MatcherList(matchers: List[Matcher]) extends AST diff --git a/src/main/scala/com/herminiogarcia/shexml/helper/SourceHelper.scala b/src/main/scala/com/herminiogarcia/shexml/helper/SourceHelper.scala index a5328d6..39ac25d 100644 --- a/src/main/scala/com/herminiogarcia/shexml/helper/SourceHelper.scala +++ b/src/main/scala/com/herminiogarcia/shexml/helper/SourceHelper.scala @@ -24,9 +24,7 @@ class SourceHelper { def getContentFromRelativePath(path: String): LoadedSource = searchFileResult(path) match { case Some(result) => result case None => - val file = if (path.equals("-")) - scala.io.Source.fromInputStream(System.in, "UTF-8") - else scala.io.Source.fromFile(path, "UTF-8") + val file = scala.io.Source.fromFile(path, "UTF-8") try { val content = LoadedSource(file.mkString, path) saveFileResult(path, content) @@ -34,6 +32,10 @@ class SourceHelper { } finally { file.close() } } + def getStdinContents(): LoadedSource = { + LoadedSource(scala.io.Source.stdin.getLines().mkString, "-") + } + } object SourceHelper { diff --git a/src/main/scala/com/herminiogarcia/shexml/parser/ASTCreatorVisitor.scala b/src/main/scala/com/herminiogarcia/shexml/parser/ASTCreatorVisitor.scala index 51227cd..16aa147 100644 --- a/src/main/scala/com/herminiogarcia/shexml/parser/ASTCreatorVisitor.scala +++ b/src/main/scala/com/herminiogarcia/shexml/parser/ASTCreatorVisitor.scala @@ -34,6 +34,7 @@ class ASTCreatorVisitor extends ShExMLParserBaseVisitor[AST] { override def visitSource(ctx: SourceContext): AST = { val url = if(ctx.URL != null) URL(ctx.URL().getText) + else if(ctx.STDIN() != null) Stdin() else if(ctx.QUERY_PART() != null) RelativePath(ctx.QUERY_PART().getText) else JdbcURL(ctx.JDBC_URL().getText) val name = createVar(ctx.variable()) diff --git a/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala b/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala index a1a7d71..72a0233 100644 --- a/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala +++ b/src/main/scala/com/herminiogarcia/shexml/visitor/RDFGeneratorVisitor.scala @@ -1,7 +1,7 @@ package com.herminiogarcia.shexml.visitor import com.github.tototoshi.csv.{CSVReader, DefaultCSVFormat} -import com.herminiogarcia.shexml.ast.{AST, Action, ActionOrLiteral, AutoIncrement, BuiltinFunction, CSVPerRow, DataTypeGeneration, DataTypeLiteral, Declaration, Exp, FieldQuery, FilePath, FunctionCalling, Graph, Index, IteratorQuery, JdbcURL, Join, JsonPath, LangTagGeneration, LangTagLiteral, LiteralObject, LiteralObjectValue, LiteralSubject, Matcher, Matchers, ObjectElement, Predicate, PredicateObject, Prefix, QueryClause, RDFAlt, RDFBag, RDFCollection, RDFList, RDFSeq, RelativePath, ShExML, Shape, ShapeLink, ShapeVar, Sparql, SparqlColumn, Sql, SqlColumn, StringOperation, Substitution, URL, Union, Var, VarResult, Variable, XmlPath} +import com.herminiogarcia.shexml.ast.{AST, Action, ActionOrLiteral, AutoIncrement, BuiltinFunction, CSVPerRow, DataTypeGeneration, DataTypeLiteral, Declaration, Exp, FieldQuery, FilePath, FilePathOrStdin, FunctionCalling, Graph, Index, IteratorQuery, JdbcURL, Join, JsonPath, LangTagGeneration, LangTagLiteral, LiteralObject, LiteralObjectValue, LiteralSubject, Matcher, Matchers, ObjectElement, Predicate, PredicateObject, Prefix, QueryClause, RDFAlt, RDFBag, RDFCollection, RDFList, RDFSeq, RelativePath, ShExML, Shape, ShapeLink, ShapeVar, Sparql, SparqlColumn, Sql, SqlColumn, Stdin, StringOperation, Substitution, URL, Union, Var, VarResult, Variable, XmlPath} import com.herminiogarcia.shexml.helper.{FunctionHubExecutor, LoadedSource, ParallelExecutionConfigurator, SourceHelper} import com.herminiogarcia.shexml.shex.{Node, ShExMLInferredCardinalitiesAndDatatypes, ShapeMapInference, ShapeMapShape} import com.herminiogarcia.shexml.visitor @@ -11,7 +11,7 @@ import net.sf.saxon.s9api.{Processor, XdmNode} import net.minidev.json.JSONArray import org.apache.jena.datatypes.xsd.XSDDatatype import org.apache.jena.datatypes.{RDFDatatype, TypeMapper} -import org.apache.jena.query.{Dataset, QueryExecutionFactory, QueryFactory, ReadWrite, ResultSet, TxnType} +import org.apache.jena.query.{Dataset, QueryExecutionFactory, QueryFactory, ResultSet, TxnType} import org.apache.jena.rdf.model._ import org.apache.jena.riot.RDFDataMgr import org.apache.jena.util.SplitIRI @@ -351,7 +351,7 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: Map[Variable, VarResult], val fileMap = Map("file" -> file) val middleArguments = arguments.map(_.++(fileMap)).getOrElse(fileMap) val varList = iteratorQueryToList(i) - if (varTable(varList.head).isInstanceOf[FilePath] && varList.size == 2) { + if (varTable(varList.head).isInstanceOf[FilePathOrStdin] && varList.size == 2) { val iteratorQueryStringRepresentation = iteratorQueryToList(i).map(_.name).mkString(".") iteratorQueryResultsCache.search(iteratorQueryStringRepresentation, file.asInstanceOf[LoadedSource]) match { case Some(value) => @@ -615,6 +615,7 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: Map[Variable, VarResult], throw new Exception("* wildcard not allowed over remote files") else List(new SourceHelper().getURLContent(url)) + case RelativePath(path) => if(isRDFSource(path)) { val fileAbsolutePath = new File(path).getAbsolutePath @@ -625,8 +626,12 @@ class RDFGeneratorVisitor(dataset: Dataset, varTable: Map[Variable, VarResult], } else if(path.contains('*')) getAllFilesContents(path) else List(new SourceHelper().getContentFromRelativePath(path)) + case JdbcURL(url) => List(LoadedSource("", url)) + case Stdin() => List(new SourceHelper().getStdinContents()) + + case default => visit(default, optionalArgument) } diff --git a/src/test/scala/com/herminiogarcia/shexml/FilmsStdin.scala b/src/test/scala/com/herminiogarcia/shexml/FilmsStdin.scala index 6b72765..8cd12ad 100644 --- a/src/test/scala/com/herminiogarcia/shexml/FilmsStdin.scala +++ b/src/test/scala/com/herminiogarcia/shexml/FilmsStdin.scala @@ -1,23 +1,22 @@ package com.herminiogarcia.shexml -import com.fasterxml.jackson.databind.ObjectMapper +import com.herminiogarcia.shexml.helper.SourceHelper import org.apache.jena.datatypes.xsd.XSDDatatype -import org.scalactic.source.Position -import org.scalatest.{BeforeAndAfter, BeforeAndAfterEach} +import org.apache.jena.rdf.model.Model +import org.scalatest.{BeforeAndAfter, ConfigMap} import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.must.Matchers +import java.io.ByteArrayInputStream -import scala.io.Source - -class FilmsStdin extends AnyFunSuite with Matchers with RDFStatementCreator with BeforeAndAfter { - - override def after(fun: => Any)(implicit pos: Position): Unit = try System.setIn(System.in) finally super.after(fun) +class FilmsStdin extends AnyFunSuite + with Matchers with RDFStatementCreator + with BeforeAndAfter with ParallelConfigInferenceDatatypesNormaliseURIsFixture{ private val example = """ PREFIX : |SOURCE films_xml_file <./src/test/resources/filmsAlt.xml> - |SOURCE films_json_file <-> + |SOURCE films_json_file |ITERATOR film_xml { | FIELD name | FIELD year @@ -44,13 +43,17 @@ class FilmsStdin extends AnyFunSuite with Matchers with RDFStatementCreator with |} """.stripMargin + private var output: Model = _ private val prefix = "http://example.com/" - val data = Source.fromInputStream(getClass.getClassLoader.getResourceAsStream("filmsAlt.json")).mkString - val node = new ObjectMapper().readTree(data) - - private val mappingLauncher = new MappingLauncher(inferenceDatatype = true, normaliseURIs = true) - private val output = mappingLauncher.launchMappingFromJsonData(example, node).getDefaultModel + override def beforeAll(configMap: ConfigMap): Unit = { + super.beforeAll(configMap) + val stream = new ByteArrayInputStream(new SourceHelper().getContentFromRelativePath("./src/test/resources/filmsAlt.json").fileContent.getBytes()) + System.setIn(stream) + stream.close() + output = mappingLauncher.launchMapping(example).getDefaultModel + System.setIn(System.in) + } test("Shape film1 contains all the data, literal action, enhancement-#97") { assert(output.contains(createStatementWithLiteral(prefix, "film1", "name", "Dunkirk", XSDDatatype.XSDstring))) From 24537d5f9a430aa39baa8a90d2e00b8e681a2f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Fri, 5 Sep 2025 17:46:10 +0200 Subject: [PATCH 13/15] Added the option to use - to read the mapping rules from stdin in the -m option. Closes #232. --- src/main/scala/com/herminiogarcia/shexml/Main.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/com/herminiogarcia/shexml/Main.scala b/src/main/scala/com/herminiogarcia/shexml/Main.scala index d7a2c53..c2c4c6a 100644 --- a/src/main/scala/com/herminiogarcia/shexml/Main.scala +++ b/src/main/scala/com/herminiogarcia/shexml/Main.scala @@ -26,7 +26,7 @@ object Main { description = Array("Map and merge heterogeneous data sources with a Shape Expressions based syntax")) class Main extends Callable[Int] { - @Option(names = Array("-m", "--mapping"), required = true, description = Array("Path to the file with the mappings")) + @Option(names = Array("-m", "--mapping"), required = true, description = Array("Path to the file with the mappings. If '-' is provided as the path the engine will read from the standard input.")) private var file: String = "" @ArgGroup(validate = false, heading = "Options for the transformation to RDF%n") @@ -39,7 +39,7 @@ class Main extends Callable[Int] { private var generalTransformationOptions: GeneralTransformationOptions = new GeneralTransformationOptions() override def call(): Int = { - val fileHandler = scala.io.Source.fromFile(file) + val fileHandler = if(file == "-") scala.io.Source.stdin else scala.io.Source.fromFile(file) val parallelExecutionConfiguration = if(generalTransformationOptions.parallel) ParallelExecutionConfigurator(generalTransformationOptions.parallelAspects, generalTransformationOptions.numberOfThreads) else ParallelExecutionConfigurator.empty From 848264fd6850afeede30ad0ec63c5a6e6a10199c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Tue, 9 Sep 2025 14:25:53 +0200 Subject: [PATCH 14/15] Added tests for the CLI --- src/test/resources/databaseTestInput.shexml | 22 + src/test/resources/filmsCLIInput.shexml | 37 + .../herminiogarcia/shexml/FilmsCLITest.scala | 706 ++++++++++++++++++ 3 files changed, 765 insertions(+) create mode 100644 src/test/resources/databaseTestInput.shexml create mode 100644 src/test/resources/filmsCLIInput.shexml create mode 100644 src/test/scala/com/herminiogarcia/shexml/FilmsCLITest.scala diff --git a/src/test/resources/databaseTestInput.shexml b/src/test/resources/databaseTestInput.shexml new file mode 100644 index 0000000..1c5d69a --- /dev/null +++ b/src/test/resources/databaseTestInput.shexml @@ -0,0 +1,22 @@ +PREFIX : +PREFIX dbr: +PREFIX schema: +PREFIX xs: +SOURCE films_database +ITERATOR films_iterator { + FIELD id + FIELD name + FIELD year + FIELD country + FIELD director +} + +EXPRESSION films + +:Films :[films.id] { + :type :Film ; + :name [films.name] @en ; + :year [films.year] xs:gYear ; + :country [films.country] ; + :director [films.director] ; +} \ No newline at end of file diff --git a/src/test/resources/filmsCLIInput.shexml b/src/test/resources/filmsCLIInput.shexml new file mode 100644 index 0000000..e89f76a --- /dev/null +++ b/src/test/resources/filmsCLIInput.shexml @@ -0,0 +1,37 @@ +PREFIX : +PREFIX xs: +PREFIX dbr: +PREFIX schema: +SOURCE films_xml_file +SOURCE films_json_file +ITERATOR film_xml { + FIELD id <@id> + FIELD name + FIELD year + FIELD country + FIELD directors + FIELD screenwritters + FIELD music + FIELD photography +} +ITERATOR film_json { + FIELD id + FIELD name + FIELD year + FIELD country + FIELD directors + FIELD screenwritters + FIELD music + FIELD photography +} +EXPRESSION films + +:Films :[films.id] { + a schema:Movie ; + schema:name [films.name] @en ; + :year [films.year] ; + schema:countryOfOrigin dbr:[films.country] ; + schema:director dbr:[films.directors] ; + :screenwritter dbr:[films.screenwritters] ; + schema:musicBy dbr:[films.music] ; +} \ No newline at end of file diff --git a/src/test/scala/com/herminiogarcia/shexml/FilmsCLITest.scala b/src/test/scala/com/herminiogarcia/shexml/FilmsCLITest.scala new file mode 100644 index 0000000..c481380 --- /dev/null +++ b/src/test/scala/com/herminiogarcia/shexml/FilmsCLITest.scala @@ -0,0 +1,706 @@ +package com.herminiogarcia.shexml + +import com.herminiogarcia.shexml.helper.PicocliLeftAlignedLayout +import org.apache.jena.rdf.model.ModelFactory +import org.scalatest.funsuite.AnyFunSuite +import picocli.CommandLine +import java.io.{ByteArrayInputStream, ByteArrayOutputStream, File} +import scala.util.Try + +class FilmsCLITest extends AnyFunSuite { + + private val filepath = "src/test/resources/filmsCLIInput.shexml" + + private val expectedTurtleOutput = + """@prefix : . + |@prefix schema: . + |@prefix dbr: . + |@prefix xs: . + | + |:4 a schema:Movie ; + | :screenwritter dbr:Jonathan_Nolan , dbr:Christopher_Nolan ; + | :year 2006 ; + | schema:countryOfOrigin dbr:USA ; + | schema:director dbr:Christopher_Nolan ; + | schema:musicBy dbr:David_Julyan ; + | schema:name "The Prestige"@en . + | + |:3 a schema:Movie ; + | :screenwritter dbr:Christopher_Nolan ; + | :year 2010 ; + | schema:countryOfOrigin dbr:USA ; + | schema:director dbr:Christopher_Nolan ; + | schema:musicBy dbr:Hans_Zimmer ; + | schema:name "Inception"@en . + | + |:2 a schema:Movie ; + | :screenwritter dbr:Jonathan_Nolan , dbr:Christopher_Nolan ; + | :year 2014 ; + | schema:countryOfOrigin dbr:USA ; + | schema:director dbr:Christopher_Nolan ; + | schema:musicBy dbr:Hans_Zimmer ; + | schema:name "Interstellar"@en . + | + |:1 a schema:Movie ; + | :screenwritter dbr:Christopher_Nolan ; + | :year 2017 ; + | schema:countryOfOrigin dbr:USA ; + | schema:director dbr:Christopher_Nolan ; + | schema:musicBy dbr:Hans_Zimmer ; + | schema:name "Dunkirk"@en . + |""".stripMargin + + private val expectedTurtleWithoutInferenceOfDatatypesOutput = + """@prefix : . + |@prefix schema: . + |@prefix dbr: . + |@prefix xs: . + | + |:4 a schema:Movie ; + | :screenwritter dbr:Jonathan_Nolan , dbr:Christopher_Nolan ; + | :year "2006" ; + | schema:countryOfOrigin dbr:USA ; + | schema:director dbr:Christopher_Nolan ; + | schema:musicBy dbr:David_Julyan ; + | schema:name "The Prestige"@en . + | + |:3 a schema:Movie ; + | :screenwritter dbr:Christopher_Nolan ; + | :year "2010" ; + | schema:countryOfOrigin dbr:USA ; + | schema:director dbr:Christopher_Nolan ; + | schema:musicBy dbr:Hans_Zimmer ; + | schema:name "Inception"@en . + | + |:2 a schema:Movie ; + | :screenwritter dbr:Jonathan_Nolan , dbr:Christopher_Nolan ; + | :year "2014" ; + | schema:countryOfOrigin dbr:USA ; + | schema:director dbr:Christopher_Nolan ; + | schema:musicBy dbr:Hans_Zimmer ; + | schema:name "Interstellar"@en . + | + |:1 a schema:Movie ; + | :screenwritter dbr:Christopher_Nolan ; + | :year "2017" ; + | schema:countryOfOrigin dbr:USA ; + | schema:director dbr:Christopher_Nolan ; + | schema:musicBy dbr:Hans_Zimmer ; + | schema:name "Dunkirk"@en . + |""".stripMargin + + private val expectedOpenShaclShapes = + """@prefix : . + |@prefix schema: . + |@prefix rdf: . + |@prefix sh: . + |@prefix dbr: . + |@prefix xsd: . + |@prefix xs: . + | + |:Films a sh:NodeShape ; + | sh:nodeKind sh:IRI ; + | sh:property [ sh:maxCount 1 ; + | sh:minCount 1 ; + | sh:nodeKind sh:IRI ; + | sh:path schema:director + | ] ; + | sh:property [ sh:languageIn ( "en" ) ; + | sh:path schema:name + | ] ; + | sh:property [ sh:maxCount 1 ; + | sh:minCount 1 ; + | sh:nodeKind sh:IRI ; + | sh:path schema:musicBy + | ] ; + | sh:property [ sh:maxCount 1 ; + | sh:minCount 1 ; + | sh:nodeKind sh:IRI ; + | sh:path schema:countryOfOrigin + | ] ; + | sh:property [ sh:minCount 1 ; + | sh:nodeKind sh:IRI ; + | sh:path :screenwritter + | ] ; + | sh:property [ sh:in ( schema:Movie ) ; + | sh:path rdf:type + | ] ; + | sh:property [ sh:maxCount 1 ; + | sh:minCount 1 ; + | sh:datatype xs:string ; + | sh:path :year + | ] ; + | sh:targetClass schema:Movie . + |""".stripMargin + + private val expectedClosedShaclShapes = expectedOpenShaclShapes + ":Films sh:closed true ." + + private val expectedRMLOutput = + """ + |@prefix : . + |@prefix schema: . + |@prefix rml: . + |@prefix rr: . + |@prefix d2rq: . + |@prefix dbr: . + |@prefix xs: . + |@prefix ql: . + |@prefix map: . + | + |map:po_4 a rr:PredicateObjectMap ; + | rr:objectMap map:o_4 ; + | rr:predicateMap map:p_4 . + | + |map:p_3 a rr:predicateMap ; + | rr:constant schema:name . + | + |map:o_11 a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{crew.screenwritter}" ; + | rr:termType rr:IRI . + | + |map:o_3 a rr:ObjectMap ; + | rr:language "en" ; + | rr:template "{name}" ; + | rr:termType rr:Literal . + | + |map:s_2 a rr:SubjectMap ; + | rr:template "http://example.com/{id}" . + | + |map:p_10 a rr:predicateMap ; + | rr:constant :screenwritter . + | + |map:po_9 a rr:PredicateObjectMap ; + | rr:objectMap map:o_9 ; + | rr:predicateMap map:p_9 . + | + |map:po_10 a rr:PredicateObjectMap ; + | rr:objectMap map:o_10 ; + | rr:predicateMap map:p_10 . + | + |map:p_8 a rr:predicateMap ; + | rr:constant schema:director . + | + |map:o_8 a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{crew/directors/director}" ; + | rr:termType rr:IRI . + | + |map:po_3 a rr:PredicateObjectMap ; + | rr:objectMap map:o_3 ; + | rr:predicateMap map:p_3 . + | + |map:p_2 a rr:predicateMap ; + | rr:constant schema:name . + | + |map:o_10 a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{crew//screenwritter}" ; + | rr:termType rr:IRI . + | + |map:o_2 a rr:ObjectMap ; + | rr:language "en" ; + | rr:template "{name}" ; + | rr:termType rr:Literal . + | + |map:l_353498812 a rml:LogicalSource ; + | rml:iterator "$.films[*]" ; + | rml:referenceFormulation ql:JSONPath ; + | rml:source "https://shexml.herminiogarcia.com/files/films.json" . + | + |map:s_1 a rr:SubjectMap ; + | rr:template "http://example.com/{@id}" . + | + |map:m_2 a rr:TriplesMap ; + | rml:logicalSource map:l_353498812 ; + | rr:predicateObjectMap map:po_5 , map:po_3 , map:po_13 , map:po_1 , map:po_11 , map:po_9 , map:po_7 ; + | rr:subjectMap map:s_2 . + | + |map:po_8 a rr:PredicateObjectMap ; + | rr:objectMap map:o_8 ; + | rr:predicateMap map:p_8 . + | + |map:p_7 a rr:predicateMap ; + | rr:constant schema:countryOfOrigin . + | + |map:o_7 a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{country}" ; + | rr:termType rr:IRI . + | + |map:po_2 a rr:PredicateObjectMap ; + | rr:objectMap map:o_2 ; + | rr:predicateMap map:p_2 . + | + |map:p_1 a rr:predicateMap ; + | rr:constant . + | + |map:l_1572684380 a rml:LogicalSource ; + | rml:iterator "//film" ; + | rml:referenceFormulation ql:XPath ; + | rml:source "https://shexml.herminiogarcia.com/files/films.xml" . + | + |map:o_1 a rr:ObjectMap ; + | rr:template "http://schema.org/Movie" ; + | rr:termType rr:IRI . + | + |map:m_1 a rr:TriplesMap ; + | rml:logicalSource map:l_1572684380 ; + | rr:predicateObjectMap map:po_12 , map:po_10 , map:po_4 , map:po_8 , map:po_1 , map:po_6 , map:po_2 ; + | rr:subjectMap map:s_1 . + | + |map:po_7 a rr:PredicateObjectMap ; + | rr:objectMap map:o_7 ; + | rr:predicateMap map:p_7 . + | + |map:p_6 a rr:predicateMap ; + | rr:constant schema:countryOfOrigin . + | + |map:o_6 a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{country}" ; + | rr:termType rr:IRI . + | + |map:po_1 a rr:PredicateObjectMap ; + | rr:objectMap map:o_1 ; + | rr:predicateMap map:p_1 . + | + |map:p_13 a rr:predicateMap ; + | rr:constant schema:musicBy . + | + |map:po_13 a rr:PredicateObjectMap ; + | rr:objectMap map:o_13 ; + | rr:predicateMap map:p_13 . + | + |map:po_6 a rr:PredicateObjectMap ; + | rr:objectMap map:o_6 ; + | rr:predicateMap map:p_6 . + | + |map:p_5 a rr:predicateMap ; + | rr:constant :year . + | + |map:o_13 a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{crew.music}" ; + | rr:termType rr:IRI . + | + |map:o_5 a rr:ObjectMap ; + | rr:template "{year}" ; + | rr:termType rr:Literal . + | + |map:p_12 a rr:predicateMap ; + | rr:constant schema:musicBy . + | + |map:po_12 a rr:PredicateObjectMap ; + | rr:objectMap map:o_12 ; + | rr:predicateMap map:p_12 . + | + |map:po_5 a rr:PredicateObjectMap ; + | rr:objectMap map:o_5 ; + | rr:predicateMap map:p_5 . + | + |map:p_4 a rr:predicateMap ; + | rr:constant :year . + | + |map:o_12 a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{crew/music}" ; + | rr:termType rr:IRI . + | + |map:o_4 a rr:ObjectMap ; + | rr:template "{year}" ; + | rr:termType rr:Literal . + | + |map:p_11 a rr:predicateMap ; + | rr:constant :screenwritter . + | + |map:po_11 a rr:PredicateObjectMap ; + | rr:objectMap map:o_11 ; + | rr:predicateMap map:p_11 . + | + |map:p_9 a rr:predicateMap ; + | rr:constant schema:director . + | + |map:o_9 a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{crew.director}" ; + | rr:termType rr:IRI . + |""".stripMargin + + private val expectedRMLPrettifiedOutput = + """ + |@prefix : . + |@prefix schema: . + |@prefix rml: . + |@prefix rr: . + |@prefix d2rq: . + |@prefix dbr: . + |@prefix xs: . + |@prefix ql: . + |@prefix map: . + | + |map:m_2 a rr:TriplesMap ; + | rml:logicalSource [ a rml:LogicalSource ; + | rml:iterator "$.films[*]" ; + | rml:referenceFormulation ql:JSONPath ; + | rml:source "https://shexml.herminiogarcia.com/files/films.json" + | ] ; + | rr:predicateObjectMap _:b0 ; + | rr:predicateObjectMap [ a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:template "{year}" ; + | rr:termType rr:Literal + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant :year + | ] + | ] ; + | rr:predicateObjectMap [ a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{crew.screenwritter}" ; + | rr:termType rr:IRI + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant :screenwritter + | ] + | ] ; + | rr:predicateObjectMap [ a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{crew.director}" ; + | rr:termType rr:IRI + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant schema:director + | ] + | ] ; + | rr:predicateObjectMap [ a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:language "en" ; + | rr:template "{name}" ; + | rr:termType rr:Literal + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant schema:name + | ] + | ] ; + | rr:predicateObjectMap [ a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{crew.music}" ; + | rr:termType rr:IRI + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant schema:musicBy + | ] + | ] ; + | rr:predicateObjectMap [ a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{country}" ; + | rr:termType rr:IRI + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant schema:countryOfOrigin + | ] + | ] ; + | rr:subjectMap [ a rr:SubjectMap ; + | rr:template "http://example.com/{id}" + | ] . + | + |map:m_1 a rr:TriplesMap ; + | rml:logicalSource [ a rml:LogicalSource ; + | rml:iterator "//film" ; + | rml:referenceFormulation ql:XPath ; + | rml:source "https://shexml.herminiogarcia.com/files/films.xml" + | ] ; + | rr:predicateObjectMap _:b0 ; + | rr:predicateObjectMap [ a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{country}" ; + | rr:termType rr:IRI + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant schema:countryOfOrigin + | ] + | ] ; + | rr:predicateObjectMap [ a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{crew/directors/director}" ; + | rr:termType rr:IRI + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant schema:director + | ] + | ] ; + | rr:predicateObjectMap [ a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{crew/music}" ; + | rr:termType rr:IRI + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant schema:musicBy + | ] + | ] ; + | rr:predicateObjectMap [ a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:template "http://dbpedia.org/resource/{crew//screenwritter}" ; + | rr:termType rr:IRI + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant :screenwritter + | ] + | ] ; + | rr:predicateObjectMap [ a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:language "en" ; + | rr:template "{name}" ; + | rr:termType rr:Literal + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant schema:name + | ] + | ] ; + | rr:predicateObjectMap [ a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:template "{year}" ; + | rr:termType rr:Literal + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant :year + | ] + | ] ; + | rr:subjectMap [ a rr:SubjectMap ; + | rr:template "http://example.com/{@id}" + | ] . + | + |_:b0 a rr:PredicateObjectMap ; + | rr:objectMap [ a rr:ObjectMap ; + | rr:template "http://schema.org/Movie" ; + | rr:termType rr:IRI + | ] ; + | rr:predicateMap [ a rr:predicateMap ; + | rr:constant + | ] . + |""".stripMargin + + private val expectedShExOutput = + """ + |PREFIX : + |PREFIX xs: + |PREFIX dbr: + |PREFIX schema: + |PREFIX rdf: + | + |:Films IRI { + | rdf:type [ schema:Movie ] ; + | schema:name [ @en ] ; + | :year xs:string ; + | schema:countryOfOrigin [ dbr:~ ] ; + | schema:director [ dbr:~ ] ; + | :screenwritter [ dbr:~ ] + ; + | schema:musicBy [ dbr:~ ] ; + |} + |""".stripMargin.trim.replaceAll("\\s+", " ") + + private val expectedShapeMapOutput = ":3@:Films,:4@:Films,:1@:Films,:2@:Films" + + private val precompilationInput = + """ + |PREFIX : + |PREFIX xs: + |SOURCE films_xml_file + |SOURCE films_json_file + |IMPORT + |EXPRESSION films + | + |:Films :[films.id] { + | :type :Film ; + | :name [films.name] ; + | :year [films.year] xs:gYear ; + | :country [films.country] ; + | :director [films.directors] ; + | :actor @:Actor ; + | :actor @:Actress ; + |} + |IMPORT + |""".stripMargin + + private val expectedPrecompilationOutput = + """ + |PREFIX : + |PREFIX xs: + |SOURCE films_xml_file + |SOURCE films_json_file + |ITERATOR film_xml { + | FIELD id <@id> + | FIELD name + | FIELD year + | FIELD country + | FIELD directors + | ITERATOR actors { + | FIELD name + | FIELD role + | FIELD film <../../@id> + | } + | ITERATOR actresses { + | FIELD name + | FIELD role + | FIELD film <../../@id> + | } + |} + |ITERATOR film_json { + | PUSHED_FIELD id + | FIELD name + | FIELD year + | FIELD country + | FIELD directors + | ITERATOR actors { + | FIELD name + | FIELD role + | POPPED_FIELD film + | } + |} + |EXPRESSION films + | + |:Films :[films.id] { + | :type :Film ; + | :name [films.name] ; + | :year [films.year] xs:gYear ; + | :country [films.country] ; + | :director [films.directors] ; + | :actor @:Actor ; + | :actor @:Actress ; + |} + |:Actor :[films.actors.name] { + | :name [films.actors.name] ; + | :appear_on :[films.actors.film] ; + |} + | + |:Actress :[films.actresses.name] { + | :name [films.actresses.name] ; + | :appear_on :[films.actresses.film] ; + |} + |""".stripMargin.trim.replaceAll("\\s+", " ") + + private val expectedDatabaseOutput = + """ + |@prefix : . + |@prefix schema: . + |@prefix dbr: . + |@prefix xs: . + | + |:9 :country "USA" ; + | :director "Christopher Nolan" ; + | :name "Batman Begins"@en ; + | :type :Film ; + | :year "2005"^^xs:gYear . + | + |:8 :country "UK" ; + | :director "Christopher Nolan" ; + | :name "Tenet"@en ; + | :type :Film ; + | :year "2020"^^xs:gYear . + |""".stripMargin + + private def executeCapturingStdout(f: CommandLine => Unit): String = { + val byteOutputStream = new ByteArrayOutputStream() + val picocliCommandLine = new CommandLine(new Main()) + .setPosixClusteredShortOptionsAllowed(false) + .setHelpFactory(PicocliLeftAlignedLayout.createCustomizedUsageHelp()) + Console.withOut(byteOutputStream) { + f(picocliCommandLine) + } + byteOutputStream.toString + } + + private def compareTwoRDFModels(model1: String, format1: String, model2: String, format2: String): Boolean = { + val result = ModelFactory.createDefaultModel() + result.read(new ByteArrayInputStream(model1.getBytes), null, format1) + val expectedResult = ModelFactory.createDefaultModel() + expectedResult.read(new ByteArrayInputStream(model2.getBytes), null, format2) + result.isIsomorphicWith(expectedResult) + } + + test("CLI generates Turtle output by default") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-nu", "-id")) + assert(compareTwoRDFModels(executionResult, "Turtle", expectedTurtleOutput, "Turtle")) + } + + test("CLI generates Turtle output by default without inference of datatypes") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-nu")) + assert(compareTwoRDFModels(executionResult, "Turtle", expectedTurtleWithoutInferenceOfDatatypesOutput, "Turtle")) + } + + test("CLI generates non valid Turtle file when not using the normalise URIs option") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath)) + val result = ModelFactory.createDefaultModel() + val parsingResult = Try(result.read(new ByteArrayInputStream(executionResult.getBytes), null, "Turtle")) + assert(parsingResult.isFailure) + } + + test("CLI generates expected Turtle output when run in parallel") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-nu", "-id", "--parallel")) + assert(compareTwoRDFModels(executionResult, "Turtle", expectedTurtleOutput, "Turtle")) + } + + test("CLI generates expected Turtle output when run in parallel, all aspect option and number of threads 10") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-nu", "-id", "--parallel", "--parallelAspects", "all", "--nThreads", "10")) + assert(compareTwoRDFModels(executionResult, "Turtle", expectedTurtleOutput, "Turtle")) + } + + test("CLI generates expected Turtle output when run in parallel, shapes aspect option and number of threads 20") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-nu", "-id", "--parallel", "--parallelAspects", "shapes", "--nThreads", "10")) + assert(compareTwoRDFModels(executionResult, "Turtle", expectedTurtleOutput, "Turtle")) + } + + test("CLI generates expected Turtle output when run in parallel, queries aspect option") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-nu", "-id", "--parallel", "--parallelAspects", "queries")) + assert(compareTwoRDFModels(executionResult, "Turtle", expectedTurtleOutput, "Turtle")) + } + + test("CLI outputs to a file") { + executeCapturingStdout(cl => cl.execute("-m", filepath, "-nu", "-id", "-o", "testOutput.ttl")) + val file = scala.io.Source.fromFile(new File("testOutput.ttl")) + assert(compareTwoRDFModels(file.mkString, "Turtle", expectedTurtleOutput, "Turtle")) + file.close() + } + + test("CLI generates RDF/XML output") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-nu", "-id", "-f", "RDF/XML")) + assert(compareTwoRDFModels(executionResult, "RDF/XML", expectedTurtleOutput, "Turtle")) + } + + test("CLI generates SHACL open shapes output") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-sh")) + assert(compareTwoRDFModels(executionResult, "Turtle", expectedOpenShaclShapes, "Turtle")) + } + + test("CLI generates SHACL closed shapes output") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-shc")) + assert(compareTwoRDFModels(executionResult, "Turtle", expectedClosedShaclShapes, "Turtle")) + } + + test("CLI generates RML output") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-r")) + assert(compareTwoRDFModels(executionResult, "Turtle", expectedRMLOutput, "Turtle")) + } + + test("CLI generates prettified RML output") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-rp")) + assert(compareTwoRDFModels(executionResult, "Turtle", expectedRMLPrettifiedOutput, "Turtle")) + } + + test("CLI generates ShEx output") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-s")) + assert(executionResult.stripMargin.trim.replaceAll("\\s+", " ") == expectedShExOutput) + } + + test("CLI generates ShapeMap output") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", filepath, "-sm")) + assert(executionResult.stripMargin.trim.replaceAll("\\s+", " ") == expectedShapeMapOutput) + } + + test("CLI precompiles ShExML file from stdin") { + val byteInputStream = new ByteArrayInputStream(precompilationInput.getBytes()) + System.setIn(byteInputStream) + val executionResult = executeCapturingStdout(cl => cl.execute("-m", "-", "-pc")) + System.setIn(System.in) + assert(executionResult.stripMargin.trim.replaceAll("\\s+", " ") == expectedPrecompilationOutput) + } + + test("CLI generates expected output from a database") { + val executionResult = executeCapturingStdout(cl => cl.execute("-m", "src/test/resources/databaseTestInput.shexml", "-u", "root", "-p", "root")) + assert(compareTwoRDFModels(executionResult, "Turtle", expectedDatabaseOutput, "Turtle")) + } + +} From 0314d42663534d902830c6e16d71b9e6a6749513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herminio=20Garc=C3=ADa=20Gonz=C3=A1lez?= Date: Tue, 9 Sep 2025 14:45:10 +0200 Subject: [PATCH 15/15] Version 0.6.0 --- build.sbt | 2 +- src/main/scala/com/herminiogarcia/shexml/Main.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index dfeac84..fd77a43 100644 --- a/build.sbt +++ b/build.sbt @@ -4,7 +4,7 @@ lazy val shexml = project .in(file(".")) .settings( name := "ShExML", - version := "0.5.5-SNAPSHOT", + version := "0.6.0", scalaVersion := "3.3.6", crossScalaVersions := Seq("2.12.20", "2.13.16", "3.3.6"), libraryDependencies ++= Seq( diff --git a/src/main/scala/com/herminiogarcia/shexml/Main.scala b/src/main/scala/com/herminiogarcia/shexml/Main.scala index c2c4c6a..5e99613 100644 --- a/src/main/scala/com/herminiogarcia/shexml/Main.scala +++ b/src/main/scala/com/herminiogarcia/shexml/Main.scala @@ -20,7 +20,7 @@ object Main { } } -@Command(name = "ShExML", version = Array("v0.5.5-SNAPSHOT"), +@Command(name = "ShExML", version = Array("v0.6.0"), mixinStandardHelpOptions = true, sortOptions = false, description = Array("Map and merge heterogeneous data sources with a Shape Expressions based syntax"))