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
-
+