From 823694d64eac24a292b810dfd5946ebe93a9be2f Mon Sep 17 00:00:00 2001 From: Paul Harrison Date: Thu, 22 Aug 2024 17:49:28 +0100 Subject: [PATCH 01/10] remove newlines from primitive tooltips --- tools/xslt/vo-dml2md.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 - + From 930c6c6977a5dd39eb542a8351ab2cee0fe4d5a5 Mon Sep 17 00:00:00 2001 From: Paul Harrison Date: Thu, 3 Oct 2024 17:21:55 +0100 Subject: [PATCH 02/10] initial vocabulary classes --- .../org/ivoa/vodml/vocabularies/Term.java | 160 ++++++++++++++++++ .../ivoa/vodml/vocabularies/Vocabulary.java | 98 +++++++++++ .../vodml/vocabularies/VocabularyTest.java | 49 ++++++ 3 files changed, 307 insertions(+) create mode 100644 runtime/java/src/main/java/org/ivoa/vodml/vocabularies/Term.java create mode 100644 runtime/java/src/main/java/org/ivoa/vodml/vocabularies/Vocabulary.java create mode 100644 runtime/java/src/test/java/org/ivoa/vodml/vocabularies/VocabularyTest.java 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..c62997de --- /dev/null +++ b/runtime/java/src/main/java/org/ivoa/vodml/vocabularies/Vocabulary.java @@ -0,0 +1,98 @@ +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.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; + } +} 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 From b682baaf8c64168458a95781a8414f10da82c320 Mon Sep 17 00:00:00 2001 From: Paul Harrison Date: Fri, 4 Oct 2024 11:56:52 +0100 Subject: [PATCH 03/10] some javadoc cleanup --- .../validation/AbstractBaseValidation.java | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) 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..f96c2093 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) { @@ -131,7 +166,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 +213,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(); From 56832a41348620e13571799c9c99735b9ce50505 Mon Sep 17 00:00:00 2001 From: Paul Harrison Date: Fri, 4 Oct 2024 16:40:25 +0100 Subject: [PATCH 04/10] support for throwing illegalArgument exception if value not in vocabulary this is clearly only runtime checking --- .../ivoa/vodml/vocabularies/Vocabulary.java | 152 ++++++++++-------- tools/xslt/common-binding.xsl | 6 + tools/xslt/jaxb.xsl | 33 +++- tools/xslt/vo-dml2java.xsl | 81 +++------- 4 files changed, 147 insertions(+), 125 deletions(-) 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 index c62997de..5f79f40f 100644 --- a/runtime/java/src/main/java/org/ivoa/vodml/vocabularies/Vocabulary.java +++ b/runtime/java/src/main/java/org/ivoa/vodml/vocabularies/Vocabulary.java @@ -17,6 +17,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Optional; import java.util.Set; /** @@ -24,75 +25,96 @@ */ 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()))); + /** + * 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()); } - if(term.has("narrower")) { - term.get("narrower").spliterator().forEachRemaining(e -> voterm.addNarrower(vocabulary.terms.get(e.textValue()))); + + // 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 } - if(term.has("parent")) { //FIXME desise does not show parent - voterm.addParent(vocabulary.terms.get(term.get("parent").textValue())); + //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); - } + } 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); + } - return vocabulary; - } + /** + * Fetch a term definition from the vocabulary. + * @param term + * @return + */ + public Optional getTerm(String term) { + return Optional.ofNullable(terms.get(term)); + } + + } 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/vo-dml2java.xsl b/tools/xslt/vo-dml2java.xsl index 6922a411..53e419b2 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. = ; + + } @@ -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 : From bb69c2c2233ef29e238ced2150e7e4a88ce34a71 Mon Sep 17 00:00:00 2001 From: Paul Harrison Date: Fri, 4 Oct 2024 16:41:32 +0100 Subject: [PATCH 05/10] update tests to support vocab checking --- models/sample/sample/vo-dml/Sample.vo-dml.xml | 4 ++-- models/sample/test/serializationExample.vo-dml.xml | 5 ++++- models/sample/test/serializationExample.vodsl | 2 +- .../test/java/org/ivoa/dm/notstccoords/CoordsModelTest.java | 6 +++--- .../org/ivoa/dm/sample/catalog/BaseSourceCatalogueTest.java | 1 + .../dm/serializationsample/SerializationExampleTest.java | 4 ++-- 6 files changed, 13 insertions(+), 9 deletions(-) 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..6c38acdd 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-09-10T15:34:00Z null IVOA-v1.0.vo-dml.xml @@ -127,6 +127,9 @@ 1 1 + + http://www.ivoa.net/rdf/product-type + diff --git a/models/sample/test/serializationExample.vodsl b/models/sample/test/serializationExample.vodsl index 1ac62a96..623a461e 100644 --- a/models/sample/test/serializationExample.vodsl +++ b/models/sample/test/serializationExample.vodsl @@ -29,7 +29,7 @@ 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 ""; 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..9d5e5e11 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 @@ -15,7 +15,7 @@ public MyModelModel createModel() { Refa refa = new Refa("a value"); Refb refb = new Refb("a name", "another val"); - List cc = List.of(new Dcont("a D", "dval"), new Econt("an E", "eval")); + List cc = List.of(new Dcont("a D", "dval"), new Econt("cube", "eval")); SomeContent c = new SomeContent(refa, refb, "a z val", cc); retval.addContent(c); @@ -28,6 +28,6 @@ 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")); + List cc = List.of(new Dcont("a D", "dval"), new Econt("image", "eval")); } } From 0e6746d56a2ddcf392f72862d33638b10149c9d8 Mon Sep 17 00:00:00 2001 From: Paul Harrison Date: Fri, 4 Oct 2024 16:41:54 +0100 Subject: [PATCH 06/10] update min java to 17 --- doc/guide/Installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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. From 721dc22ffcc0338bc1b071fe8b084fc829d840a3 Mon Sep 17 00:00:00 2001 From: Paul Harrison Date: Mon, 7 Oct 2024 16:03:30 +0100 Subject: [PATCH 07/10] added initial support for serializing primitive attribute as delimited string in rdb note that the xml and json serializations treat this as a list with each element separate. --- .../test/serializationExample.vo-dml.xml | 4 +- models/sample/test/serializationExample.vodsl | 2 +- .../vodml/testing/AutoDBRoundTripTest.java | 5 +- .../validation/AbstractBaseValidation.java | 11 ++- .../SerializationExampleTest.java | 67 +++++++++++++++---- tools/xslt/jpa.xsl | 14 +++- tools/xslt/vo-dml2java.xsl | 4 +- 7 files changed, 82 insertions(+), 25 deletions(-) diff --git a/models/sample/test/serializationExample.vo-dml.xml b/models/sample/test/serializationExample.vo-dml.xml index 6c38acdd..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-09-10T15:34:00Z + 2024-10-07T08:26:18Z null IVOA-v1.0.vo-dml.xml @@ -169,7 +169,7 @@ 1 - 1 + -1 diff --git a/models/sample/test/serializationExample.vodsl b/models/sample/test/serializationExample.vodsl index 623a461e..1048536d 100644 --- a/models/sample/test/serializationExample.vodsl +++ b/models/sample/test/serializationExample.vodsl @@ -34,7 +34,7 @@ otype Econt -> BaseC { otype SomeContent "" { ref1 references Refa ""; ref2 references Refb ""; - zval : ivoa:string ""; + zval : ivoa:string @+ ""; con: BaseC @+ as composition ""; } 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 f96c2093..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 @@ -153,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(); @@ -245,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/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 9d5e5e11..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("cube", "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("image", "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/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 53e419b2..2f98f388 100644 --- a/tools/xslt/vo-dml2java.xsl +++ b/tools/xslt/vo-dml2java.xsl @@ -942,10 +942,10 @@ package ; - + protected ; - + protected ; From 96ffc24e81b36c946cf80b22c5e9e4f452c73c6e Mon Sep 17 00:00:00 2001 From: Paul Harrison Date: Mon, 7 Oct 2024 16:05:09 +0100 Subject: [PATCH 08/10] Prepare to release version 0.5.7 --- models/ivoa/build.gradle.kts | 2 +- runtime/java/build.gradle.kts | 15 +++++++++++---- tools/ChangeLog.md | 5 ++++- tools/gradletooling/TODO.md | 4 ++++ .../gradletooling/gradle-plugin/build.gradle.kts | 5 +++-- .../ivoa/vodml/gradle/plugin/VodmlGradlePlugin.kt | 2 +- tools/gradletooling/sample/build.gradle.kts | 2 +- 7 files changed, 25 insertions(+), 10 deletions(-) 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/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/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" From 19e635caeae7d3e1d604fdbcce87b2cd18a4a1cb Mon Sep 17 00:00:00 2001 From: Paul Harrison Date: Mon, 7 Oct 2024 16:22:00 +0100 Subject: [PATCH 09/10] update to java 17 this is now the minimum version --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 45910fcd4ced31044c534799a423d952b103cdae Mon Sep 17 00:00:00 2001 From: Paul Harrison Date: Mon, 7 Oct 2024 16:29:04 +0100 Subject: [PATCH 10/10] add some forgotten files --- .../ivoa/vodml/jpa/AttributeConverters.java | 128 ++++++++++++++++++ .../dm/notstccoords/CoordsModelDbTest.java | 125 +++++++++++++++++ 2 files changed, 253 insertions(+) create mode 100644 runtime/java/src/main/java/org/ivoa/vodml/jpa/AttributeConverters.java create mode 100644 tools/gradletooling/sample/src/test/java/org/ivoa/dm/notstccoords/CoordsModelDbTest.java 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/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); + +} +}