diff --git a/README.md b/README.md index 1657563..4caaa76 100755 --- a/README.md +++ b/README.md @@ -1 +1,159 @@ -# Java API for Thing Descriptions of WoT (JDT) \ No newline at end of file +# Java API for Thing Descriptions of WoT (JDTs) +[![Maven Central](https://img.shields.io/badge/Maven%20Central-v0.1.6-orange)](https://search.maven.org/search?q=g:%22es.upm.fi.oeg%22%20AND%20a:%22wot-jtd%22) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![GitHub stars](https://img.shields.io/github/stars/Naereen/StrapDown.js.svg?style=social&label=Star&maxAge=2592000)](https://github.com/oeg-upm/wot-jtd/stargazers) + +The JDT is an ORM implementation of the current [Thing Description](https://www.w3.org/TR/wot-thing-description/) model standardised by the [W3C Web of Things group](https://www.w3.org/WoT/). The current features are: + * Serialise: + * Serialise any Thing Description as a Java Object, i.e., a JDT + * Serialise a JDT from a JSON-LD framed document + * Serialise a JDT from a set of RDF triples + * Round trip-translation: + * Translate from a JSON-LD framed document into a set of equivalent RDF triples + * Translate a set of RDF triples into its equivalent JSON-LD framed document + * Validation **(coming soon)** + * Validate a JTD using [SHACL shapes](https://www.w3.org/TR/shacl/) + * Validate a JTD using [JSON schema](https://json-schema.org/) + * Validate a JTD according to the [restrictions specified in the standard](https://www.w3.org/TR/wot-thing-description/) + +If you have any feedback or feature suggestion, please let us know posting an issue with the label **feedback** + +## Table of contents + +* Installation +* Model +* Usage: + * Serialisation of JTDs: + * From JSON-LD framed document + * From RDF triples + * Deserialisation of JTDs: + * To JSON-LD framed + * To RDF triples + * JDT validation: + * Using SHACL shapes + * Using JSON schema (**coming soon**) + * Using restrictions in the model (**coming soon**) + + + +## Installation: +Import the JDTs library as a maven dependency, **be sure to specify the latest version**: + +``` + + es.upm.fi.oeg + wot-jtd + 0.1.6 + +``` + +Alternatively, the dependency can be installed manually. First, download the latest jar from the [releases section](), and then install the dependency as follows (**be sure to specify the latest version**): +```` +mvn install:install-file -Dfile=wot-jtd.jar -DgroupId=es.upm.fi.oeg -DartifactId=wot-jtd -Dversion=0.1.6 -Dpackaging=jar +```` + +Check our [Maven Central Repository page](https://search.maven.org/artifact/es.upm.fi.oeg/wot-jtd/0.1.6/jar) to discover other installation options like Gradle Groovy or Kotlin, Scala, and others. + +## Model + +The JDT library implement as Java objects the whole model, and its restrictions, defined in the [Thing Description standard](https://www.w3.org/TR/wot-thing-description/). The overview of the model is the following: + +![Thing Description model](https://www.w3.org/TR/wot-thing-description/visualization/td.png) + + +## Usage + +### Serialisation of JTDs: + +For the next examples, let's assume the following java variables containing the same Thing description: +```` +String strJsonTD = "{ \"@context\": \"https://www.w3.org/2019/wot/td/v1\",\n" + +" \"id\": \"urn:dev:ops:32473-WoTLamp-1234\",\n" + +" \"title\": \"MyLampThing\",\n" + +" \"securityDefinitions\": { \"nosec_sc\": { \"scheme\": \"nosec\" }},\n" + +" \"security\": \"nosec_sc\",\n" + +" \"properties\": {\n" + +" \"status\": {\n" + +" \"type\": \"string\",\n" + +" \"forms\": [{\"href\": \"https://mylamp.example.com/status\"}]\n" + +" }\n" + +" }\n" + +"}"; +```` + +```` +Model modelTD = ModelFactory.createDefaultModel(); +String strRdfTD = "@prefix dc: .\n" + +"@prefix td: .\n" + +"@prefix jsonschema: .\n" + +"@prefix hctl: .\n" + +"\n" + +"\n" + +" dc:title \"MyLampThing\" ;\n" + +" td:hasPropertyAffordance [\n" + +" a ;\n" + +" jsonschema:propertyName \"status\" ;\n" + +" td:hasForm [ hctl:hasTarget ]\n" + +" ] ;\n" + +" td:hasSecurityConfiguration ;\n" + +" td:securityDefinitions [ td:scheme \"nosec\" ] ."; + +##### Read the string variable into the jena model +modelTD.read(new ByteArrayInputStream(strRdfTD.getBytes()), null, "Turtle"); +```` + + + +The following serialisation operations consists of building a JTD object Thing from either a JSON-LD framed representation or a set of RDF triples. +##### From JSON-LD framed document + +```` +JsonObject jsonTD = JTD.parseJson(strJsonTD); +Thing thing = Thing.fromJson(jsonTD); +thing = (Thing) JTD.instantiateFromJson(jsonTD, Thing.class); # Alternativelly +```` +Notice that using the method `JTD.instantiateFromJson(jsonTD, Thing.class)` any other class from the model can be serialised. + +##### From RDF triples +In order to build a JTD object from a set of RDF triples there are two main methods: +##### A) Build a list of JTDs in case that the triples contain more than one Thing resource. +````` +List things = fromRDF(modelTD) +````` +##### B) Build a unique JTDs providing the RDF resource URI. +````` +Thing thing = fromRDF(modelTD, "urn:dev:ops:32473-WoTLamp-1234") +````` + +### Deserialisation of JTDs: + +##### To JSON-LD framed +```` +JsonObject jsonTD = thing.toJson() +jsonTD = JTD.toJson(thing) # Alternativelly +```` +Notice that using the method `JTD.toJson(thing)` any other class from the model can be deserialised. + +##### To RDF triples + +```` +Model modelTD = JTD.toRDF(thing) + # Alternativelly +JsonObject jsonTD = thing.toJson() +modelTD = JTD.toRDF(jsonTD) +```` + +Notice that using the method alternative `JTD.toRDF(jsonTD)` there is actually no need to serialise the JSON-LD framed `jsonTD` as a Java object, it can be directly translated into RDF. + + +### JDT validation + +##### Using SHACL shapes +Currently, the Web of Things provides [an official SHACL shape document](https://github.com/w3c/wot-thing-description/blob/main/validation/td-validation.ttl) for validating Thing Descriptions. This shape, or any other, can be used to validate a JTD Thing as follows: + +```` +String shapesURI = "https://raw.githubusercontent.com/w3c/wot-thing-description/main/validation/td-validation.ttl" +Model shapesGraph = RDFDataMgr.loadModel(shapesURI, Lang.TURTLE); +ValidationReport shapeReport = JTD.validateWithShape(thing, shapesGraph); +```` + +##### Using JSON schema (*comming soon*) +##### Using restrictions in the model (*comming soon*) \ No newline at end of file diff --git a/pom.xml b/pom.xml index 05129af..4ce5afd 100755 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 es.upm.fi.oeg wot-jtd - 0.1.5-SNAPSHOT + 0.2.0 https://oeg-upm.github.io/wot-jtd Java Thing Description API This API aims at assisting developers for handling WoT Thing Descriptions, providing special support for RDF. @@ -48,9 +48,96 @@ - - - + + + jitpack.io + https://jitpack.io + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrh + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + true + false + release + deploy + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + 8 + false + + + + attach-javadocs + + jar + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrh + https://oss.sonatype.org/ + true + + + + @@ -77,6 +164,8 @@ hibernate-validator 6.0.13.Final + + org.glassfish javax.el @@ -107,18 +196,20 @@ commons-logging 1.2 - - - - com.apicatalog - titanium-json-ld - 1.0.0 + + + org.apache.commons + commons-lang3 + 3.11 - - org.glassfish - jakarta.json - 2.0.0 - + + + + com.github.everit-org.json-schema + org.everit.json.schema + 1.12.2 + + @@ -128,6 +219,8 @@ pom + + junit @@ -136,6 +229,7 @@ test + diff --git a/src/main/java/kehio/annotations/RdfContainer.java b/src/main/java/kehio/annotations/RdfContainer.java new file mode 100644 index 0000000..16744c0 --- /dev/null +++ b/src/main/java/kehio/annotations/RdfContainer.java @@ -0,0 +1,17 @@ +package kehio.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface RdfContainer { + String[] ignore() default {}; + RdfUrlMap[] prefixes() default {}; + RdfUrlMap[] aliases(); // if property is present in alias, overrides the ignore properties + String[] identifiers(); +} diff --git a/src/main/java/kehio/annotations/RdfDatatype.java b/src/main/java/kehio/annotations/RdfDatatype.java new file mode 100644 index 0000000..fc3e34e --- /dev/null +++ b/src/main/java/kehio/annotations/RdfDatatype.java @@ -0,0 +1,19 @@ +package kehio.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface RdfDatatype { + String value() default ""; + String lang() default ""; + String datatype() default ""; + boolean sinkLang() default false; + boolean sinkDatatype() default false; +} + diff --git a/src/main/java/wot/jtd/annotations/RdfObjectProperty.java b/src/main/java/kehio/annotations/RdfDatatypeGroup.java similarity index 69% rename from src/main/java/wot/jtd/annotations/RdfObjectProperty.java rename to src/main/java/kehio/annotations/RdfDatatypeGroup.java index e61db54..7a2af68 100644 --- a/src/main/java/wot/jtd/annotations/RdfObjectProperty.java +++ b/src/main/java/kehio/annotations/RdfDatatypeGroup.java @@ -1,4 +1,4 @@ -package wot.jtd.annotations; +package kehio.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; @@ -9,6 +9,8 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @Inherited -public @interface RdfObjectProperty { +public @interface RdfDatatypeGroup { String value() default ""; + boolean byLang() default false; + boolean byDatatype() default false; } diff --git a/src/main/java/wot/jtd/annotations/RdfAnyProperty.java b/src/main/java/kehio/annotations/RdfId.java similarity index 75% rename from src/main/java/wot/jtd/annotations/RdfAnyProperty.java rename to src/main/java/kehio/annotations/RdfId.java index ecd008c..f51948e 100644 --- a/src/main/java/wot/jtd/annotations/RdfAnyProperty.java +++ b/src/main/java/kehio/annotations/RdfId.java @@ -1,4 +1,4 @@ -package wot.jtd.annotations; +package kehio.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; @@ -7,8 +7,8 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) +@Target({ElementType.FIELD}) @Inherited -public @interface RdfAnyProperty { +public @interface RdfId { String value() default ""; } diff --git a/src/main/java/kehio/annotations/RdfObject.java b/src/main/java/kehio/annotations/RdfObject.java new file mode 100644 index 0000000..8793fd4 --- /dev/null +++ b/src/main/java/kehio/annotations/RdfObject.java @@ -0,0 +1,17 @@ +package kehio.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface RdfObject { + String value() default ""; + String base() default ""; + RdfUrlMap[] aliases() default {}; + boolean strict() default false; // if true only matches aliases +} diff --git a/src/main/java/kehio/annotations/RdfObjectGroup.java b/src/main/java/kehio/annotations/RdfObjectGroup.java new file mode 100644 index 0000000..6f09932 --- /dev/null +++ b/src/main/java/kehio/annotations/RdfObjectGroup.java @@ -0,0 +1,18 @@ +package kehio.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface RdfObjectGroup { + String value() default ""; + String key() default ""; + boolean includeKey() default true; + RdfUrlMap[] aliases() default {}; + +} diff --git a/src/main/java/wot/jtd/annotations/RdfType.java b/src/main/java/kehio/annotations/RdfPropertiesContainer.java similarity index 54% rename from src/main/java/wot/jtd/annotations/RdfType.java rename to src/main/java/kehio/annotations/RdfPropertiesContainer.java index 4d82f1c..3345895 100644 --- a/src/main/java/wot/jtd/annotations/RdfType.java +++ b/src/main/java/kehio/annotations/RdfPropertiesContainer.java @@ -1,4 +1,4 @@ -package wot.jtd.annotations; +package kehio.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; @@ -7,8 +7,10 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD, ElementType.TYPE}) +@Target(ElementType.FIELD) @Inherited -public @interface RdfType { - String[] types() default {}; +public @interface RdfPropertiesContainer { + //boolean onlyDatatypes() default false; + String[] ignore() default {}; + RdfUrlMap[] prefixes() default {}; } diff --git a/src/main/java/wot/jtd/annotations/RdfDatatypeProperty.java b/src/main/java/kehio/annotations/RdfUrlMap.java similarity index 78% rename from src/main/java/wot/jtd/annotations/RdfDatatypeProperty.java rename to src/main/java/kehio/annotations/RdfUrlMap.java index c377852..25d1322 100644 --- a/src/main/java/wot/jtd/annotations/RdfDatatypeProperty.java +++ b/src/main/java/kehio/annotations/RdfUrlMap.java @@ -1,4 +1,4 @@ -package wot.jtd.annotations; +package kehio.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; @@ -9,6 +9,7 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @Inherited -public @interface RdfDatatypeProperty { +public @interface RdfUrlMap { String value() default ""; + String key() default ""; } diff --git a/src/main/java/kehio/mapper/Kehio.java b/src/main/java/kehio/mapper/Kehio.java new file mode 100755 index 0000000..cf599ac --- /dev/null +++ b/src/main/java/kehio/mapper/Kehio.java @@ -0,0 +1,228 @@ +package kehio.mapper; + +import java.io.ByteArrayInputStream; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.Set; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.vocabulary.RDF; + +public class Kehio { + + protected static final Resource KEHIO_TYPE = ResourceFactory.createResource("http://kehio.com/model#Thing"); + private static final List mappers = new ArrayList<>(); + static { + + // Order of inclusion in the list matters + mappers.add(new RdfIdMapper()); + mappers.add(new RdfDatatypeGroupMapper()); + mappers.add(new RdfDatatypeMapper()); + + mappers.add(new RdfObjectGroupMapper()); + mappers.add(new RdfObjectMapper()); + + } + + + public static Object serializeClass(Class clazz, Model model, Resource subject) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, URISyntaxException { + Object object = null; + + object = createInstance(clazz); + Class clazzFull = Class.forName(clazz.getName()); + // Retrieve fields from super-classes + Field[] fields = extractFields(clazzFull); + instantiateObject(object, fields, model, subject); + + return object; + } + + private static Field[] extractFields(Class clazz) throws ClassNotFoundException { + // Extract fields + Field[] fields = clazz.getDeclaredFields(); + // Extract super class fields + AnnotatedType superAnnotatedClazz = clazz.getAnnotatedSuperclass(); + if(superAnnotatedClazz!=null) { + Class clazzFull = Class.forName(superAnnotatedClazz.getType().getTypeName()); + if(!clazzFull.equals(Object.class)) { + Field[] superFields = extractFields(clazzFull); + // Join current fields and super fields + fields = ArrayUtils.addAll(fields, superFields); + } + } + return fields; + } + + private static void instantiateObject(Object object, Field[] fields, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException, URISyntaxException { + if(object!=null) { + Set processedProperties = new HashSet<>(); + for (int index=0; index < fields.length; index++) { + Field field = fields[index]; + Set correctlyProcessedProperty = processSerialiseFieldAnnotation(field, object, model, subject); + if(correctlyProcessedProperty!=null) + processedProperties.addAll(correctlyProcessedProperty); + } + // add unknown RDF properties + enhanceObjectWithUnknownProperties(fields, processedProperties, object, model, subject); + // add unknown RDF triples + enhanceObjectWithUnknownTriples(fields, processedProperties, object, model, subject); + } + } + + private static void enhanceObjectWithUnknownProperties(Field[] fields, Set processedProperties, Object object, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException, URISyntaxException { + RdfPropertiesContainerMapper mapperContainer = new RdfPropertiesContainerMapper(); + mapperContainer.setPropertiesNotToContain(processedProperties); + int unknownAnnotations = 0; + for (int index=0; index < fields.length; index++) { + Field field = fields[index]; + if(mapperContainer.hasProcesableAnnotation(field)) { + if(unknownAnnotations == 0) + mapperContainer.fromRdfToObject(field, object, model, subject); + unknownAnnotations++; + }else if(unknownAnnotations > 1) { + throw new IllegalArgumentException("A Java class can be annotated only with one Container notation"); + } + } + } + + private static void enhanceObjectWithUnknownTriples(Field[] fields, Set processedProperties, Object object, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException, URISyntaxException { + RdfContainerMapper mapperContainer = new RdfContainerMapper(); + mapperContainer.setPropertiesNotToContain(processedProperties); + int unknownAnnotations = 0; + for (int index=0; index < fields.length; index++) { + Field field = fields[index]; + if(mapperContainer.hasProcesableAnnotation(field)) { + if(unknownAnnotations == 0) + mapperContainer.fromRdfToObject(field, object, model, subject); + unknownAnnotations++; + }else if(unknownAnnotations > 1) { + throw new IllegalArgumentException("A Java class can be annotated only with one Container notation"); + } + } + } + + private static Set processSerialiseFieldAnnotation(Field field, Object object, Model model, Resource subject) { + Set properties = null; + try { + for (int index=0; index < mappers.size(); index++) { + RdfMapper serialiser = mappers.get(index); + if(serialiser.hasProcesableAnnotation(field)) { + Property property = serialiser.fromRdfToObject(field, object, model, subject); + + properties = new HashSet<>(); + if(property!=null) + properties.add(property); + break; + } + } + }catch(Exception e) { + throw new IllegalArgumentException(e.toString()); + } + return properties; + } + + private static Object createInstance(Class clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + return clazz.getConstructor().newInstance(); + } + + + + // -- Deserialisation methods + + + public static Model deserializeClass(Object object) throws IllegalArgumentException, IllegalAccessException, URISyntaxException, ClassNotFoundException { + return deserializeClassExtended(object).getValue(); + } + + public static Model deserializeClass(Object object, Map prefixes) throws IllegalArgumentException, IllegalAccessException, URISyntaxException, ClassNotFoundException { + return deserializeClassExtended(object, prefixes).getValue(); + } + + protected static Entry deserializeClassExtended(Object object) throws IllegalArgumentException, IllegalAccessException, URISyntaxException, ClassNotFoundException { + return deserializeClassExtended(object, null); + } + + protected static Entry deserializeClassExtended(Object object, Map prefixes) throws IllegalArgumentException, IllegalAccessException, URISyntaxException, ClassNotFoundException { + Model model = ModelFactory.createDefaultModel(); + if(prefixes!=null && !prefixes.isEmpty()) + model.setNsPrefixes(prefixes); + + Class clazzFull = object.getClass(); + // Retrieve fields from super-classes + Field[] fields = extractFields(clazzFull); + Resource subject = instantiateModel(object, fields, model); + + return Map.entry(subject, model); + } + + + + private static Resource instantiateModel(Object object, Field[] fields, Model model) throws IllegalArgumentException, IllegalAccessException, URISyntaxException { + Resource subject = null; + if(object!=null) { + subject = findSubjectResource(fields,object, model); + model.remove(subject, RDF.type, Kehio.KEHIO_TYPE); + + for (int index=0; index < fields.length; index++) { + Field field = fields[index]; + field.setAccessible(true); + Object instantiatedField = field.get(object); + if(instantiatedField!=null) + processDeserialiseFieldAnnotation(field, object, model, subject); + } + } + return subject; + } + + private static void processDeserialiseFieldAnnotation(Field field, Object object, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException, URISyntaxException { + List mappersAux = new ArrayList<>(mappers); + mappersAux.add(new RdfPropertiesContainerMapper()); + mappersAux.add(new RdfContainerMapper()); + for (int index=0; index < mappersAux.size(); index++) { + RdfMapper mapper = mappersAux.get(index); + if(!(mapper instanceof RdfIdMapper) && mapper.hasProcesableAnnotation(field)) { + mapper.fromObjectToRdf(field, object, model, subject); + break; + + } + } + } + + private static Resource findSubjectResource(Field[] fields, Object object, Model model) throws IllegalArgumentException, IllegalAccessException, URISyntaxException { + RdfIdMapper idMapper = new RdfIdMapper(); + Resource subject = model.createResource(); + int rdfIds = 0; + for (int index=0; index < fields.length; index++) { + Field field = fields[index]; + if(idMapper.hasProcesableAnnotation(field)) { + rdfIds++; + if(rdfIds==1) { + idMapper.fromObjectToRdf(field, object, model, null); + }else { + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfId can be used only once in a class,. Please review annotation for attribute ", field.getName())); + } + } + } + // We remove the mapper + if(model.isEmpty()) + model.add(subject, RDF.type, KEHIO_TYPE); + return model.listSubjectsWithProperty(RDF.type, KEHIO_TYPE).next(); + } + + + +} diff --git a/src/main/java/kehio/mapper/KehioUtils.java b/src/main/java/kehio/mapper/KehioUtils.java new file mode 100644 index 0000000..ca9ddfb --- /dev/null +++ b/src/main/java/kehio/mapper/KehioUtils.java @@ -0,0 +1,252 @@ +package kehio.mapper; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Queue; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import org.apache.jena.query.Query; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.query.ResultSet; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.sparql.util.ResultSetUtils; + +//TODO: add more support to SPARQL paths +class KehioUtils { + + protected static final String START_CLASS_TOKEN = "<"; + protected static final String START_SECOND_CLASS_TOKEN = ", "; + protected static final String END_CLASS_TOKEN = ">"; + + private KehioUtils() { + + } + + // -- General methods + + protected static String concatStrings(String ...message) { + StringBuilder builder = new StringBuilder(); + for(int index =0; index < message.length; index++) + builder.append(message[index]); + return builder.toString(); + } + + // -- Data retrieval in RDF methods + + /*protected static List retrieveFromRdfPath(Model model, Resource subject, String propertyPath, Boolean isPath) throws IllegalArgumentException, IllegalAccessException { + List range = null; + if(isPath) { + range = extractPathData( model, subject, propertyPath); + }else { + range = model.listObjectsOfProperty(subject, ResourceFactory.createProperty(propertyPath)).toList(); + } + return range; + }*/ + + protected static List objectNodes(Model model, Resource subject, Property property){ + return model.listObjectsOfProperty(subject, property).toList(); + } + + protected static List objectNodes(Model model, Resource subject, String property){ + return model.listObjectsOfProperty(subject, ResourceFactory.createProperty(property)).toList(); + } + + private static List extractPathData(Model model, Resource subject, String annotationPathValue) throws IllegalArgumentException, IllegalAccessException { + List output = new ArrayList<>(); + Query query = QueryFactory.create(concatStrings("SELECT DISTINCT ?s ?o WHERE { <", subject.getURI(),">",annotationPathValue, " ?o . }")); + QueryExecution qexec = null; + try{ + qexec = QueryExecutionFactory.create(query, model); + ResultSet results = qexec.execSelect(); + output = ResultSetUtils.resultSetToList(results, "?o"); + + } catch (Exception e) { + e.printStackTrace(); + output = null; + }finally { + if (qexec !=null) + qexec.close(); + } + return output; + } + + // -- Datatyped properties methods + protected static final String STRING_CLASS = "java.lang.String"; + protected static final String URI_CLASS = URI.class.getName(); + protected static final String COLLECTION_CLASS = Collection.class.getName(); + + private static final List WRAPPING_PRIMITIVE_TYPES = new ArrayList<>(); + static { + WRAPPING_PRIMITIVE_TYPES.add(STRING_CLASS); + WRAPPING_PRIMITIVE_TYPES.add("java.lang.Long"); + WRAPPING_PRIMITIVE_TYPES.add("java.lang.Float"); + WRAPPING_PRIMITIVE_TYPES.add("java.lang.Double"); + WRAPPING_PRIMITIVE_TYPES.add("java.lang.Character"); + WRAPPING_PRIMITIVE_TYPES.add("java.lang.Boolean"); + WRAPPING_PRIMITIVE_TYPES.add("java.lang.Integer"); + WRAPPING_PRIMITIVE_TYPES.add("java.lang.Short"); + WRAPPING_PRIMITIVE_TYPES.add("java.lang.Byte"); + WRAPPING_PRIMITIVE_TYPES.add("java.lang.Number"); + } + + + + protected static boolean isWrappingPrimitive(Field field) { + return isWrappingPrimitive(field.getType().getName()); + } + + protected static boolean isWrappingPrimitive(String fieldName) { + return WRAPPING_PRIMITIVE_TYPES.contains(fieldName); + } + + + + + protected static boolean isFieldClass(Field field) { + return !KehioUtils.isWrappingPrimitive(field) && !KehioUtils.isCollection(field); + } + + protected static boolean isFieldString(Field field) { + return field.getType().equals(String.class); + } + + protected static boolean isFieldURI(Field field) { + return field.getType().equals(URI.class); + } + + // Collections methods + + + + public static boolean isCollection(Field field) { + Type fieldType = field.getType(); + Boolean correctType = fieldType.equals(Collection.class) || fieldType.equals(List.class) || fieldType.equals(Set.class); + correctType = correctType || fieldType.equals(Queue.class) || fieldType.equals(Deque.class) || fieldType.equals(SortedSet.class); + return correctType; + } + + protected static String extractCollectionType(Field field) { + ParameterizedType pt = (ParameterizedType) field.getGenericType(); + String typeName = pt.getTypeName(); + typeName = typeName.substring(typeName.indexOf(KehioUtils.START_CLASS_TOKEN)+1, typeName.indexOf(KehioUtils.END_CLASS_TOKEN)); + return typeName; + } + + public static boolean isCollectionOfWrappingPrimitive(Field field) { + Boolean correctType = isCollection(field) ; + correctType &= field.getGenericType() instanceof ParameterizedType; + if(correctType) { + String innerValue = extractCollectionType(field); + correctType &= KehioUtils.isWrappingPrimitive(innerValue); + } + return correctType; + } + + + + + // Map methods + + protected static Entry extractMapTypes(Field field) { + ParameterizedType pt = (ParameterizedType) field.getGenericType(); + String typeName = pt.getTypeName(); + typeName = typeName.substring(typeName.indexOf(KehioUtils.START_CLASS_TOKEN)+1, typeName.indexOf(KehioUtils.END_CLASS_TOKEN)); + String[] mapTypes = typeName.split(", "); + return Map.entry(mapTypes[0], mapTypes[1]); + } + + protected static Class extractMapValueType(Field field){ + Class clazz = null; + try { + String mapType = KehioUtils.extractMapTypes(field).getValue(); + clazz = Class.forName(mapType); + }catch(Exception e) { + throw new IllegalArgumentException(e.toString()); + } + return clazz; + } + + // other + + public static boolean isURI(String url){ + Boolean isURL = false; + try { + URI uri = new URI(url); + isURL = uri.isAbsolute() ;//contains(":"); // true && (true is implicit as far as no exception is thrown) + } catch (Exception exception) { + isURL = false; + } + return isURL; + } + + public static boolean isValidResource(String url) { + Boolean isURL = false; + try { + ResourceFactory.createResource(url); + isURL = true; + }catch(Exception e) { + isURL = false; + } + return isURL; + } + + // -- Instantiation methods + + /** + * This method receives a field ({@link Collection}, {@link Set}, {@link List}, {@link Queue}, {@link Deque}, or {@link Sortedset}) belonging to an object, and also, a generic collection containing its instantiating values.

+ * As a result, this method instantiates the field of the object with the provided collection. + * @param field the field ({@link Collection}, {@link Set}, {@link List}, {@link Queue}, {@link Deque}, or {@link Sortedset}) + * @param instantiatedCollection the instantiated collection + * @param object the generic object that has the provided field and which will be instantiated with the provided collection + * @throws IllegalArgumentException in case that the field is not one of {@link Collection}, {@link Set}, {@link List}, {@link Queue}, {@link Deque}, or {@link Sortedset} + * @throws IllegalAccessException in case the field does not belongs to the provided object + */ + protected static void instantiateCollection(Field field, Collection instantiatedCollection, Object object) throws IllegalArgumentException, IllegalAccessException { + Type fieldType = field.getType(); + Collection collection = null; + if(fieldType.equals(Collection.class) || fieldType.equals(List.class)) { + collection = instantiatedCollection; + }else if(fieldType.equals(Set.class)) { + collection = new HashSet<>(instantiatedCollection); + }else if(fieldType.equals(Queue.class) || fieldType.equals(Deque.class)) { + collection = new LinkedList<>(instantiatedCollection); + }else if(fieldType.equals(SortedSet.class)) { + collection = new TreeSet<>(instantiatedCollection); + }else{ + String illegalMessage = KehioUtils.concatStrings("@RdfDatatype and/or @RdfObject can be used with Collections, List, Set, SortedSet, Queue, Dequeue. Please create an issue to add more java data structures. Please review annotation for attribute ",field.getName()); + throw new IllegalArgumentException(illegalMessage); + } + if(collection!=null && !collection.isEmpty()) + field.set(object, collection); + } + + protected static void instantiateField(Field field, Object object, Object fieldValue) throws IllegalArgumentException, IllegalAccessException { + if(fieldValue!=null) + field.set(object, fieldValue); + } + + protected static Object instantiatedField(Field field, Object object) throws IllegalArgumentException, IllegalAccessException { + return field.get(object); + } + + + + +} diff --git a/src/main/java/kehio/mapper/RdfContainerMapper.java b/src/main/java/kehio/mapper/RdfContainerMapper.java new file mode 100644 index 0000000..7263867 --- /dev/null +++ b/src/main/java/kehio/mapper/RdfContainerMapper.java @@ -0,0 +1,324 @@ +package kehio.mapper; + +import java.lang.reflect.Field; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; + +import kehio.annotations.RdfContainer; +import kehio.annotations.RdfUrlMap; + + +class RdfContainerMapper implements RdfMapper{ + + protected Set forbidenRdfProperties; + + public void setPropertiesNotToContain(Set processedProperties) { + this.forbidenRdfProperties = processedProperties; + } + + @Override + public boolean hasProcesableAnnotation(Field field) { + return field.isAnnotationPresent(RdfContainer.class); + } + + @Override + public Property fromRdfToObject(Field field, Object object, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException, URISyntaxException { + field.setAccessible(true); + + PropertiesContainerAnotation annotation = new PropertiesContainerAnotation(field); + Map collectionOfTriples = populateMapFromRDF(annotation, model, subject, true); + + field.set(object, collectionOfTriples); + + return null; + } + + + + private Map populateMapFromRDF(PropertiesContainerAnotation annotation, Model model, Resource subject, boolean firstCall) { + Set ignore = annotation.getPropertiesToIgnore(); + Map collectionOfTriples = new HashMap<>(); + StmtIterator stIterator = model.listStatements(subject, null, (RDFNode) null); + while(stIterator.hasNext()) { + Statement st = stIterator.next(); + + List inverseAliases = annotation.inverseAlias(st.getPredicate()); + if( (!inverseAliases.isEmpty() && !firstCall) || (firstCall && !forbidenRdfProperties.contains(st.getPredicate()) && !ignore.contains(st.getPredicate()))){ + if(inverseAliases.isEmpty()) // if empty add current property, otherwise replaces current predicate with its shorten forms, i.e., inverse alias + inverseAliases.add(st.getPredicate().toString()); + for(int index=0; index < inverseAliases.size(); index++) { + String shortenPredicate = inverseAliases.get(index); + shortenPredicate = shortenURI(model, shortenPredicate); + RDFNode object = st.getObject(); + if(object.isResource()) { + updateCollectionOfTriplesWithResources(annotation, model, collectionOfTriples, shortenPredicate, object.asResource()); + }else { + updateCollectionOfTriplesWithLiterals(collectionOfTriples, shortenPredicate, object.asLiteral().getValue()); + } + } + } + } + // add suject as property if specified in annotation + if(annotation.getIdentifiers()!=null && !annotation.getIdentifiers().isEmpty()) + annotation.getIdentifiers().stream().forEach(id -> collectionOfTriples.put(id, subject.toString())); + + return collectionOfTriples; + } + + + private void updateCollectionOfTriplesWithResources(PropertiesContainerAnotation annotation, Model model, Map collectionOfTriples, String predicate, Resource object){ + + if(!model.contains(object.asResource(), null, (RDFNode) null)) { + // DONE: Si el objecto no existe en el modelo como sujeto : guardarlo como + String shortenObject = shortenURI(model, object.toString()); + collectionOfTriples.put(predicate, shortenObject); + }else { + // DONE: Si el objecto es tambien sujeto en el modelo -> entonces se traduce como un Map) : llamada recurisva + Map nestedResource = populateMapFromRDF(annotation, model, object, false); + // DONE: Si el objecto es tambien sujeto en el modelo y ya existe en el mapa acutal : entonces traducirlos como una collection de Map + updateCollectionOfTriplesWithLiterals(collectionOfTriples, predicate, nestedResource); + + } + } + + /* + * Since objects here are literals we already know that the range of the property are always literals, and thus, as object it will be collection of strings or string + */ + @SuppressWarnings("unchecked") + private void updateCollectionOfTriplesWithLiterals(Map collectionOfTriples, String predicate, Object object) { + Object oldValue = collectionOfTriples.remove(predicate); + if(oldValue!=null) { // already existed + Collection newObjects = new ArrayList<>(); + if(oldValue instanceof Collection) { + newObjects.addAll((Collection) oldValue); + }else { + newObjects.add(oldValue); + } + newObjects.add(object); + collectionOfTriples.put(predicate, newObjects); + }else { + // new element + collectionOfTriples.put(predicate, object); + } + } + + private String shortenURI(Model model, String uri) { + String shortenUri = model.shortForm(uri); + if(shortenUri==null) + shortenUri = uri; + return shortenUri; + } + + // -- + + @Override + public void fromObjectToRdf(Field field, Object object, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException, URISyntaxException { + field.setAccessible(true); + + PropertiesContainerAnotation annotation = new PropertiesContainerAnotation(field); + @SuppressWarnings("unchecked") + Map values = (Map) annotation.getField().get(object); + populateModel(annotation, model, subject, values.entrySet()); + } + + @SuppressWarnings("unchecked") + private void populateModel(PropertiesContainerAnotation annotation, Model model, Resource subject, Set> entries) { + + for (Entry entry : entries) { + Object value = entry.getValue(); + Property property = computeFullProperty(entry.getKey(), model.getNsPrefixMap()); + if (isCollection(value)) { + Collection newProperties = (Collection) value; + nestedElements(annotation, new ArrayList<>(newProperties), model, subject, property); + } else if (isMap(value)) { + resourceObjectToRDF(annotation, model, subject, property, value); + } else if (!isCollection(value) && !isMap(value)) { + keyValueToRDF(annotation, model, subject, property, value); + } + } + } + + @SuppressWarnings("unchecked") + private void resourceObjectToRDF(PropertiesContainerAnotation annotation, Model model, Resource subject, Property property, Object value) { + Resource newSubject = model.createResource(); + Map newEntries = (Map) value; + Optional propertyIdentifier = newEntries.keySet().stream().filter(keyProperty -> annotation.isPropertyIdentifier(keyProperty)).findFirst(); + if(propertyIdentifier.isPresent()) { // if a property in the json/object was set as identifier create a subject with such + String newSubjectStr = newEntries.remove(propertyIdentifier.get()).toString(); + newSubject = model.createResource(newSubjectStr); + } + model.add(subject, property, newSubject); + populateModel(annotation, model, newSubject, newEntries.entrySet()); + } + + private static Boolean isCollection(Object value) { + return value instanceof Collection; + } + + private static Boolean isMap(Object value) { + return value instanceof Map; + } + + @SuppressWarnings("unchecked") + private void nestedElements(PropertiesContainerAnotation annotation, List elements, Model model, Resource subject, Property property ) { + for(int index=0; index < elements.size(); index++) { + Object value = elements.get(index); + if(isCollection(value)) { + Collection newProperties = (Collection) value; + nestedElements(annotation, new ArrayList<>(newProperties), model, subject, property ); + }else if(isMap(value)) { + resourceObjectToRDF(annotation, model, subject, property, value); + }else if( !isMap(value) && !isCollection(value)) { + keyValueToRDF( annotation,model, subject, property, value); + } + } + } + + private static void keyValueToRDF(PropertiesContainerAnotation annotation, Model model, Resource subject, Property property, Object value) { + String url = model.expandPrefix(value.toString()); + + if(!url.equals(value) && KehioUtils.isURI(url) ) { + Property alias = annotation.getAlias(property.getURI()); + model.add(subject, alias, ResourceFactory.createResource(url)); + }else if(KehioUtils.isURI(value.toString())) { + Property alias = annotation.getAlias(property.getURI()); + model.add(subject, alias, ResourceFactory.createResource(value.toString())); + }else { + model.add(subject, property, ResourceFactory.createTypedLiteral(value)); + } + } + + + private Property computeFullProperty(String property, Map prefixes) { + Property computedProperty = ResourceFactory.createProperty(property); + int index = property.indexOf(':'); + if(index>-1) { + String prefix = property.substring(0,index); + String value = property.substring(index+1,property.length()); + String url = prefixes.get(prefix); + if(url!=null) + computedProperty = ResourceFactory.createProperty(url+value); + } + return computedProperty; + } + + + + + + + class PropertiesContainerAnotation{ + + private Field field; + + public PropertiesContainerAnotation(Field field) { + this.field = field; + checkAnnotation(); + } + + + + public Property getAlias(String predicate) { + Map aliases = this.getAliases(); + Property aliasProperty = aliases.get(predicate); + if(aliasProperty==null) + aliasProperty = ResourceFactory.createProperty(predicate); + return aliasProperty; + } + + private void checkAnnotation() { + if(!field.getType().equals(Map.class)) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfBlankContainer must be used only with a Map attribute. Please review annotation in field ", field.getName())); + Entry mapTypes = KehioUtils.extractMapTypes(field); + if(!mapTypes.getKey().contains(KehioUtils.STRING_CLASS)) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfBlankContainer must be used only with a Map that has as key type a String. Please review annotation in field ", field.getName())); + + //if(!KehioUtils.extractMapValueType(field).toString().equals(Object.class.toString())) + // throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfContainer must be used only with a Map that has as value a java generic Object. Please review annotation in field ", field.getName())); + + /* + if (onlyDatatypes() && onlyObjects()) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfContainer can have only one flag marked as true, either 'onlyDatatypes' or 'onlyObjects'. Please review annotation for field ", field.getName())); + + if(onlyDatatypes() && (!mapTypes.getValue().equals(KehioUtils.STRING_CLASS) || ) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfContainer must be used only with a Map attribute. If 'onlyDatatypes' is true, then the values of the map must be String or a Collection of Strings. Please review annotation in field ", field.getName())); + */ + } + + + /* public boolean onlyDatatypes() { + return field.getAnnotation(RdfBlankContainer.class).onlyDatatypes(); + } + + public boolean onlyObjects() { + return field.getAnnotation(RdfBlankContainer.class).onlyObjects(); + }*/ + + public Field getField() { + return field; + } + + public Set getPropertiesToIgnore() { + Set ignore = new HashSet<>(); + String[] ignorable = field.getAnnotation(RdfContainer.class).ignore(); + for(int index=0; index < ignorable.length; index++) { + ignore.add(ResourceFactory.createProperty(ignorable[index])); + } + return ignore; + } + + public Set getIdentifiers(){ + Set identifiers = new HashSet<>(); + String[] rawIdentifiers = field.getAnnotation(RdfContainer.class).identifiers(); + for(int index=0; index < rawIdentifiers.length; index++) { + identifiers.add(rawIdentifiers[index]); + } + return identifiers; + } + + public Boolean isPropertyIdentifier(String property){ + return getIdentifiers().contains(property); + } + + public Map getAliases(){ + Map aliases = new HashMap<>(); + RdfUrlMap[] rawAliases = field.getAnnotation(RdfContainer.class).aliases(); + for(int index=0; index < rawAliases.length; index++) { + aliases.put(rawAliases[index].key(), ResourceFactory.createProperty(rawAliases[index].value())); + } + return aliases; + } + + public List inverseAlias(Property predicate) { + List inverseAlias = new ArrayList<>(); + inverseAlias.addAll( getAliases().entrySet().stream().filter(entry -> entry.getValue().equals(predicate)).map(Entry::getKey).collect(Collectors.toList())); + return inverseAlias; + } + + } + + + + + + + + +} diff --git a/src/main/java/kehio/mapper/RdfDatatypeGroupMapper.java b/src/main/java/kehio/mapper/RdfDatatypeGroupMapper.java new file mode 100644 index 0000000..248b60a --- /dev/null +++ b/src/main/java/kehio/mapper/RdfDatatypeGroupMapper.java @@ -0,0 +1,140 @@ +package kehio.mapper; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.jena.datatypes.RDFDatatype; +import org.apache.jena.datatypes.TypeMapper; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; + +import kehio.annotations.RdfDatatypeGroup; + +class RdfDatatypeGroupMapper implements RdfMapper { + + + @Override + public boolean hasProcesableAnnotation(Field field) { + return field.isAnnotationPresent(RdfDatatypeGroup.class); + } + + @Override + public Property fromRdfToObject(Field field, Object object, Model model, Resource subject) throws IllegalAccessException { + field.setAccessible(true); + + DgroupAnotation anotation = new DgroupAnotation(field); + List rdfNodes = KehioUtils.objectNodes(model, subject, anotation.getAsProperty()); + + Map map = instantiateMap(rdfNodes, anotation); + if(!map.isEmpty()) + KehioUtils.instantiateField(field, object,map); + return anotation.getAsProperty(); + } + + private Map instantiateMap(List rdfNodes, DgroupAnotation anotation ){ + Map map = new HashMap<>(); + for(int index=0; index < rdfNodes.size(); index++) { + RDFNode node = rdfNodes.get(index); + if(node.isLiteral()) { + Literal literal = node.asLiteral(); + if(anotation.isByLang() && !literal.getLanguage().isEmpty()) { + map.put(literal.getLanguage(), literal.getValue().toString()); + }else if(anotation.isByDatatype()) { + map.put(literal.getDatatypeURI(), literal.getValue().toString()); + } + } + } + return map; + } + + + + + // -- from Object to RDF + + @Override + public void fromObjectToRdf(Field field, Object object, Model model, Resource subject) throws IllegalAccessException { + field.setAccessible(true); + + DgroupAnotation anotation = new DgroupAnotation(field); + + @SuppressWarnings("unchecked") + Map values = (Map) field.get(object); + if(values!=null) { + for(Entry entry : values.entrySet()) { + Literal nodeLiteral = buildLiteral(anotation, entry); + if(nodeLiteral!=null) + model.add(subject, anotation.getAsProperty(), nodeLiteral); + } + } + } + + private Literal buildLiteral(DgroupAnotation anotation, Entry entry) { + Literal literal = null; + if(anotation.isByLang()) + literal = ResourceFactory.createLangLiteral(entry.getValue(), entry.getKey()); + if(anotation.isByDatatype()) { + RDFDatatype dt = TypeMapper.getInstance().getTypeByName(entry.getKey()); + literal = ResourceFactory.createTypedLiteral(entry.getValue(), dt); + } + return literal; + } + + + +} + +class DgroupAnotation{ + + private Field field; + + public DgroupAnotation(Field field) { + this.field = field; + checkAnnotation(); + } + + private void checkAnnotation() { + if (getValue()==null || getValue().isEmpty()) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfDatatypeGroup must be initialised with a value, please review annotation for field ", field.getName())); + if(!field.getType().equals(Map.class)) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfDatatypeGroup must be used only with a Map wich keys are always a String and its values ajava wrapping primitive object. Please review annotation in field ", field.getName())); + if(isByLang() && isByDatatype()) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfDatatypeGroup must have as true only one flag, either 'byLang' or 'byDatatype'. Please review annotation in field ", field.getName())); + Entry mapTypes = KehioUtils.extractMapTypes(field); + if(!mapTypes.getKey().equals(KehioUtils.STRING_CLASS)) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfDatatypeGroup must be used with a Map wich keys are always a String. Please review annotation in field ", field.getName())); + if(!mapTypes.getValue().equals(KehioUtils.STRING_CLASS)) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfDatatypeGroup must be used with a Map wich values are always a String. Please review annotation in field ", field.getName())); + } + + public boolean isByLang() { + return field.getAnnotation(RdfDatatypeGroup.class).byLang(); + } + + public boolean isByDatatype() { + return field.getAnnotation(RdfDatatypeGroup.class).byDatatype(); + } + + + public Field getField() { + return field; + } + + + public String getValue() { + return field.getAnnotation(RdfDatatypeGroup.class).value(); + } + + public Property getAsProperty() { + return ResourceFactory.createProperty(field.getAnnotation(RdfDatatypeGroup.class).value()); + } + + +} diff --git a/src/main/java/kehio/mapper/RdfDatatypeMapper.java b/src/main/java/kehio/mapper/RdfDatatypeMapper.java new file mode 100644 index 0000000..21b7a15 --- /dev/null +++ b/src/main/java/kehio/mapper/RdfDatatypeMapper.java @@ -0,0 +1,284 @@ +package kehio.mapper; + +import java.lang.reflect.Field; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import org.apache.jena.datatypes.RDFDatatype; +import org.apache.jena.datatypes.TypeMapper; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.vocabulary.XSD; + +import kehio.annotations.RdfDatatype; + +/** + * Implements all Collection interfaces from https://www.javatpoint.com/collections-in-java + * @author cimmino + * + */ +class RdfDatatypeMapper implements RdfMapper { + + // -- Compatibility method + + @Override + public boolean hasProcesableAnnotation(Field field) { + return field.isAnnotationPresent(RdfDatatype.class); + } + + // -- from RDF to Object methods + + @Override + public Property fromRdfToObject(Field field, Object object, Model model, Resource subject) throws IllegalAccessException { + field.setAccessible(true); + + DatatypeAnotation annotation = new DatatypeAnotation(field); + List fieldValues = serialiseToWrappingPrimitiveCollection(annotation, model, subject); + if(KehioUtils.isWrappingPrimitive(field)) { + if(!fieldValues.isEmpty()) + KehioUtils.instantiateField(field, object, fieldValues.get(0)); + }else if(KehioUtils.isCollectionOfWrappingPrimitive(field)) { + KehioUtils.instantiateCollection(field, fieldValues, object); + }else { + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfDatatype must be used with wrapping primitive types: String, Integer, Boolean, [...]; or a Collection, a List, a Queue, or a Set containing one of these wrapping primitive types. Please review annotation for attribute ",field.getName())); + } + return annotation.getProperty(); + } + + private List serialiseToWrappingPrimitiveCollection(DatatypeAnotation annotation, Model model, Resource subject) { + List fieldValues = new ArrayList<>(); + Field field = annotation.getField(); + List literals = KehioUtils.objectNodes(model, subject, annotation.getProperty()); + for(int index=0; index < literals.size(); index++) { + Object fieldValue = null; + RDFNode node = literals.get(index); + if(node.isLiteral()) { + Literal literal = node.asLiteral(); + if(!KehioUtils.isFieldString(field) && (literal.getValue().getClass().equals(field.getType()) || (literal.getValue() instanceof Number && field.getType().equals(Number.class)))) { + // Non string attribute + fieldValue = literal.getValue(); + }else { + fieldValue = serialiseToString(annotation, literal); + } + } + if(fieldValue!=null) + fieldValues.add(fieldValue); + } + return fieldValues; + } + + private String serialiseToString(DatatypeAnotation annotation, Literal literal) { + String instantiatedValue = null; + String literalValue = literal.getValue().toString(); + if(annotation.isSinkLang()) { + instantiatedValue = KehioUtils.concatStrings(literalValue,"@",literal.getLanguage()); + }else if(annotation.isSinkDatatype()) { + instantiatedValue = KehioUtils.concatStrings(literalValue,"^^",literal.getDatatypeURI()); + }else if(!annotation.getLang().isEmpty() && !literal.getLanguage().isEmpty() && literal.getLanguage().equals(annotation.getLang())) { + instantiatedValue = literalValue; + }else if(!annotation.getDatatype().isEmpty() && literal.getDatatypeURI().equals(annotation.getDatatype())) { + instantiatedValue = literal.getValue().toString(); + }else if(annotation.getDatatype().isEmpty() && literal.getDatatypeURI().equals(XSD.xstring.getURI())){ + instantiatedValue = literal.getValue().toString(); + } + return instantiatedValue; + } + + + + /*private Collection serialiseToCollection(Object object, DatatypeAnotation annotation, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException { + Collection collection = new ArrayList<>(); + String collectionType = KehioUtils.extractCollectionType(annotation.getField()); + + List literals = KehioUtils.objectNodes(model, subject, annotation.getProperty()); + for(int index=0; index < literals.size(); index++) { + RDFNode node = literals.get(index); + if(node.isLiteral()) { + + } + if(fieldValue!=null) + break; + } + } + + + try { + + if(collectionType.equals(KehioUtils.STRING_CLASS)) { + instantiateNonStringCollection(object, dtypeAnnotation, model, subject, collectionClazz); + }else { + instantiateStringCollection(object, dtypeAnnotation, model, subject); + } + } catch(Exception e) { + throw new IllegalArgumentException(e.toString()); + } + + return collection; + } + + private void instantiateNonStringCollection(Object object, DatatypeAnotation annotation, Model model, Resource subject, Class collectionClazz) throws IllegalAccessException { + List nodes = KehioUtils.objectNodes(model, subject, annotation.get); + + // Collection is not string + String datatype = annotation.getDatatype(); + String expectedDatatype = TypeMapper.getInstance().getTypeByClass(collectionClazz).getURI(); + if(!datatype.isEmpty() && !datatype.equals(expectedDatatype)) { + String illegalMessage = KehioUtils.concatStrings("@RdfDatatype error, for field ",annotation.getField().getName(), " it was annotated with the datatype ",datatype," which is incompatible for the Collection<",collectionClazz.getName(),">. Please check the annotation for this field, the datatype should be ",expectedDatatype," or similar"); + throw new IllegalArgumentException(illegalMessage); + } + Collection instantiatedCollection = nodes.stream().filter(node -> node.asLiteral().getDatatypeURI().equals(expectedDatatype)).collect(Collectors.toList()); + KehioUtils.instantiateCollection(dtypeAnnotation.getField(), instantiatedCollection, object); + } + + private void instantiateStringCollection(Object object, DatatypeAnotation dtypeAnnotation, Model model, Resource subject) throws IllegalAccessException { + List literals = KehioUtils.retrieveFromRdfPath(model, subject, dtypeAnnotation.getValue(), dtypeAnnotation.isPath()); + Collection collection = new ArrayList<>(); + for(int index=0; index < literals.size(); index++) { + Literal literal = literals.get(index).asLiteral(); + String value = extractValueFromLiteral(dtypeAnnotation, literal); + collection.add(value); + } + KehioUtils.instantiateCollection(dtypeAnnotation.getField(), collection, object); + }*/ + + + // -- from Object to RDF methods + + + @Override + public void fromObjectToRdf(Field field, Object object, Model model, Resource subject) throws IllegalAccessException, URISyntaxException { + field.setAccessible(true); + + DatatypeAnotation dtypeAnnotation = new DatatypeAnotation(field); + Object attributeValue = field.get(object); + + if(KehioUtils.isWrappingPrimitive(field)) { + buildWrappingPrimitiveRdf(dtypeAnnotation, attributeValue, model, subject); + }else if(KehioUtils.isCollectionOfWrappingPrimitive(field)) { + buildCollectionOfWrappingPrimitiveRdf(dtypeAnnotation, attributeValue, model, subject); + }else { + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfDatatype must be used with wrapping primitive types: String, Integer, Boolean, [...]; or a Collection, a List, a Queue, or a Set containing one of these wrapping primitive types. Please review annotation for attribute ",field.getName())); + } + + } + + @SuppressWarnings("unchecked") + private void buildCollectionOfWrappingPrimitiveRdf(DatatypeAnotation dtypeAnnotation, Object attributeValue, Model model, Resource subject) { + Collection values = (Collection) attributeValue; + Iterator valuesIterator = values.iterator(); + while(valuesIterator.hasNext()) { + Object innerValue = valuesIterator.next(); + buildWrappingPrimitiveRdf(dtypeAnnotation, innerValue, model, subject); + } + } + + private void buildWrappingPrimitiveRdf(DatatypeAnotation dtypeAnnotation, Object attributeValue, Model model, Resource subject) { + if(attributeValue!=null) { + Property property = ResourceFactory.createProperty(dtypeAnnotation.getValue()); + Literal literal = ResourceFactory.createTypedLiteral(attributeValue); + if(!dtypeAnnotation.getDatatype().isEmpty()) { + RDFDatatype dt = TypeMapper.getInstance().getTypeByName(dtypeAnnotation.getDatatype()); + literal = ResourceFactory.createTypedLiteral(attributeValue.toString(), dt); + }else if(!dtypeAnnotation.getLang().isEmpty()) { + literal = ResourceFactory.createLangLiteral(attributeValue.toString(), dtypeAnnotation.getLang()); + }else if(dtypeAnnotation.isSinkDatatype()) { + literal = buildSinkDatatypeLiteral(attributeValue); + }else if(dtypeAnnotation.isSinkLang()) { + literal = buildSinkLangLiteral(attributeValue); + } + model.add(subject, property, literal); + } + } + + + private Literal buildSinkDatatypeLiteral(Object attributeValue) { + String value = attributeValue.toString(); + int splitIndex = value.lastIndexOf("^^")+2; + String dtype = value.substring(splitIndex, value.length()); + dtype = dtype.substring(1, dtype.length()-1); + value = value.substring(0,splitIndex-2); + RDFDatatype dt = TypeMapper.getInstance().getTypeByName(dtype); + return ResourceFactory.createTypedLiteral(value, dt); + } + + private Literal buildSinkLangLiteral(Object attributeValue) { + String value = attributeValue.toString(); + int splitIndex = value.lastIndexOf('@')+1; + String lang = value.substring(splitIndex, value.length()); + value = value.substring(0,splitIndex-1); + return ResourceFactory.createLangLiteral(value, lang); + } + + + + class DatatypeAnotation { + + private Field field; + + public DatatypeAnotation(Field field){ + this.field = field; + checkAnnotationConfiguration(); + } + + private static final String ERROR = "@RdfDatatype error, for field "; + private void checkAnnotationConfiguration() { + if (getValue() == null || getValue().isEmpty()) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfDatatype must be initialised with a value, please review annotation for attribute ",field.getName())); + if(!getDatatype().isEmpty() && isSinkLang()) + throw new IllegalArgumentException(KehioUtils.concatStrings(ERROR,field.getName(), " datatype and flag 'sinkLang' were provided. Please review annotation for attribute ",field.getName()," and keep only one.")); + if(!getLang().isEmpty() && isSinkDatatype()) + throw new IllegalArgumentException(KehioUtils.concatStrings(ERROR,field.getName(), " lang and flag 'sinkDatatype' were provided. Please review annotation for attribute ",field.getName()," and keep only one.")); + if(isSinkLang() && isSinkDatatype()) + throw new IllegalArgumentException(KehioUtils.concatStrings(ERROR,field.getName(), " both flags 'sinkDatatype' and 'sinkLang' were set to True. Please review annotation for attribute ",field.getName()," and keep only one of these flags as True.")); + if(!getDatatype().isEmpty() && !getLang().isEmpty()) + throw new IllegalArgumentException(KehioUtils.concatStrings(ERROR,field.getName(), " a datatype and a lang were provided. Please review annotation for attribute ",field.getName()," and keep only one of these options.")); + if (!getDatatype().isEmpty() && isSinkDatatype()) + throw new IllegalArgumentException(KehioUtils.concatStrings(ERROR ,field.getName(), " a datatype was provided and also 'sinkDatatype' was set to True. Please review annotation for attribute ",field.getName()," and keep only the datatype or the sinkDatatype flag.")); + if (!getLang().isEmpty() && isSinkLang()) + throw new IllegalArgumentException(KehioUtils.concatStrings(ERROR ,field.getName(), " a lang was provided and also 'sinkLang' was set to True. Please review annotation for attribute ",field.getName()," and keep only the lang or the sinkLang flag.")); + if((isSinkLang() || isSinkDatatype()) && !KehioUtils.isCollectionOfWrappingPrimitive(field) && !field.getType().equals(String.class)) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfDatatype error, 'sinkLang' and 'sinkDatatype' are only applicable for String attributes, please review the annotation for attribute ", field.getName())); + //if(isSinkLang() || isSinkDatatype() || !getLang().isEmpty()) + // throw new IllegalArgumentException( KehioUtils.concatStrings(ERROR, field.getName(), " it was used with a Collection containing a wrapping primitive that is not String, in this case flags 'sinkLang' and 'sinkDatatype', and also, 'lang' can not be used.")); + + // TODO: datatype solo se puede usar con un field string y lang tambien + } + + // -- Getters & Setters + + public String getValue() { + return field.getAnnotation(RdfDatatype.class).value().trim(); + } + + public Property getProperty() { + return ResourceFactory.createProperty(field.getAnnotation(RdfDatatype.class).value().trim()); + } + + public String getDatatype() { + return field.getAnnotation(RdfDatatype.class).datatype().trim(); + } + + public String getLang() { + return field.getAnnotation(RdfDatatype.class).lang().trim(); + } + + public boolean isSinkLang() { + return field.getAnnotation(RdfDatatype.class).sinkLang(); + } + + public boolean isSinkDatatype() { + return field.getAnnotation(RdfDatatype.class).sinkDatatype(); + } + + public Field getField() { + return field; + } + } + +} \ No newline at end of file diff --git a/src/main/java/kehio/mapper/RdfIdMapper.java b/src/main/java/kehio/mapper/RdfIdMapper.java new file mode 100644 index 0000000..c83c2e5 --- /dev/null +++ b/src/main/java/kehio/mapper/RdfIdMapper.java @@ -0,0 +1,76 @@ +package kehio.mapper; + +import java.lang.reflect.Field; +import java.net.URI; +import java.net.URISyntaxException; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.vocabulary.RDF; + +import kehio.annotations.RdfId; + +class RdfIdMapper implements RdfMapper{ + + + @Override + public boolean hasProcesableAnnotation(Field field) { + return field.isAnnotationPresent(RdfId.class); + } + + + @Override + public Property fromRdfToObject(Field field, Object object, Model model, Resource subject) throws IllegalAccessException, URISyntaxException { + field.setAccessible(true); + if(field.getType().equals(String.class)) { + instantiateStringField(field, subject, object, model); + }else if(field.getType().equals(URI.class)) { + instantiateURIField(field, subject, object, model); + }else { + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfId can be only used with String or java.net.URI types. Please review annotation for attribute ", field.getName())); + } + return null; + } + + private void instantiateStringField(Field field, Resource objectProperty, Object object, Model model) throws IllegalArgumentException, IllegalAccessException { + if(objectProperty.asNode().isBlank()){ + field.set(object, objectProperty.asNode().getBlankNodeLabel()); + }else if( objectProperty.asNode().isURI()) { + field.set(object, objectProperty.toString()); + }else { + // Nothing happens + } + } + + private void instantiateURIField(Field field, Resource objectProperty, Object object, Model model) throws IllegalArgumentException, IllegalAccessException, URISyntaxException { + if(objectProperty.asNode().isBlank()){ + field.set(object, new URI(objectProperty.asNode().getBlankNodeLabel())); + }else if( objectProperty.asNode().isURI()) { + field.set(object, new URI(objectProperty.toString())); + }else { + // Nothing happens + } + } + + // -- + + @Override + public void fromObjectToRdf(Field field, Object object, Model model, Resource nullSubject) throws IllegalArgumentException, IllegalAccessException, URISyntaxException { + field.setAccessible(true); + checkFieldCompatibility(field); + Object id = field.get(object); + Resource subject = null; + if(id!=null && !id.toString().trim().isEmpty()) { + subject = model.createResource(id.toString().trim()); + model.add(subject, RDF.type, Kehio.KEHIO_TYPE); + } + } + + private void checkFieldCompatibility(Field field) { + if(!field.getType().equals(String.class) && !field.getType().equals(URI.class)) { + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfId can be only used with String or java.net.URI types. Please review annotation for attribute ", field.getName())); + } + } + + +} diff --git a/src/main/java/kehio/mapper/RdfMapper.java b/src/main/java/kehio/mapper/RdfMapper.java new file mode 100644 index 0000000..aa8ab2f --- /dev/null +++ b/src/main/java/kehio/mapper/RdfMapper.java @@ -0,0 +1,17 @@ +package kehio.mapper; + +import java.lang.reflect.Field; +import java.net.URISyntaxException; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.Resource; + +public interface RdfMapper { + + + public boolean hasProcesableAnnotation(Field field); + public Property fromRdfToObject(Field field, Object object, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException, URISyntaxException; + public void fromObjectToRdf(Field field, Object object, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException, URISyntaxException; + +} diff --git a/src/main/java/kehio/mapper/RdfObjectGroupMapper.java b/src/main/java/kehio/mapper/RdfObjectGroupMapper.java new file mode 100644 index 0000000..ee775c5 --- /dev/null +++ b/src/main/java/kehio/mapper/RdfObjectGroupMapper.java @@ -0,0 +1,191 @@ +package kehio.mapper; + +import java.lang.reflect.Field; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; + +import kehio.annotations.RdfObjectGroup; +import kehio.annotations.RdfUrlMap; + +class RdfObjectGroupMapper implements RdfMapper { + + + @Override + public boolean hasProcesableAnnotation(Field field) { + return field.isAnnotationPresent(RdfObjectGroup.class); + } + + @Override + public Property fromRdfToObject(Field field, Object object, Model model, Resource subject) throws IllegalAccessException { + field.setAccessible(true); + + ObjectGroupAnnotation annotation = new ObjectGroupAnnotation(field); + List objectProperties = KehioUtils.objectNodes(model, subject, annotation.getValue()); + + Map instantiation = new HashMap<>(); + for(int index=0; index < objectProperties.size(); index++) { + try { + RDFNode node = objectProperties.get(index); + Object nestedObject = instantiateClassField(field, node.asResource() , model); + String key = instantiateKeyProperty(model, annotation.getGroupKey(), node.asResource(), field); + if(key!=null && nestedObject!=null) { + // Replace agrupation key for mapped value if exists + key = annotation.getGroupKeyInstantiated(key); + // Instantiate object + instantiation.put(key, nestedObject); + } + }catch(Exception e) { + throw new IllegalArgumentException(e.toString()); + } + } + if(!instantiation.isEmpty()) + field.set(object, instantiation); + return annotation.getProperty(); + } + + private String instantiateKeyProperty(Model model, String keyProperty, Resource objectProperty, Field field) { + String key = null; + List objectProperties = KehioUtils.objectNodes(model, objectProperty, keyProperty); + if(objectProperties.size()>1) { + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObjectGroup must point to a unique literal through they 'key' property, more than one were retrieved. please review annotation for attribute ", field.getName())); + }else if(objectProperties.isEmpty()) { + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObjectGroup must point to a unique literal through they 'key' property, zero were retrieved. please review annotation for attribute ", field.getName())); + }else { + RDFNode node = objectProperties.get(0); + if(node.isLiteral()) { + key = node.asLiteral().getString(); + }else { + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObjectGroup must point to a unique literal through they 'key' property, a non-literal was retrieved. please review annotation for attribute ", field.getName())); + } + } + return key; + } + + private Object instantiateClassField(Field field, Resource objectProperty, Model model) { + Object nestedObject = null; + try { + Class clazzFull = KehioUtils.extractMapValueType(field); + nestedObject = Kehio.serializeClass(clazzFull, model, objectProperty.asResource()); + }catch(Exception e) { + throw new IllegalArgumentException(e.toString()); + } + return nestedObject; + } + + + // --- + + + @Override + public void fromObjectToRdf(Field field, Object object, Model model, Resource subject) throws IllegalAccessException, URISyntaxException { + field.setAccessible(true); + + ObjectGroupAnnotation annotation = new ObjectGroupAnnotation(field); + + @SuppressWarnings("unchecked") + Map values = (Map) field.get(object); + + Model nestedModel = buildObjectRdf(annotation, values, subject, model.getNsPrefixMap()); + model.add(nestedModel); + } + + + private Model buildObjectRdf(ObjectGroupAnnotation annotation, Map values, Resource subject, Map prefixes) throws IllegalAccessException { + Model nestedModel = ModelFactory.createDefaultModel(); + + for(Entry entry : values.entrySet()) { + try { + Entry nestedObjects = Kehio.deserializeClassExtended(entry.getValue(), prefixes); + nestedModel.add(subject, ResourceFactory.createProperty(annotation.getValue()), nestedObjects.getKey()); + nestedModel.add(nestedObjects.getValue()); + if(annotation.addKey()) { + // Replace agrgupation key for mapped value if exists + String key = annotation.getGroupKeyInstantiated(entry.getKey()); + // inject into RDF + String groupKey = annotation.getGroupKey(); + nestedModel.add(nestedObjects.getKey(), ResourceFactory.createProperty(groupKey), key); + } + }catch(Exception e) { + throw new IllegalArgumentException(e.toString()); + } + } + return nestedModel; + } + + + // --- + + + private class ObjectGroupAnnotation{ + private Field field; + + public ObjectGroupAnnotation(Field field) { + this.field = field; + checkAnnotationRestrictions(); + } + + private void checkAnnotationRestrictions() { + String annotationValue = getValue(); + String anotationKey = getGroupKey(); + if (annotationValue==null || annotationValue.isEmpty()) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObjectGroup must be initialised with a value. Please review annotation for attribute ", field.getName())); + if(anotationKey==null || anotationKey.isEmpty()) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObjectGroup must be initialised with a key that must be a datatype property. Please review annotation for attribute ", field.getName())); + Entry mapTypes = KehioUtils.extractMapTypes(field); + if(!mapTypes.getKey().equals(KehioUtils.STRING_CLASS)) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObjectGroup must be used with a Map which keys are Strings. Please review annotation for attribute ", field.getName())); + if(KehioUtils.isWrappingPrimitive(mapTypes.getValue())) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObjectGroup must be used with a Map which values are non-wrapping primitive objects. Please review annotation for attribute ", field.getName())); + + } + + private String getValue() { + return field.getAnnotation(RdfObjectGroup.class).value(); + } + + private Property getProperty() { + return ResourceFactory.createProperty(field.getAnnotation(RdfObjectGroup.class).value()); + } + + private String getGroupKey() { + return field.getAnnotation(RdfObjectGroup.class).key(); + } + + private Boolean addKey() { + return field.getAnnotation(RdfObjectGroup.class).includeKey(); + } + + + private Map getMaps(){ + Map processedMap = new HashMap<>(); + RdfUrlMap[] maps = field.getAnnotation(RdfObjectGroup.class).aliases(); + if(maps!=null) { + for(int index=0; index < maps.length; index++) { + RdfUrlMap map = maps[index]; + processedMap.put(map.key(), map.value()); + } + } + return processedMap; + } + + private String getGroupKeyInstantiated(String key) { + Map maps = getMaps(); + if(maps.containsKey(key)) + key = maps.get(key); + return key; + } + + } + +} + diff --git a/src/main/java/kehio/mapper/RdfObjectMapper.java b/src/main/java/kehio/mapper/RdfObjectMapper.java new file mode 100644 index 0000000..e6d7016 --- /dev/null +++ b/src/main/java/kehio/mapper/RdfObjectMapper.java @@ -0,0 +1,305 @@ +package kehio.mapper; + +import java.lang.reflect.Field; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; + +import kehio.annotations.RdfObject; +import kehio.annotations.RdfUrlMap; + +class RdfObjectMapper implements RdfMapper { + + + @Override + public boolean hasProcesableAnnotation(Field field) { + return field.isAnnotationPresent(RdfObject.class); + } + + + @Override + public Property fromRdfToObject(Field field, Object object, Model model, Resource subject) throws IllegalAccessException, URISyntaxException { + field.setAccessible(true); + + ObjectAnnotation annotation = new ObjectAnnotation(field); + + if(KehioUtils.isCollection(field)) { + // Collection case + Collection instantiatedCollection = initialiseObjectCollection(annotation, subject, model); + KehioUtils.instantiateCollection(field, instantiatedCollection, object); + } else { + // Class, String, or URI case + Object instantiatedField = serialiseUnitary(annotation, subject, model); + KehioUtils.instantiateField(field, object, instantiatedField); + } + return annotation.getProperty(); + } + + + private Object serialiseUnitary(ObjectAnnotation annotation, Resource subject, Model model) { + Object instantiatedObject = null; + List objectProperties = KehioUtils.objectNodes(model, subject, annotation.getProperty()); + if(objectProperties.size()==1) { + RDFNode objectProperty = objectProperties.get(0); + if(isResource(objectProperty)) { + Field field = annotation.getField(); + if(KehioUtils.isFieldString(field)) { + instantiatedObject = serialiseStringField(objectProperty, annotation); + }else if(KehioUtils.isFieldURI(field)) { + instantiatedObject = serialiseURIField(objectProperty); + } else { + instantiatedObject = serialiseClassField(field.getType().getCanonicalName(), objectProperty, model); + } + } + } + + return instantiatedObject; + } + + private String serialiseStringField(RDFNode objectProperty, ObjectAnnotation annotation) { + String instantiatedObject = null; + String base = annotation.getBase(); + if(objectProperty.asNode().isBlank()){ + instantiatedObject = objectProperty.asNode().getBlankNodeLabel().replace(base, ""); + }else if( objectProperty.asNode().isURI()) { + instantiatedObject = objectProperty.toString(); + instantiatedObject = instantiatedObject.replace(base, ""); + } + // Change URL for alias value + if(instantiatedObject!=null) { + String instantiatedObjectAlias = annotation.getAliasKeyInstantiated(instantiatedObject); + if(instantiatedObjectAlias!=null) + instantiatedObject = instantiatedObjectAlias; + if(annotation.getStrict() && instantiatedObjectAlias==null) + instantiatedObject=null; + } + + return instantiatedObject; + } + + private URI serialiseURIField(RDFNode objectProperty) { + URI instantiatedObject = null; + try { + if(objectProperty.asNode().isBlank()){ + instantiatedObject = new URI(objectProperty.asNode().getBlankNodeLabel()); + }else if( objectProperty.asNode().isURI()) { + instantiatedObject = new URI(objectProperty.toString()); + } + }catch(Exception e) { + throw new IllegalArgumentException(e.toString()); + } + return instantiatedObject; + } + + private Object serialiseClassField(String className, RDFNode objectProperty, Model model) { + Object instantiatedObject = null; + try { + Class clazzFull = Class.forName(className); + instantiatedObject = Kehio.serializeClass(clazzFull, model, objectProperty.asResource()); + }catch(Exception e) { + throw new IllegalArgumentException(e.toString()); + } + return instantiatedObject; + } + + private boolean isResource(RDFNode objectProperty) { + return objectProperty.asNode().isBlank() || objectProperty.asNode().isURI(); + } + + private Collection initialiseObjectCollection(ObjectAnnotation annotation, Resource subject, Model model) throws IllegalAccessException { + Collection collection = new ArrayList<>(); + List objectProperties = KehioUtils.objectNodes(model, subject, annotation.getProperty()); + for(int index=0; index < objectProperties.size(); index++) { + RDFNode node = objectProperties.get(index); + if(node.isResource()) { + try { + String subtype = KehioUtils.extractCollectionType(annotation.getField()); + Object instantiatedObject = null; + if(subtype.equals(KehioUtils.STRING_CLASS)) { + instantiatedObject = serialiseStringField(node, annotation) ; + }else if( subtype.equals(KehioUtils.URI_CLASS)) { + instantiatedObject = serialiseURIField( node) ; + }else { + instantiatedObject= serialiseClassField( subtype, node, model); + } + if(instantiatedObject!=null) + collection.add(instantiatedObject); + }catch(Exception e) { + throw new IllegalArgumentException(e.toString()); + } + }else { + String illegalMessage = KehioUtils.concatStrings("@RdfObject must be used for properties which range in the RDF are a blank node or a URI (String or java URI) and/or a Class"); + throw new IllegalArgumentException(illegalMessage); + } + } + return collection; + } + + // -- From object to to RDF methods + + @Override + public void fromObjectToRdf(Field field, Object object, Model model, Resource subject) throws IllegalAccessException, URISyntaxException { + field.setAccessible(true); + + ObjectAnnotation annotation = new ObjectAnnotation(field); + + Object instantiatedField = KehioUtils.instantiatedField(field, object); + if(instantiatedField!=null) { + if(KehioUtils.isFieldClass(field) && !KehioUtils.isFieldURI(field)) { + // Class case + deserialiseClass(instantiatedField, annotation, model, subject); + }else if(KehioUtils.isCollection(field) ) { + // Collection case + deserialiseClassCollection(instantiatedField, annotation, model, subject); + }else if(KehioUtils.isFieldString(field) || KehioUtils.isFieldURI(field)) { + // String or URI case + deserialiseStringOrURI(instantiatedField.toString(), annotation, model, subject); + }else { + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObject must be used with a non-wrapping primitive or a Collection of non-wrapping primitives, except with String or URI which are also allowed. Please review annotation for attribute ",field.getName())); + } + } + } + + private void deserialiseStringOrURI(String instantiatedField, ObjectAnnotation annotation, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException { + String objectProperty = annotation.getBase()+annotation.getGroupValueInstantiated(instantiatedField); + + if(KehioUtils.isValidResource(objectProperty)) { + model.add(subject, annotation.getProperty(), ResourceFactory.createResource(objectProperty)); + }else { + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObject used with a String or a URI was resolved incorrectly as ", objectProperty,". Please review annotation for attribute ",annotation.getField().getName())); + } + } + + + private void deserialiseClass(Object instantiatedField, ObjectAnnotation annotation, Model model, Resource subject) { + try { + Entry nested = Kehio.deserializeClassExtended(instantiatedField, model.getNsPrefixMap()); + Resource nestedSubject = nested.getKey(); + if(nestedSubject!=null && !nested.getValue().isEmpty()) { + model.add(nested.getValue()); + model.add(subject, annotation.getProperty(), nestedSubject); + }//else { + // throw new IllegalArgumentException(KehioUtils.concatStrings("An exception occured while processing annotation @RdfObject with value, ",annotation.getProperty().toString(),". Please review attribute ",annotation.getField().getName())); + //} + }catch(Exception e) { + throw new IllegalArgumentException(e.toString()); + } + } + + @SuppressWarnings("unchecked") + private void deserialiseClassCollection(Object instantiatedField, ObjectAnnotation annotation, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException { + Collection nestedObjects = (Collection) instantiatedField; + Iterator nestedObjectsIterator = nestedObjects.iterator(); + while(nestedObjectsIterator.hasNext()) { + Object nestedObject = nestedObjectsIterator.next(); + if(nestedObject instanceof String || nestedObject instanceof URI) { + deserialiseStringOrURI(nestedObject.toString(), annotation, model, subject); + }else if(!isNotProcessable(nestedObject)) { + deserialiseClass(nestedObject, annotation, model, subject); + }else { + throw new IllegalArgumentException("@RdfObject error, the annotation was used with a collection of wrapping primitive that is not String. Instead, use a collection of String, or URI, or a Class. Please review field"); + } + } + } + + private boolean isNotProcessable(Object nestedObject) { + return nestedObject instanceof Long || nestedObject instanceof Float || nestedObject instanceof Double || nestedObject instanceof Character || nestedObject instanceof Boolean || nestedObject instanceof Integer || nestedObject instanceof Short || nestedObject instanceof Byte; + } + + // -- Annotation values methods + + + class ObjectAnnotation{ + + private Field field; + + public ObjectAnnotation(Field field) { + this.field = field; + checkout(); + } + + private void checkout() { + if (getValue()==null || getValue().isEmpty()) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObject must be initialised with a value. Please review annotation for attribute ", field.getName())); + String value = getValue(); + if(!KehioUtils.isURI(value)) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObject must be initialised with a value that is a valid URI. Please review annotation for attribute ", field.getName())); + if(!KehioUtils.isFieldClass(field) & !KehioUtils.isFieldURI(field) & !KehioUtils.isFieldString(field) && !(KehioUtils.isCollection(field) && isCollectionCompatible())) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObject must be used with attributes that are a URI, a String, a Class or a Collection containing one of the previous. Please review attribute ", field.getName())); + //if(!getBase().isEmpty() && !getMaps().isEmpty()) + // throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfObject can not be used with 'map' and 'base' at the same time. Please review attribute ", field.getName())); + + } + + private boolean isCollectionCompatible() { + String collectionType = KehioUtils.extractCollectionType(field); + return collectionType.equals(KehioUtils.STRING_CLASS) || !KehioUtils.isWrappingPrimitive(collectionType) ; + } + + private String getValue() { + return field.getAnnotation(RdfObject.class).value(); + } + + private Property getProperty() { + return ResourceFactory.createProperty(field.getAnnotation(RdfObject.class).value()); + } + + private String getBase() { + return field.getAnnotation(RdfObject.class).base(); + } + + private boolean getStrict() { + return field.getAnnotation(RdfObject.class).strict(); + } + + + private Field getField() { + return field; + } + + private Map getAliases(){ + Map processedMap = new HashMap<>(); + RdfUrlMap[] maps = field.getAnnotation(RdfObject.class).aliases(); + if(maps!=null) { + for(int index=0; index < maps.length; index++) { + RdfUrlMap map = maps[index]; + processedMap.put(map.key(), map.value()); + } + } + return processedMap; + } + + private String getAliasKeyInstantiated(String key) { + return getAliases().get(key); + } + + private String getGroupValueInstantiated(String simplifiedvalue) { + Map maps = getAliases(); + Iterator> iterator = maps.entrySet().iterator(); + while(iterator.hasNext()) { + Entry entry = iterator.next(); + if(simplifiedvalue.equals(entry.getValue())) { + simplifiedvalue = entry.getKey(); + } + } + return simplifiedvalue; + } + + + + + + } +} \ No newline at end of file diff --git a/src/main/java/kehio/mapper/RdfPropertiesContainerMapper.java b/src/main/java/kehio/mapper/RdfPropertiesContainerMapper.java new file mode 100644 index 0000000..3c8fd2a --- /dev/null +++ b/src/main/java/kehio/mapper/RdfPropertiesContainerMapper.java @@ -0,0 +1,175 @@ +package kehio.mapper; + +import java.lang.reflect.Field; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; + +import kehio.annotations.RdfPropertiesContainer; +import kehio.annotations.RdfUrlMap; + + +class RdfPropertiesContainerMapper implements RdfMapper{ + + protected Set forbidenRdfProperties; + + @Override + public boolean hasProcesableAnnotation(Field field) { + return field.isAnnotationPresent(RdfPropertiesContainer.class); + } + + public void setPropertiesNotToContain(Set forbidenRdfProperties) { + this.forbidenRdfProperties = forbidenRdfProperties; + } + + @Override + public Property fromRdfToObject(Field field, Object object, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException, URISyntaxException { + field.setAccessible(true); + + PropertiesContainerAnotation annotation = new PropertiesContainerAnotation(field); + Map collectionOfTriples = populateMapFromRDF(annotation, model, subject); + + field.set(object, collectionOfTriples); + + return null; + } + + + + private Map populateMapFromRDF(PropertiesContainerAnotation annotation , Model model, Resource subject) { + Set ignore = annotation.getPropertiesToIgnore(); + Map collectionOfTriples = new HashMap<>(); + StmtIterator stIterator = model.listStatements(subject, null, (RDFNode) null); + while(stIterator.hasNext()) { + Statement st = stIterator.next(); + if(!forbidenRdfProperties.contains(st.getPredicate()) && !ignore.contains(st.getPredicate())){ + String shortenPredicate = shortenURI(model, st.getPredicate().toString()); + String shortenObject = st.getObject().toString(); + if(st.getObject().isResource()) + shortenObject = shortenURI(model, shortenObject); + collectionOfTriples.put(shortenPredicate, shortenObject); + } + } + return collectionOfTriples; + } + + private String shortenURI(Model model, String uri) { + String shortenUri = model.shortForm(uri); + if(shortenUri==null) + shortenUri = uri; + return shortenUri; + } + + // -- + + @Override + public void fromObjectToRdf(Field field, Object object, Model model, Resource subject) throws IllegalArgumentException, IllegalAccessException, URISyntaxException { + field.setAccessible(true); + + PropertiesContainerAnotation annotation = new PropertiesContainerAnotation(field); + @SuppressWarnings("unchecked") + Map values = (Map) annotation.getField().get(object); + for(Entry entry : values.entrySet()) { + try { + Property rdfProperty = computeFullProperty(entry.getKey(), model.getNsPrefixMap()); + populateModel(model, subject, rdfProperty, entry.getValue()); + }catch(Exception e) { + throw new IllegalArgumentException(e.toString()); + } + } + } + + private Property computeFullProperty(String property, Map prefixes) { + Property computedProperty = ResourceFactory.createProperty(property); + int index = property.indexOf(':'); + if(index>-1) { + String prefix = property.substring(0,index); + String value = property.substring(index+1,property.length()); + String url = prefixes.get(prefix); + if(url!=null) + computedProperty = ResourceFactory.createProperty(url+value); + } + return computedProperty; + } + + private void populateModel(Model model, Resource subject, Property rdfProperty, String objectValue) { + + try { + RDFNode objectNode = model.createLiteral(objectValue); + model.add(subject, rdfProperty, objectNode); + }catch (Exception e) { + throw new IllegalArgumentException(e.toString()); + } + + } + + + + + class PropertiesContainerAnotation{ + + private Field field; + + public PropertiesContainerAnotation(Field field) { + this.field = field; + checkAnnotation(); + } + + private void checkAnnotation() { + if(!field.getType().equals(Map.class)) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfContainer must be used only with a Map attribute. Please review annotation in field ", field.getName())); + Entry mapTypes = KehioUtils.extractMapTypes(field); + if(!mapTypes.getKey().contains(KehioUtils.STRING_CLASS)) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfContainer must be used only with a Map that has as key type a String. Please review annotation in field ", field.getName())); + + //if(!KehioUtils.extractMapValueType(field).toString().equals(Object.class.toString())) + // throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfContainer must be used only with a Map that has as value a java generic Object. Please review annotation in field ", field.getName())); + + /* + if (onlyDatatypes() && onlyObjects()) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfContainer can have only one flag marked as true, either 'onlyDatatypes' or 'onlyObjects'. Please review annotation for field ", field.getName())); + + if(onlyDatatypes() && (!mapTypes.getValue().equals(KehioUtils.STRING_CLASS) || ) + throw new IllegalArgumentException(KehioUtils.concatStrings("@RdfContainer must be used only with a Map attribute. If 'onlyDatatypes' is true, then the values of the map must be String or a Collection of Strings. Please review annotation in field ", field.getName())); + */ + } + + + /* public boolean onlyDatatypes() { + return field.getAnnotation(RdfPropertiesContainer.class).onlyDatatypes(); + } + + public boolean onlyObjects() { + return field.getAnnotation(RdfPropertiesContainer.class).onlyObjects(); + }*/ + + public Field getField() { + return field; + } + + public Set getPropertiesToIgnore() { + Set ignore = new HashSet<>(); + String[] ignorable = field.getAnnotation(RdfPropertiesContainer.class).ignore(); + for(int index=0; index < ignorable.length; index++) { + ignore.add(ResourceFactory.createProperty(ignorable[index])); + } + return ignore; + } + + + + } + +} diff --git a/src/main/java/wot/jtd/JTD.java b/src/main/java/wot/jtd/JTD.java index 3df54b7..1486775 100755 --- a/src/main/java/wot/jtd/JTD.java +++ b/src/main/java/wot/jtd/JTD.java @@ -1,40 +1,56 @@ package wot.jtd; import java.io.IOException; -import java.util.HashSet; +import java.net.URISyntaxException; import java.util.List; -import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.regex.Pattern; import org.apache.jena.rdf.model.Model; -import com.apicatalog.jsonld.JsonLdError; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.shacl.ShaclValidator; +import org.apache.jena.shacl.Shapes; +import org.apache.jena.shacl.ValidationReport; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import wot.jtd.exception.SchemaValidationException; import wot.jtd.model.Thing; -import wot.jtd.vocabulary.Vocabulary; public class JTD { private static Boolean defaultValues = false; - private static Boolean showExternalValuesWarnings = false; - private static final ObjectMapper MAPPER = new ObjectMapper(); - private static List relevantKeys = new CopyOnWriteArrayList<>(); + private static Boolean removeNestedURNIds = false; + private static Boolean removeNestedUUIds = true; + private static Boolean includeDefaultLanguageInRDF = false; + private static List arrayCompactKeys = new CopyOnWriteArrayList<>(); + public static final boolean NORMALIZE_SECURITY_DEFINITIONS_SCHEMES = true; + public static final Pattern SECURITY_DEFINITION_SCHEMES_PATTERN = Pattern.compile("^[a-z0-9]+\\_sc$"); static { - relevantKeys.add(Vocabulary.SCOPES); - relevantKeys.add(Vocabulary.OP); - relevantKeys.add(Vocabulary.JSONLD_TYPE); - relevantKeys.add(Vocabulary.JSONLD_CONTEXT); - relevantKeys.add(Vocabulary.ITEMS); - relevantKeys.add(Vocabulary.SECURITY); + arrayCompactKeys.add(Vocabulary.SCOPES); + arrayCompactKeys.add(Vocabulary.OP); + arrayCompactKeys.add(Vocabulary.JSONLD_TYPE); + + arrayCompactKeys.add(Vocabulary.JSONLD_CONTEXT); + arrayCompactKeys.add(Vocabulary.ITEMS); + arrayCompactKeys.add(Vocabulary.SECURITY); + } + + private JTD() { + super(); + } + + // Getters & Setters + + public static List getArrayCompactKeys() { + return arrayCompactKeys; } + public static void setArrayCompactKey(String key) { + arrayCompactKeys.add(key); + } + // -- getters and setters public static Boolean getDefaultValues() { @@ -44,120 +60,76 @@ public static Boolean getDefaultValues() { public static void setDefaultValues(Boolean defaultValues) { JTD.defaultValues = defaultValues; } - - + + public static Boolean getRemoveNestedURNIds() { + return removeNestedURNIds; + } - // -- methods - - public static Object instantiateFromJson(JsonObject json, Class clazz) throws IOException { - JsonObject newJson = json.deepCopy(); - expandArrays(newJson); - return MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).readValue(newJson.toString().getBytes(), clazz); + public static void setRemoveNestedURNIds(Boolean removeNestedURNIds) { + JTD.removeNestedURNIds = removeNestedURNIds; } - - public static JsonObject toJson(Object object) throws JsonProcessingException { - ObjectMapper mapper = new ObjectMapper(); - String jsonStr = mapper.writeValueAsString(object); - JsonObject jsonObject = parseJson(jsonStr); - compactArrays(jsonObject); - return jsonObject; - } - - public static void compactArrays(JsonObject json) { - Set keys = new HashSet<>(json.keySet()); - // Find keys in the JSON that have an Array as value and which size is exactly 1, iterate over its value - keys.stream().filter(key -> relevantKeys.contains(key) && json.get(key).isJsonArray() && json.getAsJsonArray(key).size()==1) - .forEach(key -> compactArray(json, key)); // iterate and compact - - // Find keys in the JSON that have another JSON as value, and recursively call this function - keys.stream().filter(key -> json.get(key).isJsonObject()).forEach(key -> compactArrays(json.getAsJsonObject(key))); - + + public static Boolean getRemoveNestedUUIds() { + return removeNestedUUIds; + } + + public static void setRemoveNestedUUIds(Boolean removeNestedUUIds) { + JTD.removeNestedUUIds = removeNestedUUIds; } - private static void compactArray(JsonObject json, String key) { - if(json.has(key) && json.getAsJsonArray(key).size()==1) { - JsonElement element = json.getAsJsonArray(key).get(0); - if( element instanceof JsonObject) { - json.add(key, element); - }else { - json.addProperty(key, element.getAsString()); - } - } + public static boolean getIncludeDefaultLanguageInRDF() { + return includeDefaultLanguageInRDF; } - - public static void expandArrays(JsonObject json) { - // Find keys in the JSON that have a 'primitive' value and that are expandable, then expand them - Set keys = new HashSet<>(json.keySet()); - - keys.stream().filter(key -> relevantKeys.contains(key)).forEach(key -> expandArray(json,key)); - - // Find keys in the JSON that have another JSON as value, and recursively call this function - keys.stream().filter(key -> json.get(key).isJsonObject()).forEach(key -> expandArrays(json.getAsJsonObject(key))); - /*for(String key:keys) { - if(key.contains("actions")) - System.out.println("here"); - if(json.get(key).isJsonObject()) { - expandArrays(json.getAsJsonObject(key)); - } - }*/ - - // Find keys in the JSON that have an Array as value, iterate over its value - keys.stream().filter(key -> json.get(key).isJsonArray()) - .forEach(key -> callExpand(json.getAsJsonArray(key))); // iterate and filter elements that are objects - /*for(String key:keys) { - if(json.get(key).isJsonArray()) { - callExpand(json.getAsJsonArray(key)); - } - }*/ - } - - private static void callExpand(JsonArray array) { - for(int index=0; index < array.size(); index++) { - JsonElement elem = array.get(index); - - if(elem.isJsonObject()) { - JsonObject json = elem.getAsJsonObject(); - expandArrays(json); - array.set(index, json); - }else if(elem.isJsonArray()) { - callExpand( elem.getAsJsonArray()); - } - } - } - - private static void expandArray(JsonObject json, String key) { - if(json.has(key) && !json.get(key).isJsonArray()) { - JsonElement element = json.get(key); - json.remove(key); - JsonArray array = new JsonArray(); - array.add(element); - json.add(key, array); - } + public static void setIncludeDefaultLanguageInRDF(Boolean includeDefaultLanguageInRDF) { + JTD.includeDefaultLanguageInRDF = includeDefaultLanguageInRDF; } + + // -- JSON methods public static JsonObject parseJson(String jsonStr) { Gson gson = new Gson(); return gson.fromJson(jsonStr, JsonObject.class); } - - public static Boolean getShowExternalValuesWarnings() { - return showExternalValuesWarnings; + + public static Object instantiateFromJson(JsonObject json, Class clazz) throws IOException { + return JsonHandler.instantiateFromJson(json, clazz); + } + + public static JsonObject toJson(Object object) throws JsonProcessingException { + return JsonHandler.toJson(object); } + - public static void setShowExternalValuesWarnings(Boolean showExternalValues) { - JTD.showExternalValuesWarnings = showExternalValues; + // -- RDF methods + + public static Model toRDF(JsonObject td) throws IllegalAccessException, ClassNotFoundException, URISyntaxException, IOException, SchemaValidationException { + Thing thing = (Thing) JTD.instantiateFromJson(td, Thing.class); + return RdfHandler.toRDF(thing); + } + + public static Model toRDF(Thing thing) throws IllegalAccessException, ClassNotFoundException, URISyntaxException, IOException, SchemaValidationException { + return RdfHandler.toRDF(thing); } - public static Model toRDF(JsonObject td) throws JsonLdError { - RDFHandler handler = new RDFHandler(); - return handler.toRDF(td); + public static Thing fromRDF(Model model, String thingId) { + return RdfHandler.fromRDF(model, ResourceFactory.createResource(thingId)); + } + + public static List fromRDF(Model model) throws SchemaValidationException { + return RdfHandler.fromRDF(model); } + // -- Validation methods - public static List fromRDF(Model model) throws JsonLdError, IOException, SchemaValidationException { - RDFHandler handler = new RDFHandler(); - return handler.fromRDF(model); + public static ValidationReport validateWithShape(Thing thing, Model shape) throws IllegalAccessException, ClassNotFoundException, URISyntaxException, IOException, SchemaValidationException { + Shapes shapes = Shapes.parse(shape.getGraph()); + Model thingModel = JTD.toRDF(thing); + return ShaclValidator.get().validate(shapes, thingModel.getGraph()); } + + + + } diff --git a/src/main/java/wot/jtd/JsonHandler.java b/src/main/java/wot/jtd/JsonHandler.java new file mode 100644 index 0000000..7ba7871 --- /dev/null +++ b/src/main/java/wot/jtd/JsonHandler.java @@ -0,0 +1,222 @@ +package wot.jtd; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.UUID; +import java.util.regex.Pattern; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +/** + * This class + * @author Andrea Cimmino + * + */ +public class JsonHandler { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + private JsonHandler() { + super(); + } + + // -- Protected Methods + + protected static Object instantiateFromJson(JsonObject json, Class clazz) throws IOException { + JsonObject newJson = json.deepCopy(); + expandArrays(newJson); + if(!JTD.getRemoveNestedURNIds()) + removeNestedIds(newJson, true); + + return OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).readValue(newJson.toString().getBytes(), clazz); + } + + protected static JsonObject toJson(Object object) throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + String jsonStr = mapper.writeValueAsString(object); + JsonObject jsonObject = JTD.parseJson(jsonStr); + compactArrays(jsonObject); + if(!JTD.getRemoveNestedURNIds()) + removeNestedIds(jsonObject, false); + return jsonObject; + } + + // -- Methods + + public static void compactArrays(JsonObject json) { + Set keys = new HashSet<>(json.keySet()); + // Find keys in the JSON that have an Array as value and which size is exactly 1, iterate over its value + keys.stream().filter(key -> JTD.getArrayCompactKeys().contains(key) && json.get(key).isJsonArray() && json.getAsJsonArray(key).size()==1) + .forEach(key -> compactArray(json, key)); // iterate and compact + + // Find keys in the JSON that have another JSON as value, and recursively call this function + keys.stream().filter(key -> json.get(key).isJsonObject()).forEach(key -> compactArrays(json.getAsJsonObject(key))); + + //Navigate over arrays + keys.stream().filter(key -> json.get(key).isJsonArray()).forEach(key -> json.get(key).getAsJsonArray().forEach(JsonHandler::compactArraysElem)); + } + + private static void compactArraysElem(JsonElement elem) { + if(elem.isJsonObject()) + compactArrays(elem.getAsJsonObject()); + } + + + private static void removeNestedIds(JsonObject json, boolean first) { + Set keys = new HashSet<>(json.keySet()); + for(String key:keys) { + JsonElement element = json.get(key); + if(element.isJsonArray()) { + JsonArray array = element.getAsJsonArray(); + for(int index=0; index < array.size(); index++) { + JsonElement nestedElement = array.get(index); + if(nestedElement.isJsonObject()) + removeNestedIds(nestedElement.getAsJsonObject(), false); + } + }else if(element.isJsonObject()) { + removeNestedIds(element.getAsJsonObject(), false); + }else if(element.isJsonPrimitive() && (key.equals("id") || key.equals("@id")) && !first) { + removeIdentifier(json, element, key); + } + } + } + + private static void removeIdentifier(JsonObject json, JsonElement element, String key) { + Boolean isURN = URN_PATTERN.matcher(element.getAsString()).matches(); + Boolean isUUID = isUUID(element.getAsString()); + if(isURN && JTD.getRemoveNestedURNIds()) { + json.remove(key); + }else if(isUUID && JTD.getRemoveNestedUUIds()) { + json.remove(key); + }else if(!isURN && !isUUID){ + json.remove(key); + } + } + + + private static final Pattern URN_PATTERN = Pattern.compile( + "^urn:[a-z0-9][a-z0-9-]{0,31}:([a-z0-9()+,\\-.:=@;$_!*']|%[0-9a-f]{2})+/?.*$", + Pattern.CASE_INSENSITIVE); + + private static boolean isUUID(String uri) { + Boolean isUUID = false; + try { + UUID.fromString(uri); + isUUID = true; + }catch(Exception e) { + e.printStackTrace(); + } + return isUUID; + } + + private static void compactArray(JsonObject json, String key) { + if(json.has(key) && json.getAsJsonArray(key).size()==1) { + JsonElement element = json.getAsJsonArray(key).get(0); + if( element instanceof JsonObject) { + json.add(key, element); + }else { + json.addProperty(key, element.getAsString()); + } + } + } + + public static void expandArrays(JsonObject json) { + // Find keys in the JSON that have a 'primitive' value and that are expandable, then expand them + Set keys = new HashSet<>(json.keySet()); + + keys.stream().filter(key -> JTD.getArrayCompactKeys().contains(key)).forEach(key -> expandArray(json,key)); + + // Find keys in the JSON that have another JSON as value, and recursively call this function + keys.stream().filter(key -> json.get(key).isJsonObject()).forEach(key -> expandArrays(json.getAsJsonObject(key))); + + // Find keys in the JSON that have an Array as value, iterate over its value + keys.stream().filter(key -> json.get(key).isJsonArray()) + .forEach(key -> callExpand(json.getAsJsonArray(key))); // iterate and filter elements that are objects + + } + + private static void callExpand(JsonArray array) { + for(int index=0; index < array.size(); index++) { + JsonElement elem = array.get(index); + + if(elem.isJsonObject()) { + JsonObject json = elem.getAsJsonObject(); + expandArrays(json); + array.set(index, json); + }else if(elem.isJsonArray()) { + callExpand( elem.getAsJsonArray()); + } + } + } + + private static void expandArray(JsonObject json, String key) { + if(json.has(key) && !json.get(key).isJsonArray()) { + JsonElement element = json.get(key); + json.remove(key); + JsonArray array = new JsonArray(); + array.add(element); + json.add(key, array); + } + } + + // JSON comparison + + public static boolean compareJson(JsonElement element1, JsonElement element2) { + Boolean sameJson = true; + if (element1 instanceof JsonObject && element2 instanceof JsonObject) { + SortedSet keys1 = new TreeSet<>(element1.getAsJsonObject().keySet()); + SortedSet keys2 = new TreeSet<>(element2.getAsJsonObject().keySet()); + sameJson = keys1.containsAll(keys2) && keys2.containsAll(keys1); + for (String key : keys1) { + JsonElement value1 = element1.getAsJsonObject().get(key); + JsonElement value2 = element2.getAsJsonObject().get(key); + sameJson = compareJson(value1, value2); + + } + + } else if (element1 instanceof JsonArray && element2 instanceof JsonArray) { + JsonArray array1 = element1.getAsJsonArray(); + JsonArray array2 = element2.getAsJsonArray(); + sameJson = array1.size() == array2.size(); + for (int index_1 = 0; index_1 < array1.size(); index_1++) { + JsonElement nestedElement1 = array1.get(index_1); + Boolean existTheSame = false; + int indexToRemove = 0; + for (int index_2 = 0; index_2 < array2.size(); index_2++) { + JsonElement nestedElement2 = array2.get(index_2); + existTheSame = compareJson(nestedElement1, nestedElement2); + indexToRemove = index_2; + if (existTheSame) + break; + } + if (existTheSame) { + sameJson &= existTheSame; + array2.remove(indexToRemove); + } else { + sameJson = false; + break; + } + } + } else if (element1 instanceof JsonPrimitive && element2 instanceof JsonPrimitive) { + String primitive1 = element1.getAsJsonPrimitive().getAsString(); + String primitive2 = element2.getAsJsonPrimitive().getAsString(); + sameJson = primitive1.equals(primitive2); + } else { + sameJson = false; + } + + return sameJson; + } + + + +} diff --git a/src/main/java/wot/jtd/Main.java b/src/main/java/wot/jtd/Main.java deleted file mode 100755 index 7c3427a..0000000 --- a/src/main/java/wot/jtd/Main.java +++ /dev/null @@ -1,85 +0,0 @@ -package wot.jtd; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Scanner; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -public class Main { - - public static void main(String[] args) throws IOException { - File file = new File("./src/test/resources/linksmart/tds.json"); - String directoryTDs = readFile(file); - JsonObject directoryJson = JTD.parseJson(directoryTDs); - JsonArray tds = directoryJson.get("items").getAsJsonArray(); - FileWriter fw = new FileWriter("/Users/cimmino/Desktop/td-frame.csv"); - - - for(int index=0; index < tds.size(); index++) { - JsonObject td = tds.get(index).getAsJsonObject(); - try { - - if(td.has("properties")) { - JsonObject elements = td.getAsJsonObject("properties"); - elements.keySet().forEach(key -> { - try { - fw.write("properties_______"+elements.get(key)+"\n"); - } catch (IOException e) { - e.printStackTrace(); - } - }); - - }if(td.has("actions")) { - JsonObject elements = td.getAsJsonObject("actions"); - elements.keySet().forEach(key -> { - try { - fw.write("actions_______"+elements.get(key)+"\n"); - } catch (IOException e) { - e.printStackTrace(); - } - }); - - }if(td.has("events")) { - JsonObject elements = td.getAsJsonObject("events"); - elements.keySet().forEach(key -> { - try { - fw.write("events_______"+elements.get(key)+"\n"); - } catch (IOException e) { - e.printStackTrace(); - } - }); - } - - }catch(Exception e) { - e.printStackTrace(); - break; - } - } - - - fw.close(); - - } - - - private static String readFile(File myObj) { - StringBuilder builder = new StringBuilder(); - try { - Scanner myReader = new Scanner(myObj); - while (myReader.hasNextLine()) { - String data = myReader.nextLine(); - builder.append(data); - } - myReader.close(); - } catch (FileNotFoundException e) { - System.out.println("An error occurred."); - e.printStackTrace(); - } - return builder.toString(); - } - -} diff --git a/src/main/java/wot/jtd/MainWot.java b/src/main/java/wot/jtd/MainWot.java deleted file mode 100755 index 8821ecb..0000000 --- a/src/main/java/wot/jtd/MainWot.java +++ /dev/null @@ -1,76 +0,0 @@ -package wot.jtd; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Scanner; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -public class MainWot { - - public static void main(String[] args) throws IOException { - File file = new File("/Users/cimmino/Desktop/tds"); - File[] tds = file.listFiles(); - int counter=0; - JsonArray interactions = new JsonArray(); - for(File td:tds) { - String parsedTD = readFile(td); - try { - JsonObject tdJson = JTD.parseJson(parsedTD); - if(tdJson.has("interactions")) { - counter++; - interactions.addAll(tdJson.getAsJsonArray("interactions")); - }else if(tdJson.has("interaction")) { - counter++; - interactions.addAll(tdJson.getAsJsonArray("interaction")); - }else { - System.out.println("WARNING: "+td.getName()); - } - }catch(Exception e) { - System.out.println("ERROR WITH: "+td.getName()); - } - } - System.out.println(counter+" out of "+tds.length); - FileWriter fw = new FileWriter("/Users/cimmino/Desktop/td-iot-frame.csv"); - - for(int index=0; index < interactions.size(); index++) { - JsonObject interaction = interactions.get(index).getAsJsonObject(); - if(interaction.has("@type")) { - JsonArray types = interaction.getAsJsonArray("@type"); - for(int count=0; count context = new HashMap<>(); + static { + context.put("htv","http://www.w3.org/2011/http#"); + context.put("rdfs","http://www.w3.org/2000/01/rdf-schema#"); + context.put("xsd","http://www.w3.org/2001/XMLSchema#"); + context.put("td","https://www.w3.org/2019/wot/td#"); + context.put("jsonschema","https://www.w3.org/2019/wot/json-schema#"); + context.put("wotsec","https://www.w3.org/2019/wot/security#"); + context.put("hctl","https://www.w3.org/2019/wot/hypermedia#"); + context.put("dct","http://purl.org/dc/terms/"); + context.put("schema","http://schema.org/"); + context.put("rdf","http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + } + // -- Deserialisation methods + + public static Model toRDF(Thing thing) throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException, IOException, SchemaValidationException { + // Extract context + JsonObject thingJson = JTD.toJson(thing); + JsonElement contextAbstractElement = thingJson.get(CONTEXT_TAG); + Map prefixes = new HashMap<>(); + // Improve context from external specified sources + enhanceContext(contextAbstractElement, prefixes); + // Load default WoT Context + prefixes.putAll(context); + // Check if there is a default language + String defaultLanguage = prefixes.get(CONTEXT_LANGUAGE_TAG); + prefixes.remove(CONTEXT_LANGUAGE_TAG); + // Serialise and add default language if necessary + Model model = Kehio.deserializeClass(thing, prefixes); + if(JTD.getIncludeDefaultLanguageInRDF() && defaultLanguage!=null) + addLanguageToModel(model, defaultLanguage); + + return model; + } - public static void serialize() { - VersionInfo version = new VersionInfo(); - - for (Field field: version.getClass().getSuperclass().getDeclaredFields()) { - System.out.println(field.getName()); - if (field.isAnnotationPresent(RdfDatatypeProperty.class)) { - System.out.print(" -- > "+getSerializedKey(field)); - } + private static void enhanceContext(JsonElement contextAbstractElement, Map prefixes) throws JsonProcessingException { + if(contextAbstractElement.isJsonArray()) { + JsonArray contextElements = contextAbstractElement.getAsJsonArray(); + for(int index=0; index < contextElements.size(); index++) { + JsonElement contextElement = contextElements.get(index); + if(contextElement.isJsonObject()) { + JsonObject prefixOject = contextElement.getAsJsonObject(); + prefixOject.entrySet().forEach( entry -> prefixes.put(entry.getKey(), entry.getValue().getAsString())); + } + } + }else if (contextAbstractElement.isJsonObject()) { + JsonObject prefixOject = contextAbstractElement.getAsJsonObject(); + prefixOject.entrySet().stream().filter(json -> json.getValue().isJsonPrimitive()).forEach( entry -> prefixes.put(entry.getKey(), entry.getValue().getAsString())); } - for (Field field: version.getClass().getDeclaredFields()) { - System.out.println(field.getName()); - if (field.isAnnotationPresent(RdfDatatypeProperty.class)) { - System.out.print(" -- > "+getSerializedKey(field)); - } + } + + private static void addLanguageToModel(Model model, String defaultLanguage) { + List statements = model.listStatements(null, null, (RDFNode) null).toList(); + for (int index = 0; index < statements.size(); index++) { + Statement statement = statements.get(index); + RDFNode objectNode = statement.getObject(); + if (objectNode.isLiteral()) { + Literal literal = objectNode.asLiteral(); + boolean coditionTypes = literal.getDatatypeURI().equals(XSD.normalizedString.toString()) || literal.getDatatypeURI().equals(XSD.xstring.toString()) || literal.getDatatypeURI().isEmpty(); + if( coditionTypes && literal.getLanguage().isEmpty()) { + model.remove(statement); + Literal newLiteral = model.createLiteral(literal.getValue().toString(), defaultLanguage); + model.add(statement.getSubject(), statement.getPredicate(), newLiteral); + } + } } - - } - private static String getSerializedKey(Field field) { - String annotationValue = field.getAnnotation(RdfDatatypeProperty.class).value(); - - if (annotationValue.isEmpty()) { - return field.getName(); - } - else { - return annotationValue; - } - } + } - public List fromRDF(Model model) throws JsonLdError, IOException, SchemaValidationException { + // -- Serialise methods + + public static List fromRDF(Model model) throws SchemaValidationException { List things = new ArrayList<>(); - // 1. Write model as JSON-LD 1.0 - Writer writer = new StringWriter(); - model.write(writer, "Turtle"); - String jsonLDModel = writer.toString(); - System.out.println(jsonLDModel); - writer.close(); - // 1. Find any resource that is a Thing - List thingResources = findThingResource(model); - if(thingResources.isEmpty()) - throw new SchemaValidationException("RDF provided has no td:Thing instances, or they lack of mandatory properties such as dc:title ir td:securityDefinitions "); - for(int index=0; index < thingResources.size(); index++) { - Resource thing = thingResources.get(index); - // 1.1 Extract subgraph of this thing - GraphExtract graphExtractor = new GraphExtract( TripleBoundary.stopNowhere ); - Graph thingGraph = graphExtractor.extract(thing.asNode(), model.getGraph()); - try { - Thing newThing = buildThing(thing, thingGraph); - things.add(newThing); - }catch(Exception e) { // define more accurate exceptions - e.printStackTrace(); + + List thingSubjectsWithSecurity = model.listSubjectsWithProperty(ResourceFactory.createProperty("https://www.w3.org/2019/wot/td#hasSecurityConfiguration")).toList(); + List thingSubjects = model.listSubjectsWithProperty(ResourceFactory.createProperty("https://www.w3.org/2019/wot/td#securityDefinitions")).toList(); + thingSubjects.retainAll(thingSubjectsWithSecurity); + + if(thingSubjects.isEmpty()) { + throw new SchemaValidationException("Provided RDF data lacks URIs that are Things, subjects with mandatory properties and/or are missing"); + }else { + for(int index=0; index < thingSubjects.size(); index++) { + Thing tmpThing = fromRDF(model, thingSubjects.get(index)); + if(tmpThing!=null) + things.add(tmpThing); } } + return things; } - private List findThingResource(Model model) { - List resources = model.listSubjectsWithProperty(RDF.type, THING).toList(); - if(resources.isEmpty()) { - resources = model.listSubjectsWithProperty(DC_11.title).toList(); - resources.retainAll(model.listSubjectsWithProperty(SECURITY_DEFINITIONS).toList()); - } - return resources; + private static JsonNode tdContext; + static { + ObjectMapper objectMapper = new ObjectMapper(); + try { + tdContext = objectMapper.readTree("{\"value\" :\"https://www.w3.org/2019/wot/td/v1\"}").get("value"); + } catch (Exception e) { + e.printStackTrace(); + } } - private Thing buildThing(Resource resource, Graph thingGraph) throws URISyntaxException { - Model thingModel = ModelFactory.createModelForGraph(thingGraph); - // minimum thing to buid - Thing thing = new Thing(); - thing.setId(new URI(resource.toString())); + private static List prepareContext(Model model){ + List context = new ArrayList<>(); + context.add(tdContext); + ObjectMapper objectMapper = new ObjectMapper(); - //setTitle(Thing thing, Resource resource, Model thingModel, Property property) - - return thing; - } - /* - private void setLiteralElements(Thing thing, Resource resource, Model thingModel, Property property) { - Map langElements = getLangElements(resource, thingModel, property); - if(!langElements.isEmpty()) { - String title = null; - if(titles.containsKey("en")) { - title = titles.get("en"); - }else { - title = (String) titles.values().toArray()[0]; + Set> prefixes = model.getNsPrefixMap().entrySet(); + for(Entry prefix : prefixes) { + try { + JsonObject contextElement = new JsonObject(); + contextElement.addProperty(prefix.getKey(), prefix.getValue()); + context.add(objectMapper.readTree(contextElement.toString())); + }catch(Exception e) { + e.printStackTrace(); } - thing.setTitle(title); - }else { - } - }*/ - - // - - public static void fromRDF() { - VersionInfo thing = new VersionInfo(); - Method[] annotations = VersionInfo.class.getMethods(); - for(int index=0; index < annotations.length; index++) { - Method annotation = annotations[index]; - System.out.println(annotation.getName()); - List annon = Arrays.asList(annotation.getAnnotations()); - annon.forEach(elem -> System.out.println(elem)); - } - /*PropertyDescriptor[] properties = PropertyUtils.getPropertyDescriptors(thing); - for(int index=0;index < properties.length; index++) { - PropertyDescriptor property = properties[index]; - System.out.println(property.getDisplayName()); - System.out.println(property.getName()); - Method method = property.getPropertyType() - if (method.isAnnotationPresent(Init.class)) { - method.setAccessible(true); - method.invoke(object); - } - for(Annotation anon: .getAnnotations()) { - System.out.println(anon); - } - }*/ + return context; } - protected Literal extractUnitaryObjectLiteral(Model model, Resource subject, Property property) throws RDFValidationException { - Literal literal = null; - RDFNode object = extractUnitaryObject(model, subject, property); - if (object == null) - throw new RDFValidationException(concatStrings("The porperty ", property.toString(), - " must point to an existing literal, currently is not been used")); - if (object.isLiteral()) { - literal = object.asLiteral(); - } else { - throw new RDFValidationException(concatStrings("The porperty ", property.toString(), - " must point to a literal, currently is pointing to a non-literal object")); - } - return literal; - } - - protected RDFNode extractUnitaryObject(Model model, Resource subject, Property property) throws RDFValidationException { - RDFNode node = null; - List objects = model.listObjectsOfProperty(property).toList(); - if(objects.size()>1) { - throw new RDFValidationException(concatStrings("The porperty ", property.toString()," is unitary but it was used more than once with the subject ", subject.toString())); - }else { - node = objects.get(0); - } - return node; - } - protected String concatStrings(String ...message) { - StringBuilder builder = new StringBuilder(); - for(int index =0; index < message.length; index++) - builder.append(message[index]); - return builder.toString(); - } + public static Thing fromRDF(Model model, Resource thingSubject) { + Thing thing = null; + List context = prepareContext(model); + String defaultLanguage = analyseDefaultLanguage(model); + JsonNode lang = setLanguageContext(defaultLanguage); + if(lang!=null) + context.add(lang); + try { + Thing tmpThing = (Thing) Kehio.serializeClass(Thing.class, model, thingSubject); + + tmpThing.setContextValues(context); + if(tmpThing.getTitles()!=null && !tmpThing.getTitles().isEmpty() && tmpThing.getTitle()==null) { + if(tmpThing.getTitles().containsKey("en")) { + tmpThing.setTitle(tmpThing.getTitles().get("en")); + }else { + tmpThing.setTitle(tmpThing.getTitles().values().iterator().next()); + } + } + if(tmpThing!=null) { + thing = Thing.fromJson(tmpThing.toJson()); + } + + }catch(Exception e) { + e.printStackTrace(); + } + - - - - - // -- to RDF methods - - public Model toRDF(JsonObject td) throws JsonLdError { - Model model = ModelFactory.createDefaultModel(); - InputStream tdStream = new ByteArrayInputStream(td.toString().getBytes()); - Document documentTD = JsonDocument.of(tdStream); - RdfDataset dataset = JsonLd.toRdf(documentTD).get(); - Map existingBlankNodes = new HashMap<>(); - dataset.toList().forEach(triple -> populateModel(triple, model, existingBlankNodes)); - return model; + return thing; } - private void populateModel(RdfNQuad triple, Model model, Map existingBlankNodes) { - Resource subject = instantiateResource(triple.getSubject(), model, existingBlankNodes); - Property predicate = ResourceFactory.createProperty(triple.getPredicate().getValue()); - - RdfValue object = triple.getObject(); - if(object.isIRI()) { - Resource objectJena = ResourceFactory.createResource(object.getValue()); - model.add(subject, predicate, objectJena); - }else if(object.isBlankNode()){ - Resource objectJena = instantiateBlankNode(object.getValue(), model, existingBlankNodes); - model.add(subject, predicate, objectJena); - }else if(object.isLiteral()) { - RdfLiteral literal = object.asLiteral(); - Optional lang = literal.getLanguage(); - String datatype = literal.getDatatype(); - Literal jenaLiteral = ResourceFactory.createPlainLiteral(literal.getValue()); - if(lang.isPresent()) { - jenaLiteral = ResourceFactory.createLangLiteral(literal.getValue(), lang.get()); - }else if(datatype!=null) { - RDFDatatype dt = NodeFactory.getType(datatype); - jenaLiteral = ResourceFactory.createTypedLiteral(literal.getValue(), dt); + private static JsonNode setLanguageContext(String defaultLanguage) { + JsonNode lang = null; + ObjectMapper objectMapper = new ObjectMapper(); + if(defaultLanguage!=null) { + try { + JsonObject contextElement = new JsonObject(); + contextElement.addProperty("@language", defaultLanguage); + lang = objectMapper.readTree(contextElement.toString()); + }catch(Exception e) { + throw new IllegalArgumentException(e.toString()); } - model.add(subject, predicate, jenaLiteral); } + return lang; } - - private Resource instantiateResource(RdfResource resource, Model model, Map existingBlankNodes) { - Resource instantiatedResource = null; - if(resource.isIRI()) { - instantiatedResource = ResourceFactory.createResource(resource.getValue()); - }else { - instantiatedResource = instantiateBlankNode(resource.getValue(), model, existingBlankNodes); + + /** + * Returns the default language of the dataset if exists, otherwise returns null + * @param model + * @return + */ + private static String analyseDefaultLanguage(Model model) { + List statements = model.listStatements(null, null, (RDFNode) null).toList(); + String defaultLanguage = null; + boolean notExistDefaultLanguage = false; + Model auxiliarModel = ModelFactory.createDefaultModel(); + List toRemove = new ArrayList<>(); + for (int index = 0; index < statements.size(); index++) { + Statement statement = statements.get(index); + RDFNode objectNode = statement.getObject(); + if (objectNode.isLiteral()) { + Literal literal = objectNode.asLiteral(); + boolean coditionTypes = literal.getDatatypeURI().equals(XSD.normalizedString.toString()) || literal.getDatatypeURI().equals(XSD.xstring.toString()) || literal.getDatatypeURI().isEmpty(); + if( !literal.getLanguage().isEmpty()) { + String language = literal.getLanguage(); + if(defaultLanguage==null) + defaultLanguage = language; + notExistDefaultLanguage = !language.equals(defaultLanguage); + if(notExistDefaultLanguage) + break; + auxiliarModel.add(statement.getSubject(), statement.getPredicate(), model.createTypedLiteral(literal.getValue())); + toRemove.add(statement); + }else if( coditionTypes && literal.getLanguage().isEmpty()) { + // Coming here means there is a literal xsd: string or normalised string that has no language + notExistDefaultLanguage = true; + } + } } - return instantiatedResource; - } - - private Resource instantiateBlankNode(String blankNode, Model model, Map existingBlankNodes) { - Resource instantiatedResource = null; - if(!existingBlankNodes.containsKey(blankNode)) { - instantiatedResource = model.createResource(); - existingBlankNodes.put(blankNode, instantiatedResource); + + if(!notExistDefaultLanguage) { + model.remove(toRemove); + model.add(auxiliarModel); }else { - instantiatedResource = existingBlankNodes.get(blankNode); + defaultLanguage = null; } - return instantiatedResource; + return defaultLanguage; + } - } diff --git a/src/main/java/wot/jtd/ToRemove.java b/src/main/java/wot/jtd/ToRemove.java deleted file mode 100755 index 1c4bc5d..0000000 --- a/src/main/java/wot/jtd/ToRemove.java +++ /dev/null @@ -1,58 +0,0 @@ -package wot.jtd; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Scanner; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -import wot.jtd.exception.SchemaValidationException; - -public class ToRemove { - - public static void main(String[] args) throws IOException, SchemaValidationException { - File file = new File("./src/test/resources/linksmart/original/tds.json"); - String directoryTDs = readFile(file); - JsonObject directoryJson = JTD.parseJson(directoryTDs); - JsonArray tds = directoryJson.get("items").getAsJsonArray(); - - - - for(int index=0; index < tds.size(); index++) { - JsonObject td = tds.get(index).getAsJsonObject(); - FileWriter fw = new FileWriter("./src/test/resources/linksmart/td-"+index+".json"); - try { - fw.write(td.toString()); - }catch(Exception e) { - e.printStackTrace(); - break; - } - fw.close(); - } - - - - - } - - - private static String readFile(File myObj) { - StringBuilder builder = new StringBuilder(); - try { - Scanner myReader = new Scanner(myObj); - while (myReader.hasNextLine()) { - String data = myReader.nextLine(); - builder.append(data); - } - myReader.close(); - } catch (FileNotFoundException e) { - System.out.println("An error occurred."); - e.printStackTrace(); - } - return builder.toString(); - } - -} diff --git a/src/main/java/wot/jtd/Validation.java b/src/main/java/wot/jtd/Validation.java new file mode 100644 index 0000000..1617d91 --- /dev/null +++ b/src/main/java/wot/jtd/Validation.java @@ -0,0 +1,283 @@ +package wot.jtd; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +import wot.jtd.exception.ActionAffordanceValidationException; +import wot.jtd.exception.DataSchemaValidationException; +import wot.jtd.exception.EventAffordanceValidationException; +import wot.jtd.exception.ExpectedResponseValidationException; +import wot.jtd.exception.FormValidationException; +import wot.jtd.exception.InteractionAffordanceValidationException; +import wot.jtd.exception.LinkValidationException; +import wot.jtd.exception.PropertyAffordanceValidationException; +import wot.jtd.exception.SchemaValidationException; +import wot.jtd.exception.SecuritySchemeValidationException; +import wot.jtd.exception.ThingValidationException; +import wot.jtd.exception.VersionInfoValidationException; +import wot.jtd.model.ExpectedResponse; +import wot.jtd.model.Form; +import wot.jtd.model.Link; +import wot.jtd.model.Thing; +import wot.jtd.model.VersionInfo; +import wot.jtd.model.interactions.ActionAffordance; +import wot.jtd.model.interactions.EventAffordance; +import wot.jtd.model.interactions.InteractionAffordance; +import wot.jtd.model.interactions.PropertyAffordance; +import wot.jtd.model.schemas.data.DataSchema; +import wot.jtd.model.schemas.security.SecurityScheme; + +public class Validation { + + +// /** +// * This method validates an instance a {@link Thing} object. +// * @param thing an instance of {@link Thing} +// * @throws SchemaValidationException this exception is thrown when the syntax of the Thing Description as ORM is incorrect +// */ +// public static void validate(Thing thing) throws SchemaValidationException { +// ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); +// Validator validator = factory.getValidator(); +// Set> violations = validator.validate(thing); +// StringBuilder builder = new StringBuilder(); +// if(!violations.isEmpty()) { +// violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); +// throw new ThingValidationException(builder.toString()); +// } +// // TODO: throw nested expcetions +// +// // TODO: validate form restrictions +// // if PropertyAffordance readproperty and writeproperty +// // if ActionAffordance invokeaction +// // if EventAffordance subscribeevent +// } +// +// +// /** +// * This method validates an instance a {@link SecurityScheme} object. +// * @param securityScheme an instance of {@link SecurityScheme} +// * @throws SchemaValidationException this exception is thrown when the syntax of the Thing Description as ORM is incorrect +// */ +// public static void validate(SecurityScheme securityScheme) throws SchemaValidationException { +// ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); +// Validator validator = factory.getValidator(); +// Set> violations = validator.validate(securityScheme); +// StringBuilder builder = new StringBuilder(); +// if(!violations.isEmpty()) { +// violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); +// throw new SecuritySchemeValidationException(builder.toString()); +// } +// +// } +// +// /** +// * This method validates an instance of {@link PropertyAffordance}. +// * @param propertyAffordance an instance of {@link PropertyAffordance} +// * @throws SchemaValidationException this exception is thrown when the syntax of the Thing Description as ORM is incorrect +// */ +// public static void validate(PropertyAffordance propertyAffordance) throws SchemaValidationException { +// ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); +// Validator validator = factory.getValidator(); +// Set> violations = validator.validate(propertyAffordance); +// StringBuilder builder = new StringBuilder(); +// if(!violations.isEmpty()) { +// violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); +// throw new PropertyAffordanceValidationException(builder.toString()); +// } +// if(propertyAffordance.getForms()!=null) { +// for(Form form:propertyAffordance.getForms()) { +// validate(form); +// } +// } +// if(propertyAffordance.getUriVariables()!=null) { +// List schemas = new ArrayList<>(propertyAffordance.getUriVariables().values()); +// for(int index=0; index < schemas.size(); index++) { +// DataSchema.validate(schemas.get(index)); +// } +// } +// } +// +// /** +// * This method validates an instance of {@link InteractionAffordance}. +// * @param interactionAffordance an instance of {@link InteractionAffordance} +// * @throws SchemaValidationException this exception is thrown when the syntax of the Thing Description as ORM is incorrect +// */ +// public static void validate(InteractionAffordance interactionAffordance) throws SchemaValidationException { +// ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); +// Validator validator = factory.getValidator(); +// Set> violations = validator.validate(interactionAffordance); +// StringBuilder builder = new StringBuilder(); +// if(!violations.isEmpty()) { +// violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); +// throw new InteractionAffordanceValidationException(builder.toString()); +// } +// if(interactionAffordance.getForms()!=null) { +// for(Form form: interactionAffordance.getForms()) { +// validate(form); +// } +// } +// if(interactionAffordance.getUriVariables()!=null) { +// List schemas = new ArrayList<>(interactionAffordance.getUriVariables().values()); +// for(int index=0; index < schemas.size(); index++) { +// DataSchema.validate(schemas.get(index)); +// } +// } +// } +// +// /** +// * This method validates an instance of {@link EventAffordance}. +// * @param eventAffordance an instance of {@link EventAffordance} +// * @throws SchemaValidationException this exception is thrown when the syntax of the Thing Description as ORM is incorrect +// */ +// public static void validate(EventAffordance eventAffordance) throws SchemaValidationException { +// ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); +// Validator validator = factory.getValidator(); +// Set> violations = validator.validate(eventAffordance); +// StringBuilder builder = new StringBuilder(); +// if(!violations.isEmpty()) { +// violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); +// throw new EventAffordanceValidationException(builder.toString()); +// } +// if(eventAffordance.getForms()!=null) { +// for(Form form:eventAffordance.getForms()) { +// validate(form); +// } +// } +// if(eventAffordance.getUriVariables()!=null) { +// List schemas = new ArrayList<>(eventAffordance.getUriVariables().values()); +// for(int index=0; index < schemas.size(); index++) { +// DataSchema.validate(schemas.get(index)); +// } +// } +// if(eventAffordance.getSubscription()!=null) +// DataSchema.validate(eventAffordance.getSubscription()); +// if(eventAffordance.getData()!=null) +// DataSchema.validate(eventAffordance.getData()); +// if(eventAffordance.getCancellation()!=null) +// DataSchema.validate(eventAffordance.getCancellation()); +// +// } +// +// /** +// * This method validates an instance of {@link ActionAffordance}. +// * @param actionAffordance an instance of {@link ActionAffordance} +// * @throws SchemaValidationException this exception is thrown when the syntax of the Thing Description as ORM is incorrect +// */ +// public static void validate(ActionAffordance actionAffordance) throws SchemaValidationException { +// ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); +// Validator validator = factory.getValidator(); +// Set> violations = validator.validate(actionAffordance); +// StringBuilder builder = new StringBuilder(); +// if(!violations.isEmpty()) { +// violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); +// throw new ActionAffordanceValidationException(builder.toString()); +// } +// if(actionAffordance.getForms()!=null) { +// for(Form form: actionAffordance.getForms()) { +// validate(form); +// } +// } +// if(actionAffordance.getUriVariables()!=null) { +// List schemas = new ArrayList<>(actionAffordance.getUriVariables().values()); +// for(int index=0; index < schemas.size(); index++) { +// DataSchema.validate(schemas.get(index)); +// } +// } +// } +// +// // -- Validation methods +// +// /** +// * This method validates an instance of {@link VersionInfo}. +// * @param versionInfo an instance of {@link VersionInfo} +// * @throws SchemaValidationException this exception is thrown when the syntax of the Thing Description as ORM is incorrect +// */ +// public static void validate(VersionInfo versionInfo) throws SchemaValidationException { +// ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); +// Validator validator = factory.getValidator(); +// Set> violations = validator.validate(versionInfo); +// if(!violations.isEmpty()) { +// StringBuilder builder = new StringBuilder(); +// violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); +// throw new VersionInfoValidationException(builder.toString()); +// } +// } +// +// /** +// * This method validates an instance of {@link Link}. +// * @param link an instance of {@link Link} +// * @throws SchemaValidationException this exception is thrown when the syntax of the Thing Description as ORM is incorrect +// */ +// public static void validate(Link link) throws SchemaValidationException { +// ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); +// Validator validator = factory.getValidator(); +// Set> violations = validator.validate(link); +// if(!violations.isEmpty()) { +// StringBuilder builder = new StringBuilder(); +// violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); +// throw new LinkValidationException(builder.toString()); +// } +// } +// +// /** +// * This method validates an instance a {@link Form} object. +// * @param form an instance of {@link Form} +// * @throws SchemaValidationException this exception is thrown when the syntax of the Thing Description as ORM is incorrect +// */ +// public static void validate(Form form) throws SchemaValidationException { +// ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); +// Validator validator = factory.getValidator(); +// Set> violations = validator.validate(form); +// StringBuilder builder = new StringBuilder(); +// if(!violations.isEmpty()) { +// violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); +// throw new FormValidationException(builder.toString()); +// } +// // TODO: check that op is one of: readproperty, writeproperty, observeproperty, unobserveproperty, invokeaction, subscribeevent, unsubscribeevent, readallproperties, writeallproperties, readmultipleproperties, or writemultiplepropertie +// // TODO: add to the documentation that OP can be only one of these values ==> transform op in enum? +// // TODO: check that methodName is one REST operation, check if there are more +// if(form.getResponse()!=null) +// validate(form.getResponse()); +// } +// +// +// /** +// * This method validates an instance of {@link ExpectedResponse}. +// * @param expectedResponse an instance of {@link ExpectedResponse} +// * @throws SchemaValidationException this exception is thrown when the syntax of the Thing Description as ORM is incorrect +// */ +// public static void validate(ExpectedResponse expectedResponse) throws SchemaValidationException { +// ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); +// Validator validator = factory.getValidator(); +// Set> violations = validator.validate(expectedResponse); +// if(!violations.isEmpty()) { +// StringBuilder builder = new StringBuilder(); +// violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); +// throw new ExpectedResponseValidationException(builder.toString()); +// } +// } +// +// /** +// * This method validates an instance of {@link DataSchema}. +// * @param dataSchema an instance of {@link DataSchema} +// * @throws SchemaValidationException this exception is thrown when the syntax of the Thing Description as ORM is incorrect +// */ +// public static void validate(DataSchema dataSchema) throws SchemaValidationException { +// ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); +// Validator validator = factory.getValidator(); +// Set> violations = validator.validate(dataSchema); +// StringBuilder builder = new StringBuilder(); +// if(!violations.isEmpty()) { +// violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); +// throw new DataSchemaValidationException(builder.toString()); +// } +// // TODO: validate nested objects +// // TODO: validate other restrictions +// } +// +} diff --git a/src/main/java/wot/jtd/vocabulary/Vocabulary.java b/src/main/java/wot/jtd/Vocabulary.java similarity index 51% rename from src/main/java/wot/jtd/vocabulary/Vocabulary.java rename to src/main/java/wot/jtd/Vocabulary.java index 1782642..8299055 100755 --- a/src/main/java/wot/jtd/vocabulary/Vocabulary.java +++ b/src/main/java/wot/jtd/Vocabulary.java @@ -1,4 +1,4 @@ -package wot.jtd.vocabulary; +package wot.jtd; public class Vocabulary { @@ -8,7 +8,8 @@ private Vocabulary() { public static final String JSONLD_CONTEXT = "@context"; public static final String JSONLD_TYPE = "@type"; - public static final String TYPE = "type"; + public static final String JSONLD_ID = "@id"; + public static final String JSONLD_TYPE_ALIAS = "type"; public static final String STATUS_CODE_NUMBER = "htv:statusCodeNumber"; public static final String STATUS_CODE_VALUE = "htv:statusCodeValue"; @@ -17,7 +18,7 @@ private Vocabulary() { public static final String SCOPES = "scopes"; public static final String OP = "op"; public static final String ITEMS = "items"; - public static final String CONS = "cons"; + public static final String CONS = "const"; public static final String SECURITY = "security"; public static final String HEADER = "header"; @@ -25,5 +26,18 @@ private Vocabulary() { // Default values public static final String MIME_JSON = "application/json"; + public static final String JSON_SCHEMA_URI = "https://www.w3.org/2019/wot/json-schema#"; + + + // Security schemes + + public static final String NO_SECURITY_SCHEME = "nosec"; + public static final String BASIC_SECURITY_SCHEME = "basic"; + public static final String DIGEST_SECURITY_SCHEME = "digest"; + public static final String API_KEY_SECURITY_SCHEME = "apikey"; + public static final String BEARER_SECURITY_SCHEME = "bearer"; + public static final String PSK_SECURITY_SCHEME = "psk"; + public static final String OAUTH2_SECURITY_SCHEME = "oauth2"; + } diff --git a/src/main/java/wot/jtd/exception/SchemaValidationException.java b/src/main/java/wot/jtd/exception/SchemaValidationException.java index 3392ec7..8688c2a 100755 --- a/src/main/java/wot/jtd/exception/SchemaValidationException.java +++ b/src/main/java/wot/jtd/exception/SchemaValidationException.java @@ -1,5 +1,10 @@ package wot.jtd.exception; +/** + * This exception is thrown when the syntax of the Thing Description is incorrect + * @author Andrea Cimmino + * + */ public class SchemaValidationException extends Exception{ private static final long serialVersionUID = 1L; diff --git a/src/main/java/wot/jtd/model/AbstractJTDObject.java b/src/main/java/wot/jtd/model/AbstractJTDObject.java deleted file mode 100755 index d12dc78..0000000 --- a/src/main/java/wot/jtd/model/AbstractJTDObject.java +++ /dev/null @@ -1,120 +0,0 @@ -package wot.jtd.model; - -import java.net.URI; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.jena.rdf.model.Model; -import com.apicatalog.jsonld.JsonLdError; -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.gson.JsonObject; -import wot.jtd.JTD; -import wot.jtd.RDFHandler; -import wot.jtd.annotations.RdfDatatypeProperty; -import wot.jtd.vocabulary.Vocabulary; - - -public abstract class AbstractJTDObject { - - protected static final Logger LOGGER = Logger.getLogger(AbstractJTDObject.class.getName()); - static { - LOGGER.setLevel(Level.WARNING); - } - - // Shared common attributes - @JsonProperty(Vocabulary.JSONLD_TYPE) - @RdfDatatypeProperty(value="https://www.w3.org/2019/wot/td#type") - protected Collection type; - protected URI id; - - - public Collection getType() { - return type; - } - public void setType(Collection type) { - this.type = type; - } - - public URI getId() { - return id; - } - public void setId(URI id) { - this.id = id; - } - - - - // Any other property outside the standard - protected Map unknownProperties = new HashMap<>(); - - @JsonIgnore - protected Boolean hasExternalProperties = false; - - @JsonAnySetter - public void setExternal(String name, Object value) { - unknownProperties.put(name, value); - hasExternalProperties = true; - if(JTD.getShowExternalValuesWarnings()) - LOGGER.log( Level.WARNING, getWariningMessage()); - } - - private String getWariningMessage() { - StringBuilder message = new StringBuilder(); - try { - String clazzName = this.getClass().getSimpleName(); - ObjectMapper mapper = new ObjectMapper(); - String jsonUnknownProperties = mapper.writeValueAsString(unknownProperties); - message.append("Json elements outside the standard found in '").append(clazzName).append("' : ").append(jsonUnknownProperties); - }catch(Exception e) { - e.printStackTrace(); - } - return message.toString(); - } - - @JsonAnyGetter - public Map getExternal() { - return unknownProperties; - } - - public Model toRDF(JsonObject td) throws JsonLdError { - RDFHandler handler = new RDFHandler(); - return handler.toRDF(td); - } - - - - // -- Hash code and equals - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((unknownProperties == null) ? 0 : unknownProperties.hashCode()); - return result; - } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - AbstractJTDObject other = (AbstractJTDObject) obj; - if (unknownProperties == null) { - if (other.unknownProperties != null) - return false; - } else if (!unknownProperties.equals(other.unknownProperties)) - return false; - return true; - } - - -} diff --git a/src/main/java/wot/jtd/model/AbstractRdfObject.java b/src/main/java/wot/jtd/model/AbstractRdfObject.java new file mode 100755 index 0000000..011285f --- /dev/null +++ b/src/main/java/wot/jtd/model/AbstractRdfObject.java @@ -0,0 +1,115 @@ +package wot.jtd.model; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import kehio.annotations.RdfContainer; +import kehio.annotations.RdfId; +import kehio.annotations.RdfObject; +import kehio.annotations.RdfUrlMap; +import wot.jtd.Vocabulary; + + +public class AbstractRdfObject { + + + @JsonProperty(Vocabulary.JSONLD_TYPE) + @RdfObject(value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type", base="https://www.w3.org/2019/wot/td#") + protected Collection type; + + @RdfId + @JsonProperty("id") + @JsonAlias(Vocabulary.JSONLD_ID) + protected String id; + + @RdfContainer(ignore= {"https://www.w3.org/2019/wot/td#name", "https://www.w3.org/2019/wot/json-schema#propertyName"}, + prefixes= {@RdfUrlMap(key="htv", value="http://www.w3.org/2011/http#")}, + aliases={ //@RdfUrlMap(key="type", value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), + @RdfUrlMap(key="@type", value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type") + }, + identifiers={ "id"} + ) + @JsonIgnore + protected Map externalProperties = new HashMap<>(); + + // -- Getters & Setters + + public Collection getType() { + return type; + } + public void setType(Collection type) { + this.type = type; + } + + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + + + // --- + + @JsonAnySetter + public void setExternalProperties(String name, Object value) { + externalProperties.put(name, value); + } + + @JsonAnyGetter + public Map getExternalProperties() { + return externalProperties; + } + + // -- Hash code & Equals + + // -- hash code sub-methods + + protected int superHashcode(int subResult, int prime) { + int result = subResult; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((externalProperties == null) ? 0 : externalProperties.hashCode()); + return result; + } + + // -- equals sub-methods + + protected boolean sameSuperAttributes(AbstractRdfObject abstractRdfObject) { + Boolean sameAttributes = sameCollections(abstractRdfObject.getType(), abstractRdfObject.getType()); + sameAttributes &= sameAttribute(this.id, abstractRdfObject.getId()); + sameAttributes &= sameMap(this.externalProperties, abstractRdfObject.getExternalProperties()); + return sameAttributes; + } + + protected boolean sameCollections(Collection collection1, Collection collection2) { + Boolean sameCollections = collection1!=null && collection2!=null; + if(sameCollections) + sameCollections &= collection1.containsAll(collection2) && collection2.containsAll(collection1); + sameCollections |= collection1==null && collection2==null; + return sameCollections; + } + + protected boolean sameMap(Map map1, Map map2) { + Boolean sameMaps = map1!=null && map2!=null && map1.size() == map2.size() ; + if(sameMaps) { + Set entries1 = map1.entrySet(); + Set entries2 = map2.entrySet(); + sameMaps = sameCollections(entries1, entries2); + } + sameMaps |= map1==null && map2==null; + return sameMaps; + } + + protected boolean sameAttribute(Object attribute1, Object attribute2) { + return (attribute1!=null && attribute2!=null && attribute1.equals(attribute2)) || (attribute1==null && attribute2==null); + } + + +} diff --git a/src/main/java/wot/jtd/model/AbstractRdfObject_Prev.java b/src/main/java/wot/jtd/model/AbstractRdfObject_Prev.java new file mode 100644 index 0000000..7fb7dc9 --- /dev/null +++ b/src/main/java/wot/jtd/model/AbstractRdfObject_Prev.java @@ -0,0 +1,110 @@ +package wot.jtd.model; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; +import kehio.annotations.RdfPropertiesContainer; +import kehio.annotations.RdfUrlMap; +import kehio.annotations.RdfId; +import kehio.annotations.RdfObject; +import wot.jtd.Vocabulary; + + +public class AbstractRdfObject_Prev { + + + @JsonProperty(Vocabulary.JSONLD_TYPE) + @RdfObject(value="http://www.w3.org/1999/02/22-rdf-syntax-ns#type", base="https://www.w3.org/2019/wot/td#") + protected Collection type; + + @RdfId + @JsonProperty("id") + @JsonAlias(Vocabulary.JSONLD_ID) + protected String id; + + // Any other property outside the standard + @RdfPropertiesContainer(ignore= {"https://www.w3.org/2019/wot/td#name", "https://www.w3.org/2019/wot/json-schema#propertyName"}, + prefixes= { + @RdfUrlMap(key="htv", value="http://www.w3.org/2011/http#"), + }) + protected Map unknownProperties = new HashMap<>(); + + // -- Getters & Setters + + public Collection getType() { + return type; + } + public void setType(Collection type) { + this.type = type; + } + + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + + @JsonAnySetter + public void setExternal(String name, Object value) { + unknownProperties.put(name, value.toString()); + } + + @JsonAnyGetter + public Map getExternal() { + return unknownProperties; + } + + + // -- Hash code & Equals + + // -- hash code sub-methods + + protected int superHashcode(int subResult, int prime) { + int result = subResult; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((unknownProperties == null) ? 0 : unknownProperties.hashCode()); + return result; + } + + // -- equals sub-methods + + protected boolean sameSuperAttributes(AbstractRdfObject_Prev abstractRdfObject) { + Boolean sameAttributes = sameCollections(abstractRdfObject.getType(), abstractRdfObject.getType()); + sameAttributes &= sameAttribute(this.id, abstractRdfObject.getId()); + sameAttributes &= sameMap(this.unknownProperties, abstractRdfObject.getExternal()); + return sameAttributes; + } + + protected boolean sameCollections(Collection collection1, Collection collection2) { + Boolean sameCollections = collection1!=null && collection2!=null; + if(sameCollections) + sameCollections &= collection1.containsAll(collection2) && collection2.containsAll(collection1); + sameCollections |= collection1==null && collection2==null; + return sameCollections; + } + + protected boolean sameMap(Map map1, Map map2) { + Boolean sameMaps = map1!=null && map2!=null && map1.size() == map2.size() ; + if(sameMaps) { + Set entries1 = map1.entrySet(); + Set entries2 = map2.entrySet(); + sameMaps = sameCollections(entries1, entries2); + } + sameMaps |= map1==null && map2==null; + return sameMaps; + } + + protected boolean sameAttribute(Object attribute1, Object attribute2) { + return (attribute1!=null && attribute2!=null && attribute1.equals(attribute2)) || (attribute1==null && attribute2==null); + } + + +} diff --git a/src/main/java/wot/jtd/model/ActionAffordance.java b/src/main/java/wot/jtd/model/ActionAffordance.java deleted file mode 100755 index db2bd9e..0000000 --- a/src/main/java/wot/jtd/model/ActionAffordance.java +++ /dev/null @@ -1,308 +0,0 @@ -package wot.jtd.model; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; -import javax.validation.constraints.NotEmpty; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.gson.JsonObject; -import wot.jtd.JTD; -import wot.jtd.exception.ActionAffordanceValidationException; -import wot.jtd.exception.SchemaValidationException; -import wot.jtd.vocabulary.Vocabulary; - -/** - * This class implements the object ActionAffordance from a Thing Description as specified in the Web of Things (WoT) documentation.

- * @see ActionAffordance WoT documentation - * @author Andrea Cimmino - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ActionAffordance extends AbstractJTDObject{ - - // -- attributes - - @NotEmpty(message="'forms' in any InteractionAffordance (PropertyAffordance, ActionAffordance, or EventAffordance) must not be empty") - private Collection

forms; - @JsonProperty(Vocabulary.JSONLD_TYPE) - private Collection type; - private String title; - private Map titles; - private String description; - private Map descriptions; - private Map uriVariables; - - // specific attributes of ActionAffordance - private DataSchema input; - private DataSchema output; - private Boolean safe; // has default value - private Boolean idempotent; // has default value - - // -- static constructors and validation method - - /** - * This method creates a validated instance of {@link ActionAffordance}, if default values are enabled in {@link JTD} the {@link ActionAffordance} will have as the attributes 'safe' and 'idempotent' as false. - * @param forms am array with valid {@link Forms} - * @return an instantiated and validated {@link ActionAffordance} - * @throws SchemaValidationException - */ - public static ActionAffordance create(Collection forms) throws SchemaValidationException { - // create action affordance - ActionAffordance actionAffordance = new ActionAffordance(); - actionAffordance.setForms(forms); - if(JTD.getDefaultValues()) { - actionAffordance.setSafe(false); - actionAffordance.setIdempotent(false); - } - // validate - validate(actionAffordance); - return actionAffordance; - } - - /** - * This method validates an instance of {@link ActionAffordance}. - * @param actionAffordance an instance of {@link ActionAffordance} - * @throws SchemaValidationException - */ - public static void validate(ActionAffordance actionAffordance) throws SchemaValidationException { - ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - Validator validator = factory.getValidator(); - Set> violations = validator.validate(actionAffordance); - StringBuilder builder = new StringBuilder(); - if(!violations.isEmpty()) { - violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); - throw new ActionAffordanceValidationException(builder.toString()); - } - if(actionAffordance.getForms()!=null) { - for(Form form: actionAffordance.getForms()) { - Form.validate(form); - } - } - if(actionAffordance.getUriVariables()!=null) { - List schemas = new ArrayList<>(actionAffordance.getUriVariables().values()); - for(int index=0; index < schemas.size(); index++) { - DataSchema.validate(schemas.get(index)); - } - } - } - - // -- serialization and deserialization - /** - * This method transforms the current {@link ActionAffordance} object into a {@link JsonObject}. - * @return a {@link JsonObject} - * @throws JsonProcessingException - */ - public JsonObject toJson() throws JsonProcessingException { - return JTD.toJson(this); - } - - /** - * This method instantiates and validates a {@link ActionAffordance} object from a {@link JsonObject}. - * @param json a ActionAffordance expressed as a {@link JsonObject} - * @return a valid {@link ActionAffordance} - * @throws IOException - * @throws SchemaValidationException - */ - public static ActionAffordance fromJson(JsonObject json) throws IOException, SchemaValidationException { - ActionAffordance actionAffordance = (ActionAffordance) JTD.instantiateFromJson(json, ActionAffordance.class); - validate(actionAffordance); - return actionAffordance; - } - - // -- getters and setters - - public Collection getForms() { - return forms; - } - - public DataSchema getInput() { - return input; - } - - public void setInput(DataSchema input) { - this.input = input; - } - - public DataSchema getOutput() { - return output; - } - - public void setOutput(DataSchema output) { - this.output = output; - } - - public Boolean getSafe() { - return safe; - } - - public void setSafe(Boolean safe) { - this.safe = safe; - } - - public Boolean getIdempotent() { - return idempotent; - } - - public void setIdempotent(Boolean idempotent) { - this.idempotent = idempotent; - } - - public void setForms(Collection forms) { - this.forms = forms; - } - - public Collection getType() { - return type; - } - - public void setType(Collection type) { - this.type = type; - } - - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public Map getTitles() { - return titles; - } - - public void setTitles(Map titles) { - this.titles = titles; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Map getDescriptions() { - return descriptions; - } - - public void setDescriptions(Map descriptions) { - this.descriptions = descriptions; - } - - public Map getUriVariables() { - return uriVariables; - } - - public void setUriVariables(Map uriVariables) { - this.uriVariables = uriVariables; - } - - // -- hashCode and equals - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((description == null) ? 0 : description.hashCode()); - result = prime * result + ((descriptions == null) ? 0 : descriptions.hashCode()); - result = prime * result + ((forms == null) ? 0 : forms.hashCode()); - result = prime * result + ((idempotent == null) ? 0 : idempotent.hashCode()); - result = prime * result + ((input == null) ? 0 : input.hashCode()); - result = prime * result + ((output == null) ? 0 : output.hashCode()); - result = prime * result + ((safe == null) ? 0 : safe.hashCode()); - result = prime * result + ((title == null) ? 0 : title.hashCode()); - result = prime * result + ((titles == null) ? 0 : titles.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + ((uriVariables == null) ? 0 : uriVariables.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (!(obj instanceof ActionAffordance)) - return false; - ActionAffordance other = (ActionAffordance) obj; - if (description == null) { - if (other.description != null) - return false; - } else if (!description.equals(other.description)) - return false; - if (descriptions == null) { - if (other.descriptions != null) - return false; - } else if (!descriptions.equals(other.descriptions)) - return false; - if (forms == null) { - if (other.forms != null) - return false; - } else if (!forms.equals(other.forms)) - return false; - if (idempotent == null) { - if (other.idempotent != null) - return false; - } else if (!idempotent.equals(other.idempotent)) - return false; - if (input == null) { - if (other.input != null) - return false; - } else if (!input.equals(other.input)) - return false; - if (output == null) { - if (other.output != null) - return false; - } else if (!output.equals(other.output)) - return false; - if (safe == null) { - if (other.safe != null) - return false; - } else if (!safe.equals(other.safe)) - return false; - if (title == null) { - if (other.title != null) - return false; - } else if (!title.equals(other.title)) - return false; - if (titles == null) { - if (other.titles != null) - return false; - } else if (!titles.equals(other.titles)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - if (uriVariables == null) { - if (other.uriVariables != null) - return false; - } else if (!uriVariables.equals(other.uriVariables)) - return false; - return true; - } - - - - - - - - - - - -} diff --git a/src/main/java/wot/jtd/model/DataSchema.java b/src/main/java/wot/jtd/model/DataSchema.java deleted file mode 100755 index ac1a753..0000000 --- a/src/main/java/wot/jtd/model/DataSchema.java +++ /dev/null @@ -1,416 +0,0 @@ -package wot.jtd.model; - -import java.io.IOException; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; -import javax.validation.constraints.Pattern; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonRawValue; -import com.fasterxml.jackson.annotation.JsonSetter; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.google.gson.JsonObject; -import wot.jtd.JTD; -import wot.jtd.exception.DataSchemaValidationException; -import wot.jtd.exception.SchemaValidationException; -import wot.jtd.vocabulary.Vocabulary; - -/** - * This class implements the object DataSchema (and its sub-clases) from a Thing Description as specified in the Web of Things (WoT) documentation.

- * @see DataSchema WoT documentation - * @author Andrea Cimmino - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class DataSchema extends AbstractJTDObject{ - - // -- attributes - - @JsonProperty(Vocabulary.JSONLD_TYPE) - private Collection type; - - private String title; - private Map titles; - private String description; - private Map descriptions; - @Pattern(regexp = "array|object|number|integer|string|boolean|null", flags = Pattern.Flag.CASE_INSENSITIVE) - @JsonProperty(Vocabulary.TYPE) - private String schemaType; - private String unit; - private Collection oneOf; - - @JsonRawValue - @JsonProperty(Vocabulary.ENUM) - private Collection enumTypes; - - @JsonRawValue - @JsonProperty(Vocabulary.CONS) - private String cons; - - private Boolean readOnly; // has default value - private Boolean writeOnly; // has default value - private String format; - - // array - @JsonProperty(Vocabulary.ITEMS) - private Collection items; //compactable attribute - private Integer minItems; // maxInclusive = 4294967295 - private Integer maxItems; // maxInclusive = 4294967295 - // boolean + string - // number + integer - private Number minimum; - private Number maximum; - // object - private Map properties; - private Collection required; - - - - // -- constructors and validation methods (static) - /** - * This method creates a validated instance of {@link DataSchema}, if default values are enabled in {@link JTD} the {@link DataSchema} will have the attributes 'readOnly' and 'writeOnly' as false - * @return an instantiated and validated {@link DataSchema} - * @throws SchemaValidationException - */ - public static DataSchema create() throws SchemaValidationException { - DataSchema dataSchema = new DataSchema(); - if(JTD.getDefaultValues()) { - dataSchema.setReadOnly(false); - dataSchema.setWriteOnly(false); - } - validate(dataSchema); - return dataSchema; - } - - /** - * This method validates an instance of {@link DataSchema}. - * @param actionAffordance an instance of {@link DataSchema} - * @throws SchemaValidationException - */ - public static void validate(DataSchema dataSchema) throws SchemaValidationException { - ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - Validator validator = factory.getValidator(); - Set> violations = validator.validate(dataSchema); - StringBuilder builder = new StringBuilder(); - if(!violations.isEmpty()) { - violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); - throw new DataSchemaValidationException(builder.toString()); - } - // TODO: validate nested objects - // TODO: validate other restrictions - } - - // -- serialization and deserialization - - /** - * This method transforms the current {@link DataSchema} object into a {@link JsonObject}. - * @return a {@link JsonObject} - * @throws JsonProcessingException - */ - public JsonObject toJson() throws JsonProcessingException { - return JTD.toJson(this); - } - - /** - * This method instantiates and validates a {@link DataSchema} object from a {@link JsonObject}. - * @param json a ExpectedResponse expressed as a {@link JsonObject} - * @return a valid {@link DataSchema} - * @throws IOException - * @throws SchemaValidationException - */ - public static DataSchema fromJson(JsonObject json) throws IOException, SchemaValidationException { - DataSchema dataSchema = (DataSchema) JTD.instantiateFromJson(json, DataSchema.class); - validate(dataSchema); - return dataSchema; - } - - - // -- getters and setters - - public Collection getType() { - return type; - } - public void setType(Collection type) { - this.type = type; - } - public String getTitle() { - return title; - } - public void setTitle(String title) { - this.title = title; - } - public Map getTitles() { - return titles; - } - public void setTitles(Map titles) { - this.titles = titles; - } - public String getDescription() { - return description; - } - public void setDescription(String description) { - this.description = description; - } - public Map getDescriptions() { - return descriptions; - } - public void setDescriptions(Map descriptions) { - this.descriptions = descriptions; - } - public String getSchemaType() { - return schemaType; - } - public void setSchemaType(String schemaType) { - this.schemaType = schemaType; - } - public Object getCons() { - return cons; - } - - public String getUnit() { - return unit; - } - public void setUnit(String unit) { - this.unit = unit; - } - public Collection getOneOf() { - return oneOf; - } - public void setOneOf(Collection oneOf) { - this.oneOf = oneOf; - } - - public Collection getEnumTypes() { - return enumTypes; - } - - public Boolean getReadOnly() { - return readOnly; - } - public void setReadOnly(Boolean readOnly) { - this.readOnly = readOnly; - } - public Boolean getWriteOnly() { - return writeOnly; - } - public void setWriteOnly(Boolean writeOnly) { - this.writeOnly = writeOnly; - } - public String getFormat() { - return format; - } - public void setFormat(String format) { - this.format = format; - } - public Collection getItems() { - return items; - } - public void setItems(Collection items) { - this.items = items; - } - public Integer getMinItems() { - return minItems; - } - public void setMinItems(Integer minItems) { - this.minItems = minItems; - } - public Integer getMaxItems() { - return maxItems; - } - public void setMaxItems(Integer maxItems) { - this.maxItems = maxItems; - } - public Number getMinimum() { - return minimum; - } - public void setMinimum(Number minimum) { - this.minimum = minimum; - } - - public Number getMaximum() { - return maximum; - } - - public void setMaximum(Number maximum) { - this.maximum = maximum; - } - - @JsonSetter(Vocabulary.CONS) - public void setCons(JsonNode cons) { - this.cons = cons.toString(); - } - @JsonSetter(Vocabulary.ENUM) - public void setEnumTypes(List enumTypes) { - this.enumTypes = enumTypes.stream().map(elem -> elem.toString()).collect(Collectors.toList()); - } - - public Map getProperties() { - return properties; - } - public void setProperties(Map properties) { - this.properties = properties; - } - public Collection getRequired() { - return required; - } - public void setRequired(Collection required) { - this.required = required; - } - - // -- hashcode and equals - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((cons == null) ? 0 : cons.hashCode()); - result = prime * result + ((description == null) ? 0 : description.hashCode()); - result = prime * result + ((descriptions == null) ? 0 : descriptions.hashCode()); - result = prime * result + ((enumTypes == null) ? 0 : enumTypes.hashCode()); - result = prime * result + ((format == null) ? 0 : format.hashCode()); - result = prime * result + ((items == null) ? 0 : items.hashCode()); - result = prime * result + ((maxItems == null) ? 0 : maxItems.hashCode()); - result = prime * result + ((maximum == null) ? 0 : maximum.hashCode()); - result = prime * result + ((minItems == null) ? 0 : minItems.hashCode()); - result = prime * result + ((minimum == null) ? 0 : minimum.hashCode()); - result = prime * result + ((oneOf == null) ? 0 : oneOf.hashCode()); - result = prime * result + ((properties == null) ? 0 : properties.hashCode()); - result = prime * result + ((readOnly == null) ? 0 : readOnly.hashCode()); - result = prime * result + ((required == null) ? 0 : required.hashCode()); - result = prime * result + ((schemaType == null) ? 0 : schemaType.hashCode()); - result = prime * result + ((title == null) ? 0 : title.hashCode()); - result = prime * result + ((titles == null) ? 0 : titles.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + ((unit == null) ? 0 : unit.hashCode()); - result = prime * result + ((writeOnly == null) ? 0 : writeOnly.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (!(obj instanceof DataSchema)) - return false; - DataSchema other = (DataSchema) obj; - if (cons == null) { - if (other.cons != null) - return false; - } else if (!cons.equals(other.cons)) - return false; - if (description == null) { - if (other.description != null) - return false; - } else if (!description.equals(other.description)) - return false; - if (descriptions == null) { - if (other.descriptions != null) - return false; - } else if (!descriptions.equals(other.descriptions)) - return false; - if (enumTypes == null) { - if (other.enumTypes != null) - return false; - } else if (!enumTypes.equals(other.enumTypes)) - return false; - if (format == null) { - if (other.format != null) - return false; - } else if (!format.equals(other.format)) - return false; - if (items == null) { - if (other.items != null) - return false; - } else if (!items.equals(other.items)) - return false; - if (maxItems == null) { - if (other.maxItems != null) - return false; - } else if (!maxItems.equals(other.maxItems)) - return false; - if (maximum == null) { - if (other.maximum != null) - return false; - } else if (!maximum.equals(other.maximum)) - return false; - if (minItems == null) { - if (other.minItems != null) - return false; - } else if (!minItems.equals(other.minItems)) - return false; - if (minimum == null) { - if (other.minimum != null) - return false; - } else if (!minimum.equals(other.minimum)) - return false; - if (oneOf == null) { - if (other.oneOf != null) - return false; - } else if (!oneOf.equals(other.oneOf)) - return false; - if (properties == null) { - if (other.properties != null) - return false; - } else if (!properties.equals(other.properties)) - return false; - if (readOnly == null) { - if (other.readOnly != null) - return false; - } else if (!readOnly.equals(other.readOnly)) - return false; - if (required == null) { - if (other.required != null) - return false; - } else if (!required.equals(other.required)) - return false; - if (schemaType == null) { - if (other.schemaType != null) - return false; - } else if (!schemaType.equals(other.schemaType)) - return false; - if (title == null) { - if (other.title != null) - return false; - } else if (!title.equals(other.title)) - return false; - if (titles == null) { - if (other.titles != null) - return false; - } else if (!titles.equals(other.titles)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - if (unit == null) { - if (other.unit != null) - return false; - } else if (!unit.equals(other.unit)) - return false; - if (writeOnly == null) { - if (other.writeOnly != null) - return false; - } else if (!writeOnly.equals(other.writeOnly)) - return false; - return true; - } - - - - - - - - -} diff --git a/src/main/java/wot/jtd/model/EventAffordance.java b/src/main/java/wot/jtd/model/EventAffordance.java deleted file mode 100755 index 707f9b8..0000000 --- a/src/main/java/wot/jtd/model/EventAffordance.java +++ /dev/null @@ -1,300 +0,0 @@ -package wot.jtd.model; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; -import javax.validation.constraints.NotEmpty; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.gson.JsonObject; -import wot.jtd.JTD; -import wot.jtd.exception.EventAffordanceValidationException; -import wot.jtd.exception.SchemaValidationException; -import wot.jtd.vocabulary.Vocabulary; - - -/** - * This class implements the object EventAffordance from a Thing Description as specified in the Web of Things (WoT) documentation.

- * @see EventAffordance WoT documentation - * @author Andrea Cimmino - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class EventAffordance extends AbstractJTDObject{ - - // -- attributes - - @NotEmpty(message = "'forms' in any InteractionAffordance (PropertyAffordance, ActionAffordance, or EventAffordance) must not be empty") - private Collection forms; - @JsonProperty(Vocabulary.JSONLD_TYPE) - private Collection type; - private String title; - private Map titles; - private String description; - private Map descriptions; - private Map uriVariables; - - // specific attributes of EvenAffordance - private DataSchema subscription; - private DataSchema data; - private DataSchema cancellation; - - // -- static constructors and validation method - - /** - * This method creates a validated instance of {@link EventAffordance}. - * @param forms am array with valid {@link Forms} - * @return an instantiated and validated {@link EventAffordance} - * @throws SchemaValidationException - */ - public static EventAffordance create(Collection forms) throws SchemaValidationException { - // create action affordance - EventAffordance eventAffordance = new EventAffordance(); - eventAffordance.setForms(forms); - // validate - validate(eventAffordance); - return eventAffordance; - } - - /** - * This method validates an instance of {@link EventAffordance}. - * @param eventAffordance an instance of {@link EventAffordance} - * @throws SchemaValidationException - */ - public static void validate(EventAffordance eventAffordance) throws SchemaValidationException { - ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - Validator validator = factory.getValidator(); - Set> violations = validator.validate(eventAffordance); - StringBuilder builder = new StringBuilder(); - if(!violations.isEmpty()) { - violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); - throw new EventAffordanceValidationException(builder.toString()); - } - if(eventAffordance.getForms()!=null) { - for(Form form:eventAffordance.getForms()) { - Form.validate(form); - } - } - if(eventAffordance.getUriVariables()!=null) { - List schemas = new ArrayList<>(eventAffordance.getUriVariables().values()); - for(int index=0; index < schemas.size(); index++) { - DataSchema.validate(schemas.get(index)); - } - } - if(eventAffordance.getSubscription()!=null) - DataSchema.validate(eventAffordance.getSubscription()); - if(eventAffordance.getData()!=null) - DataSchema.validate(eventAffordance.getData()); - if(eventAffordance.getCancellation()!=null) - DataSchema.validate(eventAffordance.getCancellation()); - - } - - - // -- serialization and deserialization - - /** - * This method transforms the current {@link EventAffordance} object into a {@link JsonObject}. - * @return a {@link JsonObject} - * @throws JsonProcessingException - */ - public JsonObject toJson() throws JsonProcessingException { - return JTD.toJson(this); - } - - /** - * This method instantiates and validates a {@link EventAffordance} object from a {@link JsonObject}. - * @param json a EventAffordance expressed as a {@link JsonObject} - * @return a valid {@link EventAffordance} - * @throws IOException - * @throws SchemaValidationException - */ - public static EventAffordance fromJson(JsonObject json) throws IOException, SchemaValidationException { - EventAffordance eventAffordance = (EventAffordance) JTD.instantiateFromJson(json, EventAffordance.class); - validate(eventAffordance); - return eventAffordance; - } - - - // -- getters and setters - - public Collection getForms() { - return forms; - } - - public void setForms(Collection forms) { - this.forms = forms; - } - - public Collection getType() { - return type; - } - - public void setType(List type) { - this.type = type; - } - - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public Map getTitles() { - return titles; - } - - public void setTitles(Map titles) { - this.titles = titles; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Map getDescriptions() { - return descriptions; - } - - public void setDescriptions(Map descriptions) { - this.descriptions = descriptions; - } - - public Map getUriVariables() { - return uriVariables; - } - - public void setUriVariables(Map uriVariables) { - this.uriVariables = uriVariables; - } - - public DataSchema getSubscription() { - return subscription; - } - - public void setSubscription(DataSchema subscription) { - this.subscription = subscription; - } - - public DataSchema getData() { - return data; - } - - public void setData(DataSchema data) { - this.data = data; - } - - public DataSchema getCancellation() { - return cancellation; - } - - public void setCancellation(DataSchema cancellation) { - this.cancellation = cancellation; - } - - // -- hashcode and equals - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((cancellation == null) ? 0 : cancellation.hashCode()); - result = prime * result + ((data == null) ? 0 : data.hashCode()); - result = prime * result + ((description == null) ? 0 : description.hashCode()); - result = prime * result + ((descriptions == null) ? 0 : descriptions.hashCode()); - result = prime * result + ((forms == null) ? 0 : forms.hashCode()); - result = prime * result + ((subscription == null) ? 0 : subscription.hashCode()); - result = prime * result + ((title == null) ? 0 : title.hashCode()); - result = prime * result + ((titles == null) ? 0 : titles.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + ((uriVariables == null) ? 0 : uriVariables.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (!(obj instanceof EventAffordance)) - return false; - EventAffordance other = (EventAffordance) obj; - if (cancellation == null) { - if (other.cancellation != null) - return false; - } else if (!cancellation.equals(other.cancellation)) - return false; - if (data == null) { - if (other.data != null) - return false; - } else if (!data.equals(other.data)) - return false; - if (description == null) { - if (other.description != null) - return false; - } else if (!description.equals(other.description)) - return false; - if (descriptions == null) { - if (other.descriptions != null) - return false; - } else if (!descriptions.equals(other.descriptions)) - return false; - if (forms == null) { - if (other.forms != null) - return false; - } else if (!forms.equals(other.forms)) - return false; - if (subscription == null) { - if (other.subscription != null) - return false; - } else if (!subscription.equals(other.subscription)) - return false; - if (title == null) { - if (other.title != null) - return false; - } else if (!title.equals(other.title)) - return false; - if (titles == null) { - if (other.titles != null) - return false; - } else if (!titles.equals(other.titles)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - if (uriVariables == null) { - if (other.uriVariables != null) - return false; - } else if (!uriVariables.equals(other.uriVariables)) - return false; - return true; - } - - - - - - - - - -} diff --git a/src/main/java/wot/jtd/model/ExpectedResponse.java b/src/main/java/wot/jtd/model/ExpectedResponse.java index a1929ec..b4ea657 100755 --- a/src/main/java/wot/jtd/model/ExpectedResponse.java +++ b/src/main/java/wot/jtd/model/ExpectedResponse.java @@ -1,20 +1,9 @@ package wot.jtd.model; -import java.io.IOException; -import java.util.Set; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; import javax.validation.constraints.NotBlank; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.gson.JsonObject; -import wot.jtd.JTD; -import wot.jtd.exception.ExpectedResponseValidationException; -import wot.jtd.exception.SchemaValidationException; -import wot.jtd.vocabulary.Vocabulary; + +import kehio.annotations.RdfDatatype; /** * This class implements the object ExpectedResponse from a Thing Description as specified in the Web of Things (WoT) documentation.

@@ -23,74 +12,14 @@ * */ @JsonInclude(JsonInclude.Include.NON_NULL) -public class ExpectedResponse extends AbstractJTDObject{ +public class ExpectedResponse extends AbstractRdfObject{ // -- attributes - + @RdfDatatype("https://www.w3.org/2019/wot/hypermedia#forContentType") @NotBlank(message="'contentType' is mandatory and must be a valid mime type from RDC 2046") - private String contentType; //from RFC2046 - @JsonProperty(Vocabulary.STATUS_CODE_NUMBER) - private Integer statusCodeNumber; - private String description; - - // -- ExpectedResponse Object methods - - /** - * This method creates a validated instance of {@link ExpectedResponse}. - * @param contentType a valid mime type from the RFC 2046 specification - * @return - * @throws SchemaValidationException - */ - public static ExpectedResponse create(String contentType) throws SchemaValidationException { - // Create version info - ExpectedResponse expectedResponse = new ExpectedResponse(); - expectedResponse.setContentType(contentType); - // Validate version info - validate(expectedResponse); - return expectedResponse; - } - - /** - * This method validates an instance of {@link ExpectedResponse}. - * @param expectedResponse an instance of {@link ExpectedResponse} - * @throws SchemaValidationException - */ - public static void validate(ExpectedResponse expectedResponse) throws SchemaValidationException { - ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - Validator validator = factory.getValidator(); - Set> violations = validator.validate(expectedResponse); - if(!violations.isEmpty()) { - StringBuilder builder = new StringBuilder(); - violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); - throw new ExpectedResponseValidationException(builder.toString()); - } - } - - // -- serialization and deserialization - - /** - * This method transforms the current {@link ExpectedResponse} object into a {@link JsonObject}. - * @param expectedResponse a {@link ExpectedResponse} object - * @return a {@link JsonObject} - * @throws JsonProcessingException - */ - public JsonObject toJson() throws JsonProcessingException { - return JTD.toJson(this); - } + protected String contentType; //from RFC2046 - /** - * This method instantiates and validates a {@link ExpectedResponse} object from a {@link JsonObject}. - * @param json a ExpectedResponse expressed as a {@link JsonObject} - * @return a valid {@link ExpectedResponse} - * @throws IOException - * @throws ExpectedResponseValidationException - */ - public static ExpectedResponse fromJson(JsonObject json) throws IOException, SchemaValidationException { - ExpectedResponse expectedResponse = (ExpectedResponse) JTD.instantiateFromJson(json, ExpectedResponse.class); - validate(expectedResponse); - return expectedResponse; - } - // -- getters and setters + // -- Getters & Setters public String getContentType() { return contentType; @@ -100,59 +29,26 @@ public void setContentType(String contentType) { this.contentType = contentType; } - public Integer getStatusCodeNumber() { - return statusCodeNumber; - } - - public void setStatusCodeNumber(Integer statusCodeNumber) { - this.statusCodeNumber = statusCodeNumber; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - // -- hashCode and equals + // -- HashCode & Equals @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((contentType == null) ? 0 : contentType.hashCode()); - result = prime * result + ((description == null) ? 0 : description.hashCode()); - result = prime * result + ((statusCodeNumber == null) ? 0 : statusCodeNumber.hashCode()); + result = superHashcode(result, prime); return result; } @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) + if (obj == null) return false; - if (!(obj instanceof ExpectedResponse)) + if (this.getClass() != obj.getClass()) return false; + ExpectedResponse other = (ExpectedResponse) obj; - if (contentType == null) { - if (other.contentType != null) - return false; - } else if (!contentType.equals(other.contentType)) - return false; - if (description == null) { - if (other.description != null) - return false; - } else if (!description.equals(other.description)) - return false; - if (statusCodeNumber == null) { - if (other.statusCodeNumber != null) - return false; - } else if (!statusCodeNumber.equals(other.statusCodeNumber)) - return false; - return true; + return sameSuperAttributes(other) && sameAttribute(this.getContentType(), other.getContentType()); } diff --git a/src/main/java/wot/jtd/model/Form.java b/src/main/java/wot/jtd/model/Form.java index adae5e6..1d8dfb8 100755 --- a/src/main/java/wot/jtd/model/Form.java +++ b/src/main/java/wot/jtd/model/Form.java @@ -1,156 +1,113 @@ package wot.jtd.model; -import java.io.IOException; import java.util.Collection; -import java.util.Set; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.gson.JsonObject; -import wot.jtd.JTD; -import wot.jtd.exception.FormValidationException; -import wot.jtd.exception.SchemaValidationException; -import wot.jtd.vocabulary.Vocabulary; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfObject; +import wot.jtd.Vocabulary; /** - * This class implements the object Form from a Thing Description as specified in the Web of Things (WoT) documentation.

- * @see Form WoT documentation + * This class implements the object + * Form from a + * Thing Description as specified in the Web of Things (WoT) documentation. + *

+ * + * @see Form WoT + * documentation * @author Andrea Cimmino */ @JsonInclude(JsonInclude.Include.NON_NULL) -public class Form extends AbstractJTDObject{ +public class Form extends AbstractRdfObject { - // -- attributes - - @NotBlank(message = "'href' must be a valid non-empty and non-null URI or URI template") - private String href; + // -- Attributes + + @RdfObject(value = "https://www.w3.org/2019/wot/hypermedia#hasOperationType", base = "https://www.w3.org/2019/wot/td#") @JsonProperty(Vocabulary.OP) - @Pattern(regexp = "readproperty|writeproperty|observeproperty|unobserveproperty|invokeaction|subscribeevent|unsubscribeevent|readallproperties|writeallproperties|readmultipleproperties|writemultipleproperties", flags = Pattern.Flag.CASE_INSENSITIVE, message="'op' must have as value of the following: readproperty, writeproperty, observeproperty, unobserveproperty, invokeaction, subscribeevent, unsubscribeevent, readallproperties, writeallproperties, readmultipleproperties, or writemultipleproperties") + @Pattern(regexp = "readproperty|writeproperty|observeproperty|unobserveproperty|invokeaction|subscribeevent|unsubscribeevent|readallproperties|writeallproperties|readmultipleproperties|writemultipleproperties", flags = Pattern.Flag.CASE_INSENSITIVE, message = "'op' must have as value of the following: readproperty, writeproperty, observeproperty, unobserveproperty, invokeaction, subscribeevent, unsubscribeevent, readallproperties, writeallproperties, readmultipleproperties, or writemultipleproperties") private Collection op; // compactable array - private String contentType; //from RFC2046, default value - private String contentEncoding; + + @RdfObject("https://www.w3.org/2019/wot/hypermedia#hasTarget") + @NotBlank(message = "'href' must be a valid non-empty and non-null URI or URI template") + private String href; + + @RdfDatatype("https://www.w3.org/2019/wot/hypermedia#forContentType") + private String contentType; // from RFC2046, default value + + @RdfDatatype("https://www.w3.org/2019/wot/hypermedia#forContentCoding") + private String contentEncoding; + + @RdfDatatype("https://www.w3.org/2019/wot/hypermedia#forSubProtocol") private String subprotocol; + + @RdfDatatype("https://www.w3.org/2019/wot/td#hasSecurityConfiguration") private Collection security; + + @RdfDatatype("https://www.w3.org/2019/wot/security#scopes") private Collection scopes; + + @RdfObject("https://www.w3.org/2019/wot/hypermedia#returns") private ExpectedResponse response; - @JsonProperty(Vocabulary.METHOD_NAME) - private String methodName; - - // -- constructors and validation methods (static) - - /** - * This method creates a validated instance of {@link Form}, if default values are enabled in {@link JTD} the {@link Form} will have as content type 'application/json' - * @param href a valid URI - * @return an instantiated and validated {@link Form} - * @throws SchemaValidationException - */ - public static Form create(String href) throws SchemaValidationException { - // Create form - Form form = new Form(); - form.setHref(href); - if(JTD.getDefaultValues()) - form.setContentType(Vocabulary.MIME_JSON); - // Validate created form - validate(form); - return form; - } - - /** - * This method validates an instance a {@link Form} object. - * @param form an instance of {@link Form} - * @throws SchemaValidationException - */ - public static void validate(Form form) throws SchemaValidationException { - ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - Validator validator = factory.getValidator(); - Set> violations = validator.validate(form); - StringBuilder builder = new StringBuilder(); - if(!violations.isEmpty()) { - violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); - throw new FormValidationException(builder.toString()); - } - // TODO: check that op is one of: readproperty, writeproperty, observeproperty, unobserveproperty, invokeaction, subscribeevent, unsubscribeevent, readallproperties, writeallproperties, readmultipleproperties, or writemultiplepropertie - // TODO: add to the documentation that OP can be only one of these values ==> transform op in enum? - // TODO: check that methodName is one REST operation, check if there are more - if(form.getResponse()!=null) - ExpectedResponse.validate(form.getResponse()); - } - - // -- serialization and deserialization + // -- Getters & Setters - /** - * This method transforms the current {@link Form} object into a {@link JsonObject}. - * @return a {@link JsonObject} - * @throws JsonProcessingException - */ - public JsonObject toJson() throws JsonProcessingException { - return JTD.toJson(this); - } - - - /** - * This method instantiates and validates a {@link Form} object from a {@link JsonObject}. - * @param json a Link expressed as a {@link JsonObject} - * @return a valid {@link Form} - * @throws IOException - * @throws SchemaValidationException - */ - public static Form fromJson(JsonObject json) throws IOException, SchemaValidationException { - Form form = (Form) JTD.instantiateFromJson(json, Form.class); - validate(form); - return form; - } - - // -- getters and setters - public String getHref() { return href; } + public void setHref(String href) { this.href = href; } + public Collection getOp() { return op; } + public void setOp(Collection op) { this.op = op; } - + /** * - * @return a mime type from the RFC 2046 specification + * @return a mime type from the + * RFC 2046 + * specification */ public String getContentType() { return contentType; } + /** * - * @param contentType a valid mime type from the RFC 2046 specification + * @param contentType + * a valid mime type from the + * RFC 2046 + * specification */ public void setContentType(String contentType) { this.contentType = contentType; } + public String getContentEncoding() { return contentEncoding; } + public void setContentEncoding(String contentEncoding) { this.contentEncoding = contentEncoding; } + public String getSubprotocol() { return subprotocol; } + public void setSubprotocol(String subprotocol) { this.subprotocol = subprotocol; } - + public Collection getSecurity() { return security; } @@ -175,96 +132,45 @@ public void setResponse(ExpectedResponse response) { this.response = response; } - public String getMethodName() { - return methodName; - } - - public void setMethodName(String methodName) { - this.methodName = methodName; - } + // HashCode & Equals - // hashcode and equals - @Override public int hashCode() { final int prime = 31; - int result = super.hashCode(); + int result = 1; result = prime * result + ((contentEncoding == null) ? 0 : contentEncoding.hashCode()); result = prime * result + ((contentType == null) ? 0 : contentType.hashCode()); result = prime * result + ((href == null) ? 0 : href.hashCode()); - result = prime * result + ((methodName == null) ? 0 : methodName.hashCode()); result = prime * result + ((op == null) ? 0 : op.hashCode()); result = prime * result + ((response == null) ? 0 : response.hashCode()); result = prime * result + ((scopes == null) ? 0 : scopes.hashCode()); result = prime * result + ((security == null) ? 0 : security.hashCode()); result = prime * result + ((subprotocol == null) ? 0 : subprotocol.hashCode()); + result = superHashcode(result, prime); return result; } @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) + if (obj == null) return false; - if (!(obj instanceof Form)) + if (this.getClass() != obj.getClass()) return false; + Form other = (Form) obj; - if (contentEncoding == null) { - if (other.contentEncoding != null) - return false; - } else if (!contentEncoding.equals(other.contentEncoding)) - return false; - if (contentType == null) { - if (other.contentType != null) - return false; - } else if (!contentType.equals(other.contentType)) - return false; - if (href == null) { - if (other.href != null) - return false; - } else if (!href.equals(other.href)) - return false; - if (methodName == null) { - if (other.methodName != null) - return false; - } else if (!methodName.equals(other.methodName)) - return false; - if (op == null) { - if (other.op != null) - return false; - } else if (!op.equals(other.op)) - return false; - if (response == null) { - if (other.response != null) - return false; - } else if (!response.equals(other.response)) - return false; - if (scopes == null) { - if (other.scopes != null) - return false; - } else if (!scopes.equals(other.scopes)) - return false; - if (security == null) { - if (other.security != null) - return false; - } else if (!security.equals(other.security)) - return false; - if (subprotocol == null) { - if (other.subprotocol != null) - return false; - } else if (!subprotocol.equals(other.subprotocol)) - return false; - return true; - } - - + Boolean sameClass = sameSuperAttributes(other); + sameClass &= sameAttribute(this.getContentEncoding(), other.getContentEncoding()); + sameClass &= sameAttribute(this.getContentType(), other.getContentType()); + sameClass &= sameAttribute(this.getHref(), other.getHref()); + sameClass &= sameAttribute(this.getSubprotocol(), other.getSubprotocol()); + sameClass &= sameAttribute(this.getResponse(), other.getResponse()); + + sameClass &= sameCollections(this.getOp(), other.getOp()); + sameClass &= sameCollections(this.getScopes(), other.getScopes()); + sameClass &= sameCollections(this.getSecurity(), other.getSecurity()); - + return sameClass; + } - - - - } diff --git a/src/main/java/wot/jtd/model/InteractionAffordance.java b/src/main/java/wot/jtd/model/InteractionAffordance.java deleted file mode 100755 index 1bf05ed..0000000 --- a/src/main/java/wot/jtd/model/InteractionAffordance.java +++ /dev/null @@ -1,240 +0,0 @@ -package wot.jtd.model; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; -import javax.validation.constraints.NotEmpty; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.gson.JsonObject; -import wot.jtd.JTD; -import wot.jtd.exception.InteractionAffordanceValidationException; -import wot.jtd.exception.SchemaValidationException; - - -/** - * This class implements the object InteractionAffordance from a Thing Description as specified in the Web of Things (WoT) documentation.

- * @see InteractionAffordance WoT documentation - * @author Andrea Cimmino - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class InteractionAffordance extends AbstractJTDObject{ - - // -- attributes - - @NotEmpty(message="'forms' in any InteractionAffordance (InteractionAffordance, ActionAffordance, or EventAffordance) must not be empty") - protected Form[] forms; - - @JsonProperty("@type") - protected Collection type; - protected String title; - protected Map titles; - protected String description; - protected Map descriptions; - protected Map uriVariables; - - // -- static constructors and validation method - - /** - * This method creates a validated instance of {@link InteractionAffordance}. - * @param forms am array with valid {@link Forms} - * @return an instantiated and validated {@link InteractionAffordance} - * @throws SchemaValidationException - */ - public static InteractionAffordance create(Form[] forms) throws SchemaValidationException { - // Create form - InteractionAffordance interactionAffordance = new InteractionAffordance(); - interactionAffordance.setForms(forms); - // Validate created form - validate(interactionAffordance); - return interactionAffordance; - } - - /** - * This method validates an instance of {@link InteractionAffordance}. - * @param InteractionAffordance an instance of {@link InteractionAffordance} - * @throws SchemaValidationException - */ - public static void validate(InteractionAffordance interactionAffordance) throws SchemaValidationException { - ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - Validator validator = factory.getValidator(); - Set> violations = validator.validate(interactionAffordance); - StringBuilder builder = new StringBuilder(); - if(!violations.isEmpty()) { - violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); - throw new InteractionAffordanceValidationException(builder.toString()); - } - if(interactionAffordance.getForms()!=null) { - for(int index=0; index < interactionAffordance.getForms().length; index++) { - Form.validate(interactionAffordance.getForms()[index]); - } - } - if(interactionAffordance.getUriVariables()!=null) { - List schemas = new ArrayList<>(interactionAffordance.getUriVariables().values()); - for(int index=0; index < schemas.size(); index++) { - DataSchema.validate(schemas.get(index)); - } - } - } - - // -- serialization and deserialization - - /** - * This method transforms the current {@link InteractionAffordance} object into a {@link JsonObject}. - * @return a {@link JsonObject} - * @throws JsonProcessingException - */ - public JsonObject toJson() throws JsonProcessingException { - return JTD.toJson(this); - } - - /** - * This method instantiates and validates a {@link InteractionAffordance} object from a {@link JsonObject}. - * @param json a InteractionAffordance expressed as a {@link JsonObject} - * @return a valid {@link InteractionAffordance} - * @throws IOException - * @throws SchemaValidationException - */ - public static InteractionAffordance fromJson(JsonObject json) throws IOException, SchemaValidationException { - InteractionAffordance interactionAffordance = (InteractionAffordance) JTD.instantiateFromJson(json, InteractionAffordance.class); - validate(interactionAffordance); - return interactionAffordance; - } - - - // -- getters and setters - - public Form[] getForms() { - return forms; - } - - public void setForms(Form[] forms) { - this.forms = forms; - } - - public Collection getType() { - return type; - } - - public void setType(Collection type) { - this.type = type; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public Map getTitles() { - return titles; - } - - public void setTitles(Map titles) { - this.titles = titles; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Map getDescriptions() { - return descriptions; - } - - public void setDescriptions(Map descriptions) { - this.descriptions = descriptions; - } - - public Map getUriVariables() { - return uriVariables; - } - - public void setUriVariables(Map uriVariables) { - this.uriVariables = uriVariables; - } - - // -- hashcode and equals - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((description == null) ? 0 : description.hashCode()); - result = prime * result + ((descriptions == null) ? 0 : descriptions.hashCode()); - result = prime * result + Arrays.hashCode(forms); - result = prime * result + ((title == null) ? 0 : title.hashCode()); - result = prime * result + ((titles == null) ? 0 : titles.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + ((uriVariables == null) ? 0 : uriVariables.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (!(obj instanceof InteractionAffordance)) - return false; - InteractionAffordance other = (InteractionAffordance) obj; - if (description == null) { - if (other.description != null) - return false; - } else if (!description.equals(other.description)) - return false; - if (descriptions == null) { - if (other.descriptions != null) - return false; - } else if (!descriptions.equals(other.descriptions)) - return false; - if (!Arrays.equals(forms, other.forms)) - return false; - if (title == null) { - if (other.title != null) - return false; - } else if (!title.equals(other.title)) - return false; - if (titles == null) { - if (other.titles != null) - return false; - } else if (!titles.equals(other.titles)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - if (uriVariables == null) { - if (other.uriVariables != null) - return false; - } else if (!uriVariables.equals(other.uriVariables)) - return false; - return true; - } - - - - - - - - - -} diff --git a/src/main/java/wot/jtd/model/Link.java b/src/main/java/wot/jtd/model/Link.java index 3fb7862..d649ec7 100755 --- a/src/main/java/wot/jtd/model/Link.java +++ b/src/main/java/wot/jtd/model/Link.java @@ -1,23 +1,14 @@ package wot.jtd.model; -import java.io.IOException; import java.net.URI; -import java.util.Set; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.gson.JsonObject; -import wot.jtd.JTD; -import wot.jtd.exception.LinkValidationException; -import wot.jtd.exception.SchemaValidationException; -import wot.jtd.vocabulary.Vocabulary; +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfObject; +import wot.jtd.Vocabulary; /** @@ -26,77 +17,26 @@ * @author Andrea Cimmino */ @JsonInclude(JsonInclude.Include.NON_NULL) -public class Link extends AbstractJTDObject{ +public class Link extends AbstractRdfObject{ - // -- attributes + // -- Attributes + @RdfObject("https://www.w3.org/2019/wot/hypermedia#hasTarget") @NotEmpty(message= "'href' must be a valid non-empty URI") @NotNull(message = "'href' must be a valid non-null URI") - private URI href; - @JsonProperty(Vocabulary.TYPE) - private String mediaType; //from RFC2046 - private String rel; - private URI anchor; + protected URI href; - // -- static constructors and validation method + @RdfDatatype("https://www.w3.org/2019/wot/hypermedia#hintsAtMediaType") + @JsonProperty(Vocabulary.JSONLD_TYPE_ALIAS) + protected String mediaType; //from RFC2046 - /** - * This method creates a validated instance of {@link Link}. - * @param href a valid URI - * @return an instantiated and validated {@link Link} - * @throws SchemaValidationException - */ - public static Link create(URI href) throws SchemaValidationException { - // Create link - Link link = new Link(); - link.setHref(href); - // Validate link - validate(link); - return link; - } - - /** - * This method validates an instance of {@link Link}. - * @param link an instance of {@link Link} - * @throws SchemaValidationException - */ - public static void validate(Link link) throws SchemaValidationException { - ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - Validator validator = factory.getValidator(); - Set> violations = validator.validate(link); - if(!violations.isEmpty()) { - StringBuilder builder = new StringBuilder(); - violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); - throw new LinkValidationException(builder.toString()); - } - } + @RdfObject(value="https://www.w3.org/2019/wot/hypermedia#hasRelationType", base="https://www.w3.org/2019/wot/hypermedia#") + protected String rel; - // -- serialization and deserialization - - /** - * This method transforms the current {@link Link} object into a {@link JsonObject}. - * @return a {@link JsonObject} - * @throws JsonProcessingException - */ - public JsonObject toJson() throws JsonProcessingException{ - return JTD.toJson(this); - } - - /** - * This method instantiates and validates a {@link Link} object from a {@link JsonObject}. - * @param json a Link expressed as a {@link JsonObject} - * @return a valid {@link Link} - * @throws IOException - * @throws SchemaValidationException - */ - public static Link fromJson(JsonObject json) throws IOException, SchemaValidationException { - Link link = (Link) JTD.instantiateFromJson(json, Link.class); - validate(link); - return link; - } + @RdfObject("https://www.w3.org/2019/wot/hypermedia#hasAnchor") + protected URI anchor; - - // -- getters and setters + // -- Getters & Setters public URI getHref() { return href; @@ -105,7 +45,6 @@ public void setHref(URI href) { this.href = href; } - /** * * @return a mime type from the RFC 2046 specification @@ -116,22 +55,24 @@ public String getMediaType() { /** * - * @param type a valid mime type from the RFC 2046 specification + * @param mediaType a valid mime type from the RFC 2046 specification */ public void setMediaType(String mediaType) { this.mediaType = mediaType; } - public String getRel() { return rel; } + public void setRel(String rel) { this.rel = rel; } + public URI getAnchor() { return anchor; } + public void setAnchor(URI anchor) { this.anchor = anchor; } @@ -146,52 +87,29 @@ public int hashCode() { result = prime * result + ((href == null) ? 0 : href.hashCode()); result = prime * result + ((mediaType == null) ? 0 : mediaType.hashCode()); result = prime * result + ((rel == null) ? 0 : rel.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = superHashcode(result, prime); return result; } @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) + if (obj == null) return false; - if (!(obj instanceof Link)) + if (this.getClass() != obj.getClass()) return false; + Link other = (Link) obj; - if (anchor == null) { - if (other.anchor != null) - return false; - } else if (!anchor.equals(other.anchor)) - return false; - if (href == null) { - if (other.href != null) - return false; - } else if (!href.equals(other.href)) - return false; - if (mediaType == null) { - if (other.mediaType != null) - return false; - } else if (!mediaType.equals(other.mediaType)) - return false; - if (rel == null) { - if (other.rel != null) - return false; - } else if (!rel.equals(other.rel)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - return true; + Boolean sameClass = sameSuperAttributes(other); + sameClass &= sameAttribute(this.getAnchor(), other.getAnchor()); + sameClass &= sameAttribute(this.getHref(), other.getHref()); + sameClass &= sameAttribute(this.getMediaType(), other.getMediaType()); + sameClass &= sameAttribute(this.getRel(), other.getRel()); + + return sameClass; } - - - } diff --git a/src/main/java/wot/jtd/model/PropertyAffordance.java b/src/main/java/wot/jtd/model/PropertyAffordance.java deleted file mode 100755 index c81e564..0000000 --- a/src/main/java/wot/jtd/model/PropertyAffordance.java +++ /dev/null @@ -1,264 +0,0 @@ -package wot.jtd.model; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; -import javax.validation.constraints.NotEmpty; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.gson.JsonObject; -import wot.jtd.JTD; -import wot.jtd.exception.PropertyAffordanceValidationException; -import wot.jtd.exception.SchemaValidationException; -import wot.jtd.vocabulary.Vocabulary; - -/** - * This class implements the object PropertyAffordance from a Thing Description as specified in the Web of Things (WoT) documentation.

- * @see PropertyAffordance WoT documentation - * @author Andrea Cimmino - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class PropertyAffordance extends DataSchema { - - // -- attributes - - @NotEmpty(message="'forms' in any InteractionAffordance (PropertyAffordance, ActionAffordance, or EventAffordance) must not be empty") - protected Collection forms; - @JsonProperty(Vocabulary.JSONLD_TYPE) - private Collection type; - private String title; - private Map titles; - private String description; - private Map descriptions; - private Map uriVariables; - private Boolean observable; - - // -- static constructors and validation method - - /** - * This method creates a validated instance of {@link PropertyAffordance}. - * @param forms am array with valid {@link Forms} - * @return an instantiated and validated {@link PropertyAffordance} - * @throws SchemaValidationException - */ - public static PropertyAffordance create(Collection forms) throws SchemaValidationException { - // Create form - PropertyAffordance propertyAffordance = new PropertyAffordance(); - propertyAffordance.setForms(forms); - // Validate created form - validate(propertyAffordance); - return propertyAffordance; - } - - /** - * This method validates an instance of {@link PropertyAffordance}. - * @param propertyAffordance an instance of {@link PropertyAffordance} - * @throws SchemaValidationException - */ - public static void validate(PropertyAffordance propertyAffordance) throws SchemaValidationException { - ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - Validator validator = factory.getValidator(); - Set> violations = validator.validate(propertyAffordance); - StringBuilder builder = new StringBuilder(); - if(!violations.isEmpty()) { - violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); - throw new PropertyAffordanceValidationException(builder.toString()); - } - if(propertyAffordance.getForms()!=null) { - for(Form form:propertyAffordance.getForms()) { - Form.validate(form); - } - } - if(propertyAffordance.getUriVariables()!=null) { - List schemas = new ArrayList<>(propertyAffordance.getUriVariables().values()); - for(int index=0; index < schemas.size(); index++) { - DataSchema.validate(schemas.get(index)); - } - } - } - - // -- serialization and deserialization - - /** - * This method transforms the current {@link PropertyAffordance} object into a {@link JsonObject}. - * @return a {@link JsonObject} - * @throws JsonProcessingException - */ - @Override - public JsonObject toJson() throws JsonProcessingException { - return JTD.toJson(this); - } - - /** - * This method instantiates and validates a {@link PropertyAffordance} object from a {@link JsonObject}. - * @param json a PropertyAffordance expressed as a {@link JsonObject} - * @return a valid {@link PropertyAffordance} - * @throws IOException - * @throws SchemaValidationException - */ - public static PropertyAffordance fromJson(JsonObject json) throws SchemaValidationException, IOException { - PropertyAffordance propertyAffordance = (PropertyAffordance) JTD.instantiateFromJson(json, PropertyAffordance.class); - validate(propertyAffordance); - return propertyAffordance; - } - - - // -- getters and setters - public Collection getForms() { - return forms; - } - - public void setForms(Collection forms) { - this.forms = forms; - } - - @Override - public Collection getType() { - return type; - } - - @Override - public void setType(Collection type) { - this.type = type; - } - - - @Override - public String getTitle() { - return title; - } - - @Override - public void setTitle(String title) { - this.title = title; - } - - @Override - public Map getTitles() { - return titles; - } - - @Override - public void setTitles(Map titles) { - this.titles = titles; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public void setDescription(String description) { - this.description = description; - } - - @Override - public Map getDescriptions() { - return descriptions; - } - - @Override - public void setDescriptions(Map descriptions) { - this.descriptions = descriptions; - } - - public Map getUriVariables() { - return uriVariables; - } - - public void setUriVariables(Map uriVariables) { - this.uriVariables = uriVariables; - } - - public Boolean getObservable() { - return observable; - } - - public void setObservable(Boolean observable) { - this.observable = observable; - } - - // hasCode and equals - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((description == null) ? 0 : description.hashCode()); - result = prime * result + ((descriptions == null) ? 0 : descriptions.hashCode()); - result = prime * result + ((forms == null) ? 0 : forms.hashCode()); - result = prime * result + ((observable == null) ? 0 : observable.hashCode()); - result = prime * result + ((title == null) ? 0 : title.hashCode()); - result = prime * result + ((titles == null) ? 0 : titles.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + ((uriVariables == null) ? 0 : uriVariables.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (!(obj instanceof PropertyAffordance)) - return false; - PropertyAffordance other = (PropertyAffordance) obj; - if (description == null) { - if (other.description != null) - return false; - } else if (!description.equals(other.description)) - return false; - if (descriptions == null) { - if (other.descriptions != null) - return false; - } else if (!descriptions.equals(other.descriptions)) - return false; - if (forms == null) { - if (other.forms != null) - return false; - } else if (!forms.equals(other.forms)) - return false; - if (observable == null) { - if (other.observable != null) - return false; - } else if (!observable.equals(other.observable)) - return false; - if (title == null) { - if (other.title != null) - return false; - } else if (!title.equals(other.title)) - return false; - if (titles == null) { - if (other.titles != null) - return false; - } else if (!titles.equals(other.titles)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - if (uriVariables == null) { - if (other.uriVariables != null) - return false; - } else if (!uriVariables.equals(other.uriVariables)) - return false; - return true; - } - - - - - - -} diff --git a/src/main/java/wot/jtd/model/SecurityScheme.java b/src/main/java/wot/jtd/model/SecurityScheme.java deleted file mode 100755 index 394bbf2..0000000 --- a/src/main/java/wot/jtd/model/SecurityScheme.java +++ /dev/null @@ -1,457 +0,0 @@ -package wot.jtd.model; - -import java.io.IOException; -import java.net.URI; -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.gson.JsonObject; - -import wot.jtd.JTD; -import wot.jtd.exception.SchemaValidationException; -import wot.jtd.exception.SecuritySchemeValidationException; -import wot.jtd.vocabulary.Vocabulary; - -/** - * This class implements the object SecurityScheme (and its sub-classes) from a Thing Description as specified in the Web of Things (WoT) documentation.

- * @see SecurityScheme WoT documentation - * @author Andrea Cimmino - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class SecurityScheme extends AbstractJTDObject{ - - // TODO: añadir restricciones a los getters y setters basados en el schema actual - - // -- attributes - - private enum defaultSchemes { - nosec, basic, digest, psk, oauth2, bearer, apikey - } - - @JsonProperty(Vocabulary.JSONLD_TYPE) - private Collection type; - @NotBlank(message = "'scheme' must not be blank, e.g., nosec, basic, digest, bearer, psk, oauth2, or apikey") - private String scheme; - private String description; - private Map descriptions; - private URI proxy; - - // digest - @Pattern(regexp = "auth|auth-int", flags = Pattern.Flag.CASE_INSENSITIVE, message="'qop' must be one of: 'auth' or 'auth-int'.") - private String qop; - // psk - private String identity; - // oauth2 - private URI token; - private URI refresh; - private String flow; - private Collection scopes; - // bearer - private String alg; - private String format; - // oauth2 + bearer - private URI authorization; - // basic + digest + apikey + bearer - @Pattern(regexp = "header|query|body|cookie", flags = Pattern.Flag.CASE_INSENSITIVE, message="'in' must be one of: 'header', 'query', 'body', or 'cookie'") - private String in; - private String name; - - // -- constructors and validation methods (static) - - /** - * This method creates a validated instance of {@link SecurityScheme}, if default values are enabled in {@link JTD} some attributes from the {@link SecurityScheme} will be initialized depending on the schema. - * @param scheme a valid security scheme, e.g., nosec, basic, digest, psk, oauth2, bearer, or apikey - * @return an instantiated and validated {@link SecurityScheme} - * @throws SchemaValidationException - */ - public static SecurityScheme create(String scheme) throws SchemaValidationException { - // Create form - SecurityScheme securityScheme = new SecurityScheme(); - securityScheme.setScheme(scheme); - // TODO: initiaise default values based on the scheme provided - // Validate created form - validate(securityScheme); - return securityScheme; - } - - /** - * This method creates a validated instance of {@link SecurityScheme} with 'nosec' as 'scheme' - * @return an instantiated and validated {@link SecurityScheme} - * @throws SchemaValidationException - */ - public static SecurityScheme createNoSecurityScheme() throws SchemaValidationException { - return create(defaultSchemes.nosec.toString()); - } - /** - * This method creates a validated instance of {@link SecurityScheme} with 'basic' as 'scheme', if default values are enabled in {@link JTD} the attribute 'in' is initialized with 'header' - * @return an instantiated and validated {@link SecurityScheme} - * @throws SchemaValidationException - */ - public static SecurityScheme createBasicSecurityScheme() throws SchemaValidationException { - SecurityScheme scheme = create(defaultSchemes.basic.toString()); - if(JTD.getDefaultValues()) - scheme.setIn(Vocabulary.HEADER); - return scheme; - } - /** - * This method creates a validated instance of {@link SecurityScheme} with 'digest' as 'scheme', if default values are enabled in {@link JTD} the attribute 'in' is initialized with 'header' and 'qop' with 'auth' - * @return an instantiated and validated {@link SecurityScheme} - * @throws SchemaValidationException - */ - public static SecurityScheme createDigestSecurityScheme() throws SchemaValidationException { - SecurityScheme scheme = create(defaultSchemes.digest.toString()); - if(JTD.getDefaultValues()) { - scheme.setIn(Vocabulary.HEADER); - scheme.setQop("auth"); - } - return scheme; - } - /** - * This method creates a validated instance of {@link SecurityScheme} with 'bearer' as 'scheme', if default values are enabled in {@link JTD} the attribute 'in' is initialized with 'header', 'alg' with 'ES256', and 'format' with 'jwt' - * @return an instantiated and validated {@link SecurityScheme} - * @throws SchemaValidationException - */ - public static SecurityScheme createBearerSecurityScheme() throws SchemaValidationException { - SecurityScheme scheme = create(defaultSchemes.bearer.toString()); - if(JTD.getDefaultValues()) { - scheme.setIn(Vocabulary.HEADER); - scheme.setAlg("ES256"); - scheme.setFormat("jwt"); - } - return scheme; - } - /** - * This method creates a validated instance of {@link SecurityScheme} with 'apikey' as 'scheme', if default values are enabled in {@link JTD} the attribute 'in' is initialized with 'query' - * @return an instantiated and validated {@link SecurityScheme} - * @throws SchemaValidationException - */ - public static SecurityScheme createAPIKeySecurityScheme() throws SchemaValidationException { - SecurityScheme scheme = create(defaultSchemes.apikey.toString()); - if(JTD.getDefaultValues()) - scheme.setIn("query"); - return scheme; - } - /** - * This method creates a validated instance of {@link SecurityScheme} with 'psk' as 'scheme'. - * @return an instantiated and validated {@link SecurityScheme} - * @throws SchemaValidationException - */ - public static SecurityScheme createPSKSecurityScheme() throws SchemaValidationException { - return create(defaultSchemes.psk.toString()); - } - /** - * This method creates a validated instance of {@link SecurityScheme} with 'oauth2' as 'scheme'. - * @return an instantiated and validated {@link SecurityScheme} - * @throws SchemaValidationException - */ - public static SecurityScheme createOAuth2SecurityScheme() throws SchemaValidationException { - return create(defaultSchemes.oauth2.toString()); - } - - /** - * This method validates an instance a {@link SecurityScheme} object. - * @param securityScheme an instance of {@link SecurityScheme} - * @throws SchemaValidationException - */ - public static void validate(SecurityScheme securityScheme) throws SchemaValidationException { - ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - Validator validator = factory.getValidator(); - Set> violations = validator.validate(securityScheme); - StringBuilder builder = new StringBuilder(); - if(!violations.isEmpty()) { - violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); - throw new SecuritySchemeValidationException(builder.toString()); - } - - } - - // -- serialization and deserialization - - /** - * This method transforms the current {@link SecurityScheme} object into a {@link JsonObject}. - * @return a {@link JsonObject} - * @throws JsonProcessingException - */ - public JsonObject toJson() throws JsonProcessingException { - return JTD.toJson(this); - } - - /** - * This method instantiates and validates a {@link SecurityScheme} object from a {@link JsonObject}. - * @param json a SecurityScheme expressed as a {@link JsonObject} - * @return a valid {@link SecurityScheme} - * @throws IOException - * @throws SchemaValidationException - */ - public static SecurityScheme fromJson(JsonObject json) throws IOException, SchemaValidationException { - SecurityScheme securityScheme = (SecurityScheme) JTD.instantiateFromJson(json, SecurityScheme.class); - validate(securityScheme); - return securityScheme; - } - - - // -- getters and setters - - public Collection getType() { - return type; - } - - public void setType(Collection type) { - this.type = type; - } - - - public String getScheme() { - return scheme; - } - - public void setScheme(String scheme) { - this.scheme = scheme; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Map getDescriptions() { - return descriptions; - } - - public void setDescriptions(Map descriptions) { - this.descriptions = descriptions; - } - - public URI getProxy() { - return proxy; - } - - public void setProxy(URI proxy) { - this.proxy = proxy; - } - - public String getQop() { - return qop; - } - - public void setQop(String qop) { - this.qop = qop; - } - - public String getIdentity() { - return identity; - } - - public void setIdentity(String identity) { - this.identity = identity; - } - - public URI getToken() { - return token; - } - - public void setToken(URI token) { - this.token = token; - } - - public URI getRefresh() { - return refresh; - } - - public void setRefresh(URI refresh) { - this.refresh = refresh; - } - - public String getFlow() { - return flow; - } - - public void setFlow(String flow) { - this.flow = flow; - } - - public Collection getScopes() { - return scopes; - } - - public void setScopes(Collection scopes) { - this.scopes = scopes; - } - - public String getAlg() { - return alg; - } - - public void setAlg(String alg) { - this.alg = alg; - } - - public String getFormat() { - return format; - } - - public void setFormat(String format) { - this.format = format; - } - - public URI getAuthorization() { - return authorization; - } - - public void setAuthorization(URI authorization) { - this.authorization = authorization; - } - - public String getIn() { - return in; - } - - public void setIn(String in) { - this.in = in; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - // hashcode and equals - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((alg == null) ? 0 : alg.hashCode()); - result = prime * result + ((authorization == null) ? 0 : authorization.hashCode()); - result = prime * result + ((description == null) ? 0 : description.hashCode()); - result = prime * result + ((descriptions == null) ? 0 : descriptions.hashCode()); - result = prime * result + ((flow == null) ? 0 : flow.hashCode()); - result = prime * result + ((format == null) ? 0 : format.hashCode()); - result = prime * result + ((identity == null) ? 0 : identity.hashCode()); - result = prime * result + ((in == null) ? 0 : in.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((proxy == null) ? 0 : proxy.hashCode()); - result = prime * result + ((qop == null) ? 0 : qop.hashCode()); - result = prime * result + ((refresh == null) ? 0 : refresh.hashCode()); - result = prime * result + ((scheme == null) ? 0 : scheme.hashCode()); - result = prime * result + ((scopes == null) ? 0 : scopes.hashCode()); - result = prime * result + ((token == null) ? 0 : token.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (!(obj instanceof SecurityScheme)) - return false; - SecurityScheme other = (SecurityScheme) obj; - if (alg == null) { - if (other.alg != null) - return false; - } else if (!alg.equals(other.alg)) - return false; - if (authorization == null) { - if (other.authorization != null) - return false; - } else if (!authorization.equals(other.authorization)) - return false; - if (description == null) { - if (other.description != null) - return false; - } else if (!description.equals(other.description)) - return false; - if (descriptions == null) { - if (other.descriptions != null) - return false; - } else if (!descriptions.equals(other.descriptions)) - return false; - if (flow == null) { - if (other.flow != null) - return false; - } else if (!flow.equals(other.flow)) - return false; - if (format == null) { - if (other.format != null) - return false; - } else if (!format.equals(other.format)) - return false; - if (identity == null) { - if (other.identity != null) - return false; - } else if (!identity.equals(other.identity)) - return false; - if (in == null) { - if (other.in != null) - return false; - } else if (!in.equals(other.in)) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - if (proxy == null) { - if (other.proxy != null) - return false; - } else if (!proxy.equals(other.proxy)) - return false; - if (qop == null) { - if (other.qop != null) - return false; - } else if (!qop.equals(other.qop)) - return false; - if (refresh == null) { - if (other.refresh != null) - return false; - } else if (!refresh.equals(other.refresh)) - return false; - if (scheme == null) { - if (other.scheme != null) - return false; - } else if (!scheme.equals(other.scheme)) - return false; - if (scopes == null) { - if (other.scopes != null) - return false; - } else if (!scopes.equals(other.scopes)) - return false; - if (token == null) { - if (other.token != null) - return false; - } else if (!token.equals(other.token)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - return true; - } - - - - - - -} diff --git a/src/main/java/wot/jtd/model/Thing.java b/src/main/java/wot/jtd/model/Thing.java index d77e94e..95f86d2 100755 --- a/src/main/java/wot/jtd/model/Thing.java +++ b/src/main/java/wot/jtd/model/Thing.java @@ -2,22 +2,13 @@ import java.io.IOException; import java.net.URI; -import java.util.Arrays; import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -import org.apache.jena.rdf.model.Model; - -import com.apicatalog.jsonld.JsonLdError; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRawValue; @@ -26,10 +17,18 @@ import com.fasterxml.jackson.databind.JsonNode; import com.google.gson.JsonObject; +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfDatatypeGroup; +import kehio.annotations.RdfObject; +import kehio.annotations.RdfObjectGroup; +import kehio.annotations.RdfUrlMap; import wot.jtd.JTD; +import wot.jtd.Vocabulary; import wot.jtd.exception.SchemaValidationException; -import wot.jtd.exception.ThingValidationException; -import wot.jtd.vocabulary.Vocabulary; +import wot.jtd.model.interactions.ActionAffordance; +import wot.jtd.model.interactions.EventAffordance; +import wot.jtd.model.interactions.PropertyAffordance; +import wot.jtd.model.schemas.security.SecurityScheme; /** * This class implements the object Thing from a Thing Description as specified in the Web of Things (WoT) documentation.

@@ -37,182 +36,176 @@ * @author Andrea Cimmino */ @JsonInclude(JsonInclude.Include.NON_NULL) -public class Thing extends AbstractJTDObject{ +public class Thing extends AbstractRdfObject{ + + // -- Attributes - // -- attributes @JsonRawValue @NotEmpty(message="The value of @context must not be empty, it can be either a URI or an array cointatinig URIs or JSONs") @JsonProperty(Vocabulary.JSONLD_CONTEXT) - private Collection context; + protected Collection context; + @RdfDatatype("http://purl.org/dc/terms/title") @NotNull(message="the title of a td:Thing must not be null") - private String title; - private Map titles; - private String description; - private Map descriptions; - private VersionInfo version; - private String created; - private String modified; - private URI support; - private URI base; - private Collection links; - - // TODO: lements in this array must be keys from the securityDefinitions + protected String title; + + @RdfDatatype("http://purl.org/dc/terms/description") + protected String description; + + @RdfDatatypeGroup(value="http://purl.org/dc/terms/title", byLang=true) + protected Map titles; + + @RdfDatatypeGroup(value="http://purl.org/dc/terms/description", byLang=true) + protected Map descriptions; + + @RdfObject("https://www.w3.org/2019/wot/td#versionInfo") + protected VersionInfo version; + + @RdfDatatype(value="http://purl.org/dc/terms/created", datatype="http://www.w3.org/2001/XMLSchema#dateTime") + protected String created; + + @RdfDatatype(value="http://purl.org/dc/terms/modified", datatype="http://www.w3.org/2001/XMLSchema#dateTime") + protected String modified; + + @RdfObject("https://www.w3.org/2019/wot/td#supportContact") + protected URI support; + + @RdfObject("https://www.w3.org/2019/wot/td#base") + protected URI base; + + @RdfObject("https://www.w3.org/2019/wot/td#hasLink") + protected Collection links; + + @RdfObject(value="https://www.w3.org/2019/wot/td#hasSecurityConfiguration") // add base URI @NotEmpty(message="security must not be blank, choose one from the security definitions") - private Collection security; + protected Collection security; + + @RdfObjectGroup(value="https://www.w3.org/2019/wot/td#securityDefinitions", key="https://www.w3.org/2019/wot/td#scheme", + includeKey=false, + aliases={ + @RdfUrlMap(key="nosec", value="nosec_sc"), + @RdfUrlMap(key="basic", value="basic_sc"), + @RdfUrlMap(key="digest", value="digest_sc"), + @RdfUrlMap(key="bearer", value="bearer_sc"), + @RdfUrlMap(key="psk", value="psk_sc"), + @RdfUrlMap(key="oauth2", value="oauth2_sc"), + @RdfUrlMap(key="apikey", value="apikey_sc") + }) @NotEmpty - private Map securityDefinitions; - - // TODO: validate these restrictions - // if PropertyAffordance readproperty and writeproperty - // if ActionAffordance invokeaction - // if EventAffordance subscribeevent - private Form[] forms; - - private Map properties; - private Map actions; - private Map events; - - // -- static constructors and validation method - - // TODO: create another static contructor to change the context - /** - * This method creates a validated instance of {@link Thing}. - * @param title a {@link String} title for the Thing - * @param security a {@link Collection} of security schemes that are keys in the map of 'securityDefinitions' parameter - * @param securityDeffinitions a {@link Map} between security names and {@link SecurityScheme} - * @return an instantiated and validated {@link Thing} - * @throws SchemaValidationException - */ - public static Thing create(String title, Collection security, Map securityDefinitions) throws SchemaValidationException { - // Create Thing - Thing thing = new Thing(); - thing.setTitle(title); - thing.setSecurity(security); - thing.setSecurityDefinitions(securityDefinitions); - // validate Thing - validate(thing); - return thing; - } - - /** - * This method validates an instance a {@link Thing} object. - * @param thing an instance of {@link Thing} - * @throws SchemaValidationException - */ - public static void validate(Thing thing) throws SchemaValidationException { - ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - Validator validator = factory.getValidator(); - Set> violations = validator.validate(thing); - StringBuilder builder = new StringBuilder(); - if(!violations.isEmpty()) { - violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); - throw new ThingValidationException(builder.toString()); - } - // TODO: throw nested expcetions - } - + protected Map securityDefinitions; - // -- serialization and deserialization + @RdfObject("https://www.w3.org/2019/wot/td#hasForm") + protected Collection forms; - /** - * This method transforms the current {@link Thing} object into a {@link JsonObject}. - * @return a {@link JsonObject} - * @throws JsonProcessingException - */ - public JsonObject toJson() throws JsonProcessingException { - return JTD.toJson(this); - } - - /** - * This method instantiates and validates a {@link Thing} object from a {@link JsonObject}. - * @param json a Thing expressed as a {@link JsonObject} - * @return a valid {@link SecurityScheme} - * @throws IOException - * @throws ThingValidationException - */ - public static Thing fromJson(JsonObject json) throws IOException, SchemaValidationException { - Thing thing = (Thing) JTD.instantiateFromJson(json.deepCopy(), Thing.class); - validate(thing); - return thing; - } + @RdfObjectGroup(value="https://www.w3.org/2019/wot/td#hasPropertyAffordance", key="https://www.w3.org/2019/wot/td#name") + protected Map properties; + + @RdfObjectGroup(value="https://www.w3.org/2019/wot/td#hasActionAffordance", key="https://www.w3.org/2019/wot/td#name") + protected Map actions; + + @RdfObjectGroup(value="https://www.w3.org/2019/wot/td#hasEventAffordance", key="https://www.w3.org/2019/wot/td#name") + protected Map events; - // -- getters and setters + + // -- Getters & Setters public Collection getContext() { return context; } @JsonSetter(Vocabulary.JSONLD_CONTEXT) - public void setContext(Collection context) { - this.context = context.stream().map(elem -> elem.toString()).collect(Collectors.toList()); + public void setContextValues(Collection context) { + this.context = context.stream().map(JsonNode::toString).collect(Collectors.toList()); } - + public void setContext(Collection context) { + this.context = context; + } public String getTitle() { return title; } + public void setTitle(String title) { this.title = title; } + public Map getTitles() { return titles; } + public void setTitles(Map titles) { this.titles = titles; } + public String getDescription() { return description; } + public void setDescription(String description) { this.description = description; } + public Map getDescriptions() { return descriptions; } + public void setDescriptions(Map descriptions) { this.descriptions = descriptions; } + public VersionInfo getVersion() { return version; } + public void setVersion(VersionInfo version) { this.version = version; } + public String getCreated() { return created; } + public void setCreated(String created) { this.created = created; } + public String getModified() { return modified; } + public void setModified(String modified) { this.modified = modified; } + public URI getSupport() { return support; } + public void setSupport(URI support) { this.support = support; } + public URI getBase() { return base; } + public void setBase(URI base) { this.base = base; } + public Collection getLinks() { return links; } + public void setLinks(Collection links) { this.links = links; } + public Collection getSecurity() { return security; } + public void setSecurity(Collection security) { this.security = security; } @@ -220,13 +213,28 @@ public void setSecurity(Collection security) { public Map getSecurityDefinitions() { return securityDefinitions; } + public void setSecurityDefinitions(Map securityDefinitions) { this.securityDefinitions = securityDefinitions; + if(JTD.NORMALIZE_SECURITY_DEFINITIONS_SCHEMES) { + Set keys = this.securityDefinitions.keySet(); + for(String key:keys) { + if(!JTD.SECURITY_DEFINITION_SCHEMES_PATTERN.matcher(key).matches()) { + String newKey = key.replace("SecurityScheme", "").toLowerCase(); + newKey = newKey.substring(newKey.indexOf(':')+1) + "_sc"; + SecurityScheme scheme = this.securityDefinitions.remove(key); + this.securityDefinitions.put(newKey, scheme); + } + } + } + } - public Form[] getForms() { + + public Collection getForms() { return forms; } - public void setForms(Form[] forms) { + + public void setForms(Collection forms) { this.forms = forms; } @@ -253,18 +261,15 @@ public Map getEvents() { public void setEvents(Map events) { this.events = events; } + - @JsonIgnore - public boolean getHasExternalProperties() { - return this.hasExternalProperties; - } - - // -- hascode and equals + // -- HasCode and equals + @Override public int hashCode() { final int prime = 31; - int result = super.hashCode(); + int result = 1; result = prime * result + ((actions == null) ? 0 : actions.hashCode()); result = prime * result + ((base == null) ? 0 : base.hashCode()); result = prime * result + ((context == null) ? 0 : context.hashCode()); @@ -272,8 +277,13 @@ public int hashCode() { result = prime * result + ((description == null) ? 0 : description.hashCode()); result = prime * result + ((descriptions == null) ? 0 : descriptions.hashCode()); result = prime * result + ((events == null) ? 0 : events.hashCode()); - result = prime * result + Arrays.hashCode(forms); - result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((forms == null) ? 0 : forms.hashCode()); + result = partialHash(prime, result); + result = superHashcode(result, prime); + return result; + } + + private int partialHash(int prime, int result) { result = prime * result + ((links == null) ? 0 : links.hashCode()); result = prime * result + ((modified == null) ? 0 : modified.hashCode()); result = prime * result + ((properties == null) ? 0 : properties.hashCode()); @@ -282,131 +292,65 @@ public int hashCode() { result = prime * result + ((support == null) ? 0 : support.hashCode()); result = prime * result + ((title == null) ? 0 : title.hashCode()); result = prime * result + ((titles == null) ? 0 : titles.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); result = prime * result + ((version == null) ? 0 : version.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) + if (obj == null) return false; - if (!(obj instanceof Thing)) + if (this.getClass() != obj.getClass()) return false; + Thing other = (Thing) obj; - if (actions == null) { - if (other.actions != null) - return false; - } else if (!actions.equals(other.actions)) - return false; - if (base == null) { - if (other.base != null) - return false; - } else if (!base.equals(other.base)) - return false; - if (context == null) { - if (other.context != null) - return false; - } else if (!context.equals(other.context)) - return false; - if (created == null) { - if (other.created != null) - return false; - } else if (!created.equals(other.created)) - return false; - if (description == null) { - if (other.description != null) - return false; - } else if (!description.equals(other.description)) - return false; - if (descriptions == null) { - if (other.descriptions != null) - return false; - } else if (!descriptions.equals(other.descriptions)) - return false; - if (events == null) { - if (other.events != null) - return false; - } else if (!events.equals(other.events)) - return false; - if (!Arrays.equals(forms, other.forms)) - return false; - if (id == null) { - if (other.id != null) - return false; - } else if (!id.equals(other.id)) - return false; - if (links == null) { - if (other.links != null) - return false; - } else if (!links.equals(other.links)) - return false; - if (modified == null) { - if (other.modified != null) - return false; - } else if (!modified.equals(other.modified)) - return false; - if (properties == null) { - if (other.properties != null) - return false; - } else if (!properties.equals(other.properties)) - return false; - if (security == null) { - if (other.security != null) - return false; - } else if (!security.equals(other.security)) - return false; - if (securityDefinitions == null) { - if (other.securityDefinitions != null) - return false; - } else if (!securityDefinitions.equals(other.securityDefinitions)) - return false; - if (support == null) { - if (other.support != null) - return false; - } else if (!support.equals(other.support)) - return false; - if (title == null) { - if (other.title != null) - return false; - } else if (!title.equals(other.title)) - return false; - if (titles == null) { - if (other.titles != null) - return false; - } else if (!titles.equals(other.titles)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - if (version == null) { - if (other.version != null) - return false; - } else if (!version.equals(other.version)) - return false; - return true; + Boolean sameClass = sameSuperAttributes(other); + // Map-based attributes + sameClass &= sameMap(this.getActions(), other.getActions()); + sameClass &= sameMap(this.getEvents(), other.getEvents()); + sameClass &= sameMap(this.getProperties(), other.getProperties()); + sameClass &= sameMap(this.getSecurityDefinitions(), other.getSecurityDefinitions()); + sameClass &= sameMap(this.getDescriptions(), other.getDescriptions()); + sameClass &= sameMap(this.getTitles(), other.getTitles()); + // Collection attributes + sameClass &= sameCollections(this.getContext(), other.getContext()); + sameClass &= sameCollections(this.getSecurity(), other.getSecurity()); + sameClass &= sameCollections(this.getLinks(), other.getLinks()); + sameClass &= sameCollections(this.getForms(), other.getForms()); + // Primitive or Object attributes + sameClass &= sameAttribute(this.getBase(), other.getBase()); + sameClass &= sameAttribute(this.getCreated(), other.getCreated()); + sameClass &= sameAttribute(this.getDescription(), other.getDescription()); + sameClass &= sameAttribute(this.getTitle(), other.getTitle()); + sameClass &= sameAttribute(this.getModified(), other.getModified()); + sameClass &= sameAttribute(this.getSupport(), other.getSupport()); + sameClass &= sameAttribute(this.getVersion(), other.getVersion()); + + return sameClass; } - - /** - * This method translates the TDs into RDF and then compares their isomorphism to check if they are equivalent - * @param td a {@link JsonObject} TD - * @return - * @throws JsonLdError - * @throws JsonProcessingException - */ - public boolean isEquivalent(JsonObject td) throws JsonProcessingException, JsonLdError { - Model model = this.toRDF(this.toJson()); - Model tdModel = this.toRDF(td); - return model.isIsomorphicWith(tdModel); - } - + // -- Serialization and Deserialization + + /** + * This method transforms the current {@link Thing} object into a {@link JsonObject}. + * @return a {@link JsonObject} + * @throws JsonProcessingException this exception is thrown when the syntax of the Thing Description as {@link JsonObject} is incorrect + */ + public JsonObject toJson() throws JsonProcessingException { + return JTD.toJson(this); + } + /** + * This method instantiates and validates a {@link Thing} object from a {@link JsonObject}. + * @param json a Thing expressed as a {@link JsonObject} + * @return a valid {@link SecurityScheme} + * @throws IOException this exception is thrown when the syntax of the {@link JsonObject} is incorrect + * @throws SchemaValidationException this exception is thrown when the syntax of the Thing Description as {@link JsonObject} is incorrect + */ + public static Thing fromJson(JsonObject json) throws IOException { + return (Thing) JTD.instantiateFromJson(json.deepCopy(), Thing.class); + } diff --git a/src/main/java/wot/jtd/model/VersionInfo.java b/src/main/java/wot/jtd/model/VersionInfo.java index 27e7e82..8b067f7 100755 --- a/src/main/java/wot/jtd/model/VersionInfo.java +++ b/src/main/java/wot/jtd/model/VersionInfo.java @@ -1,23 +1,11 @@ package wot.jtd.model; -import java.io.IOException; -import java.util.Set; - -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.gson.JsonObject; -import wot.jtd.JTD; -import wot.jtd.annotations.RdfDatatypeProperty; -import wot.jtd.exception.SchemaValidationException; -import wot.jtd.exception.VersionInfoValidationException; +import kehio.annotations.RdfDatatype; /** * This class implements the object VersionInfo from a Thing Description as specified in the Web of Things (WoT) documentation.

@@ -25,76 +13,16 @@ * @author Andrea Cimmino */ @JsonInclude(JsonInclude.Include.NON_NULL) -public class VersionInfo extends AbstractJTDObject{ +public class VersionInfo extends AbstractRdfObject{ // -- attributes - //@RdfLiteralProperty//("https://www.w3.org/2019/wot/td#instance") - @RdfDatatypeProperty(value="https://www.w3.org/2019/wot/td#instance") + @RdfDatatype(value="https://www.w3.org/2019/wot/td#instance") @Pattern(regexp = "^[0-9]\\.[0-9]\\.[0-9]$", message="The pattern of 'instance' must be three numbers separated by '.'; e.g., '1.0.3'") @NotBlank(message = "The 'instance' must be a non-blak string that follows the semantic versioning pattern from https://semver.org/") - private String instance; - - // -- static constructors and validation method - - /** - * This method creates a validated instance of {@link VersionInfo}. - * @param instance a valid version number following the pattern '^[0-9]\.[0-9]\.[0-9]$', e.g., "1.0.3" - * @return an instantiated and validated {@link VersionInfo} - * @throws SchemaValidationException - */ - public static VersionInfo create(String instance) throws SchemaValidationException { - // Create version info - VersionInfo versionInfo = new VersionInfo(); - versionInfo.setInstance(instance); - // Validate version info - validate(versionInfo); - return versionInfo; - } - - /** - * This method validates an instance of {@link VersionInfo}. - * @param versionInfo an instance of {@link VersionInfo} - * @throws SchemaValidationException - */ - public static void validate(VersionInfo versionInfo) throws SchemaValidationException { - ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); - Validator validator = factory.getValidator(); - Set> violations = validator.validate(versionInfo); - if(!violations.isEmpty()) { - StringBuilder builder = new StringBuilder(); - violations.forEach(msg -> builder.append(msg.getMessage()).append("\n")); - throw new VersionInfoValidationException(builder.toString()); - } - } - - // -- serialization and de-serialization - - /** - * This method transforms the current {@link VersionInfo} object into a {@link JsonObject}. - * @return a {@link JsonObject} - * @throws JsonProcessingException - */ - public JsonObject toJson() throws JsonProcessingException{ - return JTD.toJson(this); - } - - /** - * This method instantiates and validates a {@link VersionInfo} object from a {@link JsonObject}. - * @param json a VersionInfo expressed as a {@link JsonObject} - * @return a valid {@link VersionInfo} - * @throws IOException - * @throws SchemaValidationException - */ - public static VersionInfo fromJson(JsonObject json) throws IOException, SchemaValidationException { - VersionInfo versionInfo = (VersionInfo) JTD.instantiateFromJson(json, VersionInfo.class); - validate(versionInfo); - return versionInfo; - } + protected String instance; - - - // -- getters and setters + // -- Getters & Setters public String getInstance() { return instance; @@ -109,32 +37,25 @@ public void setInstance(String instance) { @Override public int hashCode() { final int prime = 31; - int result = super.hashCode(); + int result = super.hashCode(); result = prime * result + ((instance == null) ? 0 : instance.hashCode()); + // Super class hashCode + result = superHashcode(result, prime); return result; } @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) + if (obj == null) return false; - if (!(obj instanceof VersionInfo)) + if (this.getClass() != obj.getClass()) return false; + VersionInfo other = (VersionInfo) obj; - if (instance == null) { - if (other.instance != null) - return false; - } else if (!instance.equals(other.instance)) - return false; - return true; + Boolean sameClass = sameSuperAttributes(other); + sameClass &= sameAttribute(this.instance, other.getInstance()); + + return sameClass; } - - - - - - } diff --git a/src/main/java/wot/jtd/model/interactions/ActionAffordance.java b/src/main/java/wot/jtd/model/interactions/ActionAffordance.java new file mode 100755 index 0000000..117f006 --- /dev/null +++ b/src/main/java/wot/jtd/model/interactions/ActionAffordance.java @@ -0,0 +1,110 @@ +package wot.jtd.model.interactions; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfObject; +import wot.jtd.model.schemas.data.DataSchema; + +/** + * This class implements the object ActionAffordance from a Thing Description as specified in the Web of Things (WoT) documentation.

+ * @see ActionAffordance WoT documentation + * @author Andrea Cimmino + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ActionAffordance extends InteractionAffordance{ + + // -- Attributes + + @RdfObject("https://www.w3.org/2019/wot/td#hasInputSchema") + protected DataSchema input; + + @RdfObject("https://www.w3.org/2019/wot/td#hasOutputSchema") + protected DataSchema output; + + @RdfDatatype("https://www.w3.org/2019/wot/td#isSafe") + protected Boolean safe; // has default value + + @RdfDatatype("https://www.w3.org/2019/wot/td#isIdempotent") + protected Boolean idempotent; // has default value + + // -- Getters & Setters + + public DataSchema getInput() { + return input; + } + + public void setInput(DataSchema input) { + this.input = input; + } + + public DataSchema getOutput() { + return output; + } + + public void setOutput(DataSchema output) { + this.output = output; + } + + public Boolean getSafe() { + return safe; + } + + public void setSafe(Boolean safe) { + this.safe = safe; + } + + public Boolean getIdempotent() { + return idempotent; + } + + public void setIdempotent(Boolean idempotent) { + this.idempotent = idempotent; + } + + + // -- HashCode & Equals + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = computeHashCode(result, prime); + + result = prime * result + ((input == null) ? 0 : input.hashCode()); + result = prime * result + ((output == null) ? 0 : output.hashCode()); + result = prime * result + ((safe == null) ? 0 : safe.hashCode()); + result = prime * result + ((idempotent == null) ? 0 : idempotent.hashCode()); + + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (this.getClass() != obj.getClass()) + return false; + + ActionAffordance other = (ActionAffordance) obj; + Boolean sameClass = sameSuperAttributes(other); + sameClass &= sameCollections(this.getForms(), other.getForms()); + sameClass &= sameMap(this.getDescriptions(), other.getDescriptions()); + sameClass &= sameMap(this.getTitles(), other.getTitles()); + sameClass &= sameMap(this.getUriVariables(), other.getUriVariables()); + sameClass &= sameAttribute(this.getTitle(), other.getTitle()); + sameClass &= sameAttribute(this.getDescription(), other.getDescription()); + + sameClass &= sameAttribute(this.getInput(), other.getInput()); + sameClass &= sameAttribute(this.getOutput(), other.getOutput()); + sameClass &= sameAttribute(this.getSafe(), other.getSafe()); + sameClass &= sameAttribute(this.getIdempotent(), other.getIdempotent()); + + return sameClass; + } + + + + + +} diff --git a/src/main/java/wot/jtd/model/interactions/EventAffordance.java b/src/main/java/wot/jtd/model/interactions/EventAffordance.java new file mode 100755 index 0000000..5f24f53 --- /dev/null +++ b/src/main/java/wot/jtd/model/interactions/EventAffordance.java @@ -0,0 +1,91 @@ +package wot.jtd.model.interactions; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import kehio.annotations.RdfObject; +import wot.jtd.model.schemas.data.DataSchema; + + +/** + * This class implements the object EventAffordance from a Thing Description as specified in the Web of Things (WoT) documentation.

+ * @see EventAffordance WoT documentation + * @author Andrea Cimmino + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class EventAffordance extends InteractionAffordance{ + + // -- Attributes + + @RdfObject(value="https://www.w3.org/2019/wot/td#hasSubscriptionSchema") + protected DataSchema subscription; + + @RdfObject(value="https://www.w3.org/2019/wot/td#hasNotificationSchema") + protected DataSchema data; + + @RdfObject(value="https://www.w3.org/2019/wot/td#hasCancellationSchema") + protected DataSchema cancellation; + + // -- Getters & Setters + + public DataSchema getSubscription() { + return subscription; + } + + public void setSubscription(DataSchema subscription) { + this.subscription = subscription; + } + + public DataSchema getData() { + return data; + } + + public void setData(DataSchema data) { + this.data = data; + } + + public DataSchema getCancellation() { + return cancellation; + } + + public void setCancellation(DataSchema cancellation) { + this.cancellation = cancellation; + } + + // -- HashCode & Equals + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = computeHashCode(result, prime); + result = prime * result + ((subscription==null) ? 0: subscription.hashCode()); + result = prime * result + ((data==null) ? 0: data.hashCode()); + result = prime * result + ((cancellation==null) ? 0: cancellation.hashCode()); + result = superHashcode(result, prime); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (this.getClass() != obj.getClass()) + return false; + + EventAffordance other = (EventAffordance) obj; + Boolean sameClass = sameSuperAttributes(other); + sameClass &= sameCollections(this.getForms(), other.getForms()); + sameClass &= sameMap(this.getDescriptions(), other.getDescriptions()); + sameClass &= sameMap(this.getTitles(), other.getTitles()); + sameClass &= sameMap(this.getUriVariables(), other.getUriVariables()); + sameClass &= sameAttribute(this.getTitle(), other.getTitle()); + sameClass &= sameAttribute(this.getDescription(), other.getDescription()); + + sameClass &= sameAttribute(this.getSubscription(), other.getSubscription()); + sameClass &= sameAttribute(this.getData(), other.getData()); + sameClass &= sameAttribute(this.getCancellation(), other.getCancellation()); + + return sameClass; + } + +} diff --git a/src/main/java/wot/jtd/model/interactions/InteractionAffordance.java b/src/main/java/wot/jtd/model/interactions/InteractionAffordance.java new file mode 100755 index 0000000..898ff23 --- /dev/null +++ b/src/main/java/wot/jtd/model/interactions/InteractionAffordance.java @@ -0,0 +1,144 @@ +package wot.jtd.model.interactions; + +import java.util.Collection; +import java.util.Map; +import javax.validation.constraints.NotEmpty; +import com.fasterxml.jackson.annotation.JsonInclude; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfDatatypeGroup; +import kehio.annotations.RdfObject; +import kehio.annotations.RdfObjectGroup; +import wot.jtd.model.AbstractRdfObject; +import wot.jtd.model.Form; +import wot.jtd.model.schemas.data.DataSchema; + +/** + * This class implements the object InteractionAffordance + * from a Thing Description as specified in the Web of Things (WoT) + * documentation. + *

+ * + * @see InteractionAffordance + * WoT documentation + * @author Andrea Cimmino + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class InteractionAffordance extends AbstractRdfObject { + + // -- Attributes: from InteractionAffordance + + @RdfObject("https://www.w3.org/2019/wot/td#hasForm") + @NotEmpty(message = "'forms' in any InteractionAffordance (PropertyAffordance, ActionAffordance, or EventAffordance) must not be empty") + protected Collection forms; + + @RdfDatatype("http://purl.org/dc/terms/title") + protected String title; + + @RdfDatatypeGroup(value = "http://purl.org/dc/terms/title", byLang = true) + protected Map titles; + + @RdfDatatype("http://purl.org/dc/terms/description") + protected String description; + + @RdfDatatypeGroup(value = "http://purl.org/dc/terms/description", byLang = true) + protected Map descriptions; + + @RdfObjectGroup(value = "https://www.w3.org/2019/wot/td#hasUriTemplateSchema", key = "https://www.w3.org/2019/wot/td#name", includeKey = true) + protected Map uriVariables; + + // -- Getters & Setters + + public Collection getForms() { + return forms; + } + + public void setForms(Collection forms) { + this.forms = forms; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Map getTitles() { + return titles; + } + + public void setTitles(Map titles) { + this.titles = titles; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Map getDescriptions() { + return descriptions; + } + + public void setDescriptions(Map descriptions) { + this.descriptions = descriptions; + } + + public Map getUriVariables() { + return uriVariables; + } + + public void setUriVariables(Map uriVariables) { + this.uriVariables = uriVariables; + } + + // -- HashCode and equals + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = computeHashCode(result, prime); + result = superHashcode(result, prime); + return result; + } + + protected int computeHashCode(int resultInput, int prime) { + int result = resultInput; + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((descriptions == null) ? 0 : descriptions.hashCode()); + result = prime * result + ((forms == null) ? 0 : forms.hashCode()); + result = prime * result + ((title == null) ? 0 : title.hashCode()); + result = prime * result + ((titles == null) ? 0 : titles.hashCode()); + result = prime * result + ((uriVariables == null) ? 0 : uriVariables.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (this.getClass() != obj.getClass()) + return false; + + InteractionAffordance other = (InteractionAffordance) obj; + Boolean sameClass = sameSuperAttributes(other); + sameClass &= sameCollections(this.getForms(), other.getForms()); + sameClass &= sameMap(this.getDescriptions(), other.getDescriptions()); + sameClass &= sameMap(this.getTitles(), other.getTitles()); + sameClass &= sameMap(this.getUriVariables(), other.getUriVariables()); + sameClass &= sameAttribute(this.getTitle(), other.getTitle()); + sameClass &= sameAttribute(this.getDescription(), other.getDescription()); + + return sameClass; + } + + +} diff --git a/src/main/java/wot/jtd/model/interactions/PropertyAffordance.java b/src/main/java/wot/jtd/model/interactions/PropertyAffordance.java new file mode 100755 index 0000000..8045fe6 --- /dev/null +++ b/src/main/java/wot/jtd/model/interactions/PropertyAffordance.java @@ -0,0 +1,113 @@ +package wot.jtd.model.interactions; + +import java.util.Collection; +import java.util.Map; +import javax.validation.constraints.NotEmpty; +import com.fasterxml.jackson.annotation.JsonInclude; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfObject; +import kehio.annotations.RdfObjectGroup; +import wot.jtd.model.Form; +import wot.jtd.model.schemas.data.DataSchema; + +/** + * This class implements the object PropertyAffordance from a Thing Description as specified in the Web of Things (WoT) documentation.

+ * @see PropertyAffordance WoT documentation + * @author Andrea Cimmino + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class PropertyAffordance extends DataSchema { + + // -- Attributes: from InteractionAffordance + + @RdfObject("https://www.w3.org/2019/wot/td#hasForm") + @NotEmpty(message="'forms' in any InteractionAffordance (PropertyAffordance, ActionAffordance, or EventAffordance) must not be empty") + protected Collection forms; + + @RdfObjectGroup(value="https://www.w3.org/2019/wot/td#hasUriTemplateSchema", key="https://www.w3.org/2019/wot/td#name", includeKey=true) + protected Map uriVariables; + + @RdfDatatype("https://www.w3.org/2019/wot/td#isObservable") + protected Boolean observable; // extended attribute from InteractionAffordance + + // -- Getters & Setters + + public Collection getForms() { + return forms; + } + + public void setForms(Collection forms) { + this.forms = forms; + } + + public Map getUriVariables() { + return uriVariables; + } + + public void setUriVariables(Map uriVariables) { + this.uriVariables = uriVariables; + } + + public Boolean getObservable() { + return observable; + } + + public void setObservable(Boolean observable) { + this.observable = observable; + } + + // HasCode and Equals + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = computeHashCode(result, prime); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((descriptions == null) ? 0 : descriptions.hashCode()); + result = prime * result + ((forms == null) ? 0 : forms.hashCode()); + result = prime * result + ((title == null) ? 0 : title.hashCode()); + result = prime * result + ((titles == null) ? 0 : titles.hashCode()); + result = prime * result + ((uriVariables == null) ? 0 : uriVariables.hashCode()); + result = prime * result + ((observable == null) ? 0 : observable.hashCode()); + + result = superHashcode(result, prime); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (this.getClass() != obj.getClass()) + return false; + + PropertyAffordance other = (PropertyAffordance) obj; + Boolean sameClass = sameSuperAttributes(other); + sameClass &= sameMap(this.getDescriptions(), other.getDescriptions()); + sameClass &= sameMap(this.getTitles(), other.getTitles()); + sameClass &= sameAttribute(this.getTitle(), other.getTitle()); + sameClass &= sameAttribute(this.getDescription(), other.getDescription()); + sameClass &= sameAttribute(this.getSchemaType(), other.getSchemaType()); + sameClass &= sameAttribute(this.getCons(), other.getCons()); + sameClass &= sameAttribute(this.getFormat(), other.getFormat()); + sameClass &= sameAttribute(this.getReadOnly(), other.getReadOnly()); + sameClass &= sameAttribute(this.getUnit(), other.getUnit()); + sameClass &= sameAttribute(this.getWriteOnly(), other.getWriteOnly()); + + sameClass &= sameCollections(this.getOneOf(), other.getOneOf()); + sameClass &= sameCollections(this.getEnumTypes(), other.getEnumTypes()); + sameClass &= sameCollections(this.getForms(), other.getForms()); + sameClass &= sameMap(this.getDescriptions(), other.getDescriptions()); + sameClass &= sameMap(this.getTitles(), other.getTitles()); + sameClass &= sameMap(this.getUriVariables(), other.getUriVariables()); + sameClass &= sameAttribute(this.getTitle(), other.getTitle()); + sameClass &= sameAttribute(this.getDescription(), other.getDescription()); + sameClass &= sameAttribute(this.getObservable(), other.getObservable()); + + return sameClass; + } + + +} diff --git a/src/main/java/wot/jtd/model/schemas/data/AbstractDataSchema.java b/src/main/java/wot/jtd/model/schemas/data/AbstractDataSchema.java new file mode 100644 index 0000000..869f98d --- /dev/null +++ b/src/main/java/wot/jtd/model/schemas/data/AbstractDataSchema.java @@ -0,0 +1,277 @@ +package wot.jtd.model.schemas.data; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.validation.constraints.Pattern; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRawValue; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.databind.JsonNode; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfDatatypeGroup; +import kehio.annotations.RdfObject; +import kehio.annotations.RdfUrlMap; +import wot.jtd.Vocabulary; +import wot.jtd.model.AbstractRdfObject; + +/** + * This class implements the object DataSchema from a Thing Description as specified in the Web of Things + * (WoT) documentation. + *

+ * + * @see DataSchema WoT + * documentation + * @author Andrea Cimmino + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public abstract class AbstractDataSchema extends AbstractRdfObject { + + // -- Attributes + + @RdfDatatype("http://purl.org/dc/terms/title") + protected String title; + + @RdfDatatypeGroup(value = "http://purl.org/dc/terms/title", byLang = true) + protected Map titles; + + @RdfDatatype("http://purl.org/dc/terms/decription") + protected String description; + + @RdfDatatypeGroup(value = "http://purl.org/dc/terms/decription", byLang = true) + protected Map descriptions; + + @RdfObject(value = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", strict = true, aliases = { + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#ObjectSchema", value = "object"), + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#ArraySchema", value = "array"), + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#BooleanSchema", value = "boolean"), + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#StringSchema", value = "string"), + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#NumberSchema", value = "number"), + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#IntegerSchema", value = "integer"), + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#NullSchema", value = "null") }) + @Pattern(regexp = "array|object|number|integer|string|boolean|null", flags = Pattern.Flag.CASE_INSENSITIVE) + @JsonProperty(Vocabulary.JSONLD_TYPE_ALIAS) + protected String schemaType; + + @RdfObject("http://schema.org/unitCode") + protected String unit; + + @RdfObject("https://www.w3.org/2019/wot/json-schema#const") + @JsonRawValue + @JsonProperty(Vocabulary.CONS) + protected String cons; + + @RdfObject("https://www.w3.org/2019/wot/json-schema#oneOf") + protected Collection oneOf; + + @RdfObject("https://www.w3.org/2019/wot/json-schema#enum") + @JsonRawValue + @JsonProperty(Vocabulary.ENUM) + protected Collection enumTypes; + + @RdfDatatype("https://www.w3.org/2019/wot/json-schema#readOnly") + protected Boolean readOnly; // has default value + + @RdfDatatype("https://www.w3.org/2019/wot/json-schema#writeOnly") + protected Boolean writeOnly; // has default value + + @RdfDatatype("https://www.w3.org/2019/wot/json-schema#format") + protected String format; + + // -- Getters & Setters + + @Override + public Collection getType() { + return type; + } + + protected static final Map JSON_SCHEMA_TYPES = new HashMap<>(); + static { + JSON_SCHEMA_TYPES.put("https://www.w3.org/2019/wot/json-schema#ObjectSchema", "object"); + JSON_SCHEMA_TYPES.put("https://www.w3.org/2019/wot/json-schema#ArraySchema", "array"); + JSON_SCHEMA_TYPES.put("https://www.w3.org/2019/wot/json-schema#BooleanSchema", "boolean"); + JSON_SCHEMA_TYPES.put("https://www.w3.org/2019/wot/json-schema#StringSchema", "string"); + JSON_SCHEMA_TYPES.put("https://www.w3.org/2019/wot/json-schema#NumberSchema", "number"); + JSON_SCHEMA_TYPES.put("https://www.w3.org/2019/wot/json-schema#IntegerSchema", "integer"); + JSON_SCHEMA_TYPES.put("https://www.w3.org/2019/wot/json-schema#NullSchema", "null"); + } + + @Override + public void setType(Collection type) { + String removeType = null; + Iterator typeIterator = type.iterator(); + while (typeIterator.hasNext()) { + String typeIterate = typeIterator.next(); + if (JSON_SCHEMA_TYPES.containsKey(typeIterate)) { + removeType = typeIterate; + break; + } + } + type.remove(removeType); + this.setSchemaType(JSON_SCHEMA_TYPES.get(removeType)); + if (!type.isEmpty()) + this.type = type; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Map getTitles() { + return titles; + } + + public void setTitles(Map titles) { + this.titles = titles; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Map getDescriptions() { + return descriptions; + } + + public void setDescriptions(Map descriptions) { + this.descriptions = descriptions; + } + + public String getSchemaType() { + return schemaType; + } + + public void setSchemaType(String schemaType) { + this.schemaType = schemaType; + } + + public Object getCons() { + return cons; + } + + public String getUnit() { + return unit; + } + + public void setUnit(String unit) { + this.unit = unit; + } + + public Collection getOneOf() { + return oneOf; + } + + public void setOneOf(Collection oneOf) { + this.oneOf = oneOf; + } + + public Collection getEnumTypes() { + return enumTypes; + } + + public Boolean getReadOnly() { + return readOnly; + } + + public void setReadOnly(Boolean readOnly) { + this.readOnly = readOnly; + } + + public Boolean getWriteOnly() { + return writeOnly; + } + + public void setWriteOnly(Boolean writeOnly) { + this.writeOnly = writeOnly; + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + @JsonSetter(Vocabulary.CONS) + public void setCons(JsonNode cons) { + this.cons = cons.toString(); + } + + @JsonSetter(Vocabulary.ENUM) + public void setEnumTypes(List enumTypes) { + this.enumTypes = enumTypes.stream().map(elem -> elem.toString()).collect(Collectors.toList()); + } + + // -- HashCode & Equals + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = computeHashCode(result, prime); + result = superHashcode(result, prime); + return result; + } + + protected int computeHashCode(int resultInput, int prime) { + int result = resultInput; + result = prime * result + ((cons == null) ? 0 : cons.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((descriptions == null) ? 0 : descriptions.hashCode()); + result = prime * result + ((enumTypes == null) ? 0 : enumTypes.hashCode()); + result = prime * result + ((format == null) ? 0 : format.hashCode()); + result = prime * result + ((oneOf == null) ? 0 : oneOf.hashCode()); + result = prime * result + ((readOnly == null) ? 0 : readOnly.hashCode()); + result = prime * result + ((schemaType == null) ? 0 : schemaType.hashCode()); + result = prime * result + ((title == null) ? 0 : title.hashCode()); + result = prime * result + ((titles == null) ? 0 : titles.hashCode()); + result = prime * result + ((unit == null) ? 0 : unit.hashCode()); + result = prime * result + ((writeOnly == null) ? 0 : writeOnly.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (this.getClass() != obj.getClass()) + return false; + + DataSchema other = (DataSchema) obj; + Boolean sameClass = sameSuperAttributes(other); + sameClass &= sameMap(this.getDescriptions(), other.getDescriptions()); + sameClass &= sameMap(this.getTitles(), other.getTitles()); + sameClass &= sameAttribute(this.getTitle(), other.getTitle()); + sameClass &= sameAttribute(this.getDescription(), other.getDescription()); + sameClass &= sameAttribute(this.getSchemaType(), other.getSchemaType()); + sameClass &= sameAttribute(this.getCons(), other.getCons()); + sameClass &= sameAttribute(this.getFormat(), other.getFormat()); + sameClass &= sameAttribute(this.getReadOnly(), other.getReadOnly()); + sameClass &= sameAttribute(this.getUnit(), other.getUnit()); + sameClass &= sameAttribute(this.getWriteOnly(), other.getWriteOnly()); + sameClass &= sameCollections(this.getOneOf(), other.getOneOf()); + sameClass &= sameCollections(this.getEnumTypes(), other.getEnumTypes()); + + return sameClass; + + } + +} diff --git a/src/main/java/wot/jtd/model/schemas/data/DataSchema.java b/src/main/java/wot/jtd/model/schemas/data/DataSchema.java new file mode 100755 index 0000000..5522c00 --- /dev/null +++ b/src/main/java/wot/jtd/model/schemas/data/DataSchema.java @@ -0,0 +1,182 @@ +package wot.jtd.model.schemas.data; + +import java.util.Collection; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfObject; +import kehio.annotations.RdfObjectGroup; +import wot.jtd.Vocabulary; + +/** + * This class implements the object DataSchema from + * a Thing Description as specified in the Web of Things (WoT) documentation. + *

+ * + * @see DataSchema WoT + * documentation + * @author Andrea Cimmino + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DataSchema extends AbstractDataSchema { + + // -- Attributes + + // String, Null & Boolean + + // Array + + @RdfObject("https://www.w3.org/2019/wot/json-schema#items") + @JsonProperty(Vocabulary.ITEMS) + protected Collection items; // compactable attribute + + @RdfDatatype("https://www.w3.org/2019/wot/json-schema#minItems") + protected Integer minItems; // maxInclusive = 4294967295 + + @RdfDatatype("https://www.w3.org/2019/wot/json-schema#maxItems") + protected Integer maxItems; // maxInclusive = 4294967295 + + // Integer & Number + + @RdfDatatype("https://www.w3.org/2019/wot/json-schema#minimum") + protected Number minimum; + + @RdfDatatype("https://www.w3.org/2019/wot/json-schema#maximum") + protected Number maximum; + + // Object + + @RdfObjectGroup(value = "https://www.w3.org/2019/wot/json-schema#properties", key = "https://www.w3.org/2019/wot/json-schema#propertyName", includeKey = true + /*aliases = { + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#ObjectSchema", value = "object"), + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#ArraySchema", value = "array"), + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#BooleanSchema", value = "boolean"), + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#StringSchema", value = "string"), + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#NumberSchema", value = "number"), + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#IntegerSchema", value = "integer"), + @RdfUrlMap(key = "https://www.w3.org/2019/wot/json-schema#NullSchema", value = "null") }*/ + ) + protected Map properties; + + @RdfDatatype("https://www.w3.org/2019/wot/json-schema#required") + protected Collection required; + + // -- Getters & Setters + + public Collection getItems() { + return items; + } + + public void setItems(Collection items) { + this.items = items; + } + + public Integer getMinItems() { + return minItems; + } + + public void setMinItems(Integer minItems) { + this.minItems = minItems; + } + + public Integer getMaxItems() { + return maxItems; + } + + public void setMaxItems(Integer maxItems) { + this.maxItems = maxItems; + } + + public Number getMinimum() { + return minimum; + } + + public void setMinimum(Number minimum) { + this.minimum = minimum; + } + + public Number getMaximum() { + return maximum; + } + + public void setMaximum(Number maximum) { + this.maximum = maximum; + } + + public Map getProperties() { + return properties; + } + + public void setProperties(Map properties) { + this.properties = properties; + } + + public Collection getRequired() { + return required; + } + + public void setRequired(Collection required) { + this.required = required; + } + + // -- HashCode & Equals + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = computeHashCode(result, prime); + result = prime * result + ((items == null) ? 0 : items.hashCode()); + result = prime * result + ((maxItems == null) ? 0 : maxItems.hashCode()); + result = prime * result + ((minItems == null) ? 0 : minItems.hashCode()); + + result = prime * result + ((maximum == null) ? 0 : maximum.hashCode()); + result = prime * result + ((minimum == null) ? 0 : minimum.hashCode()); + + result = prime * result + ((properties == null) ? 0 : properties.hashCode()); + result = prime * result + ((required == null) ? 0 : required.hashCode()); + + result = superHashcode(result, prime); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (this.getClass() != obj.getClass()) + return false; + + DataSchema other = (DataSchema) obj; + Boolean sameClass = sameSuperAttributes(other); + sameClass &= sameMap(this.getDescriptions(), other.getDescriptions()); + sameClass &= sameMap(this.getTitles(), other.getTitles()); + sameClass &= sameAttribute(this.getTitle(), other.getTitle()); + sameClass &= sameAttribute(this.getDescription(), other.getDescription()); + sameClass &= sameAttribute(this.getSchemaType(), other.getSchemaType()); + sameClass &= sameAttribute(this.getCons(), other.getCons()); + sameClass &= sameAttribute(this.getFormat(), other.getFormat()); + sameClass &= sameAttribute(this.getReadOnly(), other.getReadOnly()); + sameClass &= sameAttribute(this.getUnit(), other.getUnit()); + sameClass &= sameAttribute(this.getWriteOnly(), other.getWriteOnly()); + sameClass &= sameCollections(this.getOneOf(), other.getOneOf()); + sameClass &= sameCollections(this.getEnumTypes(), other.getEnumTypes()); + + sameClass &= sameCollections(this.getItems(), other.getItems()); + sameClass &= sameAttribute(this.getMaxItems(), other.getMaxItems()); + sameClass &= sameAttribute(this.getMinItems(), other.getMinItems()); + + sameClass &= sameAttribute(this.getMaximum(), other.getMaximum()); + sameClass &= sameAttribute(this.getMinimum(), other.getMinimum()); + + sameClass &= sameMap(this.getProperties(), other.getProperties()); + sameClass &= sameCollections(this.getRequired(), other.getRequired()); + + return sameClass; + } + +} diff --git a/src/main/java/wot/jtd/model/schemas/security/SecurityScheme.java b/src/main/java/wot/jtd/model/schemas/security/SecurityScheme.java new file mode 100755 index 0000000..5e645b0 --- /dev/null +++ b/src/main/java/wot/jtd/model/schemas/security/SecurityScheme.java @@ -0,0 +1,265 @@ +package wot.jtd.model.schemas.security; + +import java.net.URI; +import java.util.Collection; +import java.util.Map; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfDatatypeGroup; +import kehio.annotations.RdfObject; +import wot.jtd.model.AbstractRdfObject; + +/** + * This class implements the object SecurityScheme + * (and its sub-classes) from a Thing Description as specified in the Web of + * Things (WoT) documentation. + *

+ * + * @see SecurityScheme + * WoT documentation + * @author Andrea Cimmino + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class SecurityScheme extends AbstractRdfObject { + + // -- Attributes + + @RdfDatatype("https://www.w3.org/2019/wot/td#scheme") + @NotBlank(message = "'scheme' must not be blank, e.g., nosec, basic, digest, bearer, psk, oauth2, or apikey") + private String scheme; + + @RdfDatatype("http://purl.org/dc/terms/description") + private String description; + + @RdfDatatypeGroup(value = "http://purl.org/dc/terms/description", byLang = true) + private Map descriptions; + + @RdfObject("https://www.w3.org/2019/wot/td#proxy") + private URI proxy; + + // digest + @RdfDatatype("https://www.w3.org/2019/wot/td#qop") + @Pattern(regexp = "auth|auth-int", flags = Pattern.Flag.CASE_INSENSITIVE, message = "'qop' must be one of: 'auth' or 'auth-int'.") + private String qop; + + // psk + @RdfDatatype("https://www.w3.org/2019/wot/td#identity") + private String identity; + + // oauth2 + @RdfObject("https://www.w3.org/2019/wot/td#token") + private URI token; + + @RdfObject("https://www.w3.org/2019/wot/td#refresh") + private URI refresh; + + @RdfDatatype("https://www.w3.org/2019/wot/td#flow") + private String flow; + + @RdfDatatype("https://www.w3.org/2019/wot/td#scopes") + private Collection scopes; + + // bearer + @RdfDatatype("https://www.w3.org/2019/wot/td#alg") + private String alg; + + @RdfDatatype("https://www.w3.org/2019/wot/td#format") + private String format; + + // oauth2 + bearer + @RdfObject("https://www.w3.org/2019/wot/td#authorization") + private URI authorization; + + // basic + digest + apikey + bearer + @RdfDatatype("https://www.w3.org/2019/wot/td#in") + @Pattern(regexp = "header|query|body|cookie", flags = Pattern.Flag.CASE_INSENSITIVE, message = "'in' must be one of: 'header', 'query', 'body', or 'cookie'") + private String in; + + @RdfDatatype("https://www.w3.org/2019/wot/td#name") + private String name; + + // -- Getters & Setters + + public String getScheme() { + return scheme; + } + + public void setScheme(String scheme) { + this.scheme = scheme; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Map getDescriptions() { + return descriptions; + } + + public void setDescriptions(Map descriptions) { + this.descriptions = descriptions; + } + + public URI getProxy() { + return proxy; + } + + public void setProxy(URI proxy) { + this.proxy = proxy; + } + + public String getQop() { + return qop; + } + + public void setQop(String qop) { + this.qop = qop; + } + + public String getIdentity() { + return identity; + } + + public void setIdentity(String identity) { + this.identity = identity; + } + + public URI getToken() { + return token; + } + + public void setToken(URI token) { + this.token = token; + } + + public URI getRefresh() { + return refresh; + } + + public void setRefresh(URI refresh) { + this.refresh = refresh; + } + + public String getFlow() { + return flow; + } + + public void setFlow(String flow) { + this.flow = flow; + } + + public Collection getScopes() { + return scopes; + } + + public void setScopes(Collection scopes) { + this.scopes = scopes; + } + + public String getAlg() { + return alg; + } + + public void setAlg(String alg) { + this.alg = alg; + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public URI getAuthorization() { + return authorization; + } + + public void setAuthorization(URI authorization) { + this.authorization = authorization; + } + + public String getIn() { + return in; + } + + public void setIn(String in) { + this.in = in; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((alg == null) ? 0 : alg.hashCode()); + result = prime * result + ((authorization == null) ? 0 : authorization.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((descriptions == null) ? 0 : descriptions.hashCode()); + result = prime * result + ((flow == null) ? 0 : flow.hashCode()); + result = prime * result + ((format == null) ? 0 : format.hashCode()); + result = prime * result + ((identity == null) ? 0 : identity.hashCode()); + result = prime * result + ((in == null) ? 0 : in.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((proxy == null) ? 0 : proxy.hashCode()); + result = prime * result + ((qop == null) ? 0 : qop.hashCode()); + result = prime * result + ((refresh == null) ? 0 : refresh.hashCode()); + result = prime * result + ((scheme == null) ? 0 : scheme.hashCode()); + result = prime * result + ((scopes == null) ? 0 : scopes.hashCode()); + result = prime * result + ((token == null) ? 0 : token.hashCode()); + result = superHashcode(result, prime); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (this.getClass() != obj.getClass()) + return false; + + SecurityScheme other = (SecurityScheme) obj; + Boolean sameClass = sameSuperAttributes(other); + sameClass &= sameAttribute(this.getDescription(), other.getDescription()); + sameClass &= sameAttribute(this.getScheme(), other.getScheme()); + sameClass &= sameAttribute(this.getProxy(), other.getProxy()); + sameClass &= sameMap(this.getDescriptions(), other.getDescriptions()); + // apikey + basic + (~bearer) + (~digest) + sameClass &= sameAttribute(this.getIn(), other.getIn()); + sameClass &= sameAttribute(this.getName(), other.getName()); + // (~bearer) + (~oauth) + sameClass &= sameAttribute(this.getAuthorization(), other.getAuthorization()); + sameClass &= sameAttribute(this.getAlg(), other.getAlg()); + sameClass &= sameAttribute(this.getFormat(), other.getFormat()); + // (~digest) + sameClass &= sameAttribute(this.getQop(), other.getQop()); + // oauth + sameClass &= sameAttribute(this.getToken(), other.getToken()); + sameClass &= sameAttribute(this.getRefresh(), other.getRefresh()); + sameClass &= sameCollections(this.getScopes(), other.getScopes()); + sameClass &= sameAttribute(this.getFlow(), other.getFlow()); + // psk + sameClass &= sameAttribute(this.getIdentity(), other.getIdentity()); + return sameClass; + } + + +} diff --git a/src/test/java/kehio/fromRDF/datatype/tests/DatatypeGroupRDFTest.java b/src/test/java/kehio/fromRDF/datatype/tests/DatatypeGroupRDFTest.java new file mode 100644 index 0000000..cfc2476 --- /dev/null +++ b/src/test/java/kehio/fromRDF/datatype/tests/DatatypeGroupRDFTest.java @@ -0,0 +1,38 @@ +package kehio.fromRDF.datatype.tests; + +import java.lang.reflect.InvocationTargetException; +import java.net.URISyntaxException; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.junit.Assert; +import org.junit.Test; + +import kehio.mapper.Kehio; +import kehio.models.test.TestPost1; +import kehio.models.test.TestPost2; + +public class DatatypeGroupRDFTest { + + + @Test + public void testDatatype1() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException, InstantiationException, InvocationTargetException, NoSuchMethodException, SecurityException { + Model model = TestPost1.expectedModel; + Resource subject = model.listSubjectsWithProperty(ResourceFactory.createProperty("http://xmlns.com/foaf/0.1/description")).next(); + TestPost1 object = (TestPost1) Kehio.serializeClass(TestPost1.class, model, subject); + TestPost1 expectedObject = new TestPost1(true); + + Assert.assertTrue(expectedObject.equals(object)); + } + + @Test + public void testDatatype2() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException, InstantiationException, InvocationTargetException, NoSuchMethodException, SecurityException { + Model model = TestPost2.expectedModel; + Resource subject = model.listSubjectsWithProperty(ResourceFactory.createProperty("http://xmlns.com/foaf/0.1/numbers")).next(); + TestPost2 object = (TestPost2) Kehio.serializeClass(TestPost2.class, model, subject); + TestPost2 expectedObject = new TestPost2(true); + + Assert.assertTrue(expectedObject.equals(object)); + } +} \ No newline at end of file diff --git a/src/test/java/kehio/fromRDF/datatype/tests/DatatypeRDFTest.java b/src/test/java/kehio/fromRDF/datatype/tests/DatatypeRDFTest.java new file mode 100644 index 0000000..f628bf3 --- /dev/null +++ b/src/test/java/kehio/fromRDF/datatype/tests/DatatypeRDFTest.java @@ -0,0 +1,37 @@ +package kehio.fromRDF.datatype.tests; + +import java.lang.reflect.InvocationTargetException; +import java.net.URISyntaxException; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.junit.Assert; +import org.junit.Test; + +import kehio.mapper.Kehio; +import kehio.models.test.TestPost1; +import kehio.models.test.TestPost2; + +public class DatatypeRDFTest { + + + + @Test + public void testDatatypeGroup1() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, URISyntaxException { + TestPost1 expectedObject = new TestPost1(true); + Model model = TestPost1.expectedModel; + Resource subject = model.listSubjectsWithProperty(ResourceFactory.createProperty("http://xmlns.com/foaf/0.1/description")).next(); + TestPost1 object = (TestPost1) Kehio.serializeClass(TestPost1.class, model, subject); + Assert.assertTrue(expectedObject.equals(object)); + } + + @Test + public void testDatatypeGroup2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, URISyntaxException { + TestPost2 expectedObject = new TestPost2(true); + Model model = TestPost2.expectedModel; + Resource subject = model.listSubjectsWithProperty(ResourceFactory.createProperty("http://xmlns.com/foaf/0.1/numbers")).next(); + TestPost2 object = (TestPost2) Kehio.serializeClass(TestPost2.class, model, subject); + Assert.assertTrue(expectedObject.equals(object)); + } +} \ No newline at end of file diff --git a/src/test/java/kehio/fromRDF/datatype/tests/ObjectRdfTest.java b/src/test/java/kehio/fromRDF/datatype/tests/ObjectRdfTest.java new file mode 100644 index 0000000..068e3f9 --- /dev/null +++ b/src/test/java/kehio/fromRDF/datatype/tests/ObjectRdfTest.java @@ -0,0 +1,69 @@ +package kehio.fromRDF.datatype.tests; + +import java.io.ByteArrayInputStream; +import java.lang.reflect.InvocationTargetException; +import java.net.URISyntaxException; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.junit.Assert; +import org.junit.Test; + +import kehio.mapper.Kehio; +import kehio.models.test.TestPerson1; +import kehio.models.test.TestPerson2; + +public class ObjectRdfTest { + + + private static final String TEST1 = " \n" + + " \"John\" ;\n" + + " \n" + + " [ \n" + + " \"+34 54 65 23\" ] ;\n" + + " \n" + + " \"Fold\" , \"Doe\"\n" + + " ."; + + + @Test + public void test1() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException, InstantiationException, InvocationTargetException, NoSuchMethodException, SecurityException { + + Model model = ModelFactory.createDefaultModel(); + model.read(new ByteArrayInputStream(TEST1.getBytes()), null, "Turtle"); + TestPerson1 person = (TestPerson1) Kehio.serializeClass(TestPerson1.class, model, ResourceFactory.createResource("http://kehio-tests.com/instance1")); + + TestPerson1 expectedPerson = new TestPerson1(true); + Assert.assertTrue(expectedPerson.equals(person)); + } + + private static final String TEST2 = "[ \n" + + " \"John\" ;\n" + + " \n" + + " [ \n" + + " \"+34 54 65 23\" ] ;\n" + + " \n" + + " [ \n" + + " \"+34 54 65 23\" ] ;\n" + + " \n" + + " \"Fold\" , \"Doe\"\n" + + "] ."; + + @Test + public void test2() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException, InstantiationException, InvocationTargetException, NoSuchMethodException, SecurityException { + + Model model = ModelFactory.createDefaultModel(); + model.read(new ByteArrayInputStream(TEST2.getBytes()), null, "Turtle"); + Resource subject = model.listSubjectsWithProperty(ResourceFactory.createProperty("http://xmlns.com/foaf/0.1/name")).next(); + TestPerson2 person = (TestPerson2) Kehio.serializeClass(TestPerson2.class, model, subject); + + + TestPerson2 expectedPerson = new TestPerson2(true); + System.out.println(person.toString()); + System.out.println(expectedPerson.toString()); + Assert.assertTrue(expectedPerson.equals(person)); + } + + +} diff --git a/src/test/java/kehio/models/test/ORM4RDF1DTTest.java b/src/test/java/kehio/models/test/ORM4RDF1DTTest.java new file mode 100644 index 0000000..36b9de6 --- /dev/null +++ b/src/test/java/kehio/models/test/ORM4RDF1DTTest.java @@ -0,0 +1,117 @@ +package kehio.models.test; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfId; + +public class ORM4RDF1DTTest { + + @RdfId + public String id; + + @RdfDatatype("http://xmlns.com/foaf/0.1/age") + public Integer attrInteger; + + @RdfDatatype("http://xmlns.com/foaf/0.1/age") + public String attrString; + + @RdfDatatype("http://xmlns.com/foaf/0.1/age") + public Boolean attrBool; + + + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("ID: ").append(id).append("\n"); + builder.append("AttrInt: ").append(attrInteger).append("\n"); + builder.append("AttrStr: ").append(attrString).append("\n"); + builder.append("AttrBool: ").append(attrBool).append("\n"); + return builder.toString(); + } + + + public String getId() { + return id; + } + + + public void setId(String id) { + this.id = id; + } + + + public Integer getAttrInteger() { + return attrInteger; + } + + + public void setAttrInteger(Integer attrInteger) { + this.attrInteger = attrInteger; + } + + + public String getAttrString() { + return attrString; + } + + + public void setAttrString(String attrString) { + this.attrString = attrString; + } + + + public Boolean getAttrBool() { + return attrBool; + } + + + public void setAttrBool(Boolean attrBool) { + this.attrBool = attrBool; + } + + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((attrBool == null) ? 0 : attrBool.hashCode()); + result = prime * result + ((attrInteger == null) ? 0 : attrInteger.hashCode()); + result = prime * result + ((attrString == null) ? 0 : attrString.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof ORM4RDF1DTTest)) + return false; + ORM4RDF1DTTest other = (ORM4RDF1DTTest) obj; + if (attrBool == null) { + if (other.attrBool != null) + return false; + } else if (!attrBool.equals(other.attrBool)) + return false; + if (attrInteger == null) { + if (other.attrInteger != null) + return false; + } else if (!attrInteger.equals(other.attrInteger)) + return false; + if (attrString == null) { + if (other.attrString != null) + return false; + } else if (!attrString.equals(other.attrString)) + return false; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + + + +} diff --git a/src/test/java/kehio/models/test/ORM4RDF2DTTest.java b/src/test/java/kehio/models/test/ORM4RDF2DTTest.java new file mode 100644 index 0000000..9fc2817 --- /dev/null +++ b/src/test/java/kehio/models/test/ORM4RDF2DTTest.java @@ -0,0 +1,118 @@ +package kehio.models.test; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfId; + +public class ORM4RDF2DTTest { + + @RdfId + public String id; + + @RdfDatatype("http://xmlns.com/foaf/0.1/age") + public Integer attrInteger; + + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", datatype="http://www.w3.org/2001/XMLSchema#int") + public String attrString1; + + @RdfDatatype("http://xmlns.com/foaf/0.1/age") + public String attrString2; + + + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("ID: ").append(id).append("\n"); + builder.append("AttrInt: ").append(attrInteger).append("\n"); + builder.append("AttrStr: ").append(attrString1).append("\n"); + builder.append("AttrStr: ").append(attrString2).append("\n"); + return builder.toString(); + } + + + public String getId() { + return id; + } + + + public void setId(String id) { + this.id = id; + } + + + public Integer getAttrInteger() { + return attrInteger; + } + + + public void setAttrInteger(Integer attrInteger) { + this.attrInteger = attrInteger; + } + + + public String getAttrString1() { + return attrString1; + } + + + public void setAttrString1(String attrString1) { + this.attrString1 = attrString1; + } + + + public String getAttrString2() { + return attrString2; + } + + + public void setAttrString2(String attrString2) { + this.attrString2 = attrString2; + } + + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((attrInteger == null) ? 0 : attrInteger.hashCode()); + result = prime * result + ((attrString1 == null) ? 0 : attrString1.hashCode()); + result = prime * result + ((attrString2 == null) ? 0 : attrString2.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof ORM4RDF2DTTest)) + return false; + ORM4RDF2DTTest other = (ORM4RDF2DTTest) obj; + if (attrInteger == null) { + if (other.attrInteger != null) + return false; + } else if (!attrInteger.equals(other.attrInteger)) + return false; + if (attrString1 == null) { + if (other.attrString1 != null) + return false; + } else if (!attrString1.equals(other.attrString1)) + return false; + if (attrString2 == null) { + if (other.attrString2 != null) + return false; + } else if (!attrString2.equals(other.attrString2)) + return false; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + + + + +} diff --git a/src/test/java/kehio/models/test/TestPerson1.java b/src/test/java/kehio/models/test/TestPerson1.java new file mode 100644 index 0000000..b0d24a9 --- /dev/null +++ b/src/test/java/kehio/models/test/TestPerson1.java @@ -0,0 +1,82 @@ +package kehio.models.test; + +import java.util.HashSet; +import java.util.Set; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfObject; + +public class TestPerson1 { + + @RdfDatatype("http://xmlns.com/foaf/0.1/name") + private String name; + @RdfDatatype("http://xmlns.com/foaf/0.1/surnames") + private Set surnames; + @RdfObject("http://xmlns.com/foaf/0.1/phone") + private TestTelephone phone; + + public TestPerson1(){ + + } + + public TestPerson1(boolean init){ + if(init) { + name = "John"; + surnames = new HashSet<>(); + surnames.add("Doe"); + surnames.add("Fold"); + TestTelephone phone = new TestTelephone(true); + this.phone = phone; + } + + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Name: ").append(name).append("\n"); + builder.append("Surname: ").append(surnames).append("\n"); + builder.append("Phone: ").append(phone).append("\n"); + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((phone == null) ? 0 : phone.hashCode()); + result = prime * result + ((surnames == null) ? 0 : surnames.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof TestPerson1)) + return false; + TestPerson1 other = (TestPerson1) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (phone == null) { + if (other.phone != null) + return false; + } else if (!phone.equals(other.phone)) + return false; + if (surnames == null) { + if (other.surnames != null) + return false; + } else if (!surnames.equals(other.surnames)) + return false; + return true; + } + + + + +} diff --git a/src/test/java/kehio/models/test/TestPerson2.java b/src/test/java/kehio/models/test/TestPerson2.java new file mode 100644 index 0000000..92ce38f --- /dev/null +++ b/src/test/java/kehio/models/test/TestPerson2.java @@ -0,0 +1,81 @@ +package kehio.models.test; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfObject; + +public class TestPerson2 { + @RdfDatatype("http://xmlns.com/foaf/0.1/name") + private String name; + @RdfDatatype("http://xmlns.com/foaf/0.1/surnames") + private Set surnames; + @RdfObject("http://xmlns.com/foaf/0.1/phone") + private List phones; + + public TestPerson2() { + + } + public TestPerson2(boolean init){ + if(init) { + name = "John"; + surnames = new HashSet<>(); + surnames.add("Doe"); + surnames.add("Fold"); + TestTelephone phone1 = new TestTelephone(true); + TestTelephone phone2 = new TestTelephone(true); + this.phones = new ArrayList<>(); + this.phones.add(phone1); + this.phones.add(phone2); + } + + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Name: ").append(name).append("\n"); + builder.append("Surname: ").append(surnames).append("\n"); + builder.append("Phones: ").append(phones).append("\n"); + return builder.toString(); + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((phones == null) ? 0 : phones.hashCode()); + result = prime * result + ((surnames == null) ? 0 : surnames.hashCode()); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof TestPerson2)) + return false; + TestPerson2 other = (TestPerson2) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (phones == null) { + if (other.phones != null) + return false; + } else if (!phones.equals(other.phones)) + return false; + if (surnames == null) { + if (other.surnames != null) + return false; + } else if (!surnames.equals(other.surnames)) + return false; + return true; + } + + +} diff --git a/src/test/java/kehio/models/test/TestPost1.java b/src/test/java/kehio/models/test/TestPost1.java new file mode 100644 index 0000000..fb691ae --- /dev/null +++ b/src/test/java/kehio/models/test/TestPost1.java @@ -0,0 +1,75 @@ +package kehio.models.test; + +import java.io.ByteArrayInputStream; +import java.util.HashMap; +import java.util.Map; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; + +import kehio.annotations.RdfDatatypeGroup; + +public class TestPost1 { + + private static final String OUTPUT = "[ \"esto es un ejemplo\"@es , \"Ceci est un exemple\"@fr , \"questo é un esempio\"@it , \"this is an example\"@en ] ."; + public static Model expectedModel = ModelFactory.createDefaultModel(); + static{ + expectedModel.read(new ByteArrayInputStream(OUTPUT.getBytes()), null, "Turtle"); + } + + @RdfDatatypeGroup(value="http://xmlns.com/foaf/0.1/description", byLang=true) + private Map post; + + public TestPost1() { + + } + + public TestPost1(boolean init) { + if(init) { + post = new HashMap<>(); + post.put("en", "this is an example"); + post.put("es", "esto es un ejemplo"); + post.put("it", "questo é un esempio"); + post.put("fr", "Ceci est un exemple"); + } + } + + public Map getPost() { + return post; + } + + public void setPost(Map post) { + this.post = post; + } + + public String toString() { + return this.post.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((post == null) ? 0 : post.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof TestPost1)) + return false; + TestPost1 other = (TestPost1) obj; + if (post == null) { + if (other.post != null) + return false; + } else if (!post.equals(other.post)) + return false; + return true; + } + + +} diff --git a/src/test/java/kehio/models/test/TestPost2.java b/src/test/java/kehio/models/test/TestPost2.java new file mode 100644 index 0000000..aea092f --- /dev/null +++ b/src/test/java/kehio/models/test/TestPost2.java @@ -0,0 +1,79 @@ +package kehio.models.test; + +import java.io.ByteArrayInputStream; +import java.util.HashMap; +import java.util.Map; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; + +import kehio.annotations.RdfDatatypeGroup; + +public class TestPost2 { + + // -- RDF representation + private static final String OUTPUT = "[ \"12\"^^ , \"12.2\"^^ , \"this is an example\" , \"2002-09-24\"^^ ] ."; + public static Model expectedModel = ModelFactory.createDefaultModel(); + static{ + expectedModel.read(new ByteArrayInputStream(OUTPUT.getBytes()), null, "Turtle"); + } + + // ---- + + + @RdfDatatypeGroup(value="http://xmlns.com/foaf/0.1/numbers", byDatatype=true) + private Map post; + + public TestPost2() { + + } + + public TestPost2(boolean init) { + if(init) { + post = new HashMap<>(); + post.put("http://www.w3.org/2001/XMLSchema#string", "this is an example"); + post.put("http://www.w3.org/2001/XMLSchema#int", "12"); + post.put("http://www.w3.org/2001/XMLSchema#double", "12.2"); + post.put("http://www.w3.org/2001/XMLSchema#date", "2002-09-24"); + } + } + + public Map getPost() { + return post; + } + + public void setPost(Map post) { + this.post = post; + } + + public String toString() { + return this.post.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((post == null) ? 0 : post.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof TestPost2)) + return false; + TestPost2 other = (TestPost2) obj; + if (post == null) { + if (other.post != null) + return false; + } else if (!post.equals(other.post)) + return false; + return true; + } + + +} diff --git a/src/test/java/kehio/models/test/TestPost3.java b/src/test/java/kehio/models/test/TestPost3.java new file mode 100644 index 0000000..f3de163 --- /dev/null +++ b/src/test/java/kehio/models/test/TestPost3.java @@ -0,0 +1,23 @@ +package kehio.models.test; + +import java.util.Map; + +import kehio.annotations.RdfDatatypeGroup; + +public class TestPost3 { + + // -- RDF representation + // throws exception + // ---- + + @RdfDatatypeGroup(value="http://xmlns.com/foaf/0.1/numbers", byDatatype=true) + private Map post; + + public TestPost3() { + + } + + public TestPost3(boolean init) { + + } +} diff --git a/src/test/java/kehio/models/test/TestPost4.java b/src/test/java/kehio/models/test/TestPost4.java new file mode 100644 index 0000000..f1431d4 --- /dev/null +++ b/src/test/java/kehio/models/test/TestPost4.java @@ -0,0 +1,23 @@ +package kehio.models.test; + +import java.util.Map; + +import kehio.annotations.RdfDatatypeGroup; + +public class TestPost4 { + + // -- RDF representation + // throws exception + // ---- + + @RdfDatatypeGroup(value="http://xmlns.com/foaf/0.1/numbers", byDatatype=true) + private Map post; + + public TestPost4() { + + } + + public TestPost4(boolean init) { + + } +} diff --git a/src/test/java/kehio/models/test/TestTelephone.java b/src/test/java/kehio/models/test/TestTelephone.java new file mode 100644 index 0000000..7c15e2b --- /dev/null +++ b/src/test/java/kehio/models/test/TestTelephone.java @@ -0,0 +1,50 @@ +package kehio.models.test; + +import kehio.annotations.RdfDatatype; + +public class TestTelephone { + @RdfDatatype("http://xmlns.com/foaf/0.1/number") + private String number; + + public TestTelephone() { + + } + + public TestTelephone(boolean b) { + this.number = "+34 54 65 23"; + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("number: ").append(number).append("\n"); + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((number == null) ? 0 : number.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof TestTelephone)) + return false; + TestTelephone other = (TestTelephone) obj; + if (number == null) { + if (other.number != null) + return false; + } else if (!number.equals(other.number)) + return false; + return true; + } + + + +} diff --git a/src/test/java/kehio/toRDF/datatype/tests/DatatypeCollectionTest.java b/src/test/java/kehio/toRDF/datatype/tests/DatatypeCollectionTest.java new file mode 100644 index 0000000..7488224 --- /dev/null +++ b/src/test/java/kehio/toRDF/datatype/tests/DatatypeCollectionTest.java @@ -0,0 +1,433 @@ +package kehio.toRDF.datatype.tests; + +import java.io.ByteArrayInputStream; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Deque; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.SortedSet; +import java.util.TreeSet; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.sparql.vocabulary.FOAF; +import org.junit.Assert; +import org.junit.Test; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfId; +import kehio.mapper.Kehio; + +public class DatatypeCollectionTest { + + private static final String OUTPUT = " \"21\" , \"42\"^^ , \"32\"^^ , \"12\"^^ , \"20\" , \"31\"^^ , \"11\"^^ , \"41\"^^ ;\n" + + " \"text 12\"@en , \"Texto@algo mas 21\"@es , \"Text@ 21\"@en , \"text 11\"@en ."; + private static Model expectedModel = ModelFactory.createDefaultModel(); + static { + expectedModel.read(new ByteArrayInputStream(OUTPUT.getBytes()), null, "Turtle"); + } + + @Test + public void testDatatype1() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection1 testingObject = new ORMTestDtypeCollection1(); + Model model = Kehio.deserializeClass(testingObject); + Assert.assertTrue(expectedModel.containsAll(model)); + } + + @Test + public void testDatatype2() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection2 testingObject = new ORMTestDtypeCollection2(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + } catch (Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + @Test + public void testDatatype3() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection3 testingObject = new ORMTestDtypeCollection3(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + } catch (Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + @Test + public void testDatatype4() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection4 testingObject = new ORMTestDtypeCollection4(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + } catch (Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + @Test + public void testDatatype5() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection5 testingObject = new ORMTestDtypeCollection5(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + } catch (Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + @Test + public void testDatatype6() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection6 testingObject = new ORMTestDtypeCollection6(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + } catch (Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + @Test + public void testDatatype7() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection7 testingObject = new ORMTestDtypeCollection7(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + } catch (Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + @Test + public void testDatatype8() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection8 testingObject = new ORMTestDtypeCollection8(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, ResourceFactory.createPlainLiteral("1")); + Assert.assertTrue(correct); + } + + @Test + public void testDatatype9() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection9 testingObject = new ORMTestDtypeCollection9(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, + ResourceFactory.createLangLiteral("1", "http://www.w3.org/2001/XMLSchema#double")); + Assert.assertTrue(correct); + } + + @Test + public void testDatatype10() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection10 testingObject = new ORMTestDtypeCollection10(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, ResourceFactory.createPlainLiteral("1")); + Assert.assertTrue(correct); + } + + @Test + public void testDatatype11() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection11 testingObject = new ORMTestDtypeCollection11(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, ResourceFactory.createPlainLiteral("1")); + Assert.assertTrue(correct); + } + + @Test + public void testDatatype12() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection12 testingObject = new ORMTestDtypeCollection12(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, ResourceFactory.createPlainLiteral("1")); + Assert.assertTrue(correct); + } + + @Test + public void testDatatype13() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection13 testingObject = new ORMTestDtypeCollection13(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, ResourceFactory.createPlainLiteral("1")); + Assert.assertTrue(correct); + } + + @Test + public void testDatatype14() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection14 testingObject = new ORMTestDtypeCollection14(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, ResourceFactory.createPlainLiteral("1")); + Assert.assertTrue(correct); + } + + @Test + public void testDatatype15() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection15 testingObject = new ORMTestDtypeCollection15(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, ResourceFactory.createPlainLiteral("1")); + Assert.assertTrue(correct); + } + + + @Test + public void testDatatype16() + throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection16 testingObject = new ORMTestDtypeCollection16(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, ResourceFactory.createPlainLiteral("1")); + Assert.assertTrue(correct); + } + + @Test + public void testDatatype17() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtypeCollection17 testingObject = new ORMTestDtypeCollection17(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + } catch (Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + +} + +class ORMTestDtypeCollection1 { + // Ok + @RdfId + public String id = "http://example-instance.com/resource"; + + @RdfDatatype("http://xmlns.com/foaf/0.1/age") + public Collection age_1 = new ArrayList<>(); + + @RdfDatatype("http://xmlns.com/foaf/0.1/age") + public Collection age_2 = new ArrayList<>(); + + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", datatype = "http://www.w3.org/2001/XMLSchema#int") + public Collection age_3 = new ArrayList<>(); + + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", sinkDatatype = true) + public Collection age_4 = new ArrayList<>(); + + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/text", lang = "en") + public Collection text_1 = new ArrayList<>(); + + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/text", sinkLang = true) + public Collection text_2 = new ArrayList<>(); + + public ORMTestDtypeCollection1() { + age_1.add(11); + age_1.add(12); + age_2.add("20"); + age_2.add("21"); + age_3.add("31"); + age_3.add("32"); + age_4.add("41^^"); + age_4.add("42^^"); + text_1.add("text 11"); + text_1.add("text 12"); + text_2.add("Text@ 21@en"); + text_2.add("Texto@algo mas 21@es"); + } +} + +class ORMTestDtypeCollection2 { + // Exception + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", datatype = "http://www.w3.org/2001/XMLSchema#double", sinkLang = true) + public Collection age_1 = new ArrayList<>(); + + public ORMTestDtypeCollection2() { + age_1.add("1@en"); + age_1.add("2@en"); + } + +} + +class ORMTestDtypeCollection3 { + // Exception + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", datatype = "http://www.w3.org/2001/XMLSchema#double", sinkDatatype = true) + public Collection age_1 = new ArrayList<>(); + + public ORMTestDtypeCollection3() { + age_1.add("1^^http://www.w3.org/2001/XMLSchema#double"); + age_1.add("2^^http://www.w3.org/2001/XMLSchema#double"); + } +} + +class ORMTestDtypeCollection4 { + // Exception + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", lang = "en", sinkDatatype = true) + public Collection age_1 = new ArrayList<>(); + + public ORMTestDtypeCollection4() { + age_1.add("1^^http://www.w3.org/2001/XMLSchema#double"); + age_1.add("2^^http://www.w3.org/2001/XMLSchema#double"); + } +} + +class ORMTestDtypeCollection5 { + // Exception + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", lang = "en", sinkLang = true) + public Collection age_1 = new ArrayList<>(); + + public ORMTestDtypeCollection5() { + age_1.add("1@en"); + age_1.add("1@en"); + } +} + +class ORMTestDtypeCollection6 { + // Exception + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", datatype = "http://www.w3.org/2001/XMLSchema#double", lang = "en") + public Collection age_1 = new ArrayList<>(); + + public ORMTestDtypeCollection6() { + age_1.add("1"); + age_1.add("1"); + } +} + +class ORMTestDtypeCollection7 { + // Exception + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", sinkDatatype = true, sinkLang = true) + public Collection age_1 = new ArrayList<>(); + + public ORMTestDtypeCollection7() { + age_1.add("1"); + age_1.add("1"); + } +} + +class ORMTestDtypeCollection8 { + // Ok + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", datatype = "es") + public Collection age_1 = new ArrayList<>(); + + public ORMTestDtypeCollection8() { + age_1.add("1"); + age_1.add("1"); + } +} + +class ORMTestDtypeCollection9 { + // Ok + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", lang = "http://www.w3.org/2001/XMLSchema#double") + public Collection age_1 = new ArrayList<>(); + + public ORMTestDtypeCollection9() { + age_1.add("1"); + age_1.add("1"); + } +} + +class ORMTestDtypeCollection10 { + // Ok + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", lang = " ") + public Collection age_1 = new ArrayList<>(); + + public ORMTestDtypeCollection10() { + age_1.add("1"); + age_1.add("1"); + } +} + +class ORMTestDtypeCollection11 { + // Ok + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", datatype = " ") + public Collection age_1 = new ArrayList<>(); + + public ORMTestDtypeCollection11() { + age_1.add("1"); + age_1.add("1"); + } +} + +class ORMTestDtypeCollection12 { + // Ok + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", datatype = " ") + public List age_1 = new ArrayList<>(); + + public ORMTestDtypeCollection12() { + age_1.add("1"); + age_1.add("1"); + } +} + +class ORMTestDtypeCollection13 { + // Ok + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", datatype = " ") + public Queue age_1 = new LinkedList<>(); + + public ORMTestDtypeCollection13() { + age_1.add("1"); + age_1.add("1"); + } +} + +class ORMTestDtypeCollection14 { + // Ok + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", datatype = " ") + public List age_1 = new LinkedList<>(); + + public ORMTestDtypeCollection14() { + age_1.add("1"); + age_1.add("1"); + } +} + +class ORMTestDtypeCollection15 { + // Ok + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", datatype = " ") + public Deque age_1 = new LinkedList<>(); + + public ORMTestDtypeCollection15() { + age_1.add("1"); + age_1.add("1"); + } +} + +class ORMTestDtypeCollection16 { + // Ok + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", datatype = " ") + public SortedSet age_1 = new TreeSet<>(); + + public ORMTestDtypeCollection16() { + age_1.add("1"); + age_1.add("1"); + } +} + +class ORMTestDtypeCollection17 { + // Exception + @RdfDatatype(value = "http://xmlns.com/foaf/0.1/age", datatype = " ") + public Map age_1 = new HashMap<>(); + + public ORMTestDtypeCollection17() { + age_1.put("1","1"); + age_1.put("1","1"); + } +} \ No newline at end of file diff --git a/src/test/java/kehio/toRDF/datatype/tests/DatatypeGroupTest.java b/src/test/java/kehio/toRDF/datatype/tests/DatatypeGroupTest.java new file mode 100644 index 0000000..f20bf7b --- /dev/null +++ b/src/test/java/kehio/toRDF/datatype/tests/DatatypeGroupTest.java @@ -0,0 +1,61 @@ +package kehio.toRDF.datatype.tests; + +import java.net.URISyntaxException; + +import org.apache.jena.rdf.model.Model; +import org.junit.Assert; +import org.junit.Test; + +import kehio.mapper.Kehio; +import kehio.models.test.TestPost1; +import kehio.models.test.TestPost2; +import kehio.models.test.TestPost3; +import kehio.models.test.TestPost4; + +public class DatatypeGroupTest { + + + + @Test + public void testDatatype1() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + TestPost1 testingObject = new TestPost1(true); + Model model = Kehio.deserializeClass(testingObject); + Assert.assertTrue(TestPost1.expectedModel.getGraph().isIsomorphicWith(model.getGraph())); + } + + @Test + public void testDatatype2() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + TestPost2 testingObject = new TestPost2(true); + Model model = Kehio.deserializeClass(testingObject); + Assert.assertTrue(TestPost2.expectedModel.getGraph().isIsomorphicWith(model.getGraph())); + } + + + @Test + public void testDatatype3() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + Boolean correct = false; + try { + TestPost3 testingObject = new TestPost3(true); + Kehio.deserializeClass(testingObject); + }catch(Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + + @Test + public void testDatatype4() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + Boolean correct = false; + try { + TestPost4 testingObject = new TestPost4(true); + Kehio.deserializeClass(testingObject); + }catch(Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + + +} \ No newline at end of file diff --git a/src/test/java/kehio/toRDF/datatype/tests/DatatypeTest.java b/src/test/java/kehio/toRDF/datatype/tests/DatatypeTest.java new file mode 100644 index 0000000..92d7787 --- /dev/null +++ b/src/test/java/kehio/toRDF/datatype/tests/DatatypeTest.java @@ -0,0 +1,225 @@ +package kehio.toRDF.datatype.tests; + +import java.io.ByteArrayInputStream; +import java.net.URISyntaxException; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.sparql.vocabulary.FOAF; +import org.junit.Assert; +import org.junit.Test; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfId; +import kehio.mapper.Kehio; + +public class DatatypeTest { + + private static final String OUTPUT = " \"4\"^^ , \"3\"^^, \"2\", \"1\"^^ ;\n" + + " \"Text@ 2\"@en , \"Text 1\"@en ."; + private static Model expectedModel = ModelFactory.createDefaultModel(); + static{ + expectedModel.read(new ByteArrayInputStream(OUTPUT.getBytes()), null, "Turtle"); + } + + @Test + public void testDatatype1() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtype1 testingObject = new ORMTestDtype1(); + Model model = Kehio.deserializeClass(testingObject); + Assert.assertTrue(expectedModel.containsAll(model)); + } + + @Test + public void testDatatype2() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtype2 testingObject = new ORMTestDtype2(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + }catch(Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + @Test + public void testDatatype3() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtype3 testingObject = new ORMTestDtype3(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + }catch(Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + @Test + public void testDatatype4() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtype4 testingObject = new ORMTestDtype4(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + }catch(Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + @Test + public void testDatatype5() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtype5 testingObject = new ORMTestDtype5(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + }catch(Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + @Test + public void testDatatype6() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtype6 testingObject = new ORMTestDtype6(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + }catch(Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + @Test + public void testDatatype7() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtype7 testingObject = new ORMTestDtype7(); + Boolean correct = false; + try { + Kehio.deserializeClass(testingObject); + }catch(Exception e) { + correct = true; + } + Assert.assertTrue(correct); + } + + @Test + public void testDatatype8() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtype8 testingObject = new ORMTestDtype8(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, ResourceFactory.createPlainLiteral("1")); + Assert.assertTrue(correct); + } + @Test + public void testDatatype9() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtype9 testingObject = new ORMTestDtype9(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, ResourceFactory.createLangLiteral("1","http://www.w3.org/2001/XMLSchema#double")); + Assert.assertTrue(correct); + } + @Test + public void testDatatype10() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtype10 testingObject = new ORMTestDtype10(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, ResourceFactory.createPlainLiteral("1")); + Assert.assertTrue(correct); + } + @Test + public void testDatatype11() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestDtype11 testingObject = new ORMTestDtype11(); + Model model = Kehio.deserializeClass(testingObject); + boolean correct = model.contains(null, FOAF.age, ResourceFactory.createPlainLiteral("1")); + Assert.assertTrue(correct); + } + +} + +class ORMTestDtype1 { + + public ORMTestDtype1() { + + } + + // Ok + @RdfId + public String id = "http://example-instance.com/resource"; + + @RdfDatatype("http://xmlns.com/foaf/0.1/age") + public Integer age_1 = 1; + + @RdfDatatype("http://xmlns.com/foaf/0.1/age") + public String age_2 = "2"; + + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", datatype="http://www.w3.org/2001/XMLSchema#int") + public String age_3= "3"; + + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", sinkDatatype=true) + public String age_4 = "4^^"; + + @RdfDatatype(value="http://xmlns.com/foaf/0.1/text", lang="en") + public String text_1 = "Text 1"; + + @RdfDatatype(value="http://xmlns.com/foaf/0.1/text", sinkLang=true) + public String text_2 = "Text@ 2@en"; + +} + +class ORMTestDtype2 { + // Exception + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", datatype="http://www.w3.org/2001/XMLSchema#double", sinkLang=true) + public String age_1 = "1@en"; +} + +class ORMTestDtype3 { + // Exception + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", datatype="http://www.w3.org/2001/XMLSchema#double", sinkDatatype=true) + public String age_1 = "1^^http://www.w3.org/2001/XMLSchema#double"; +} + + +class ORMTestDtype4 { + // Exception + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", lang="en", sinkDatatype=true) + public String age_1 = "1^^http://www.w3.org/2001/XMLSchema#double"; +} + +class ORMTestDtype5 { + // Exception + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", lang="en", sinkLang=true) + public String age_1 = "1@en"; +} + +class ORMTestDtype6 { + // Exception + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", datatype="http://www.w3.org/2001/XMLSchema#double", lang="en") + public String age_1 = "1"; +} + +class ORMTestDtype7 { + // Exception + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", sinkDatatype=true, sinkLang=true) + public String age_1 = "1"; +} + +class ORMTestDtype8 { + // Ok + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", datatype="es") + public String age_1 = "1"; +} + +class ORMTestDtype9 { + // Ok + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", lang="http://www.w3.org/2001/XMLSchema#double") + public String age_1 = "1"; +} + +class ORMTestDtype10 { + // Ok + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", lang=" ") + public String age_1 = "1"; +} + +class ORMTestDtype11 { + // Ok + @RdfDatatype(value="http://xmlns.com/foaf/0.1/age", datatype=" ") + public String age_1 = "1"; +} \ No newline at end of file diff --git a/src/test/java/kehio/toRDF/datatype/tests/IdTest.java b/src/test/java/kehio/toRDF/datatype/tests/IdTest.java new file mode 100644 index 0000000..57d6459 --- /dev/null +++ b/src/test/java/kehio/toRDF/datatype/tests/IdTest.java @@ -0,0 +1,155 @@ +package kehio.toRDF.datatype.tests; + +import java.io.ByteArrayInputStream; +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.sparql.vocabulary.FOAF; +import org.junit.Test; + +import org.junit.Assert; + +import kehio.annotations.RdfDatatype; +import kehio.annotations.RdfId; +import kehio.mapper.Kehio; + +public class IdTest { + + private static final String OUTPUT = " \"test\" ."; + private static Model expectedModel = ModelFactory.createDefaultModel(); + static{ + expectedModel.read(new ByteArrayInputStream(OUTPUT.getBytes()), null, "Turtle"); + } + + @Test + public void testId1() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestId1 testingObject = new ORMTestId1(); + Model model = Kehio.deserializeClass(testingObject); + Assert.assertTrue(expectedModel.containsAll(model)); + } + + @Test + public void testId2() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestId2 testingObject = new ORMTestId2(); + Model model = Kehio.deserializeClass(testingObject); + Assert.assertTrue(expectedModel.containsAll(model)); + } + + @Test + public void testId3() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestId3 testingObject = new ORMTestId3(); + Model model = Kehio.deserializeClass(testingObject); + Resource subject = model.listSubjectsWithProperty(FOAF.name, "test").next(); + Assert.assertTrue(subject.isAnon() && model.contains(null, FOAF.name, "test")); + } + + @Test + public void testId4() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestId4 testingObject = new ORMTestId4(); + Model model = Kehio.deserializeClass(testingObject); + Resource subject = model.listSubjectsWithProperty(FOAF.name, "test").next(); + Assert.assertTrue(subject.isAnon() && model.contains(null, FOAF.name, "test")); + } + + @Test + public void testId5() { + ORMTestId5 testingObject = new ORMTestId5(); + Boolean test = false; + try { + Model model = Kehio.deserializeClass(testingObject); + model.write(System.out, "Turtle"); + }catch(Exception e) { + test = true; + } + Assert.assertTrue(test); + } + + @Test + public void testId6() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestId6 testingObject = new ORMTestId6(); + Model model = Kehio.deserializeClass(testingObject); + Resource subject = model.listSubjectsWithProperty(FOAF.name, "test").next(); + Assert.assertTrue(subject.isAnon() && model.contains(null, FOAF.name, "test")); + } + + @Test + public void testId7() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + ORMTestId7 testingObject = new ORMTestId7(); + Boolean test = false; + try { + Model model = Kehio.deserializeClass(testingObject); + model.write(System.out, "Turtle"); + }catch(Exception e) { + test = true; + } + Assert.assertTrue(test); + } + +} + +class ORMTestId1 { + // Ok + @RdfId + public String id = "http://example-instance.com/resource"; + @RdfDatatype(value="http://xmlns.com/foaf/0.1/name") + public String test = "test"; +} + +class ORMTestId2 { + // Ok + @RdfId + public URI id; + @RdfDatatype(value="http://xmlns.com/foaf/0.1/name") + public String test = "test"; + public ORMTestId2() { + try { + id = new URI("http://example-instance.com/resource"); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + } +} + +class ORMTestId3 { + // Ok + @RdfId + public URI id; + @RdfDatatype(value="http://xmlns.com/foaf/0.1/name") + public String test = "test"; +} + +class ORMTestId4 { + // Ok + @RdfId + public String id; + @RdfDatatype(value="http://xmlns.com/foaf/0.1/name") + public String test = "test"; +} + +class ORMTestId5 { + // Exception + @RdfId + public Integer id; + @RdfDatatype(value="http://xmlns.com/foaf/0.1/name") + public String test = "test"; +} + +class ORMTestId6 { + // Ok + @RdfDatatype(value="http://xmlns.com/foaf/0.1/name") + public String test = "test"; +} + +class ORMTestId7 { + // Exception + @RdfId + public String id_1 = "http://example-instance.com/resource"; + @RdfId + public URI id_2; + + @RdfDatatype(value="http://xmlns.com/foaf/0.1/name") + public String test = "test"; +} diff --git a/src/test/java/kehio/toRDF/datatype/tests/ObjectTest.java b/src/test/java/kehio/toRDF/datatype/tests/ObjectTest.java new file mode 100644 index 0000000..0ebddd5 --- /dev/null +++ b/src/test/java/kehio/toRDF/datatype/tests/ObjectTest.java @@ -0,0 +1,60 @@ +package kehio.toRDF.datatype.tests; + +import java.io.ByteArrayInputStream; +import java.net.URISyntaxException; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.junit.Assert; +import org.junit.Test; + +import kehio.mapper.Kehio; +import kehio.models.test.TestPerson1; +import kehio.models.test.TestPerson2; + +public class ObjectTest { + + + private static final String TEST1 = "[ \n" + + " \"John\" ;\n" + + " \n" + + " [ \n" + + " \"+34 54 65 23\" ] ;\n" + + " \n" + + " \"Fold\" , \"Doe\"\n" + + "] ."; + + + @Test + public void test1() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + TestPerson1 person = new TestPerson1(true); + Model model = Kehio.deserializeClass(person); + Model expectedModel = ModelFactory.createDefaultModel(); + expectedModel.read(new ByteArrayInputStream(TEST1.getBytes()), null, "Turtle"); + Assert.assertTrue(expectedModel.getGraph().isIsomorphicWith(model.getGraph())); + } + + private static final String TEST2 = "[ \n" + + " \"John\" ;\n" + + " \n" + + " [ \n" + + " \"+34 54 65 23\" ] ;\n" + + " \n" + + " [ \n" + + " \"+34 54 65 23\" ] ;\n" + + " \n" + + " \"Fold\" , \"Doe\"\n" + + "] ."; + + @Test + public void test2() throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException, URISyntaxException { + TestPerson2 person = new TestPerson2(true); + Model model = Kehio.deserializeClass(person); + Model expectedModel = ModelFactory.createDefaultModel(); + expectedModel.read(new ByteArrayInputStream(TEST2.getBytes()), null, "Turtle"); + + Assert.assertTrue(expectedModel.getGraph().isIsomorphicWith(model.getGraph())); + } + + +} + diff --git a/src/test/java/wot/jdt/tds/json_ld/LinkSmartTest.java b/src/test/java/wot/jdt/tds/json_ld/LinkSmartTest.java deleted file mode 100755 index 4bca08f..0000000 --- a/src/test/java/wot/jdt/tds/json_ld/LinkSmartTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package wot.jdt.tds.json_ld; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.Scanner; -import org.apache.jena.query.ARQ; -import org.apache.jena.sparql.mgt.Explain.InfoLevel; -import org.junit.Assert; -import org.junit.Test; - -import com.apicatalog.jsonld.JsonLdError; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; -import com.google.gson.JsonObject; - -import wot.jtd.JTD; -import wot.jtd.model.Thing; - -public class LinkSmartTest { - - - - @Test - public void test1() throws JsonProcessingException, JsonLdError { - ARQ.setExecutionLogging(InfoLevel.NONE); - JTD.setShowExternalValuesWarnings(false); - JsonObject td = readJsonFile(new File("./src/test/resources/linksmart/td-1.json")); - - Thing thing = null; - try { - thing = Thing.fromJson(td); - }catch (UnrecognizedPropertyException e) { - e.printStackTrace(); - }catch(Exception e) { - e.printStackTrace(); - } - - Assert.assertTrue(thing!=null && thing.isEquivalent(td)); - - } - - - private static JsonObject readJsonFile(File myObj) { - StringBuilder builder = new StringBuilder(); - try { - Scanner myReader = new Scanner(myObj); - while (myReader.hasNextLine()) { - String data = myReader.nextLine(); - builder.append(data); - } - myReader.close(); - } catch (FileNotFoundException e) { - System.out.println("An error occurred."); - e.printStackTrace(); - } - return JTD.parseJson(builder.toString()); - } - -} diff --git a/src/test/java/wot/jdt/tds/rdf/LinkSmartTest.java b/src/test/java/wot/jdt/tds/rdf/LinkSmartTest.java deleted file mode 100755 index 2330ba6..0000000 --- a/src/test/java/wot/jdt/tds/rdf/LinkSmartTest.java +++ /dev/null @@ -1,97 +0,0 @@ -package wot.jdt.tds.rdf; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.HashMap; -import java.util.Scanner; - -import org.apache.jena.graph.Graph; -import org.apache.jena.query.ARQ; -import org.apache.jena.rdf.model.Model; - -import org.apache.jena.rdf.model.ModelFactory; -import org.apache.jena.sparql.mgt.Explain.InfoLevel; -import org.junit.Assert; -import org.junit.Test; - -import com.apicatalog.jsonld.JsonLdError; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; -import com.google.gson.JsonObject; - -import thewebsemantic.Bean2RDF; -import wot.jtd.JTD; -import wot.jtd.RDFHandler; -import wot.jtd.model.Thing; -import wot.jtd.model.VersionInfo; - -public class LinkSmartTest { - - - - @Test - public void test1() throws JsonProcessingException, JsonLdError { - JTD.setShowExternalValuesWarnings(false); - JsonObject td = readJsonFile(new File("./src/test/resources/linksmart/td-1.json")); - JsonObject instance = new JsonObject(); - instance.addProperty("instance", "1.2.3"); - td.add("version", instance); - Model modelTD = JTD.toRDF(td); - Thing thing = null; - try { - //modelTD.write(System.out, "TURTLE"); - //thing = JTD.fromRDF(modelTD); - //JTD.fromRDF(modelTD); - ObjectMapper mapper = new ObjectMapper(); - - //VersionInfo version = RDFMapper.create().readValue(modelTD, VersionInfo.class.getClass()); - - VersionInfo test = new VersionInfo(); - test.setInstance("3.21"); - /*org.eclipse.rdf4j.model.Model aGraph = RDFMapper.create().writeValue(test); - aGraph.forEach(st -> System.out.println(st.getSubject()+" "+ st.getPredicate()+" "+st.getObject())); - - ValueFactory vf = SimpleValueFactory.getInstance(); - IRI subject = vf.createIRI("tag:complexible:pinto:af626ae3c3aee94a4b3199d0392c5cf8"); - IRI pred = vf.createIRI("http://www.w3.org/2011/http#method"); - Literal obj = vf.createLiteral("GET"); - IRI graph = null; - aGraph.add(subject, pred, obj, graph); - IRI objectType = vf.createIRI("https://www.w3.org/2019/wot/td#VersionInfo"); - aGraph.remove(subject, RDF.TYPE, objectType, graph); - System.out.println("_--------------------__"); - aGraph.forEach(st -> System.out.println(st.getSubject()+" "+ st.getPredicate()+" "+st.getObject())); - - VersionInfo version = RDFMapper.create().readValue(aGraph, VersionInfo.class); - System.out.println(version.toJson());*/ - - RDFHandler.serialize(); - - }catch(Exception e) { - e.printStackTrace(); - } - - - Assert.assertTrue(thing!=null && thing.isEquivalent(td)); - - } - - private static JsonObject readJsonFile(File myObj) { - StringBuilder builder = new StringBuilder(); - try { - Scanner myReader = new Scanner(myObj); - while (myReader.hasNextLine()) { - String data = myReader.nextLine(); - builder.append(data); - } - myReader.close(); - } catch (FileNotFoundException e) { - System.out.println("An error occurred."); - e.printStackTrace(); - } - return JTD.parseJson(builder.toString()); - } - -} diff --git a/src/test/java/wot/jdt/tds/tests/JSONLinkSmartTest.java b/src/test/java/wot/jdt/tds/tests/JSONLinkSmartTest.java new file mode 100755 index 0000000..2a2b9d8 --- /dev/null +++ b/src/test/java/wot/jdt/tds/tests/JSONLinkSmartTest.java @@ -0,0 +1,459 @@ +package wot.jdt.tds.tests; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Scanner; +import org.apache.jena.query.ARQ; +import org.apache.jena.sparql.mgt.Explain.InfoLevel; +import org.junit.Assert; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; +import com.google.gson.JsonObject; + +import wot.jtd.JTD; +import wot.jtd.JsonHandler; +import wot.jtd.model.Thing; + +/** + * These tests read the TDs provided by LinkSmart. Each test parses from a file a {@link JsonObject}, then such JSON is parsed as a {@link Thing}, finally the original {@link JsonObject} is compared with the {@link Thing} translated into a {@link JsonObject}. + * The test prove that any JSON-LD framed parsed into a Thing can be translated back. + * @author Andrea Cimmino + * + */ +public class JSONLinkSmartTest { + + static { + ARQ.setExecutionLogging(InfoLevel.NONE); + } + + private boolean performGenericTest(String file) throws JsonProcessingException { + JsonObject td = readJsonFile(new File(file)); + JsonHandler.compactArrays(td); + Thing thing = null; + try { + thing = Thing.fromJson(td); + } catch (UnrecognizedPropertyException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + + return thing != null && JsonHandler.compareJson(thing.toJson(), td); + } + + private static JsonObject readJsonFile(File myObj) { + StringBuilder builder = new StringBuilder(); + try { + Scanner myReader = new Scanner(myObj); + while (myReader.hasNextLine()) { + String data = myReader.nextLine(); + builder.append(data); + } + myReader.close(); + } catch (FileNotFoundException e) { + System.out.println("An error occurred."); + e.printStackTrace(); + } + return JTD.parseJson(builder.toString()); + } + + @Test + public void test0() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-0.json"); + Assert.assertTrue(testResult); + } + + + @Test + public void test1() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-1.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test2() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-2.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test3() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-3.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test4() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-4.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test5() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-5.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test6() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-6.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test7() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-7.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test8() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-8.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test9() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-9.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test10() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-10.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test11() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-11.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test12() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-12.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test13() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-13.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test14() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-14.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test15() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-15.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test16() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-16.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test17() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-17.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test18() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-18.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test19() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-19.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test20() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-20.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test21() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-21.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test22() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-22.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test23() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-23.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test24() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-24.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test25() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-25.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test26() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-26.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test27() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-27.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test28() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-28.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test29() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-29.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test30() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-30.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test31() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-31.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test32() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-32.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test33() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-33.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test34() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-34.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test35() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-35.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test36() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-36.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test37() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-37.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test38() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-38.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test39() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-39.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test40() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-40.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test41() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-41.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test42() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-42.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test43() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-43.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test44() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-44.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test45() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-45.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test46() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-46.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test47() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-47.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test48() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-48.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test49() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-49.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test50() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-50.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test51() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-51.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test52() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-52.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test53() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-53.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test54() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-54.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test55() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-55.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test56() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-56.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test57() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-57.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test58() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-58.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test59() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-59.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test60() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-60.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test61() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-61.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test62() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-62.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test63() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-63.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test64() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-64.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test65() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-65.json"); + Assert.assertTrue(testResult); + } + +} diff --git a/src/test/java/wot/jdt/tds/tests/JSONWoTTest.java b/src/test/java/wot/jdt/tds/tests/JSONWoTTest.java new file mode 100644 index 0000000..07a84bd --- /dev/null +++ b/src/test/java/wot/jdt/tds/tests/JSONWoTTest.java @@ -0,0 +1,237 @@ +package wot.jdt.tds.tests; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Scanner; +import org.junit.Assert; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; +import com.google.gson.JsonObject; + +import wot.jtd.JTD; +import wot.jtd.JsonHandler; +import wot.jtd.model.Thing; + +public class JSONWoTTest { + + + + private boolean performGenericTest(String file) throws JsonProcessingException { + JsonObject td = readJsonFile(new File(file)); + JsonHandler.compactArrays(td); + Thing thing = null; + + try { + thing = Thing.fromJson(td); + + } catch (UnrecognizedPropertyException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + + return thing != null && JsonHandler.compareJson(td, thing.toJson()); + } + + private static JsonObject readJsonFile(File myObj) { + StringBuilder builder = new StringBuilder(); + try { + Scanner myReader = new Scanner(myObj); + while (myReader.hasNextLine()) { + String data = myReader.nextLine(); + builder.append(data); + } + myReader.close(); + } catch (FileNotFoundException e) { + System.out.println("An error occurred."); + e.printStackTrace(); + } + return JTD.parseJson(builder.toString()); + } + + @Test + public void test1() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-1.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test2() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-2.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test3() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-3.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test6() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-6.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test7() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-7.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test8() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-8.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test9() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-9.json"); + Assert.assertTrue(testResult); + } + + + + @Test + public void test11() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-11.json"); + Assert.assertTrue(testResult); + } + + + + @Test + public void test13() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-13.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test14() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-14.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test15() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-15.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test16() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-16.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test17() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-17.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test18() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-18.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test19() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-19.json"); + Assert.assertTrue(testResult); + } + + + + @Test + public void test20() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-20.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test21() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-21.json"); + Assert.assertTrue(testResult); + } + + + @Test + public void test23() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-23.json"); + Assert.assertTrue(testResult); + } + @Test + public void test24() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-24.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test25() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-25.json"); + Assert.assertTrue(testResult); + } + @Test + public void test26() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-26.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test28() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-28.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test29() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-29.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test30() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-30.json"); + Assert.assertTrue(testResult); + } + @Test + public void test31() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-31.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test32() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-32.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test33() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-33.json"); + Assert.assertTrue(testResult); + } + @Test + public void test34() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-34.json"); + Assert.assertTrue(testResult); + } + @Test + public void test35() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-35.json"); + Assert.assertTrue(testResult); + } + + + @Test + public void test36() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-36.json"); + Assert.assertTrue(testResult); + } + +} diff --git a/src/test/java/wot/jdt/tds/tests/LinkSmartToRdfTest.java b/src/test/java/wot/jdt/tds/tests/LinkSmartToRdfTest.java new file mode 100644 index 0000000..8c4cf7f --- /dev/null +++ b/src/test/java/wot/jdt/tds/tests/LinkSmartToRdfTest.java @@ -0,0 +1,504 @@ +package wot.jdt.tds.tests; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.Scanner; + +import org.apache.jena.graph.Graph; +import org.apache.jena.query.ARQ; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.riot.Lang; +import org.apache.jena.riot.RDFDataMgr; +import org.apache.jena.shacl.ShaclValidator; +import org.apache.jena.shacl.Shapes; +import org.apache.jena.shacl.ValidationReport; +import org.apache.jena.shacl.lib.ShLib; +import org.apache.jena.sparql.mgt.Explain.InfoLevel; +import org.junit.Assert; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; +import com.google.gson.JsonObject; + +import kehio.mapper.Kehio; +import wot.jtd.JTD; +import wot.jtd.JsonHandler; +import wot.jtd.model.Thing; + +public class LinkSmartToRdfTest { + + static { + ARQ.setExecutionLogging(InfoLevel.NONE); + } + + private boolean performGenericTest(String file) throws JsonProcessingException { + JsonObject td = readJsonFile(new File(file)); + Thing thing = null; + Thing thingFromRDF = null; + try { + thing = Thing.fromJson(td); + Model generatedModel = JTD.toRDF(td); + //generatedModel.write(System.out, "Turtle"); + applyShape(generatedModel.getGraph()); + thingFromRDF = JTD.fromRDF(generatedModel).get(0); + thingFromRDF.setContext(thing.getContext()); + } catch (UnrecognizedPropertyException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println(thingFromRDF.toJson()); + System.out.println(thing.toJson()); + Boolean sameModels = thing != null && thingFromRDF != null && JsonHandler.compareJson(thing.toJson(), thingFromRDF.toJson()) && thing.equals(thingFromRDF) ; + return sameModels; + } + + private static void applyShape(Graph dataGraph) { + Graph shapesGraph = RDFDataMgr.loadGraph("https://raw.githubusercontent.com/w3c/wot-thing-description/main/validation/td-validation.ttl", Lang.TURTLE); + Shapes shapes = Shapes.parse(shapesGraph); + ValidationReport report = ShaclValidator.get().validate(shapes, dataGraph); + System.out.println(report.conforms()); + ShLib.printReport(report); + System.out.println(); + RDFDataMgr.write(System.out, report.getModel(), Lang.TTL); + System.out.println("_------"); + } + + + private static JsonObject readJsonFile(File myObj) { + StringBuilder builder = new StringBuilder(); + try { + Scanner myReader = new Scanner(myObj); + while (myReader.hasNextLine()) { + String data = myReader.nextLine(); + builder.append(data); + } + myReader.close(); + } catch (FileNotFoundException e) { + System.out.println("An error occurred."); + e.printStackTrace(); + } + + return JTD.parseJson(builder.toString()); + } + + + @Test + public void test0() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-0-0.json"); + Assert.assertTrue(testResult); + } + /* + @Test + public void test1() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-1.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test2() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-2.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test3() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-3.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test4() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-4.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test5() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-5.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test6() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-6.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test7() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-7.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test8() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-8.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test9() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-9.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test10() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-10.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test11() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-11.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test12() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-12.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test13() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-13.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test14() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-14.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test15() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-15.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test16() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-16.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test17() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-17.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test18() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-18.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test19() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-19.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test20() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-20.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test21() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-21.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test22() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-22.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test23() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-23.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test24() throws JsonProcessingException { + Boolean testResult = false; + try { + performGenericTest("./src/test/resources/linksmart/framed/td-24.json"); + }catch(Exception e) { + testResult = true; + } + Assert.assertTrue(testResult); + } + + @Test + public void test25() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-25.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test26() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-26.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test27() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-27.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test28() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-28.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test29() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-29.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test30() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-30.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test31() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-31.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test32() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-32.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test33() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-33.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test34() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-34.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test35() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-35.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test36() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-36.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test37() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-37.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test38() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-38.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test39() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-39.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test40() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-40.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test41() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-41.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test42() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-42.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test43() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-43.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test44() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-44.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test45() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-45.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test46() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-46.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test47() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-47.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test48() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-48.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test49() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-49.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test50() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-50.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test51() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-51.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test52() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-52.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test53() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-53.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test54() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-54.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test55() throws JsonProcessingException { + Boolean testResult = false; + try { + performGenericTest("./src/test/resources/linksmart/framed/td-55.json"); + }catch(Exception e) { + testResult = true; + } + Assert.assertTrue(testResult); + } + + @Test + public void test56() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-56.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test57() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-57.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test58() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-58.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test59() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-59.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test60() throws JsonProcessingException { + Boolean testResult = false; + try { + performGenericTest("./src/test/resources/linksmart/framed/td-60.json"); + }catch(Exception e) { + testResult = true; + } + Assert.assertTrue(testResult); + } + + @Test + public void test61() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-61.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test62() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-62.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test63() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-63.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test64() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-64.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test65() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/linksmart/framed/td-65.json"); + Assert.assertTrue(testResult); + } +*/ +} diff --git a/src/test/java/wot/jdt/tds/tests/RDFWoTTest.java b/src/test/java/wot/jdt/tds/tests/RDFWoTTest.java new file mode 100644 index 0000000..74e438d --- /dev/null +++ b/src/test/java/wot/jdt/tds/tests/RDFWoTTest.java @@ -0,0 +1,270 @@ +package wot.jdt.tds.tests; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Scanner; +import org.apache.jena.rdf.model.Model; +import org.junit.Assert; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; +import com.google.gson.JsonObject; +import wot.jtd.JTD; +import wot.jtd.JsonHandler; +import wot.jtd.model.Thing; + +public class RDFWoTTest { + + private boolean performGenericTest(String file) throws JsonProcessingException { + JsonObject td = readJsonFile(new File(file)); + Thing thing = null; + Thing thingFromRDF = null; + try { + thing = Thing.fromJson(td); + Model generatedModel = JTD.toRDF(td); + //generatedModel.write(System.out, "Turtle"); + thingFromRDF = JTD.fromRDF(generatedModel).get(0); + + thingFromRDF.setContext(thing.getContext()); + } catch (UnrecognizedPropertyException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + + Boolean sameModels = thing != null && thingFromRDF != null && JsonHandler.compareJson(thing.toJson(), thingFromRDF.toJson()) && thing.equals(thingFromRDF) ; + return sameModels; + } + + + + public static JsonObject readJsonFile(File myObj) { + StringBuilder builder = new StringBuilder(); + try { + Scanner myReader = new Scanner(myObj); + while (myReader.hasNextLine()) { + String data = myReader.nextLine(); + builder.append(data); + } + myReader.close(); + } catch (FileNotFoundException e) { + System.out.println("An error occurred."); + e.printStackTrace(); + } + + return JTD.parseJson(builder.toString()); + } + + @Test + public void test0() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-1.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test1() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-1.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test2() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-2.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test3() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-3.json"); + Assert.assertTrue(testResult); + } + + + + @Test + public void test6() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-6.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test7() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-7.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test8() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-8.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test9() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-9.json"); + Assert.assertTrue(testResult); + } + + + + @Test + public void test11() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-11.json"); + Assert.assertTrue(testResult); + } + + + + @Test + public void test13() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-13.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test14() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-14.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test15() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-15.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test16() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-16.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test17() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-17.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test18() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-18.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test19() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-19.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test20() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-20.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test21() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-21.json"); + Assert.assertTrue(testResult); + } + + + + @Test + public void test23() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-23.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test24() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-24.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test25() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-25.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test26() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-26.json"); + Assert.assertTrue(testResult); + } + + + @Test + public void test28() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-28.json"); + Assert.assertTrue(testResult); + } + + + @Test + public void test29() throws JsonProcessingException { + Boolean testResult = false; + try { + testResult = performGenericTest("./src/test/resources/wot/example-29.json"); + }catch(Exception e) { + System.out.println(e.toString()); + } + + Assert.assertTrue(testResult); + } + + @Test + public void test30() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-30.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test31() throws JsonProcessingException { + JTD.setArrayCompactKey("ace:scopes"); + // Json representation are equal thanks to JTD.setArrayCompactKey("ace:scopes"); that compacts unitary values for ace:scopes outside an array + // but as objects one thing will have ace:scopes as an array and another as a string value + Boolean testResult = performGenericTest("./src/test/resources/wot/example-31.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test32() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-32.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test33() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-33.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test34() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-34.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test35() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-35.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test36() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-36.json"); + Assert.assertTrue(testResult); + } + + @Test + public void test37() throws JsonProcessingException { + Boolean testResult = performGenericTest("./src/test/resources/wot/example-37.json"); + Assert.assertTrue(testResult); + } + +} diff --git a/src/test/resources/linksmart/original/tds.json b/src/test/resources/linksmart/framed/original/tds.json similarity index 100% rename from src/test/resources/linksmart/original/tds.json rename to src/test/resources/linksmart/framed/original/tds.json diff --git a/src/test/resources/linksmart/framed/td-0-0.json b/src/test/resources/linksmart/framed/td-0-0.json new file mode 100644 index 0000000..2aea85d --- /dev/null +++ b/src/test/resources/linksmart/framed/td-0-0.json @@ -0,0 +1,45 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { + "htv": "http://www.w3.org/2011/http#", + "iot": "http://iotschema.org/", + "om": "http://www.wurvoc.org/vocabularies/om-1.8/" + } + ], + "events": { + "hybridcastCompanionConnectListener": { + "data": { + "type": "object" + }, + "forms": [ + { + "contentType": "application/json", + "href": "ws://192.168.30.132:8887/antwapp/websocket", + "op": "subscribeevent" + } + ], + "properties": { + "value": { + "type": "number" + } + }, + "title": "Message is emitted.", + "titles": { + "en": "Message is emitted.", + "ja": "メッセージが送出された." + } + } + }, + "id": "URN:nhkrd:antwapp", + "modified": "2020-12-18T12:44:28.620627722Z", + "security": [ + "nosec_sc" + ], + "securityDefinitions": { + "nosec_sc": { + "scheme": "nosec" + } + }, + "title": "HybridcastConnectReceiver" +} \ No newline at end of file diff --git a/src/test/resources/linksmart/td-0.json b/src/test/resources/linksmart/framed/td-0.json similarity index 100% rename from src/test/resources/linksmart/td-0.json rename to src/test/resources/linksmart/framed/td-0.json diff --git a/src/test/resources/linksmart/td-1.json b/src/test/resources/linksmart/framed/td-1.json similarity index 100% rename from src/test/resources/linksmart/td-1.json rename to src/test/resources/linksmart/framed/td-1.json diff --git a/src/test/resources/linksmart/td-10.json b/src/test/resources/linksmart/framed/td-10.json similarity index 100% rename from src/test/resources/linksmart/td-10.json rename to src/test/resources/linksmart/framed/td-10.json diff --git a/src/test/resources/linksmart/td-11.json b/src/test/resources/linksmart/framed/td-11.json similarity index 100% rename from src/test/resources/linksmart/td-11.json rename to src/test/resources/linksmart/framed/td-11.json diff --git a/src/test/resources/linksmart/td-12.json b/src/test/resources/linksmart/framed/td-12.json similarity index 100% rename from src/test/resources/linksmart/td-12.json rename to src/test/resources/linksmart/framed/td-12.json diff --git a/src/test/resources/linksmart/td-13.json b/src/test/resources/linksmart/framed/td-13.json similarity index 100% rename from src/test/resources/linksmart/td-13.json rename to src/test/resources/linksmart/framed/td-13.json diff --git a/src/test/resources/linksmart/td-14.json b/src/test/resources/linksmart/framed/td-14.json similarity index 100% rename from src/test/resources/linksmart/td-14.json rename to src/test/resources/linksmart/framed/td-14.json diff --git a/src/test/resources/linksmart/td-15.json b/src/test/resources/linksmart/framed/td-15.json similarity index 100% rename from src/test/resources/linksmart/td-15.json rename to src/test/resources/linksmart/framed/td-15.json diff --git a/src/test/resources/linksmart/td-16.json b/src/test/resources/linksmart/framed/td-16.json similarity index 100% rename from src/test/resources/linksmart/td-16.json rename to src/test/resources/linksmart/framed/td-16.json diff --git a/src/test/resources/linksmart/td-17.json b/src/test/resources/linksmart/framed/td-17.json similarity index 100% rename from src/test/resources/linksmart/td-17.json rename to src/test/resources/linksmart/framed/td-17.json diff --git a/src/test/resources/linksmart/td-18.json b/src/test/resources/linksmart/framed/td-18.json similarity index 100% rename from src/test/resources/linksmart/td-18.json rename to src/test/resources/linksmart/framed/td-18.json diff --git a/src/test/resources/linksmart/td-19.json b/src/test/resources/linksmart/framed/td-19.json similarity index 100% rename from src/test/resources/linksmart/td-19.json rename to src/test/resources/linksmart/framed/td-19.json diff --git a/src/test/resources/linksmart/td-2.json b/src/test/resources/linksmart/framed/td-2.json similarity index 100% rename from src/test/resources/linksmart/td-2.json rename to src/test/resources/linksmart/framed/td-2.json diff --git a/src/test/resources/linksmart/td-20.json b/src/test/resources/linksmart/framed/td-20.json similarity index 100% rename from src/test/resources/linksmart/td-20.json rename to src/test/resources/linksmart/framed/td-20.json diff --git a/src/test/resources/linksmart/td-21.json b/src/test/resources/linksmart/framed/td-21.json similarity index 100% rename from src/test/resources/linksmart/td-21.json rename to src/test/resources/linksmart/framed/td-21.json diff --git a/src/test/resources/linksmart/td-22.json b/src/test/resources/linksmart/framed/td-22.json similarity index 100% rename from src/test/resources/linksmart/td-22.json rename to src/test/resources/linksmart/framed/td-22.json diff --git a/src/test/resources/linksmart/td-23.json b/src/test/resources/linksmart/framed/td-23.json similarity index 100% rename from src/test/resources/linksmart/td-23.json rename to src/test/resources/linksmart/framed/td-23.json diff --git a/src/test/resources/linksmart/td-24.json b/src/test/resources/linksmart/framed/td-24.json similarity index 100% rename from src/test/resources/linksmart/td-24.json rename to src/test/resources/linksmart/framed/td-24.json diff --git a/src/test/resources/linksmart/td-25.json b/src/test/resources/linksmart/framed/td-25.json similarity index 100% rename from src/test/resources/linksmart/td-25.json rename to src/test/resources/linksmart/framed/td-25.json diff --git a/src/test/resources/linksmart/td-26.json b/src/test/resources/linksmart/framed/td-26.json similarity index 100% rename from src/test/resources/linksmart/td-26.json rename to src/test/resources/linksmart/framed/td-26.json diff --git a/src/test/resources/linksmart/td-27.json b/src/test/resources/linksmart/framed/td-27.json similarity index 100% rename from src/test/resources/linksmart/td-27.json rename to src/test/resources/linksmart/framed/td-27.json diff --git a/src/test/resources/linksmart/td-28.json b/src/test/resources/linksmart/framed/td-28.json similarity index 100% rename from src/test/resources/linksmart/td-28.json rename to src/test/resources/linksmart/framed/td-28.json diff --git a/src/test/resources/linksmart/td-29.json b/src/test/resources/linksmart/framed/td-29.json similarity index 100% rename from src/test/resources/linksmart/td-29.json rename to src/test/resources/linksmart/framed/td-29.json diff --git a/src/test/resources/linksmart/td-3.json b/src/test/resources/linksmart/framed/td-3.json similarity index 100% rename from src/test/resources/linksmart/td-3.json rename to src/test/resources/linksmart/framed/td-3.json diff --git a/src/test/resources/linksmart/td-30.json b/src/test/resources/linksmart/framed/td-30.json similarity index 100% rename from src/test/resources/linksmart/td-30.json rename to src/test/resources/linksmart/framed/td-30.json diff --git a/src/test/resources/linksmart/td-31.json b/src/test/resources/linksmart/framed/td-31.json similarity index 100% rename from src/test/resources/linksmart/td-31.json rename to src/test/resources/linksmart/framed/td-31.json diff --git a/src/test/resources/linksmart/td-32.json b/src/test/resources/linksmart/framed/td-32.json similarity index 100% rename from src/test/resources/linksmart/td-32.json rename to src/test/resources/linksmart/framed/td-32.json diff --git a/src/test/resources/linksmart/td-33.json b/src/test/resources/linksmart/framed/td-33.json similarity index 100% rename from src/test/resources/linksmart/td-33.json rename to src/test/resources/linksmart/framed/td-33.json diff --git a/src/test/resources/linksmart/td-34.json b/src/test/resources/linksmart/framed/td-34.json similarity index 100% rename from src/test/resources/linksmart/td-34.json rename to src/test/resources/linksmart/framed/td-34.json diff --git a/src/test/resources/linksmart/td-35.json b/src/test/resources/linksmart/framed/td-35.json similarity index 100% rename from src/test/resources/linksmart/td-35.json rename to src/test/resources/linksmart/framed/td-35.json diff --git a/src/test/resources/linksmart/td-36.json b/src/test/resources/linksmart/framed/td-36.json similarity index 100% rename from src/test/resources/linksmart/td-36.json rename to src/test/resources/linksmart/framed/td-36.json diff --git a/src/test/resources/linksmart/td-37.json b/src/test/resources/linksmart/framed/td-37.json similarity index 100% rename from src/test/resources/linksmart/td-37.json rename to src/test/resources/linksmart/framed/td-37.json diff --git a/src/test/resources/linksmart/td-38.json b/src/test/resources/linksmart/framed/td-38.json similarity index 100% rename from src/test/resources/linksmart/td-38.json rename to src/test/resources/linksmart/framed/td-38.json diff --git a/src/test/resources/linksmart/td-39.json b/src/test/resources/linksmart/framed/td-39.json similarity index 100% rename from src/test/resources/linksmart/td-39.json rename to src/test/resources/linksmart/framed/td-39.json diff --git a/src/test/resources/linksmart/td-4.json b/src/test/resources/linksmart/framed/td-4.json similarity index 100% rename from src/test/resources/linksmart/td-4.json rename to src/test/resources/linksmart/framed/td-4.json diff --git a/src/test/resources/linksmart/td-40.json b/src/test/resources/linksmart/framed/td-40.json similarity index 100% rename from src/test/resources/linksmart/td-40.json rename to src/test/resources/linksmart/framed/td-40.json diff --git a/src/test/resources/linksmart/td-41.json b/src/test/resources/linksmart/framed/td-41.json similarity index 100% rename from src/test/resources/linksmart/td-41.json rename to src/test/resources/linksmart/framed/td-41.json diff --git a/src/test/resources/linksmart/td-42.json b/src/test/resources/linksmart/framed/td-42.json similarity index 100% rename from src/test/resources/linksmart/td-42.json rename to src/test/resources/linksmart/framed/td-42.json diff --git a/src/test/resources/linksmart/td-43.json b/src/test/resources/linksmart/framed/td-43.json similarity index 100% rename from src/test/resources/linksmart/td-43.json rename to src/test/resources/linksmart/framed/td-43.json diff --git a/src/test/resources/linksmart/td-44.json b/src/test/resources/linksmart/framed/td-44.json similarity index 100% rename from src/test/resources/linksmart/td-44.json rename to src/test/resources/linksmart/framed/td-44.json diff --git a/src/test/resources/linksmart/td-45.json b/src/test/resources/linksmart/framed/td-45.json similarity index 100% rename from src/test/resources/linksmart/td-45.json rename to src/test/resources/linksmart/framed/td-45.json diff --git a/src/test/resources/linksmart/td-46.json b/src/test/resources/linksmart/framed/td-46.json similarity index 100% rename from src/test/resources/linksmart/td-46.json rename to src/test/resources/linksmart/framed/td-46.json diff --git a/src/test/resources/linksmart/td-47.json b/src/test/resources/linksmart/framed/td-47.json similarity index 100% rename from src/test/resources/linksmart/td-47.json rename to src/test/resources/linksmart/framed/td-47.json diff --git a/src/test/resources/linksmart/td-48.json b/src/test/resources/linksmart/framed/td-48.json similarity index 100% rename from src/test/resources/linksmart/td-48.json rename to src/test/resources/linksmart/framed/td-48.json diff --git a/src/test/resources/linksmart/td-49.json b/src/test/resources/linksmart/framed/td-49.json similarity index 100% rename from src/test/resources/linksmart/td-49.json rename to src/test/resources/linksmart/framed/td-49.json diff --git a/src/test/resources/linksmart/td-5.json b/src/test/resources/linksmart/framed/td-5.json similarity index 100% rename from src/test/resources/linksmart/td-5.json rename to src/test/resources/linksmart/framed/td-5.json diff --git a/src/test/resources/linksmart/td-50.json b/src/test/resources/linksmart/framed/td-50.json similarity index 100% rename from src/test/resources/linksmart/td-50.json rename to src/test/resources/linksmart/framed/td-50.json diff --git a/src/test/resources/linksmart/td-51.json b/src/test/resources/linksmart/framed/td-51.json similarity index 100% rename from src/test/resources/linksmart/td-51.json rename to src/test/resources/linksmart/framed/td-51.json diff --git a/src/test/resources/linksmart/td-52.json b/src/test/resources/linksmart/framed/td-52.json similarity index 100% rename from src/test/resources/linksmart/td-52.json rename to src/test/resources/linksmart/framed/td-52.json diff --git a/src/test/resources/linksmart/td-53.json b/src/test/resources/linksmart/framed/td-53.json similarity index 100% rename from src/test/resources/linksmart/td-53.json rename to src/test/resources/linksmart/framed/td-53.json diff --git a/src/test/resources/linksmart/td-54.json b/src/test/resources/linksmart/framed/td-54.json similarity index 100% rename from src/test/resources/linksmart/td-54.json rename to src/test/resources/linksmart/framed/td-54.json diff --git a/src/test/resources/linksmart/td-55.json b/src/test/resources/linksmart/framed/td-55.json similarity index 100% rename from src/test/resources/linksmart/td-55.json rename to src/test/resources/linksmart/framed/td-55.json diff --git a/src/test/resources/linksmart/td-56.json b/src/test/resources/linksmart/framed/td-56.json similarity index 100% rename from src/test/resources/linksmart/td-56.json rename to src/test/resources/linksmart/framed/td-56.json diff --git a/src/test/resources/linksmart/td-57.json b/src/test/resources/linksmart/framed/td-57.json similarity index 100% rename from src/test/resources/linksmart/td-57.json rename to src/test/resources/linksmart/framed/td-57.json diff --git a/src/test/resources/linksmart/td-58.json b/src/test/resources/linksmart/framed/td-58.json similarity index 100% rename from src/test/resources/linksmart/td-58.json rename to src/test/resources/linksmart/framed/td-58.json diff --git a/src/test/resources/linksmart/td-59.json b/src/test/resources/linksmart/framed/td-59.json similarity index 100% rename from src/test/resources/linksmart/td-59.json rename to src/test/resources/linksmart/framed/td-59.json diff --git a/src/test/resources/linksmart/td-6.json b/src/test/resources/linksmart/framed/td-6.json similarity index 100% rename from src/test/resources/linksmart/td-6.json rename to src/test/resources/linksmart/framed/td-6.json diff --git a/src/test/resources/linksmart/td-60.json b/src/test/resources/linksmart/framed/td-60.json similarity index 100% rename from src/test/resources/linksmart/td-60.json rename to src/test/resources/linksmart/framed/td-60.json diff --git a/src/test/resources/linksmart/td-61.json b/src/test/resources/linksmart/framed/td-61.json similarity index 100% rename from src/test/resources/linksmart/td-61.json rename to src/test/resources/linksmart/framed/td-61.json diff --git a/src/test/resources/linksmart/td-62.json b/src/test/resources/linksmart/framed/td-62.json similarity index 100% rename from src/test/resources/linksmart/td-62.json rename to src/test/resources/linksmart/framed/td-62.json diff --git a/src/test/resources/linksmart/td-63.json b/src/test/resources/linksmart/framed/td-63.json similarity index 100% rename from src/test/resources/linksmart/td-63.json rename to src/test/resources/linksmart/framed/td-63.json diff --git a/src/test/resources/linksmart/td-64.json b/src/test/resources/linksmart/framed/td-64.json similarity index 100% rename from src/test/resources/linksmart/td-64.json rename to src/test/resources/linksmart/framed/td-64.json diff --git a/src/test/resources/linksmart/td-65.json b/src/test/resources/linksmart/framed/td-65.json similarity index 100% rename from src/test/resources/linksmart/td-65.json rename to src/test/resources/linksmart/framed/td-65.json diff --git a/src/test/resources/linksmart/td-7.json b/src/test/resources/linksmart/framed/td-7.json similarity index 100% rename from src/test/resources/linksmart/td-7.json rename to src/test/resources/linksmart/framed/td-7.json diff --git a/src/test/resources/linksmart/td-8.json b/src/test/resources/linksmart/framed/td-8.json similarity index 100% rename from src/test/resources/linksmart/td-8.json rename to src/test/resources/linksmart/framed/td-8.json diff --git a/src/test/resources/linksmart/td-9.json b/src/test/resources/linksmart/framed/td-9.json similarity index 100% rename from src/test/resources/linksmart/td-9.json rename to src/test/resources/linksmart/framed/td-9.json diff --git a/src/test/resources/linksmart/rdf/td-0.nt b/src/test/resources/linksmart/rdf/td-0.nt new file mode 100755 index 0000000..22f554e --- /dev/null +++ b/src/test/resources/linksmart/rdf/td-0.nt @@ -0,0 +1,184 @@ + "2020-12-18T12:44:28.620627722Z"^^ . + "HybridcastConnectEmulator:Antwapp" . + "HybridcastConnectEmulator:Antwapp"@en . + "ハイコネエミュレーター"@ja . + "2020-12-18T12:44:28.620627722Z"^^ . + "HybridcastConnectReceiver" . + "HybridcastConnectReceiver"@en . + "ハイコネプロトコル対応受信機"@ja . + . + _:b0 . + _:b12 . + _:b16 . + _:b26 . + <_:nosec_sc> . + _:b39 . + "86400"^^ . +_:b0 _:b1 . +_:b0 _:b2 . +_:b0 _:b11 . +_:b0 "false"^^ . +_:b0 "true"^^ . +_:b1 "POST" . +_:b1 "application/json" . +_:b1 . +_:b1 . +_:b10 "The Transport_stream_id Schema" . +_:b10 . +_:b10 "65535"^^ . +_:b10 "0"^^ . +_:b10 "transport_stream_id" . +_:b11 "launchmode: " . +_:b11 "app" . +_:b11 "tune" . +_:b11 "string" . +_:b12 "Message is emitted." . +_:b12 "Message is emitted."@en . +_:b12 "メッセージが送出された."@ja . +_:b12 _:b13 . +_:b12 _:b14 . +_:b12 _:b15 . +_:b13 "application/json" . +_:b13 . +_:b13 . +_:b14 . +_:b15 . +_:b15 "value" . +_:b16 "available media on a TV set" . +_:b16 "available media on a TV set"@en . +_:b16 "メディア利用可否"@ja . +_:b16 "available media on a TV set" . +_:b16 "available media on a TV set"@en . +_:b16 "メディア利用可否"@ja . +_:b16 _:b17 . +_:b16 _:b22 . +_:b16 "media" . +_:b16 _:b25 . +_:b17 . +_:b17 _:b18 . +_:b17 _:b19 . +_:b17 _:b20 . +_:b17 _:b21 . +_:b17 "body" . +_:b18 "Availability of receiving Broadcasting Satelite" . +_:b18 . +_:b18 "Available" . +_:b18 "NotAvailable" . +_:b18 "BS" . +_:b19 "Availability of receiving Comunication Satelite" . +_:b19 . +_:b19 "Available" . +_:b19 "NotAvailable" . +_:b19 "CS" . +_:b2 . +_:b2 _:b3 . +_:b2 _:b7 . +_:b20 "Availability of receiving Telestrial Digital broadcasting" . +_:b20 . +_:b20 "Available" . +_:b20 "NotAvailable" . +_:b20 "TD" . +_:b21 "The date of the file created" . +_:b21 . +_:b21 "created_at" . +_:b22 . +_:b22 _:b23 . +_:b22 _:b24 . +_:b22 "head" . +_:b23 "code" . +_:b24 "message" . +_:b25 "GET" . +_:b25 "application/json" . +_:b25 . +_:b25 . +_:b25 "full_access" . +_:b26 "HybridcastReceiverStatus" . +_:b26 "HybridcastReceiverStatus"@en . +_:b26 "受信機状態"@ja . +_:b26 "HybridcastReceiverStatus" . +_:b26 "HybridcastReceiverStatus"@en . +_:b26 "受信機状態"@ja . +_:b26 _:b27 . +_:b26 _:b35 . +_:b26 "receiverStatus" . +_:b26 _:b38 . +_:b27 . +_:b27 _:b28 . +_:b27 "body" . +_:b28 . +_:b28 _:b29 . +_:b28 _:b30 . +_:b28 _:b31 . +_:b28 "status" . +_:b29 "The number of Companion_apps" . +_:b29 . +_:b29 "companion_apps" . +_:b3 . +_:b3 _:b4 . +_:b3 _:b5 . +_:b3 _:b6 . +_:b3 "hybridcast" . +_:b30 "The status of Hybridcast Browser" . +_:b30 . +_:b30 "NotStarted" . +_:b30 "Running" . +_:b30 "hybridcast" . +_:b31 . +_:b31 _:b32 . +_:b31 _:b33 . +_:b31 _:b34 . +_:b31 "resource" . +_:b32 "The Original_network_id of broadcasting" . +_:b32 . +_:b32 "65535"^^ . +_:b32 "0"^^ . +_:b32 "original_network_id" . +_:b33 "Service_id of broadcasting" . +_:b33 . +_:b33 "65535"^^ . +_:b33 "0"^^ . +_:b33 "service_id" . +_:b34 "The Transport_stream_id of broadcasting" . +_:b34 . +_:b34 "65535"^^ . +_:b34 "0"^^ . +_:b34 "transport_stream_id" . +_:b35 . +_:b35 _:b36 . +_:b35 _:b37 . +_:b35 "head" . +_:b36 "code" . +_:b37 "message" . +_:b38 "GET" . +_:b38 "application/json" . +_:b38 . +_:b38 . +_:b39 "nosec" . +_:b4 "The Aiturl Schema" . +_:b4 . +_:b4 "aiturl" . +_:b5 "The Appid Schema" . +_:b5 . +_:b5 "4294967295"^^ . +_:b5 "0"^^ . +_:b5 "appid" . +_:b6 "The Orgid Schema" . +_:b6 . +_:b6 "65535"^^ . +_:b6 "0"^^ . +_:b6 "orgid" . +_:b7 . +_:b7 _:b10 . +_:b7 _:b8 . +_:b7 _:b9 . +_:b7 "resource" . +_:b8 "The Original_network_id Schema" . +_:b8 . +_:b8 "65535"^^ . +_:b8 "0"^^ . +_:b8 "original_network_id" . +_:b9 "The Service_id Schema" . +_:b9 . +_:b9 "65535"^^ . +_:b9 "0"^^ . +_:b9 "service_id" . diff --git a/src/test/resources/linksmart/rdf/td-1.nt b/src/test/resources/linksmart/rdf/td-1.nt new file mode 100755 index 0000000..77d4cae --- /dev/null +++ b/src/test/resources/linksmart/rdf/td-1.nt @@ -0,0 +1,117 @@ + "2020-12-18T12:43:59.910105655Z"^^ . + "A virtual coffee machine to learn the WoT TD standard"@en . + "2020-12-18T12:43:59.910105655Z"^^ . + "Virtual-Coffee-Machine_1_1"@en . + . + _:b0 . + _:b2 . + _:b5 . + _:b10 . + _:b7 . + _:b13 . + _:b14 . + _:b16 . + _:b18 . + _:b20 . + <_:nosec_sc> . + _:b22 . + "86400"^^ . +_:b0 _:b1 . +_:b0 "false"^^ . +_:b0 "false"^^ . +_:b1 "POST"@en . +_:b1 "application/json" . +_:b1 . +_:b1 . +_:b10 _:b11 . +_:b10 _:b12 . +_:b11 "application/json" . +_:b11 "longpoll" . +_:b11 . +_:b11 . +_:b12 . +_:b13 "application/json" . +_:b13 . +_:b13 . +_:b13 . +_:b13 . +_:b13 . +_:b14 . +_:b14 . +_:b14 "100"^^ . +_:b14 "0"^^ . +_:b14 "binStatus"@en . +_:b14 "true"^^ . +_:b14 "false"^^ . +_:b14 _:b15 . +_:b14 "false"^^ . +_:b15 "GET"@en . +_:b15 "application/json" . +_:b15 . +_:b15 . +_:b16 . +_:b16 . +_:b16 "100"^^ . +_:b16 "0"^^ . +_:b16 "coffeeStatus"@en . +_:b16 "true"^^ . +_:b16 "false"^^ . +_:b16 _:b17 . +_:b16 "false"^^ . +_:b17 "GET"@en . +_:b17 "application/json" . +_:b17 . +_:b17 . +_:b18 . +_:b18 "Brewing"@en . +_:b18 "Error"@en . +_:b18 "Ready"@en . +_:b18 "state"@en . +_:b18 "true"^^ . +_:b18 "false"^^ . +_:b18 _:b19 . +_:b18 "false"^^ . +_:b19 "GET"@en . +_:b19 "application/json" . +_:b19 . +_:b19 . +_:b2 _:b3 . +_:b2 _:b4 . +_:b2 "false"^^ . +_:b2 "false"^^ . +_:b20 . +_:b20 . +_:b20 "100"^^ . +_:b20 "0"^^ . +_:b20 "waterStatus"@en . +_:b20 "true"^^ . +_:b20 "false"^^ . +_:b20 _:b21 . +_:b20 "false"^^ . +_:b21 "GET"@en . +_:b21 "application/json" . +_:b21 . +_:b21 . +_:b22 "nosec"@en . +_:b3 "POST"@en . +_:b3 "application/json" . +_:b3 . +_:b3 . +_:b4 . +_:b4 "cappuccino"@en . +_:b4 "espresso"@en . +_:b4 "latte-machiato"@en . +_:b5 _:b6 . +_:b5 "false"^^ . +_:b5 "false"^^ . +_:b6 "POST"@en . +_:b6 "application/json" . +_:b6 . +_:b6 . +_:b7 _:b8 . +_:b7 _:b9 . +_:b8 "application/json" . +_:b8 "longpoll" . +_:b8 . +_:b8 . +_:b9 . diff --git a/src/test/resources/wot/example-1.json b/src/test/resources/wot/example-1.json new file mode 100644 index 0000000..0907650 --- /dev/null +++ b/src/test/resources/wot/example-1.json @@ -0,0 +1,29 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "basic_sc": {"scheme": "basic", "in":"header"} + }, + "security": ["basic_sc"], + "properties": { + "status" : { + "type": "string", + "forms": [{"href": "https://mylamp.example.com/status"}] + } + }, + "actions": { + "toggle" : { + "forms": [{"href": "https://mylamp.example.com/toggle"}] + } + }, + "events":{ + "overheating":{ + "data": {"type": "string"}, + "forms": [{ + "href": "https://mylamp.example.com/oh", + "subprotocol": "longpoll" + }] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-1.nt b/src/test/resources/wot/example-1.nt new file mode 100644 index 0000000..a346d3e --- /dev/null +++ b/src/test/resources/wot/example-1.nt @@ -0,0 +1,19 @@ + "MyLampThing" . + _:b0 . + _:b2 . + _:b5 . + . + _:b7 . +_:b0 _:b1 . +_:b1 . +_:b2 _:b3 . +_:b2 _:b4 . +_:b3 "longpoll" . +_:b3 . +_:b4 . +_:b5 . +_:b5 "status" . +_:b5 _:b6 . +_:b6 . +_:b7 "header" . +_:b7 "basic" . diff --git a/src/test/resources/wot/example-11.json b/src/test/resources/wot/example-11.json new file mode 100644 index 0000000..ed68796 --- /dev/null +++ b/src/test/resources/wot/example-11.json @@ -0,0 +1,25 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "proxy_sc": { + "scheme": "digest", + "proxy": "https://portal.example.com/" + }, + "bearer_sc": { + "in":"header", + "scheme": "bearer", + "format": "jwt", + "alg": "ES256", + "authorization": "https://servient.example.com:8443/" + } + }, + "security": ["proxy_sc", "bearer_sc"], + "properties": { + "status" : { + "type": "string", + "forms": [{"href": "https://mylamp.example.com/status"}] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-11.nt b/src/test/resources/wot/example-11.nt new file mode 100644 index 0000000..084b80b --- /dev/null +++ b/src/test/resources/wot/example-11.nt @@ -0,0 +1,17 @@ + "MyLampThing" . + _:b0 . + . + . + _:b2 . + _:b3 . +_:b0 . +_:b0 "status" . +_:b0 _:b1 . +_:b1 . +_:b2 "ES256" . +_:b2 "https://servient.example.com:8443/" . +_:b2 "jwt" . +_:b2 "header" . +_:b2 "bearer" . +_:b3 "https://portal.example.com/" . +_:b3 "digest" . diff --git a/src/test/resources/wot/example-13.json b/src/test/resources/wot/example-13.json new file mode 100644 index 0000000..333ec3c --- /dev/null +++ b/src/test/resources/wot/example-13.json @@ -0,0 +1,32 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "basic_sc": {"scheme": "basic"}, + "nosec_sc": {"scheme": "nosec"} + }, + "security": ["basic_sc"], + "properties": { + "status": { + "forms": [{ + "href": "https://mylamp.example.com/status" + }] + } + }, + "actions": { + "toggle": { + "forms": [{ + "href": "https://mylamp.example.com/toggle" + }] + } + }, + "events": { + "overheating": { + "forms": [{ + "href": "https://mylamp.example.com/oh", + "security": ["nosec_sc"] + }] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-13.td b/src/test/resources/wot/example-13.td new file mode 100644 index 0000000..ed085c0 --- /dev/null +++ b/src/test/resources/wot/example-13.td @@ -0,0 +1,17 @@ + "MyLampThing" . + _:b0 . + _:b2 . + _:b4 . + . + _:b6 . + _:b7 . +_:b0 _:b1 . +_:b1 . +_:b2 _:b3 . +_:b3 . +_:b3 . +_:b4 "status" . +_:b4 _:b5 . +_:b5 . +_:b6 "basic" . +_:b7 "nosec" . diff --git a/src/test/resources/wot/example-14.json b/src/test/resources/wot/example-14.json new file mode 100644 index 0000000..cfd410b --- /dev/null +++ b/src/test/resources/wot/example-14.json @@ -0,0 +1,24 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "basic_sc": { "scheme": "basic" }, + "digest_sc": { "scheme": "digest" }, + "bearer_sc": { "scheme": "bearer" } + }, + "security": ["basic_sc"], + "properties": { + "status": { + "forms": [{ + "href": "https://mylamp.example.com/status" + }, { + "href": "https://mylamp.example.com/status", + "security": ["digest_sc"] + }, { + "href": "https://mylamp.example.com/status", + "security": ["bearer_sc"] + }] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-14.td b/src/test/resources/wot/example-14.td new file mode 100644 index 0000000..ffb0782 --- /dev/null +++ b/src/test/resources/wot/example-14.td @@ -0,0 +1,18 @@ + "MyLampThing" . + _:b0 . + . + _:b4 . + _:b5 . + _:b6 . +_:b0 "status" . +_:b0 _:b1 . +_:b0 _:b2 . +_:b0 _:b3 . +_:b1 . +_:b2 . +_:b2 . +_:b3 . +_:b3 . +_:b4 "basic" . +_:b5 "bearer" . +_:b6 "digest" . diff --git a/src/test/resources/wot/example-15.json b/src/test/resources/wot/example-15.json new file mode 100644 index 0000000..b8c164b --- /dev/null +++ b/src/test/resources/wot/example-15.json @@ -0,0 +1,31 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "properties": { + "status": { + "forms": [{ + "href": "https://scopes.example.com/status", + "scopes": ["limited"] + }] + } + }, + "actions": { + "configure": { + "forms": [{ + "href": "https://scopes.example.com/configure", + "scopes": ["special"] + }] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-15.td b/src/test/resources/wot/example-15.td new file mode 100644 index 0000000..8204c8e --- /dev/null +++ b/src/test/resources/wot/example-15.td @@ -0,0 +1,18 @@ + "MyLampThing" . + _:b0 . + _:b2 . + . + _:b4 . +_:b0 _:b1 . +_:b1 . +_:b1 "special" . +_:b2 "status" . +_:b2 _:b3 . +_:b3 . +_:b3 "limited" . +_:b4 "https://example.com/authorization" . +_:b4 "code" . +_:b4 "oauth2" . +_:b4 "limited" . +_:b4 "special" . +_:b4 "https://example.com/token" . diff --git a/src/test/resources/wot/example-16.json b/src/test/resources/wot/example-16.json new file mode 100644 index 0000000..15d48e7 --- /dev/null +++ b/src/test/resources/wot/example-16.json @@ -0,0 +1,41 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "properties": { + "on": { + "type": "boolean" + }, + "status": { + "type": "object", + "properties": { + "brightness": { + "type": "number", + "minimum": 0.0, + "maximum": 100.0 + }, + "rgb": { + "type": "array", + "items" : { + "type" : "number", + "minimum": 0, + "maximum": 255 + }, + "minItems": 3, + "maxItems": 3 + } + }, + "required": ["brightness", "rgb"] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-16.td b/src/test/resources/wot/example-16.td new file mode 100644 index 0000000..fb7b948 --- /dev/null +++ b/src/test/resources/wot/example-16.td @@ -0,0 +1,31 @@ + "MyLampThing" . + _:b0 . + _:b1 . + . + _:b5 . +_:b0 . +_:b0 "on" . +_:b1 . +_:b1 _:b2 . +_:b1 _:b3 . +_:b1 "status" . +_:b1 "brightness" . +_:b1 "rgb" . +_:b2 . +_:b2 "100"^^ . +_:b2 "0"^^ . +_:b2 "brightness" . +_:b3 . +_:b3 _:b4 . +_:b3 "3"^^ . +_:b3 "3"^^ . +_:b3 "rgb" . +_:b4 . +_:b4 "255"^^ . +_:b4 "0"^^ . +_:b5 "https://example.com/authorization" . +_:b5 "code" . +_:b5 "oauth2" . +_:b5 "limited" . +_:b5 "special" . +_:b5 "https://example.com/token" . diff --git a/src/test/resources/wot/example-17.json b/src/test/resources/wot/example-17.json new file mode 100644 index 0000000..ca2e3c2 --- /dev/null +++ b/src/test/resources/wot/example-17.json @@ -0,0 +1,39 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "actions": { + "fade" : { + "title": "Fade in/out", + "description": "Smooth fade in and out animation.", + "input": { + "type": "object", + "properties": { + "from": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "to": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "duration": {"type": "number"} + }, + "required": ["to","duration"] + }, + "output": {"type": "string"} + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-17.nt b/src/test/resources/wot/example-17.nt new file mode 100644 index 0000000..741fe26 --- /dev/null +++ b/src/test/resources/wot/example-17.nt @@ -0,0 +1,31 @@ + "MyLampThing" . + _:b0 . + . + _:b6 . +_:b0 "Smooth fade in and out animation." . +_:b0 "Fade in/out" . +_:b0 _:b1 . +_:b0 _:b5 . +_:b1 . +_:b1 _:b2 . +_:b1 _:b3 . +_:b1 _:b4 . +_:b1 "duration" . +_:b1 "to" . +_:b2 . +_:b2 "duration" . +_:b3 . +_:b3 "100"^^ . +_:b3 "0"^^ . +_:b3 "from" . +_:b4 . +_:b4 "100"^^ . +_:b4 "0"^^ . +_:b4 "to" . +_:b5 . +_:b6 "https://example.com/authorization" . +_:b6 "code" . +_:b6 "oauth2" . +_:b6 "limited" . +_:b6 "special" . +_:b6 "https://example.com/token" . diff --git a/src/test/resources/wot/example-18.json b/src/test/resources/wot/example-18.json new file mode 100644 index 0000000..cbd155c --- /dev/null +++ b/src/test/resources/wot/example-18.json @@ -0,0 +1,22 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "events": { + "overheated": { + "data" : { + "type": "string" + } + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-18.nt b/src/test/resources/wot/example-18.nt new file mode 100644 index 0000000..9ba14b3 --- /dev/null +++ b/src/test/resources/wot/example-18.nt @@ -0,0 +1,12 @@ + "MyLampThing" . + _:b0 . + . + _:b2 . +_:b0 _:b1 . +_:b1 . +_:b2 "https://example.com/authorization" . +_:b2 "code" . +_:b2 "oauth2" . +_:b2 "limited" . +_:b2 "special" . +_:b2 "https://example.com/token" . diff --git a/src/test/resources/wot/example-19.json b/src/test/resources/wot/example-19.json new file mode 100644 index 0000000..4dde13b --- /dev/null +++ b/src/test/resources/wot/example-19.json @@ -0,0 +1,20 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "links": [{ + "rel": "controlledBy", + "href": "https://servient.example.com/things/lampController", + "type": "application/td+json" + }] +} \ No newline at end of file diff --git a/src/test/resources/wot/example-19.nt b/src/test/resources/wot/example-19.nt new file mode 100644 index 0000000..caa21c1 --- /dev/null +++ b/src/test/resources/wot/example-19.nt @@ -0,0 +1,13 @@ + "MyLampThing" . + _:b0 . + . + _:b1 . +_:b0 . +_:b0 . +_:b0 "application/td+json" . +_:b1 "https://example.com/authorization" . +_:b1 "code" . +_:b1 "oauth2" . +_:b1 "limited" . +_:b1 "special" . +_:b1 "https://example.com/token" . diff --git a/src/test/resources/wot/example-2.json b/src/test/resources/wot/example-2.json new file mode 100644 index 0000000..bb5def4 --- /dev/null +++ b/src/test/resources/wot/example-2.json @@ -0,0 +1,39 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { "saref": "https://w3id.org/saref#" } + ], + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "@type": "saref:LightSwitch", + "securityDefinitions": {"basic_sc": { + "scheme": "basic", + "in": "header" + }}, + "security": ["basic_sc"], + "properties": { + "status": { + "@type": "saref:OnOffState", + "type": "string", + "forms": [{ + "href": "https://mylamp.example.com/status" + }] + } + }, + "actions": { + "toggle": { + "@type": "saref:ToggleCommand", + "forms": [{ + "href": "https://mylamp.example.com/toggle" + }] + } + }, + "events": { + "overheating": { + "data": {"type": "string"}, + "forms": [{ + "href": "https://mylamp.example.com/oh" + }] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-2.nt b/src/test/resources/wot/example-2.nt new file mode 100644 index 0000000..ff4c0ca --- /dev/null +++ b/src/test/resources/wot/example-2.nt @@ -0,0 +1,21 @@ + "MyLampThing" . + . + _:b0 . + _:b2 . + _:b5 . + . + _:b7 . +_:b0 . +_:b0 _:b1 . +_:b1 . +_:b2 _:b3 . +_:b2 _:b4 . +_:b3 . +_:b4 . +_:b5 . +_:b5 . +_:b5 "status" . +_:b5 _:b6 . +_:b6 . +_:b7 "header" . +_:b7 "basic" . diff --git a/src/test/resources/wot/example-20.json b/src/test/resources/wot/example-20.json new file mode 100644 index 0000000..cc1b243 --- /dev/null +++ b/src/test/resources/wot/example-20.json @@ -0,0 +1,21 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "forms": [{ + "op": "writeproperty", + "href" : "http://mytemp.example.com:5683/temp", + "contentType": "application/json", + "htv:methodName": "POST" + }] +} \ No newline at end of file diff --git a/src/test/resources/wot/example-20.nt b/src/test/resources/wot/example-20.nt new file mode 100644 index 0000000..f689189 --- /dev/null +++ b/src/test/resources/wot/example-20.nt @@ -0,0 +1,14 @@ + "MyLampThing" . + _:b0 . + . + _:b1 . +_:b0 "POST" . +_:b0 "application/json" . +_:b0 . +_:b0 . +_:b1 "https://example.com/authorization" . +_:b1 "code" . +_:b1 "oauth2" . +_:b1 "limited" . +_:b1 "special" . +_:b1 "https://example.com/token" . diff --git a/src/test/resources/wot/example-21.json b/src/test/resources/wot/example-21.json new file mode 100644 index 0000000..f832ca4 --- /dev/null +++ b/src/test/resources/wot/example-21.json @@ -0,0 +1,30 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { "eg": "http://www.example.org/iot#" } + ], + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "actions": { + "LeftDown": { + "uriVariables": { + "p" : { "type": "integer", "minimum": 0, "maximum": 16, "@type": "eg:SomeKindOfAngle" }, + "d" : { "type": "integer", "minimum": 0, "maximum": 1, "@type": "eg:Direction" } + }, + "forms": [{ + "href" : "http://192.168.1.25/left{?p,d}", + "htv:methodName": "GET" + }] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-21.nt b/src/test/resources/wot/example-21.nt new file mode 100644 index 0000000..2c4d176 --- /dev/null +++ b/src/test/resources/wot/example-21.nt @@ -0,0 +1,23 @@ + "MyLampThing" . + _:b0 . + . + _:b4 . +_:b0 _:b1 . +_:b0 _:b2 . +_:b0 _:b3 . +_:b1 "GET" . +_:b1 . +_:b2 . +_:b2 "1"^^ . +_:b2 "0"^^ . +_:b2 "integer" . +_:b3 . +_:b3 "16"^^ . +_:b3 "0"^^ . +_:b3 "integer" . +_:b4 "https://example.com/authorization" . +_:b4 "code" . +_:b4 "oauth2" . +_:b4 "limited" . +_:b4 "special" . +_:b4 "https://example.com/token" . diff --git a/src/test/resources/wot/example-23.json b/src/test/resources/wot/example-23.json new file mode 100644 index 0000000..11576c3 --- /dev/null +++ b/src/test/resources/wot/example-23.json @@ -0,0 +1,30 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { "eg": "http://www.example.org/iot#" } + ], + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "actions": { + "takePhoto": { + "forms": [{ + "op": "invokeaction", + "href": "http://camera.example.com/api/snapshot", + "contentType": "application/json", + "response": { + "contentType": "image/jpeg" + } + }] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-23.nt b/src/test/resources/wot/example-23.nt new file mode 100644 index 0000000..0d78073 --- /dev/null +++ b/src/test/resources/wot/example-23.nt @@ -0,0 +1,16 @@ + "MyLampThing" . + _:b0 . + . + _:b3 . +_:b0 _:b1 . +_:b1 "application/json" . +_:b1 . +_:b1 . +_:b1 _:b2 . +_:b2 "image/jpeg" . +_:b3 "https://example.com/authorization" . +_:b3 "code" . +_:b3 "oauth2" . +_:b3 "limited" . +_:b3 "special" . +_:b3 "https://example.com/token" . diff --git a/src/test/resources/wot/example-24.json b/src/test/resources/wot/example-24.json new file mode 100644 index 0000000..538de1d --- /dev/null +++ b/src/test/resources/wot/example-24.json @@ -0,0 +1,40 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { "eg": "http://www.example.org/iot#" } + ], + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "properties": { + "on": { + "type": "boolean" + }, + "brightness": { + "type": "number" + }, + "timer": { + "type": "integer" + } + }, + "forms": [{ + "op": "readallproperties", + "href": "https://mylamp.example.com/allproperties", + "contentType": "application/json", + "htv:methodName": "GET" + }, { + "op": "writeallproperties", + "href": "https://mylamp.example.com/allproperties", + "contentType": "application/json", + "htv:methodName": "PUT" + }] +} \ No newline at end of file diff --git a/src/test/resources/wot/example-24.nt b/src/test/resources/wot/example-24.nt new file mode 100644 index 0000000..9b5de7b --- /dev/null +++ b/src/test/resources/wot/example-24.nt @@ -0,0 +1,28 @@ + "MyLampThing" . + _:b0 . + _:b1 . + _:b2 . + _:b3 . + _:b4 . + . + _:b5 . +_:b0 "GET" . +_:b0 "application/json" . +_:b0 . +_:b0 . +_:b1 "PUT" . +_:b1 "application/json" . +_:b1 . +_:b1 . +_:b2 . +_:b2 "brightness" . +_:b3 . +_:b3 "on" . +_:b4 . +_:b4 "timer" . +_:b5 "https://example.com/authorization" . +_:b5 "code" . +_:b5 "oauth2" . +_:b5 "limited" . +_:b5 "special" . +_:b5 "https://example.com/token" . diff --git a/src/test/resources/wot/example-25.json b/src/test/resources/wot/example-25.json new file mode 100644 index 0000000..e7856c9 --- /dev/null +++ b/src/test/resources/wot/example-25.json @@ -0,0 +1,43 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { "eg": "http://www.example.org/iot#" } + ], + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "type": "object", + "properties": { + "status": { + "title": "Status", + "type": "string", + "enum": ["On", "Off", "Error"] + }, + "brightness": { + "title": "Brightness value", + "type": "number", + "minimum": 0.0, + "maximum": 100.0 + }, + "rgb": { + "title": "RGB color value", + "type": "array", + "items" : { + "type" : "number", + "minimum": 0, + "maximum": 255 + }, + "minItems": 3, + "maxItems": 3 + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-26.json b/src/test/resources/wot/example-26.json new file mode 100644 index 0000000..5f65c3c --- /dev/null +++ b/src/test/resources/wot/example-26.json @@ -0,0 +1,36 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { "eg": "http://www.example.org/iot#" } + ], + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "properties": { + "status": { + "description": "Read or write On/Off status.", + "type": "object", + "properties": { + "latestStatus": { + "type": "string", + "enum": ["On", "Off"], + "readOnly": true + }, + "newStatusValue": { + "type": "string", + "enum": ["On", "Off"], + "writeOnly": true + } + } + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-28.json b/src/test/resources/wot/example-28.json new file mode 100644 index 0000000..f11df28 --- /dev/null +++ b/src/test/resources/wot/example-28.json @@ -0,0 +1,36 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { + "v": "http://www.example.org/versioningTerms#", + "saref": "https://w3id.org/saref#", + "om": "http://www.ontology-of-units-of-measure.org/resource/om-2/" + } + ], + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "version": { + "instance": "1.2.1", + "v:firmware": "0.9.1", + "v:hardware": "1.0" + }, + "@type": "saref:TemperatureSensor", + "title": "MyLampThing", + "properties": { + "temperature": { + "description": "Temperature value of the weather station", + "type": "number", + "minimum": -32.5, + "maximum": 55.2, + "unit": "om:degree_Celsius" + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-29.json b/src/test/resources/wot/example-29.json new file mode 100644 index 0000000..cc6dd62 --- /dev/null +++ b/src/test/resources/wot/example-29.json @@ -0,0 +1,35 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { + "saref": "https://w3id.org/saref#", + "ssn": "http://www.w3.org/ns/ssn/" + } + ], + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "@type": "saref:LightSwitch", + "securityDefinitions": {"nosec_sc": {"scheme": "nosec"}}, + "security": ["nosec_sc"], + "saref:hasState": { + "id": "urn:dev:ops:32473-WoTLamp-1234/state", + "@type": "saref:OnOffState" + }, + "properties": { + "status": { + "ssn:forProperty": "urn:dev:ops:32473-WoTLamp-1234/state", + "type": "string", + "forms": [{"href": "https://mylamp.example.com/status"}] + }, + "fullStatus": { + "ssn:forProperty": "urn:dev:ops:32473-WoTLamp-1234/state", + "type": "object", + "properties": { + "statusString": { "type": "string" }, + "statusCode": { "type": "number" }, + "statusDescription": { "type": "string" } + }, + "forms": [{"href": "https://mylamp.example.com/status?full=true"}] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-3.json b/src/test/resources/wot/example-3.json new file mode 100644 index 0000000..5d0e98c --- /dev/null +++ b/src/test/resources/wot/example-3.json @@ -0,0 +1,55 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "basic_sc": { + "scheme": "basic", + "in": "header" + } + }, + "security": [ + "basic_sc" + ], + "properties": { + "status": { + "type": "string", + "readOnly" : false, + "writeOnly" : false, + "forms": [{ + "op": [ + "readproperty", + "writeproperty" + ], + "href": "https://mylamp.example.com/status", + "contentType": "application/json" + }] + } + }, + "actions": { + "toggle": { + "safe": false, + "idempotent": false, + "forms": [{ + "op": "invokeaction", + "href": "https://mylamp.example.com/toggle", + "contentType": "application/json" + }] + } + }, + "events": { + "overheating": { + "data": { + "type": "string", + "readOnly" : false, + "writeOnly" : false + }, + "forms": [{ + "op": "subscribeevent", + "href": "https://mylamp.example.com/oh", + "contentType": "application/json", + "subprotocol": "longpoll" + }] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-3.nt b/src/test/resources/wot/example-3.nt new file mode 100644 index 0000000..a7c1cbc --- /dev/null +++ b/src/test/resources/wot/example-3.nt @@ -0,0 +1,32 @@ + "MyLampThing" . + _:b0 . + _:b2 . + _:b5 . + . + _:b7 . +_:b0 _:b1 . +_:b0 "false"^^ . +_:b0 "false"^^ . +_:b1 "application/json" . +_:b1 . +_:b1 . +_:b2 _:b3 . +_:b2 _:b4 . +_:b3 "application/json" . +_:b3 "longpoll" . +_:b3 . +_:b3 . +_:b4 . +_:b4 "false"^^ . +_:b4 "false"^^ . +_:b5 . +_:b5 "status" . +_:b5 "false"^^ . +_:b5 "false"^^ . +_:b5 _:b6 . +_:b6 "application/json" . +_:b6 . +_:b6 . +_:b6 . +_:b7 "header" . +_:b7 "basic" . diff --git a/src/test/resources/wot/example-30.json b/src/test/resources/wot/example-30.json new file mode 100644 index 0000000..be0cd9a --- /dev/null +++ b/src/test/resources/wot/example-30.json @@ -0,0 +1,34 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { "cov": "http://www.example.org/coap-binding#" } + ], + "title": "MyLampThing", + "securityDefinitions": { + "oauth2_sc": { + "scheme": "oauth2", + "flow": "code", + "authorization": "https://example.com/authorization", + "token": "https://example.com/token", + "scopes": ["limited", "special"] + } + }, + "security": ["oauth2_sc"], + "properties": { + "brightness": { + "description": "The current brightness setting", + "type": "integer", + "minimum": -64, + "maximum": 64, + "forms": [{ + "op": "readproperty", + "href": "coap://example.org:61616/api/brightness", + "cov:methodName": "GET" + }, { + "op": "writeproperty", + "href": "coap://example.org:61616/api/brightness", + "cov:methodName": "POST" + }] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-31.json b/src/test/resources/wot/example-31.json new file mode 100644 index 0000000..ef51907 --- /dev/null +++ b/src/test/resources/wot/example-31.json @@ -0,0 +1,42 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { + "cov": "http://www.example.org/coap-binding#", + "ace": "http://www.example.org/ace-security#" + } + ], + "securityDefinitions": { + "ace_sc": { + "scheme": "ace:ACESecurityScheme", + "ace:as": "coaps://as.example.com/token", + "ace:audience": "coaps://rs.example.com", + "ace:scopes": ["limited", "special"], + "ace:cnonce": true + } + }, + "title" : "Example 31", + "security": ["ace_sc"], + "properties": { + "status": { + "forms": [{ + "op": "readproperty", + "href": "coaps://rs.example.com/status", + "contentType": "application/cbor", + "cov:methodName": "GET", + "ace:scopes": ["limited"] + }] + } + }, + "actions": { + "configure": { + "forms": [{ + "op": "invokeaction", + "href": "coaps://rs.example.com/configure", + "contentType": "application/cbor", + "cov:methodName": "POST", + "ace:scopes": ["special"] + }] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-31.nt b/src/test/resources/wot/example-31.nt new file mode 100644 index 0000000..86bc513 --- /dev/null +++ b/src/test/resources/wot/example-31.nt @@ -0,0 +1,23 @@ +_:b0 _:b1 . +_:b0 _:b3 . +_:b0 . +_:b0 _:b5 . +_:b1 _:b2 . +_:b2 "special" . +_:b2 "POST" . +_:b2 "application/cbor" . +_:b2 . +_:b2 . +_:b3 "status" . +_:b3 _:b4 . +_:b4 "limited" . +_:b4 "GET" . +_:b4 "application/cbor" . +_:b4 . +_:b4 . +_:b5 "coaps://as.example.com/token" . +_:b5 "coaps://rs.example.com" . +_:b5 "true"^^ . +_:b5 "limited" . +_:b5 "special" . +_:b5 "ace:ACESecurityScheme" . diff --git a/src/test/resources/wot/example-32.json b/src/test/resources/wot/example-32.json new file mode 100644 index 0000000..cb6fd20 --- /dev/null +++ b/src/test/resources/wot/example-32.json @@ -0,0 +1,56 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "securityDefinitions": { + "basic_sc": { + "scheme": "basic", + "in": "header" + } + }, + "security": [ + "basic_sc" + ], + "properties": { + "status": { + "type": "string", + "forms": [ + { + "op": "readproperty", + "href": "https://mylamp.example.com/status", + "htv:methodName": "GET" + }, + { + "op": "writeproperty", + "href": "https://mylamp.example.com/status", + "htv:methodName": "PUT" + } + ] + } + }, + "actions": { + "toggle": { + "forms": [ + { + "op": "invokeaction", + "href": "https://mylamp.example.com/toggle", + "htv:methodName": "POST" + } + ] + } + }, + "events": { + "overheating": { + "data": { + "type": "string" + }, + "forms": [ + { + "op": "subscribeevent", + "href": "https://mylamp.example.com/oh", + "subprotocol": "longpoll" + } + ] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-32.nt b/src/test/resources/wot/example-32.nt new file mode 100644 index 0000000..68b7dd8 --- /dev/null +++ b/src/test/resources/wot/example-32.nt @@ -0,0 +1,28 @@ + "MyLampThing" . + _:b0 . + _:b2 . + _:b5 . + . + _:b8 . +_:b0 _:b1 . +_:b1 "POST" . +_:b1 . +_:b1 . +_:b2 _:b3 . +_:b2 _:b4 . +_:b3 "longpoll" . +_:b3 . +_:b3 . +_:b4 . +_:b5 . +_:b5 "status" . +_:b5 _:b6 . +_:b5 _:b7 . +_:b6 "GET" . +_:b6 . +_:b6 . +_:b7 "PUT" . +_:b7 . +_:b7 . +_:b8 "header" . +_:b8 "basic" . diff --git a/src/test/resources/wot/example-33.json b/src/test/resources/wot/example-33.json new file mode 100644 index 0000000..b0e4958 --- /dev/null +++ b/src/test/resources/wot/example-33.json @@ -0,0 +1,44 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { + "cov": "http://www.example.org/coap-binding#" + } + ], + "id": "urn:dev:ops:32473-WoTLamp-1234", + "title": "MyLampThing", + "description" : "MyLampThing uses JSON serialization", + "securityDefinitions": {"psk_sc":{"scheme": "psk"}}, + "security": ["psk_sc"], + "properties": { + "status": { + "description" : "Shows the current status of the lamp", + "type": "string", + "forms": [{ + "op": "readproperty", + "href": "coaps://mylamp.example.com/status", + "cov:methodName" : "GET" + }] + } + }, + "actions": { + "toggle": { + "description" : "Turn on or off the lamp", + "forms": [{ + "href": "coaps://mylamp.example.com/toggle", + "cov:methodName" : "POST" + }] + } + }, + "events": { + "overheating": { + "description" : "Lamp reaches a critical temperature (overheating)", + "data": {"type": "string"}, + "forms": [{ + "href": "coaps://mylamp.example.com/oh", + "cov:methodName" : "GET", + "subprotocol" : "cov:observe" + }] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-33.nt b/src/test/resources/wot/example-33.nt new file mode 100644 index 0000000..df228f3 --- /dev/null +++ b/src/test/resources/wot/example-33.nt @@ -0,0 +1,26 @@ + "MyLampThing uses JSON serialization" . + "MyLampThing" . + _:b0 . + _:b2 . + _:b5 . + . + _:b7 . +_:b0 "Turn on or off the lamp" . +_:b0 _:b1 . +_:b1 "POST" . +_:b1 . +_:b2 "Lamp reaches a critical temperature (overheating)" . +_:b2 _:b3 . +_:b2 _:b4 . +_:b3 "GET" . +_:b3 "cov:observe" . +_:b3 . +_:b4 . +_:b5 "Shows the current status of the lamp" . +_:b5 . +_:b5 "status" . +_:b5 _:b6 . +_:b6 "GET" . +_:b6 . +_:b6 . +_:b7 "psk" . diff --git a/src/test/resources/wot/example-34.json b/src/test/resources/wot/example-34.json new file mode 100644 index 0000000..2d72362 --- /dev/null +++ b/src/test/resources/wot/example-34.json @@ -0,0 +1,19 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "title": "MyIlluminanceSensor", + "id": "urn:dev:ops:32473-WoTIlluminanceSensor-1234", + "securityDefinitions": {"nosec_sc": {"scheme": "nosec"}}, + "security": ["nosec_sc"], + "events": { + "illuminance": { + "data":{"type": "integer"}, + "forms": [ + { + "href": "mqtt://192.168.1.187:1883/illuminance", + "contentType" : "text/plain", + "op" : "subscribeevent" + } + ] + } + } +} diff --git a/src/test/resources/wot/example-34.nt b/src/test/resources/wot/example-34.nt new file mode 100644 index 0000000..80eb95f --- /dev/null +++ b/src/test/resources/wot/example-34.nt @@ -0,0 +1,11 @@ + "MyIlluminanceSensor" . + _:b0 . + . + _:b3 . +_:b0 _:b1 . +_:b0 _:b2 . +_:b1 "text/plain" . +_:b1 . +_:b1 . +_:b2 . +_:b3 "nosec" . diff --git a/src/test/resources/wot/example-35.json b/src/test/resources/wot/example-35.json new file mode 100644 index 0000000..2d60585 --- /dev/null +++ b/src/test/resources/wot/example-35.json @@ -0,0 +1,59 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "id": "urn:dev:ops:32473-Thing-1234", + "title": "WebhookThing", + "description": "Webhook-based Event with subscription and unsubscribe form.", + "securityDefinitions": {"nosec_sc": {"scheme": "nosec"}}, + "security": ["nosec_sc"], + "events": { + "temperature": { + "description": "Provides periodic temperature value updates.", + "subscription": { + "type": "object", + "properties": { + "callbackURL": { + "type": "string", + "format": "uri", + "description": "Callback URL provided by subscriber for Webhook notifications.", + "writeOnly": true + }, + "subscriptionID": { + "type": "string", + "description": "Unique subscription ID for cancellation provided by WebhookThing.", + "readOnly": true + } + } + }, + "data": { + "type": "number", + "description": "Latest temperature value that is sent to the callback URL." + }, + "cancellation": { + "type": "object", + "properties": { + "subscriptionID": { + "type": "integer", + "description": "Required subscription ID to cancel subscription.", + "writeOnly": true + } + } + }, + "uriVariables": { + "subscriptionID": { "type": "string" } + }, + "forms": [ + { + "op": "subscribeevent", + "href": "http://192.168.0.124:8080/events/temp/subscribe", + "contentType": "application/json", + "htv:methodName": "POST" + }, + { + "op": "unsubscribeevent", + "href": "http://192.168.0.124:8080/events/temp/{subscriptionID}", + "htv:methodName": "DELETE" + } + ] + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-35.nt b/src/test/resources/wot/example-35.nt new file mode 100644 index 0000000..f390db0 --- /dev/null +++ b/src/test/resources/wot/example-35.nt @@ -0,0 +1,41 @@ + "Webhook-based Event with subscription and unsubscribe form." . + "WebhookThing" . + _:b0 . + . + _:b10 . +_:b0 "Provides periodic temperature value updates." . +_:b0 _:b1 . +_:b0 _:b3 . +_:b0 _:b4 . +_:b0 _:b5 . +_:b0 _:b6 . +_:b0 _:b9 . +_:b1 . +_:b1 _:b2 . +_:b10 "nosec" . +_:b2 "Required subscription ID to cancel subscription." . +_:b2 . +_:b2 "subscriptionID" . +_:b2 "true"^^ . +_:b3 "POST" . +_:b3 "application/json" . +_:b3 . +_:b3 . +_:b4 "DELETE" . +_:b4 . +_:b4 . +_:b5 "Latest temperature value that is sent to the callback URL." . +_:b5 . +_:b6 . +_:b6 _:b7 . +_:b6 _:b8 . +_:b7 "Callback URL provided by subscriber for Webhook notifications." . +_:b7 . +_:b7 "uri" . +_:b7 "callbackURL" . +_:b7 "true"^^ . +_:b8 "Unique subscription ID for cancellation provided by WebhookThing." . +_:b8 . +_:b8 "subscriptionID" . +_:b8 "true"^^ . +_:b9 "string" . diff --git a/src/test/resources/wot/example-36.json b/src/test/resources/wot/example-36.json new file mode 100644 index 0000000..9076783 --- /dev/null +++ b/src/test/resources/wot/example-36.json @@ -0,0 +1,26 @@ +{ + "@context": ["https://www.w3.org/2019/wot/td/v1"], + "@type" : "ThingTemplate", + "title": "Lamp Thing Description Template", + "description" : "Lamp Thing Description Template", + "securityDefinitions": {"nosec_sc": {"scheme": "nosec"}}, + "security": ["nosec_sc"], + "properties": { + "status": { + "description" : "current status of the lamp (on|off)", + "type": "string", + "readOnly": true + } + }, + "actions": { + "toggle": { + "description" : "Turn the lamp on or off" + } + }, + "events": { + "overheating": { + "description" : "Lamp reaches a critical temperature (overheating)", + "data": {"type": "string"} + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-36.nt b/src/test/resources/wot/example-36.nt new file mode 100644 index 0000000..c9970f2 --- /dev/null +++ b/src/test/resources/wot/example-36.nt @@ -0,0 +1,14 @@ +_:b0 "Lamp Thing Description Template" . +_:b0 "Lamp Thing Description Template" . +_:b0 . +_:b0 _:b1 . +_:b0 _:b2 . +_:b0 _:b4 . +_:b1 "Turn the lamp on or off" . +_:b2 "Lamp reaches a critical temperature (overheating)" . +_:b2 _:b3 . +_:b3 . +_:b4 "current status of the lamp (on|off)" . +_:b4 . +_:b4 "status" . +_:b4 "true"^^ . diff --git a/src/test/resources/wot/example-37.json b/src/test/resources/wot/example-37.json new file mode 100644 index 0000000..6cd2c8f --- /dev/null +++ b/src/test/resources/wot/example-37.json @@ -0,0 +1,13 @@ +{ + "@context": ["https://www.w3.org/2019/wot/td/v1"], + "@type" : "ThingTemplate", + "title": "Buzzer Thing Description Template", + "securityDefinitions": {"nosec_sc": {"scheme": "nosec"}}, + "security": ["nosec_sc"], + "description" : "Thing Description Template of a buzzer that makes noise for 10 seconds", + "actions": { + "buzz": { + "description" : "buzz for 10 seconds" + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-37.nt b/src/test/resources/wot/example-37.nt new file mode 100644 index 0000000..f5069bd --- /dev/null +++ b/src/test/resources/wot/example-37.nt @@ -0,0 +1,5 @@ +_:b0 "Thing Description Template of a buzzer that makes noise for 10 seconds" . +_:b0 "Buzzer Thing Description Template" . +_:b0 . +_:b0 _:b1 . +_:b1 "buzz for 10 seconds" . diff --git a/src/test/resources/wot/example-6.json b/src/test/resources/wot/example-6.json new file mode 100644 index 0000000..a47458f --- /dev/null +++ b/src/test/resources/wot/example-6.json @@ -0,0 +1,22 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { "@language" : "en" } + ], + "title": "MyThing", + "description": "Human readable information.", + "securityDefinitions": { + "basic_sc": {"scheme": "basic", "in":"header"} + }, + "security": ["basic_sc"], + "properties": { + "on": { + "title" : "On/Off", + "type": "boolean" + }, + "status": { + "title" : "Status", + "type": "object" + } + } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-6.nt b/src/test/resources/wot/example-6.nt new file mode 100644 index 0000000..1515a28 --- /dev/null +++ b/src/test/resources/wot/example-6.nt @@ -0,0 +1,14 @@ +_:b0 "Human readable information."@en . +_:b0 "MyThing"@en . +_:b0 _:b1 . +_:b0 _:b2 . +_:b0 . +_:b0 _:b3 . +_:b1 "On/Off"@en . +_:b1 . +_:b1 "on"@en . +_:b2 "Status"@en . +_:b2 . +_:b2 "status"@en . +_:b3 "header"@en . +_:b3 "basic"@en . diff --git a/src/test/resources/wot/example-7.json b/src/test/resources/wot/example-7.json new file mode 100644 index 0000000..e27095c --- /dev/null +++ b/src/test/resources/wot/example-7.json @@ -0,0 +1,42 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "title": "MyThing", + "titles": { + "en":"MyThing", + "de": "MeinDing", + "ja" : "私の物", + "zh-Hans" : "我的东西", + "zh-Hant" : "我的東西" + }, + "descriptions": { + "en":"Human readable information.", + "de": "Menschenlesbare Informationen.", + "ja" : "人間が読むことができる情報", + "zh-Hans" : "人们可阅读的信息", + "zh-Hant" : "人們可閱讀的資訊" + }, + "properties": { + "on": { + "titles": { + "en": "On/Off", + "de": "An/Aus", + "ja": "オンオフ", + "zh-Hans": "开关", + "zh-Hant": "開關" }, + "type": "boolean" + }, + "status": { + "titles": { + "en": "Status", + "de": "Zustand", + "ja": "状態", + "zh-Hans": "状态", + "zh-Hant": "狀態" }, + "type": "object" + } + }, + "securityDefinitions": { + "basic_sc": {"scheme": "basic", "in":"header"} + }, + "security": ["basic_sc"] +} \ No newline at end of file diff --git a/src/test/resources/wot/example-7.nt b/src/test/resources/wot/example-7.nt new file mode 100644 index 0000000..a985a01 --- /dev/null +++ b/src/test/resources/wot/example-7.nt @@ -0,0 +1,31 @@ +_:b0 "Human readable information."@en . +_:b0 "Menschenlesbare Informationen."@de . +_:b0 "人们可阅读的信息"@zh-hans . +_:b0 "人們可閱讀的資訊"@zh-hant . +_:b0 "人間が読むことができる情報"@ja . +_:b0 "MeinDing"@de . +_:b0 "MyThing" . +_:b0 "MyThing"@en . +_:b0 "我的东西"@zh-hans . +_:b0 "我的東西"@zh-hant . +_:b0 "私の物"@ja . +_:b0 _:b1 . +_:b0 _:b2 . +_:b0 . +_:b0 _:b3 . +_:b1 "An/Aus"@de . +_:b1 "On/Off"@en . +_:b1 "オンオフ"@ja . +_:b1 "开关"@zh-hans . +_:b1 "開關"@zh-hant . +_:b1 . +_:b1 "on" . +_:b2 "Status"@en . +_:b2 "Zustand"@de . +_:b2 "状态"@zh-hans . +_:b2 "状態"@ja . +_:b2 "狀態"@zh-hant . +_:b2 . +_:b2 "status" . +_:b3 "header" . +_:b3 "basic" . diff --git a/src/test/resources/wot/example-8.json b/src/test/resources/wot/example-8.json new file mode 100644 index 0000000..c316b1f --- /dev/null +++ b/src/test/resources/wot/example-8.json @@ -0,0 +1,48 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { "@language" : "de" } + ], + "title": "MyThing", + "titles": { + "en":"MyThing", + "de": "MeinDing", + "ja" : "私の物", + "zh-Hans" : "我的东西", + "zh-Hant" : "我的東西" + }, + "description": "Menschenlesbare Informationen.", + "descriptions": { + "en":"Human readable information.", + "de": "Menschenlesbare Informationen.", + "ja" : "人間が読むことができる情報", + "zh-Hans" : "人们可阅读的信息", + "zh-Hant" : "人們可閱讀的資訊" + }, + "properties": { + "on": { + "title" : "An/Aus", + "titles": { + "en": "On/Off", + "de": "An/Aus", + "ja": "オンオフ", + "zh-Hans": "开关", + "zh-Hant": "開關" }, + "type": "boolean" + }, + "status": { + "title" : "Zustand", + "titles": { + "en": "Status", + "de": "Zustand", + "ja": "状態", + "zh-Hans": "状态", + "zh-Hant": "狀態" }, + "type": "object" + } + }, + "securityDefinitions": { + "basic_sc": {"scheme": "basic", "in":"header"} + }, + "security": ["basic_sc"] +} \ No newline at end of file diff --git a/src/test/resources/wot/example-8.nt b/src/test/resources/wot/example-8.nt new file mode 100644 index 0000000..bdb4e4f --- /dev/null +++ b/src/test/resources/wot/example-8.nt @@ -0,0 +1,31 @@ +_:b0 "Human readable information."@en . +_:b0 "Menschenlesbare Informationen."@de . +_:b0 "人们可阅读的信息"@zh-hans . +_:b0 "人們可閱讀的資訊"@zh-hant . +_:b0 "人間が読むことができる情報"@ja . +_:b0 "MeinDing"@de . +_:b0 "MyThing"@de . +_:b0 "MyThing"@en . +_:b0 "我的东西"@zh-hans . +_:b0 "我的東西"@zh-hant . +_:b0 "私の物"@ja . +_:b0 _:b1 . +_:b0 _:b2 . +_:b0 . +_:b0 _:b3 . +_:b1 "An/Aus"@de . +_:b1 "On/Off"@en . +_:b1 "オンオフ"@ja . +_:b1 "开关"@zh-hans . +_:b1 "開關"@zh-hant . +_:b1 . +_:b1 "on"@de . +_:b2 "Status"@en . +_:b2 "Zustand"@de . +_:b2 "状态"@zh-hans . +_:b2 "状態"@ja . +_:b2 "狀態"@zh-hant . +_:b2 . +_:b2 "status"@de . +_:b3 "header"@de . +_:b3 "basic"@de . diff --git a/src/test/resources/wot/example-9.json b/src/test/resources/wot/example-9.json new file mode 100644 index 0000000..691ce83 --- /dev/null +++ b/src/test/resources/wot/example-9.json @@ -0,0 +1,49 @@ +{ + "@context": [ + "https://www.w3.org/2019/wot/td/v1", + { "@language" : "de" } + ], + "title": "MyThing", + "titles": { + "en":"MyThing", + "de": "MeinDing", + "ja" : "私の物", + "zh-Hans" : "我的东西", + "zh-Hant" : "我的東西" + }, + "description": "Menschenlesbare Informationen.", + "descriptions": { + "en":"Human readable information.", + "de": "Menschenlesbare Informationen.", + "ja" : "人間が読むことができる情報", + "zh-Hans" : "人们可阅读的信息", + "zh-Hant" : "人們可閱讀的資訊" + }, + "properties": { + "on": { + "title" : "An/Aus", + "titles": { + "en": "On/Off", + "de": "An/Aus", + "ja": "オンオフ", + "zh-Hans": "开关", + "zh-Hant": "開關" }, + "type": "boolean" + }, + "status": { + "title" : "Zustand", + "titles": { + "en": "Status", + "de": "Zustand", + "ja": "状態", + "zh-Hans": "状态", + "zh-Hant": "狀態" }, + "type": "object" + } + }, + "securityDefinitions": { + "basic_sc": {"scheme": "basic", "in":"header"} + }, + "security": ["basic_sc"], + "version": { "instance": "1.2.1" } +} \ No newline at end of file diff --git a/src/test/resources/wot/example-9.nt b/src/test/resources/wot/example-9.nt new file mode 100644 index 0000000..4206f82 --- /dev/null +++ b/src/test/resources/wot/example-9.nt @@ -0,0 +1,33 @@ +_:b0 "Human readable information."@en . +_:b0 "Menschenlesbare Informationen."@de . +_:b0 "人们可阅读的信息"@zh-hans . +_:b0 "人們可閱讀的資訊"@zh-hant . +_:b0 "人間が読むことができる情報"@ja . +_:b0 "MeinDing"@de . +_:b0 "MyThing"@de . +_:b0 "MyThing"@en . +_:b0 "我的东西"@zh-hans . +_:b0 "我的東西"@zh-hant . +_:b0 "私の物"@ja . +_:b0 _:b1 . +_:b0 _:b2 . +_:b0 . +_:b0 _:b3 . +_:b0 _:b4 . +_:b1 "An/Aus"@de . +_:b1 "On/Off"@en . +_:b1 "オンオフ"@ja . +_:b1 "开关"@zh-hans . +_:b1 "開關"@zh-hant . +_:b1 . +_:b1 "on"@de . +_:b2 "Status"@en . +_:b2 "Zustand"@de . +_:b2 "状态"@zh-hans . +_:b2 "状態"@ja . +_:b2 "狀態"@zh-hant . +_:b2 . +_:b2 "status"@de . +_:b3 "header"@de . +_:b3 "basic"@de . +_:b4 "1.2.1"@de .