diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e28c45fc..ac31cdf2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,10 +20,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v2 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: Build java runtime with Gradle uses: gradle/actions/setup-gradle@v3 diff --git a/doc/guide/Installation.md b/doc/guide/Installation.md index 815a33e3..717f1374 100644 --- a/doc/guide/Installation.md +++ b/doc/guide/Installation.md @@ -2,8 +2,8 @@ Installation ============ The VO-DML tooling is based around [gradle](https://gradle.org) (currently version 8) which itself -is based on Java. It is recommended that a minimum of JDK 11 is installed -(JDK 17 has also been tested) using a package manager for your OS and +is based on Java. It is recommended that a minimum of JDK 17 is installed +using a package manager for your OS and similarly use a package manager for gradle installation. Although if you are working with a repository that already has a `gradelw` file at the top level, then that can be used in place of the gradle command, and it will handle the downloading and running of the correct gradle version. diff --git a/models/ivoa/build.gradle.kts b/models/ivoa/build.gradle.kts index 5cbed5a7..a39012fc 100644 --- a/models/ivoa/build.gradle.kts +++ b/models/ivoa/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("net.ivoa.vo-dml.vodmltools") version "0.5.6" + id("net.ivoa.vo-dml.vodmltools") version "0.5.7" // id ("com.diffplug.spotless") version "5.17.1" `maven-publish` id("io.github.gradle-nexus.publish-plugin") version "1.3.0" diff --git a/models/sample/sample/vo-dml/Sample.vo-dml.xml b/models/sample/sample/vo-dml/Sample.vo-dml.xml index 7dc05c9e..44cc976c 100644 --- a/models/sample/sample/vo-dml/Sample.vo-dml.xml +++ b/models/sample/sample/vo-dml/Sample.vo-dml.xml @@ -330,8 +330,8 @@ 1 - http://purl.org/astronomy/vocab/DataObjectTypes/DataObjectType - http://purl.org/astronomy/vocab/DataObjectTypes + http://www.ivoa.net/rdf/object-type#DataObjectType + http://www.ivoa.net/rdf/object-type diff --git a/models/sample/test/serializationExample.vo-dml.xml b/models/sample/test/serializationExample.vo-dml.xml index 33984d43..62649860 100644 --- a/models/sample/test/serializationExample.vo-dml.xml +++ b/models/sample/test/serializationExample.vo-dml.xml @@ -8,7 +8,7 @@ 1.0 - 2024-05-31T11:12:57Z + 2024-10-07T08:26:18Z null IVOA-v1.0.vo-dml.xml @@ -127,6 +127,9 @@ 1 1 + + http://www.ivoa.net/rdf/product-type + @@ -166,7 +169,7 @@ 1 - 1 + -1 diff --git a/models/sample/test/serializationExample.vodsl b/models/sample/test/serializationExample.vodsl index 1ac62a96..1048536d 100644 --- a/models/sample/test/serializationExample.vodsl +++ b/models/sample/test/serializationExample.vodsl @@ -29,12 +29,12 @@ otype Dcont -> BaseC { } otype Econt -> BaseC { - evalue: ivoa:string ""; + evalue: ivoa:string "" semantic in "http://www.ivoa.net/rdf/product-type"; } otype SomeContent "" { ref1 references Refa ""; ref2 references Refb ""; - zval : ivoa:string ""; + zval : ivoa:string @+ ""; con: BaseC @+ as composition ""; } diff --git a/runtime/java/build.gradle.kts b/runtime/java/build.gradle.kts index 6c86c05f..e6d6d5e2 100644 --- a/runtime/java/build.gradle.kts +++ b/runtime/java/build.gradle.kts @@ -6,7 +6,7 @@ plugins { signing } group = "org.javastro.ivoa.vo-dml" -version = "0.7.1" +version = "0.7.2" dependencies { @@ -15,7 +15,7 @@ dependencies { implementation("jakarta.xml.bind:jakarta.xml.bind-api:4.0.0") // implementation("org.glassfish.jaxb:jaxb-runtime:2.3.6") implementation("jakarta.persistence:jakarta.persistence-api:3.1.0") - implementation("com.fasterxml.jackson.core:jackson-databind:2.15.1") + implementation("com.fasterxml.jackson.core:jackson-databind:2.17.0") implementation("org.hibernate.orm:hibernate-core:6.2.7.Final") implementation("org.slf4j:slf4j-api:1.7.36") @@ -40,12 +40,16 @@ dependencies { //} java { -// modularity.inferModulePath.set(false) // still can only build on java 1.8 toolchain { - languageVersion.set(JavaLanguageVersion.of(11)) + languageVersion = JavaLanguageVersion.of(17) } withJavadocJar() withSourcesJar() + +} + +tasks.javadoc { + (options as StandardJavadocDocletOptions).tags("TODO","IMPL") } tasks.test { @@ -110,6 +114,9 @@ publishing.publications.withType(MavenPublication::class.java).forEach { publica } } println ("java property skipSigning= " + project.hasProperty("skipSigning")) +repositories { + mavenCentral() +} signing { diff --git a/runtime/java/src/main/java/org/ivoa/vodml/jpa/AttributeConverters.java b/runtime/java/src/main/java/org/ivoa/vodml/jpa/AttributeConverters.java new file mode 100644 index 00000000..5d45ba05 --- /dev/null +++ b/runtime/java/src/main/java/org/ivoa/vodml/jpa/AttributeConverters.java @@ -0,0 +1,128 @@ +/* + * Created on 7 Oct 2024 + * Copyright 2024 Paul Harrison (paul.harrison@manchester.ac.uk) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License in file LICENSE + */ + +package org.ivoa.vodml.jpa; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import jakarta.persistence.AttributeConverter; + +/** + * Attribute converters to convert lists to comma separated strings. + * @author Paul Harrison (paul.harrison@manchester.ac.uk) + */ +public class AttributeConverters { + + private static final String SPLIT_CHAR = ";"; + public static class StringListConverter implements AttributeConverter, String> { + + + /** + * {@inheritDoc} + * overrides @see jakarta.persistence.AttributeConverter#convertToDatabaseColumn(java.lang.Object) + */ + @Override + public String convertToDatabaseColumn(List attribute) { + return attribute != null ? String.join(SPLIT_CHAR, attribute) : ""; + } + + /** + * {@inheritDoc} + * overrides @see jakarta.persistence.AttributeConverter#convertToEntityAttribute(java.lang.Object) + */ + @Override + public List convertToEntityAttribute(String dbData) { + return dbData != null ? Arrays.asList(dbData.split(SPLIT_CHAR)) : new ArrayList() ; + } + + } + + public static abstract class NumberListConverter implements AttributeConverter, String> { + + /** + * {@inheritDoc} + * overrides @see jakarta.persistence.AttributeConverter#convertToDatabaseColumn(java.lang.Object) + */ + @Override + public String convertToDatabaseColumn(List attribute) { + + if(attribute!= null) + { + return attribute.stream().map(T::toString).collect(Collectors.joining (SPLIT_CHAR)); + } + else + { + return ""; + } + } + + + } + public static class IntListConverter extends NumberListConverter + { + + /** + * {@inheritDoc} + * overrides @see jakarta.persistence.AttributeConverter#convertToEntityAttribute(java.lang.Object) + */ + @Override + public List convertToEntityAttribute(String dbData) { + if (dbData != null) + { + return Stream.of(dbData.split(SPLIT_CHAR)).map(Integer::parseInt).toList(); + } + else return new ArrayList<>(); + + } + + } + public static class DoubleListConverter extends NumberListConverter + { + + /** + * {@inheritDoc} + * overrides @see jakarta.persistence.AttributeConverter#convertToEntityAttribute(java.lang.Object) + */ + @Override + public List convertToEntityAttribute(String dbData) { + if (dbData != null) + { + return Stream.of(dbData.split(SPLIT_CHAR)).map(Double::parseDouble).toList(); + } + else return new ArrayList<>(); + + } + + } + public static class BooleanListConverter extends NumberListConverter + { + + /** + * {@inheritDoc} + * overrides @see jakarta.persistence.AttributeConverter#convertToEntityAttribute(java.lang.Object) + */ + @Override + public List convertToEntityAttribute(String dbData) { + if (dbData != null) + { + return Stream.of(dbData.split(SPLIT_CHAR)).map(Boolean::parseBoolean).toList(); + } + else return new ArrayList<>(); + + + } + + } +} + + diff --git a/runtime/java/src/main/java/org/ivoa/vodml/testing/AutoDBRoundTripTest.java b/runtime/java/src/main/java/org/ivoa/vodml/testing/AutoDBRoundTripTest.java index d380f0a3..40b48650 100644 --- a/runtime/java/src/main/java/org/ivoa/vodml/testing/AutoDBRoundTripTest.java +++ b/runtime/java/src/main/java/org/ivoa/vodml/testing/AutoDBRoundTripTest.java @@ -33,7 +33,7 @@ public abstract class AutoDBRoundTripTest , I, T extends * @param e the entity to be tested. */ public abstract void testEntity(T e); - + @Test void testRDBRoundTrip() { @@ -46,7 +46,8 @@ void testRDBRoundTrip() testEntity(result.retval); } - + + } diff --git a/runtime/java/src/main/java/org/ivoa/vodml/validation/AbstractBaseValidation.java b/runtime/java/src/main/java/org/ivoa/vodml/validation/AbstractBaseValidation.java index ed169640..b709b57a 100644 --- a/runtime/java/src/main/java/org/ivoa/vodml/validation/AbstractBaseValidation.java +++ b/runtime/java/src/main/java/org/ivoa/vodml/validation/AbstractBaseValidation.java @@ -39,7 +39,17 @@ import org.ivoa.vodml.jpa.JPAManipulationsForObjectType; import org.ivoa.vodml.validation.ModelValidator.ValidationResult; +/** + * Base Class for doing validating tests. + */ public abstract class AbstractBaseValidation { + /** + * Do a JSON round trip of a model instance. + * @param m A model instance. + * @return The result of the round trip test. + * @param The Model class . + * @throws JsonProcessingException + */ protected RoundTripResult roundTripJSON(VodmlModel m) throws JsonProcessingException { T model = m.management().theModel(); if(m.management().hasReferences()) @@ -57,6 +67,10 @@ protected RoundTripResult roundTripJSON(VodmlModel m) throws JsonProc } + /** + * The result of doing a round trip test. + * @param the model class. + */ public static class RoundTripResult { public final boolean isValid; public final T retval; @@ -66,6 +80,18 @@ public static class RoundTripResult { } } + /** + * Do a XML round trip of a model instance. + * @param vodmlModel a model instance. + * @return the result of doing a round trip. + * @param The model class. + * @throws ParserConfigurationException + * @throws JAXBException + * @throws PropertyException + * @throws TransformerFactoryConfigurationError + * @throws TransformerConfigurationException + * @throws TransformerException + */ protected > RoundTripResult roundtripXML(VodmlModel vodmlModel) throws ParserConfigurationException, JAXBException, PropertyException, TransformerFactoryConfigurationError, TransformerConfigurationException, TransformerException { @@ -108,7 +134,16 @@ protected > RoundTripResult roundtripXML(VodmlModel(!vc.hasEvents(), modelin); } - + + /** + * Do an RDB round trip of a model instance. + * @param modelManagement Then model management + * @param entity The entity to round trip. + * @return + * @param the model class. + * @param The type of the identifier for the entity. + * @param The type of the entity. + */ protected > RoundTripResult roundtripRDB(ModelManagement modelManagement, T entity) { @@ -118,7 +153,8 @@ protected > RoundTripResult em.persist(entity); em.getTransaction().commit(); I id = entity.getId(); - + String dumpfile = setDbDumpFile(); + if(dumpfile!= null) dumpDbData(em, dumpfile); //flush any existing entities em.clear(); em.getEntityManagerFactory().getCache().evictAll(); @@ -131,7 +167,12 @@ protected > RoundTripResult return new RoundTripResult(true, r); } - + + /** + * Create an Entity manager for a memory-based test database; + * @param puname the persistence unit name of the JPA DB. + * @return the EntityManager for the database. + */ protected EntityManager setupH2Db(String puname){ Map props = new HashMap<>(); @@ -173,7 +214,14 @@ protected EntityManager setupH2Db(String puname){ return em; } - + + /** + * Validate a model instance. This is done via JAXB. + * @param m the model instance. + * @return result of the validation. + * @param the model class. + * @throws JAXBException exception when there is a JAXB problem. + */ protected ValidationResult validateModel(VodmlModel m) throws JAXBException { final ModelDescription desc = m.descriptor(); @@ -198,4 +246,12 @@ protected void dumpDbData(jakarta.persistence.EntityManager em, String filename) }); } + /** + * set the name of the file to which the dbDump is written. The default is null so that no file is written. + * @return the filename. + */ + protected String setDbDumpFile() { + return null; + } + } diff --git a/runtime/java/src/main/java/org/ivoa/vodml/vocabularies/Term.java b/runtime/java/src/main/java/org/ivoa/vodml/vocabularies/Term.java new file mode 100644 index 00000000..51380bd4 --- /dev/null +++ b/runtime/java/src/main/java/org/ivoa/vodml/vocabularies/Term.java @@ -0,0 +1,160 @@ +package org.ivoa.vodml.vocabularies; +/* + * Created on 10/09/2024 by Paul Harrison (paul.harrison@manchester.ac.uk). + */ + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * An IVOA vocabulary Term as described in https://www.ivoa.net/documents/Vocabularies. + */ +public class Term { + + + + /** + * the actual string used in annotating the term. + */ + private final String term; + + /** + * string that should be presented to humans instead of the slightly formalised terms. + */ + private final String label; + + /** + * A description of the term. should be sufficiently precise to allow someone with a certain amount of domain expertise to decide whether a certain "thing" is or is not covered by the term (or more precisely, the underlying concept). + */ + private final String description; + + /** + * Marks whether the term is preliminary and might disappear + */ + private final boolean preliminary; + + /** + * Marks whether the term is deprecated. If deprecated it should not be used in new applications. + */ + private final boolean deprecated; + + private List wider = new ArrayList<>(); + private List narrower = new ArrayList<>(); + private Term parent; + + + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + public Term(@JsonProperty("term") String term, + @JsonProperty("label") String label, + @JsonProperty("description") String description, + @JsonProperty("preliminary") String preliminary, + @JsonProperty("deprecated") String deprecated) { + this.term = term; + this.label = label; + this.description = description; + this.preliminary = preliminary != null; + this.deprecated = deprecated != null; + } + + @JsonProperty + public String getTerm() { + return term; + } + @JsonProperty + public String getLabel() { + return label; + } + @JsonProperty + public String getDescription() { + return description; + } + @JsonProperty + public boolean isPreliminary() { + return preliminary; + } + @JsonProperty + public boolean isDeprecated() { + return deprecated; + } + + + // comparison is only made on term string + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Term term1 = (Term) o; + return Objects.equals(term, term1.term); + } + + @Override + public int hashCode() { + return Objects.hashCode(term); + } + + @Override + public String toString() { + return "Term{" + + "term='" + term + '\'' + + ", label='" + label + '\'' + + ", description='" + description + '\'' + + ", preliminary=" + preliminary + + ", deprecated=" + deprecated + + '}'; + } + + /** + * is the given term wider than this. + * @param t the term. + * @return true if the given term is wider. + */ + public boolean hasWiderTerm(Term t) { + return wider.contains(t); + } + + /** + * add a wider term to the description. + * @param wider the wider term. + */ + public void addWider(Term wider) { + this.wider.add(wider); + } + + /** + * add a narrower term to the description. + * @param term the narrower term. + */ + public void addNarrower(Term term) { + this.narrower.add(term); + } + + + /** + * is the given term narrower than this. + * @param term the term + * @return true if the given term is narrower. + */ + public boolean hasNarrowerTerm(Term term) { + return narrower.contains(term); + } + + /** + * add the parent term. + * @param parent the term that is the parent. + */ + public void addParent(Term parent) { + this.parent= parent; + } + + /** + * Get the parent term to this. + * @return The parent term; + */ + public Term getParent() { + return parent; + } +} diff --git a/runtime/java/src/main/java/org/ivoa/vodml/vocabularies/Vocabulary.java b/runtime/java/src/main/java/org/ivoa/vodml/vocabularies/Vocabulary.java new file mode 100644 index 00000000..5f79f40f --- /dev/null +++ b/runtime/java/src/main/java/org/ivoa/vodml/vocabularies/Vocabulary.java @@ -0,0 +1,120 @@ +package org.ivoa.vodml.vocabularies; +/* + * Created on 10/09/2024 by Paul Harrison (paul.harrison@manchester.ac.uk). + */ + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * an IVOA vocabulary as described in https://www.ivoa.net/documents/Vocabularies. + */ +public class Vocabulary { + + /** + * The terms in the vocabulary. + */ + Map terms = new HashMap<>(); + + public Vocabulary(String url) { + this.url = url; + } + + /** + * The base URL that defines the vocabulary. + */ + private String url; + + /** + * Load a vocabulary. Note that this is implemented by requesting the "desise" format for ease. + * @TODO should probably be reimplemented to read RDF + * @param url the location of the vocabulary + * @return the vocabulary + */ + public static Vocabulary load(String url) { + + Vocabulary vocabulary = new Vocabulary(url); + try { + HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build(); + + // read the vocabulary in the 'desise' format + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(url)) + .header("Accept", "application/x-desise+json") + .GET() + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // Check if the response is OK (status code 200) + if (response.statusCode() != 200) { + throw new RuntimeException("cannot load vocabulary : " + response.statusCode()); + } + + // Parse the JSON using Jackson + ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + JsonNode rootNode = objectMapper.readTree(response.body()); + // read the initial terms + for ( var entry : rootNode.get("terms").properties()) { + + ObjectNode term = (ObjectNode) entry.getValue(); + term.put("term", entry.getKey()); + vocabulary.terms.put(entry.getKey(),objectMapper.treeToValue(term, Term.class)); //FIXME the deprecated and preliminary JSON are not being actually written as boolean in desise + } + //connect the wider and narrower. + for ( var entry : rootNode.get("terms").properties()) { + ObjectNode term = (ObjectNode) entry.getValue(); + Term voterm = vocabulary.terms.get(entry.getKey()); + if(term.has("wider")) { + term.get("wider").spliterator().forEachRemaining(e -> voterm.addWider(vocabulary.terms.get(e.textValue()))); + } + if(term.has("narrower")) { + term.get("narrower").spliterator().forEachRemaining(e -> voterm.addNarrower(vocabulary.terms.get(e.textValue()))); + } + if(term.has("parent")) { //FIXME desise does not show parent + voterm.addParent(vocabulary.terms.get(term.get("parent").textValue())); + } + } + } catch (IOException | InterruptedException e) { + throw new RuntimeException("cannot load vocabulary",e); + } + + + + return vocabulary; + } + + /** + * Does the term exist in the vocabulary. + * @param term expressed as a string. + * @return true if the term is in the vocabulary. + */ + public boolean hasTerm(String term) + { + return terms.containsKey(term); + } + + /** + * Fetch a term definition from the vocabulary. + * @param term + * @return + */ + public Optional getTerm(String term) { + return Optional.ofNullable(terms.get(term)); + } + + +} diff --git a/runtime/java/src/test/java/org/ivoa/vodml/vocabularies/VocabularyTest.java b/runtime/java/src/test/java/org/ivoa/vodml/vocabularies/VocabularyTest.java new file mode 100644 index 00000000..0f386585 --- /dev/null +++ b/runtime/java/src/test/java/org/ivoa/vodml/vocabularies/VocabularyTest.java @@ -0,0 +1,49 @@ +package org.ivoa.vodml.vocabularies; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/* + * Created on 11/09/2024 by Paul Harrison (paul.harrison@manchester.ac.uk). + */ + +class VocabularyTest { + + @Test + void load() { + + Vocabulary v = Vocabulary.load("http://www.ivoa.net/rdf/product-type"); + assertNotNull(v); + + Term cube = v.terms.get("cube"); + assertNotNull(cube); + assertTrue(cube.hasWiderTerm(v.terms.get("spatially-resolved-dataset"))); + assertTrue(cube.hasNarrowerTerm(v.terms.get("spectral-cube"))); + + } + + @Test + void deprecated() { + Vocabulary v2 = Vocabulary.load("http://www.ivoa.net/rdf/voresource/relationship_type"); + assertNotNull(v2); + Term term = v2.terms.get("mirror-of"); + System.out.println(term.toString()); + assertTrue(term.isDeprecated(),"should be deprecated"); + + } + + /* FIXME desise does not show parent + @Test + void parent() { + Vocabulary v2 = Vocabulary.load("http://www.ivoa.net/rdf/datalink/core"); + assertNotNull(v2); + Term bias = v2.terms.get("bias"); + assertNotNull(bias); + assertEquals(v2.terms.get("calibration"),bias.getParent()); + + } + + */ + +} \ No newline at end of file diff --git a/tools/ChangeLog.md b/tools/ChangeLog.md index 072accc7..3a53429a 100644 --- a/tools/ChangeLog.md +++ b/tools/ChangeLog.md @@ -55,4 +55,7 @@ * 0.5.5 * allow binding to specify eager fetching for JPA * 0.5.6 - * correct some file URIs for windows \ No newline at end of file + * correct some file URIs for windows +* 0.5.7 + * Added support for validation against IVOA vocabularies + * Added support for rdb serialization of primitive attributes with unbounded multiplicity as colon separated string \ No newline at end of file diff --git a/tools/gradletooling/TODO.md b/tools/gradletooling/TODO.md index b01443e4..8f5fab8f 100644 --- a/tools/gradletooling/TODO.md +++ b/tools/gradletooling/TODO.md @@ -83,6 +83,9 @@ VODML Tooling TODO * before and after serialization, the references need to be processed - it would be nice to do this automatically.... e.g. https://github.com/FasterXML/jackson-databind/issues/279 for jackson. * references * would be nice if the tooling warned when contained references are created bare.... - e.g. the filters in the original sample. +* Vocabularies + * would be good to add in off-line capability - store the desise at generation time and read that if the on-line not accessible + * only does run-time checking - perhaps compile-time would be good? * JAXB * ~~idrefs referred to objects are not being output - http://stackoverflow.com/questions/12914382/marshalling-unmarshalling-fields-to-tag-with-attributes-using-jaxb~~ * make the subsets create substitution group xml (i.e. have elements rather than xsi:type) http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html @@ -116,6 +119,7 @@ VODML Tooling TODO * JSON * allow refs to be serialized/deserialized as ids always.... - for use in APIs.... https://stackoverflow.com/questions/51172496/how-to-dynamically-ignore-a-property-on-jackson-serialization * perhaps have custom written ivoa base schema.... express some better rules... e.g. non neg integer... + * modern usage https://blogs.oracle.com/javamagazine/post/java-json-serialization-jackson # Python production diff --git a/tools/gradletooling/gradle-plugin/build.gradle.kts b/tools/gradletooling/gradle-plugin/build.gradle.kts index a31ca9ff..b07dab6e 100644 --- a/tools/gradletooling/gradle-plugin/build.gradle.kts +++ b/tools/gradletooling/gradle-plugin/build.gradle.kts @@ -14,7 +14,7 @@ plugins { } group = "net.ivoa.vo-dml" -version = "0.5.6" +version = "0.5.7" repositories { mavenLocal() // FIXME remove this when releasing - just here to pick up local vodsl updates @@ -73,10 +73,11 @@ gradlePlugin { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(11))//NB needs to stay at 11 for gradle plugin ATM + languageVersion =JavaLanguageVersion.of(17) } } + sourceSets { main { // slightly complex way of adding the xslt and xsd directories to resources (they are at different levels) diff --git a/tools/gradletooling/gradle-plugin/src/main/kotlin/net/ivoa/vodml/gradle/plugin/VodmlGradlePlugin.kt b/tools/gradletooling/gradle-plugin/src/main/kotlin/net/ivoa/vodml/gradle/plugin/VodmlGradlePlugin.kt index e8537e7f..ed5313e0 100644 --- a/tools/gradletooling/gradle-plugin/src/main/kotlin/net/ivoa/vodml/gradle/plugin/VodmlGradlePlugin.kt +++ b/tools/gradletooling/gradle-plugin/src/main/kotlin/net/ivoa/vodml/gradle/plugin/VodmlGradlePlugin.kt @@ -159,7 +159,7 @@ class VodmlGradlePlugin: Plugin { //add the dependencies for JAXB and JPA - using the hibernate implementation - listOf("org.javastro.ivoa.vo-dml:vodml-runtime:0.7.1", + listOf("org.javastro.ivoa.vo-dml:vodml-runtime:0.7.2", "jakarta.xml.bind:jakarta.xml.bind-api:4.0.0", "org.glassfish.jaxb:jaxb-runtime:4.0.2", // "org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.10", // supports JPA 2.2 diff --git a/tools/gradletooling/sample/build.gradle.kts b/tools/gradletooling/sample/build.gradle.kts index 14ffe157..d05249f6 100644 --- a/tools/gradletooling/sample/build.gradle.kts +++ b/tools/gradletooling/sample/build.gradle.kts @@ -6,7 +6,7 @@ import ru.vyarus.gradle.plugin.python.task.PythonTask * */ plugins { - id("net.ivoa.vo-dml.vodmltools") version "0.5.6" + id("net.ivoa.vo-dml.vodmltools") version "0.5.7" id("com.diffplug.spotless") version "6.25.0" id("ru.vyarus.use-python") version "4.0.0" diff --git a/tools/gradletooling/sample/src/test/java/org/ivoa/dm/notstccoords/CoordsModelDbTest.java b/tools/gradletooling/sample/src/test/java/org/ivoa/dm/notstccoords/CoordsModelDbTest.java new file mode 100644 index 00000000..e3a0ade4 --- /dev/null +++ b/tools/gradletooling/sample/src/test/java/org/ivoa/dm/notstccoords/CoordsModelDbTest.java @@ -0,0 +1,125 @@ +/* + * Created on 5 Nov 2021 + * Copyright 2021 Paul Harrison (paul.harrison@manchester.ac.uk) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License in file LICENSE + */ + +package org.ivoa.dm.notstccoords; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; + +import org.ivoa.dm.ivoa.RealQuantity; +import org.ivoa.dm.ivoa.Unit; +import org.ivoa.vodml.testing.AutoDBRoundTripTest; + +/** + * An example test for the "not coords" model. + * note that this test runs JSON and XML serialisation test as well as validating the model instance. + * @author Paul Harrison (paul.harrison@manchester.ac.uk) + * @since 5 Nov 2021 + */ +class CoordsModelDbTest extends AutoDBRoundTripTest { + + /** logger for this class */ + private static final org.slf4j.Logger logger = + org.slf4j.LoggerFactory.getLogger(CoordsModelDbTest.class); +private AnObject a; + + @Override + public CoordsModel createModel() { + // see + // https://github.com/mcdittmar/ivoa-dm-examples/blob/master/assets/examples/coords/current/instances/astrocoordsys.jovial for jovial version of this test. + Unit deg = new Unit("deg"); + SpaceSys ICRS_SYS = + new SpaceSys() + .withFrame( + SpaceFrame.createSpaceFrame( + f -> { + f.refPosition = new StdRefLocation("TOPOCENTER"); + f.spaceRefFrame = "ICRS"; + f.planetaryEphem = "DE432"; + })); + + TimeSys TIMESYS_TT = + new TimeSys() + .withFrame( + TimeFrame.createTimeFrame( + f -> { + f.refPosition = new StdRefLocation("TOPOCENTER"); + f.timescale = "TT"; + f.refDirection = + new CustomRefLocation() + .withEpoch("J2014.25") + .withPosition( + LonLatPoint.createLonLatPoint( + p -> { + p.lon = new RealQuantity(6.752477, deg); + p.lat = new RealQuantity(-16.716116, deg); + p.dist = new RealQuantity(8.6, new Unit("ly")); + p.coordSys = ICRS_SYS; + })); + })); + GenericSys SPECSYS = + new GenericSys() + .withFrame( + GenericFrame.createGenericFrame( + f -> { + f.refPosition = new StdRefLocation("TOPOCENTER"); + f.planetaryEphem = "DE432"; + })); + + + + // note that this cannot be added directly as it is a dtype... + LonLatPoint llp = new LonLatPoint(new RealQuantity(45.0, deg), new RealQuantity(15.0, deg), new RealQuantity(1.5, new Unit("Mpc")), ICRS_SYS); + a = new AnObject(llp); + CoordsModel modelInstance = new CoordsModel(); + + modelInstance.addReference(TIMESYS_TT); + modelInstance.addReference(SPECSYS); + modelInstance.addReference(ICRS_SYS); + modelInstance.addContent(a); + + + + + return modelInstance; + } + + @Override + public void testModel(CoordsModel coordsModel) { + List ts = coordsModel.getContent(AnObject.class); + assertNotNull(ts); + assertEquals(1, ts.size()); + AnObject ts1 = ts.get(0); + SpaceSys ss = ts1.getPosition().getCoordSys(); + assertNotNull(ss); + + } + +/** + * {@inheritDoc} + * overrides @see org.ivoa.vodml.testing.AutoDBRoundTripTest#entityForDb() + */ +@Override +public AnObject entityForDb() { + return a; + +} + +/** + * {@inheritDoc} + * overrides @see org.ivoa.vodml.testing.AutoDBRoundTripTest#testEntity(org.ivoa.vodml.jpa.JPAManipulationsForObjectType) + */ +@Override +public void testEntity(AnObject e) { + SpaceSys ss = e.getPosition().getCoordSys(); + assertNotNull(ss); + +} +} diff --git a/tools/gradletooling/sample/src/test/java/org/ivoa/dm/notstccoords/CoordsModelTest.java b/tools/gradletooling/sample/src/test/java/org/ivoa/dm/notstccoords/CoordsModelTest.java index bced3c5b..8671f5e2 100644 --- a/tools/gradletooling/sample/src/test/java/org/ivoa/dm/notstccoords/CoordsModelTest.java +++ b/tools/gradletooling/sample/src/test/java/org/ivoa/dm/notstccoords/CoordsModelTest.java @@ -39,7 +39,7 @@ public CoordsModel createModel() { .withFrame( SpaceFrame.createSpaceFrame( f -> { - f.refPosition = new StdRefLocation("TOPOCENTRE"); + f.refPosition = new StdRefLocation("TOPOCENTER"); f.spaceRefFrame = "ICRS"; f.planetaryEphem = "DE432"; })); @@ -49,7 +49,7 @@ public CoordsModel createModel() { .withFrame( TimeFrame.createTimeFrame( f -> { - f.refPosition = new StdRefLocation("TOPOCENTRE"); + f.refPosition = new StdRefLocation("TOPOCENTER"); f.timescale = "TT"; f.refDirection = new CustomRefLocation() @@ -68,7 +68,7 @@ public CoordsModel createModel() { .withFrame( GenericFrame.createGenericFrame( f -> { - f.refPosition = new StdRefLocation("TOPOCENTRE"); + f.refPosition = new StdRefLocation("TOPOCENTER"); f.planetaryEphem = "DE432"; })); diff --git a/tools/gradletooling/sample/src/test/java/org/ivoa/dm/sample/catalog/BaseSourceCatalogueTest.java b/tools/gradletooling/sample/src/test/java/org/ivoa/dm/sample/catalog/BaseSourceCatalogueTest.java index 5194a0fd..1e003a39 100644 --- a/tools/gradletooling/sample/src/test/java/org/ivoa/dm/sample/catalog/BaseSourceCatalogueTest.java +++ b/tools/gradletooling/sample/src/test/java/org/ivoa/dm/sample/catalog/BaseSourceCatalogueTest.java @@ -87,6 +87,7 @@ void setUp() { s -> { s.name = "testSource"; s.classification = SourceClassification.AGN; + s.label = "cepheid"; s.position = createSkyCoordinate( co -> { diff --git a/tools/gradletooling/sample/src/test/java/org/ivoa/dm/serializationsample/SerializationExampleTest.java b/tools/gradletooling/sample/src/test/java/org/ivoa/dm/serializationsample/SerializationExampleTest.java index db7cd7a9..1abe6c88 100644 --- a/tools/gradletooling/sample/src/test/java/org/ivoa/dm/serializationsample/SerializationExampleTest.java +++ b/tools/gradletooling/sample/src/test/java/org/ivoa/dm/serializationsample/SerializationExampleTest.java @@ -1,5 +1,7 @@ package org.ivoa.dm.serializationsample; +import static org.junit.jupiter.api.Assertions.assertEquals; + import java.util.List; import org.junit.jupiter.api.Test; @@ -7,27 +9,64 @@ * Created on 16/05/2023 by Paul Harrison (paul.harrison@manchester.ac.uk). */ public class SerializationExampleTest - extends org.ivoa.vodml.testing.AutoRoundTripTest { + extends org.ivoa.vodml.testing.AutoDBRoundTripTest { - @Override + private MyModelModel themodel; +private SomeContent someContent; +private Refa refa; +private Refb refb; + +@Override public MyModelModel createModel() { - MyModelModel retval = new MyModelModel(); - Refa refa = new Refa("a value"); - Refb refb = new Refb("a name", "another val"); + themodel = new MyModelModel(); + refa = new Refa("a value"); + refb = new Refb("a name", "another val"); - List cc = List.of(new Dcont("a D", "dval"), new Econt("an E", "eval")); + List clist = List.of(new Dcont("a D", "dval"), new Econt("cube", "eval")); - SomeContent c = new SomeContent(refa, refb, "a z val", cc); - retval.addContent(c); + someContent = new SomeContent(refa, refb, List.of("some","z","values"), clist); + themodel.addContent(someContent); - return retval; + return themodel; } @Override - public void testModel(org.ivoa.dm.serializationsample.MyModelModel myModelModel) {} - - @Test - public void testStandaloneList() { - List cc = List.of(new Dcont("a D", "dval"), new Econt("an E", "eval")); + public void testModel(org.ivoa.dm.serializationsample.MyModelModel myModelModel) { + //should test the model integrity } + + + +/** + * {@inheritDoc} + * overrides @see org.ivoa.vodml.testing.AutoDBRoundTripTest#entityForDb() + */ +@Override +public SomeContent entityForDb() { + return someContent; +} + +/** + * {@inheritDoc} + * overrides @see org.ivoa.vodml.testing.AutoDBRoundTripTest#testEntity(org.ivoa.vodml.jpa.JPAManipulationsForObjectType) + */ +@Override +public void testEntity(SomeContent e) { + //test that the array transformation to string working. + assertEquals("some",e.getZval().get(0)); + assertEquals("z",e.getZval().get(1)); + assertEquals("values",e.getZval().get(2)); + +} + +/** + * {@inheritDoc} + * overrides @see org.ivoa.vodml.validation.AbstractBaseValidation#setDbDumpFile() + */ +@Override +protected String setDbDumpFile() { + return "serialization_dump.sql"; + +} + } diff --git a/tools/xslt/common-binding.xsl b/tools/xslt/common-binding.xsl index f619c405..6c6da974 100644 --- a/tools/xslt/common-binding.xsl +++ b/tools/xslt/common-binding.xsl @@ -536,4 +536,10 @@ + + + + + + \ No newline at end of file diff --git a/tools/xslt/jaxb.xsl b/tools/xslt/jaxb.xsl index 17f718ef..0ae15828 100644 --- a/tools/xslt/jaxb.xsl +++ b/tools/xslt/jaxb.xsl @@ -222,10 +222,9 @@ import org.ivoa.vodml.annotation.VodmlRole; import org.ivoa.vodml.ModelContext; import org.ivoa.vodml.nav.ReferenceCache; + import org.ivoa.vodml.vocabularies.Vocabulary; - - - @XmlAccessorType(XmlAccessType.NONE) + @XmlAccessorType(XmlAccessType.NONE) @XmlRootElement @JsonTypeInfo(include=JsonTypeInfo.As.WRAPPER_OBJECT, use=JsonTypeInfo.Id.NAME) @JsonIgnoreProperties({"refmap"}) @@ -268,7 +267,33 @@ }) private List<Object> content = new ArrayList<>(); - + + private static Map<String,Vocabulary> vocabs = new HashMap<>(); + + static { + + + vocabs.put(,Vocabulary.load()); + + } + + /** + * Test if a term is in the vocabulary. + * @param value the value to test + * @param vocabulary the uri for the vocabulary. + * @return + */ + public static boolean isInVocabulary(String value, String vocabulary) + { + if(vocabs.containsKey(vocabulary)) + { + return vocabs.get(vocabulary).hasTerm(value); + } + return false; + } + + + /** * add to model. diff --git a/tools/xslt/jpa.xsl b/tools/xslt/jpa.xsl index 4e0168e8..ebda3531 100644 --- a/tools/xslt/jpa.xsl +++ b/tools/xslt/jpa.xsl @@ -154,9 +154,17 @@ _ - @jakarta.persistence.ElementCollection - @jakarta.persistence.CollectionTable(name = "", joinColumns = @jakarta.persistence.JoinColumn(name="containerId") ) - @jakarta.persistence.Column( name = "", nullable = ) + + + + + + + + + + @jakarta.persistence.Convert(converter=org.ivoa.vodml.jpa.AttributeConverters..class) + @jakarta.persistence.Column( name = "", nullable = ) //FIXME - how to do arrays for JPA. diff --git a/tools/xslt/vo-dml2java.xsl b/tools/xslt/vo-dml2java.xsl index 6922a411..2f98f388 100644 --- a/tools/xslt/vo-dml2java.xsl +++ b/tools/xslt/vo-dml2java.xsl @@ -370,7 +370,15 @@ super(); - this. = ; + + + set; + + + this. = ; + + + } @@ -485,7 +493,14 @@ super (superinstance); - this. = ; + + + set; + + + this. = ; + + } @@ -927,10 +942,10 @@ package ; - + protected ; - + protected ; @@ -1021,6 +1036,12 @@ package ; * @param p value to set */ public void set(final p) { + + if (!) + { + throw new IllegalArgumentException(p+" is not a value in vocabulary "); + } + this. = p; } @@ -1030,47 +1051,14 @@ package ; * @return */ public &bl;with(final p) { - this. = p; + set(p); return this; } - - - - - - - - if ("".equals(vodmlRef)) { - set(([])pValue); - return true; - } - - - - - - - - - - - if ("".equals(vodmlRef)) { - - - set(.fromValue(pValue)); - - - set(new (pValue)); - - - return true; - } - - + @@ -1384,25 +1372,6 @@ package ; - - - /** * Value : diff --git a/tools/xslt/vo-dml2md.xsl b/tools/xslt/vo-dml2md.xsl index ac8df484..44bf55ca 100644 --- a/tools/xslt/vo-dml2md.xsl +++ b/tools/xslt/vo-dml2md.xsl @@ -543,7 +543,7 @@ Subsets - +